1115013Smarcel/* 2160157SmarcelCopyright (c) 2003-2006 Hewlett-Packard Development Company, L.P. 3121642SmarcelPermission is hereby granted, free of charge, to any person 4121642Smarcelobtaining a copy of this software and associated documentation 5121642Smarcelfiles (the "Software"), to deal in the Software without 6121642Smarcelrestriction, including without limitation the rights to use, 7121642Smarcelcopy, modify, merge, publish, distribute, sublicense, and/or sell 8121642Smarcelcopies of the Software, and to permit persons to whom the 9121642SmarcelSoftware is furnished to do so, subject to the following 10121642Smarcelconditions: 11115013Smarcel 12121642SmarcelThe above copyright notice and this permission notice shall be 13121642Smarcelincluded in all copies or substantial portions of the Software. 14121642Smarcel 15121642SmarcelTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16121642SmarcelEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17121642SmarcelOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18121642SmarcelNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19121642SmarcelHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20121642SmarcelWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21121642SmarcelFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22121642SmarcelOTHER DEALINGS IN THE SOFTWARE. 23121642Smarcel*/ 24121642Smarcel 25115013Smarcel#include "uwx_env.h" 26115013Smarcel#include "uwx_uinfo.h" 27115013Smarcel#include "uwx_utable.h" 28115013Smarcel#include "uwx_scoreboard.h" 29115013Smarcel#include "uwx_bstream.h" 30115013Smarcel#include "uwx_trace.h" 31160163Smarcel#include "uwx_swap.h" 32115013Smarcel 33115013Smarcelint uwx_count_ones(unsigned int mask); 34115013Smarcel 35115013Smarcel/* 36115013Smarcel * uwx_uinfo.c 37115013Smarcel * 38115013Smarcel * This file contains the routines for reading and decoding 39115013Smarcel * the unwind information block. 40115013Smarcel * 41115013Smarcel * The main entry point, uwx_decode_uinfo(), is given a pointer 42115013Smarcel * to an unwind table entry and a pointer (passed by reference) 43115013Smarcel * to be filled in with a pointer to an update vector. It will 44115013Smarcel * read and decode the unwind descriptors contained in the 45115013Smarcel * unwind information block, then build the register state array, 46115013Smarcel * which describes the actions necessary to step from the current 47115013Smarcel * frame to the previous one. 48115013Smarcel */ 49115013Smarcel 50115013Smarcel#define COPYIN_UINFO_4(dest, src) \ 51115013Smarcel (env->remote? \ 52160157Smarcel (*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \ 53115013Smarcel WORDSZ, env->cb_token) : \ 54160157Smarcel (*(uint32_t *)(intptr_t)(dest) = *(uint32_t *)(intptr_t)(src), WORDSZ) ) 55115013Smarcel 56115013Smarcel#define COPYIN_UINFO_8(dest, src) \ 57115013Smarcel (env->remote? \ 58160157Smarcel (*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \ 59115013Smarcel DWORDSZ, env->cb_token) : \ 60160157Smarcel (*(uint64_t *)(intptr_t)(dest) = *(uint64_t *)(intptr_t)(src), DWORDSZ) ) 61115013Smarcel 62115013Smarcel 63115013Smarcel/* uwx_default_rstate: Returns the default register state for a leaf routine */ 64115013Smarcel 65115013Smarcelint uwx_default_rstate(struct uwx_env *env, uint64_t **rstatep) 66115013Smarcel{ 67115013Smarcel struct uwx_scoreboard *sb; 68115013Smarcel 69115013Smarcel sb = uwx_init_scoreboards(env); 70115013Smarcel *rstatep = sb->rstate; 71115013Smarcel return UWX_OK; 72115013Smarcel} 73115013Smarcel 74115013Smarcel 75115013Smarcel/* uwx_decode_uinfo: Decodes unwind info region */ 76115013Smarcel 77115013Smarcelint uwx_decode_uinfo( 78115013Smarcel struct uwx_env *env, 79115013Smarcel struct uwx_utable_entry *uentry, 80115013Smarcel uint64_t **rstatep) 81115013Smarcel{ 82115013Smarcel uint64_t uinfohdr; 83115013Smarcel unsigned int ulen; 84115013Smarcel int len; 85115013Smarcel struct uwx_bstream bstream; 86115013Smarcel struct uwx_scoreboard *scoreboard; 87115013Smarcel int ip_slot; 88115013Smarcel int cur_slot; 89115013Smarcel int status; 90115013Smarcel struct uwx_rhdr rhdr; 91115013Smarcel 92115013Smarcel /* Remember the offset from the start of the function */ 93115013Smarcel /* to the current IP. This helps the client find */ 94115013Smarcel /* the symbolic information. */ 95115013Smarcel 96129059Smarcel env->function_offset = env->remapped_ip - uentry->code_start; 97115013Smarcel 98115013Smarcel /* Read the unwind info header using the copyin callback. */ 99115013Smarcel /* (If we're reading a 32-bit unwind table, we need to */ 100115013Smarcel /* read the header as two 32-bit pieces to preserve the */ 101115013Smarcel /* guarantee that we always call copyin for aligned */ 102115013Smarcel /* 4-byte or 8-byte chunks.) */ 103115013Smarcel /* Then compute the length of the unwind descriptor */ 104115013Smarcel /* region and initialize a byte stream to read it. */ 105115013Smarcel 106115013Smarcel if (uentry->unwind_flags & UNWIND_TBL_32BIT) { 107115013Smarcel len = COPYIN_UINFO_4((char *)&uinfohdr, uentry->unwind_info); 108115013Smarcel len += COPYIN_UINFO_4((char *)&uinfohdr + WORDSZ, 109115013Smarcel uentry->unwind_info + WORDSZ); 110115013Smarcel } 111115013Smarcel else 112115013Smarcel len = COPYIN_UINFO_8((char *)&uinfohdr, uentry->unwind_info); 113115013Smarcel if (len != DWORDSZ) 114115013Smarcel return UWX_ERR_COPYIN_UINFO; 115115013Smarcel if (env->byte_swap) 116115013Smarcel uwx_swap8(&uinfohdr); 117115013Smarcel if (uentry->unwind_flags & UNWIND_TBL_32BIT) 118115013Smarcel ulen = UNW_LENGTH(uinfohdr) * WORDSZ; 119115013Smarcel else 120115013Smarcel ulen = UNW_LENGTH(uinfohdr) * DWORDSZ; 121115013Smarcel uwx_init_bstream(&bstream, env, 122115013Smarcel uentry->unwind_info + DWORDSZ, ulen, UWX_COPYIN_UINFO); 123115013Smarcel 124160157Smarcel /* Save the header and a pointer to the personality routine ptr */ 125160157Smarcel /* for later use in exception handling. */ 126160157Smarcel 127160157Smarcel env->uinfo_hdr = uinfohdr; 128160157Smarcel env->uinfo_end = uentry->unwind_info + DWORDSZ + ulen; 129160157Smarcel 130115013Smarcel TRACE_R_UIB(uentry, ulen) 131115013Smarcel 132115013Smarcel /* Create an initial scoreboard for tracking the unwind state. */ 133115013Smarcel 134115013Smarcel scoreboard = uwx_init_scoreboards(env); 135115013Smarcel 136115013Smarcel /* Prepare to read and decode the unwind regions described */ 137115013Smarcel /* by the unwind info block. Find the target "ip" slot */ 138115013Smarcel /* relative to the beginning of the region. The lower 4 bits */ 139115013Smarcel /* of the actual IP encode the slot number within a bundle. */ 140115013Smarcel 141115013Smarcel cur_slot = 0; 142115013Smarcel ip_slot = (int) ((env->context.special[UWX_REG_IP] & ~0x0fLL) 143115013Smarcel - uentry->code_start) 144115013Smarcel / BUNDLESZ * SLOTSPERBUNDLE 145115013Smarcel + (unsigned int) (env->context.special[UWX_REG_IP] & 0x0f); 146115013Smarcel 147115013Smarcel /* Loop over the regions in the unwind info block. */ 148115013Smarcel 149115013Smarcel for (;;) { 150115013Smarcel 151115013Smarcel /* Decode the next region header. */ 152115013Smarcel /* We have an error if we reach the end of the info block, */ 153115013Smarcel /* since we should have found our target ip slot by then. */ 154115013Smarcel /* We also have an error if the next byte isn't a region */ 155115013Smarcel /* header record. */ 156115013Smarcel 157115013Smarcel status = uwx_decode_rhdr(env, &bstream, &rhdr); 158115013Smarcel if (status != UWX_OK) 159115013Smarcel return status; 160115013Smarcel 161115013Smarcel /* If a prologue region, get a new scoreboard, pushing */ 162115013Smarcel /* the previous one onto the prologue stack. Then read */ 163115013Smarcel /* and decode the prologue region records. */ 164115013Smarcel 165115013Smarcel if (rhdr.is_prologue) { 166115013Smarcel scoreboard = uwx_new_scoreboard(env, scoreboard); 167115013Smarcel if (scoreboard == 0) 168115013Smarcel return UWX_ERR_NOMEM; 169115013Smarcel status = uwx_decode_prologue(env, &bstream, 170115013Smarcel scoreboard, &rhdr, ip_slot); 171115013Smarcel } 172115013Smarcel 173115013Smarcel /* If a body region, read and decode the body region */ 174115013Smarcel /* records. If the body has an epilogue count, */ 175115013Smarcel /* uwx_decode_body will note that in the region header */ 176115013Smarcel /* record for use at the bottom of the loop. */ 177115013Smarcel 178115013Smarcel else { 179115013Smarcel status = uwx_decode_body(env, &bstream, scoreboard, &rhdr, ip_slot); 180115013Smarcel } 181115013Smarcel 182115013Smarcel if (status != UWX_OK) 183115013Smarcel return status; 184115013Smarcel 185115013Smarcel TRACE_R_DUMP_SB(scoreboard, rhdr, cur_slot, ip_slot) 186115013Smarcel 187115013Smarcel /* If the target ip slot is within this region, we're done. */ 188115013Smarcel /* Return the scoreboard's register state array. */ 189115013Smarcel 190115013Smarcel if (ip_slot < rhdr.rlen) { 191115013Smarcel *rstatep = scoreboard->rstate; 192115013Smarcel return UWX_OK; 193115013Smarcel } 194115013Smarcel 195115013Smarcel /* Otherwise, update the current ip slot, pop the */ 196115013Smarcel /* scoreboard stack based on the epilogue count, */ 197115013Smarcel /* and loop back around for the next region. */ 198115013Smarcel 199115013Smarcel cur_slot += rhdr.rlen; 200115013Smarcel ip_slot -= rhdr.rlen; 201115013Smarcel if (rhdr.ecount > 0) { 202115013Smarcel scoreboard = uwx_pop_scoreboards(env, scoreboard, rhdr.ecount); 203115013Smarcel if (scoreboard == 0) 204115013Smarcel return UWX_ERR_PROLOG_UF; 205115013Smarcel } 206115013Smarcel } 207115013Smarcel /*NOTREACHED*/ 208115013Smarcel} 209115013Smarcel 210115013Smarcel 211115013Smarcel/* uwx_decode_rhdr: Decodes a region header record */ 212115013Smarcel 213115013Smarcelint uwx_decode_rhdr( 214115013Smarcel struct uwx_env *env, 215115013Smarcel struct uwx_bstream *bstream, 216115013Smarcel struct uwx_rhdr *rhdr) 217115013Smarcel{ 218115013Smarcel int b0; 219115013Smarcel int b1; 220115013Smarcel uint64_t val; 221115013Smarcel int status; 222115013Smarcel 223115013Smarcel /* Get the first byte of the next descriptor record. */ 224115013Smarcel b0 = uwx_get_byte(bstream); 225115013Smarcel if (b0 < 0) 226115013Smarcel return UWX_ERR_NOUDESC; 227115013Smarcel 228115013Smarcel /* Initialize region header record. */ 229115013Smarcel 230115013Smarcel rhdr->is_prologue = 0; 231115013Smarcel rhdr->rlen = 0; 232115013Smarcel rhdr->mask = 0; 233115013Smarcel rhdr->grsave = 0; 234115013Smarcel rhdr->ecount = 0; 235115013Smarcel 236115013Smarcel /* Format R1 */ 237115013Smarcel 238115013Smarcel if (b0 < 0x40) { 239115013Smarcel if ((b0 & 0x20) == 0) { 240115013Smarcel TRACE_I_DECODE_RHDR_1("(R1) prologue", b0) 241115013Smarcel rhdr->is_prologue = 1; 242120925Smarcel } 243120925Smarcel else { 244117465Smarcel TRACE_I_DECODE_RHDR_1("(R1) body", b0) 245115013Smarcel } 246115013Smarcel rhdr->rlen = b0 & 0x1f; 247115013Smarcel } 248115013Smarcel 249115013Smarcel /* Format R2 */ 250115013Smarcel 251115013Smarcel else if (b0 < 0x60) { 252115013Smarcel b1 = uwx_get_byte(bstream); 253115013Smarcel if (b1 < 0) 254115013Smarcel return UWX_ERR_BADUDESC; 255115013Smarcel status = uwx_get_uleb128(bstream, &val); 256115013Smarcel if (status != 0) 257115013Smarcel return UWX_ERR_BADUDESC; 258115013Smarcel TRACE_I_DECODE_RHDR_2L("(R2) prologue_gr", b0, b1, val) 259115013Smarcel rhdr->is_prologue = 1; 260115013Smarcel rhdr->rlen = (unsigned int) val; 261115013Smarcel rhdr->mask = ((b0 & 0x07) << 1) | (b1 >> 7); 262115013Smarcel rhdr->grsave = b1 & 0x7f; 263115013Smarcel } 264115013Smarcel 265115013Smarcel /* Format R3 */ 266115013Smarcel 267115013Smarcel else if (b0 < 0x80) { 268115013Smarcel status = uwx_get_uleb128(bstream, &val); 269115013Smarcel if (status != 0) 270115013Smarcel return UWX_ERR_BADUDESC; 271115013Smarcel if ((b0 & 0x03) == 0) { 272115013Smarcel TRACE_I_DECODE_RHDR_1L("(R3) prologue", b0, val) 273115013Smarcel rhdr->is_prologue = 1; 274120925Smarcel } 275120925Smarcel else { 276117465Smarcel TRACE_I_DECODE_RHDR_1L("(R3) body", b0, val) 277115013Smarcel } 278115013Smarcel rhdr->rlen = (unsigned int) val; 279115013Smarcel } 280115013Smarcel 281115013Smarcel /* Otherwise, not a region header record. */ 282115013Smarcel 283115013Smarcel else { 284115013Smarcel TRACE_I_DECODE_RHDR_1("(?)", b0) 285115013Smarcel return UWX_ERR_BADUDESC; 286115013Smarcel } 287115013Smarcel 288115013Smarcel return UWX_OK; 289115013Smarcel} 290115013Smarcel 291115013Smarcel 292115013Smarcel/* uwx_decode_prologue: Decodes a prologue region */ 293115013Smarcel 294115013Smarcelint uwx_decode_prologue( 295115013Smarcel struct uwx_env *env, 296115013Smarcel struct uwx_bstream *bstream, 297115013Smarcel struct uwx_scoreboard *scoreboard, 298115013Smarcel struct uwx_rhdr *rhdr, 299115013Smarcel int ip_slot) 300115013Smarcel{ 301115013Smarcel int status; 302115013Smarcel int reg; 303115013Smarcel int mask; 304115013Smarcel int b0; 305115013Smarcel int b1; 306115013Smarcel int b2; 307115013Smarcel int b3; 308115013Smarcel int r; 309115013Smarcel int t; 310115013Smarcel int i; 311115013Smarcel uint64_t parm1; 312115013Smarcel uint64_t parm2; 313115013Smarcel uint64_t newrstate[NSBREG]; 314115013Smarcel int tspill[NSBREG]; 315115013Smarcel int priunat_mem_rstate; 316115013Smarcel int t_priunat_mem; 317115013Smarcel unsigned int gr_mem_mask; 318115013Smarcel unsigned int br_mem_mask; 319115013Smarcel unsigned int fr_mem_mask; 320115013Smarcel unsigned int gr_gr_mask; 321115013Smarcel unsigned int br_gr_mask; 322115013Smarcel int ngr; 323115013Smarcel int nbr; 324115013Smarcel int nfr; 325115013Smarcel unsigned int spill_base; 326115013Smarcel unsigned int gr_base; 327115013Smarcel unsigned int br_base; 328115013Smarcel unsigned int fr_base; 329115013Smarcel 330115013Smarcel /* Initialize an array of register states from the current */ 331115013Smarcel /* scoreboard, along with a parallel array of spill times. */ 332115013Smarcel /* We use this as a temporary scoreboard, then update the */ 333115013Smarcel /* real scoreboard at the end of the procedure. */ 334115013Smarcel /* We initialize the spill time to (rhdr.rlen - 1) so that */ 335115013Smarcel /* spills without a "when" descriptor will take effect */ 336115013Smarcel /* at the end of the prologue region. */ 337115013Smarcel /* (Boundary condition: all actions in a zero-length prologue */ 338115013Smarcel /* will appear to have happened in the instruction slot */ 339115013Smarcel /* immediately preceding the prologue.) */ 340115013Smarcel 341115013Smarcel for (i = 0; i < env->nsbreg; i++) { 342115013Smarcel newrstate[i] = scoreboard->rstate[i]; 343115013Smarcel tspill[i] = rhdr->rlen - 1; 344115013Smarcel } 345115013Smarcel priunat_mem_rstate = UWX_DISP_NONE; 346115013Smarcel t_priunat_mem = rhdr->rlen - 1; 347115013Smarcel 348115013Smarcel fr_mem_mask = 0; 349115013Smarcel gr_mem_mask = 0; 350115013Smarcel br_mem_mask = 0; 351115013Smarcel gr_gr_mask = 0; 352115013Smarcel br_gr_mask = 0; 353160157Smarcel nfr = 127; 354160157Smarcel ngr = 127; 355160157Smarcel nbr = 127; 356115013Smarcel spill_base = 0; 357115013Smarcel 358115013Smarcel /* If prologue_gr header record supplied mask and grsave, */ 359115013Smarcel /* record these in the scoreboard. */ 360115013Smarcel 361115013Smarcel reg = rhdr->grsave; 362115013Smarcel mask = rhdr->mask; 363115013Smarcel if (mask & 0x8) { 364115013Smarcel newrstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_GR(reg)); 365115013Smarcel reg++; 366115013Smarcel } 367115013Smarcel if (mask & 0x4) { 368115013Smarcel newrstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_GR(reg)); 369115013Smarcel reg++; 370115013Smarcel } 371115013Smarcel if (mask & 0x2) { 372115013Smarcel newrstate[SBREG_PSP] = UWX_DISP_REG(UWX_REG_GR(reg)); 373115013Smarcel reg++; 374115013Smarcel } 375115013Smarcel if (mask & 0x1) { 376115013Smarcel newrstate[SBREG_PREDS] = UWX_DISP_REG(UWX_REG_GR(reg)); 377115013Smarcel reg++; 378115013Smarcel } 379115013Smarcel 380115013Smarcel /* Read prologue descriptor records until */ 381115013Smarcel /* we hit another region header. */ 382115013Smarcel 383115013Smarcel for (;;) { 384115013Smarcel 385115013Smarcel b0 = uwx_get_byte(bstream); 386115013Smarcel 387115013Smarcel if (b0 < 0x80) { 388115013Smarcel /* Return the last byte read to the byte stream, since it's */ 389115013Smarcel /* really the first byte of the next region header record. */ 390115013Smarcel if (b0 >= 0) 391115013Smarcel (void) uwx_unget_byte(bstream, b0); 392115013Smarcel break; 393115013Smarcel } 394115013Smarcel 395115013Smarcel switch ((b0 & 0x70) >> 4) { 396115013Smarcel 397115013Smarcel case 0: /* 1000 xxxx */ 398115013Smarcel case 1: /* 1001 xxxx */ 399115013Smarcel /* Format P1 (br_mem) */ 400115013Smarcel TRACE_I_DECODE_PROLOGUE_1("(P1) br_mem", b0) 401115013Smarcel br_mem_mask = b0 & 0x1f; 402115013Smarcel break; 403115013Smarcel 404115013Smarcel case 2: /* 1010 xxxx */ 405115013Smarcel /* Format P2 (br_gr) */ 406115013Smarcel b1 = uwx_get_byte(bstream); 407115013Smarcel if (b1 < 0) 408115013Smarcel return UWX_ERR_BADUDESC; 409115013Smarcel TRACE_I_DECODE_PROLOGUE_2("(P2) br_gr", b0, b1) 410115013Smarcel mask = ((b0 & 0x0f) << 1) | (b1 >> 7); 411115013Smarcel reg = b1 & 0x7f; 412115013Smarcel br_gr_mask = mask; 413115013Smarcel for (i = 0; i < NSB_BR && mask != 0; i++) { 414115013Smarcel if (mask & 0x01) { 415115013Smarcel newrstate[SBREG_BR + i] = UWX_DISP_REG(UWX_REG_GR(reg)); 416115013Smarcel reg++; 417115013Smarcel } 418115013Smarcel mask = mask >> 1; 419115013Smarcel } 420115013Smarcel break; 421115013Smarcel 422115013Smarcel case 3: /* 1011 xxxx */ 423115013Smarcel /* Format P3 */ 424115013Smarcel if (b0 < 0xb8) { 425115013Smarcel b1 = uwx_get_byte(bstream); 426115013Smarcel if (b1 < 0) 427115013Smarcel return UWX_ERR_BADUDESC; 428129059Smarcel r = ((b0 & 0x7) << 1) | (b1 >> 7); 429115013Smarcel reg = b1 & 0x7f; 430115013Smarcel switch (r) { 431115013Smarcel case 0: /* psp_gr */ 432115013Smarcel TRACE_I_DECODE_PROLOGUE_2("(P3) psp_gr", b0, b1) 433115013Smarcel newrstate[SBREG_PSP] = UWX_DISP_REG(UWX_REG_GR(reg)); 434115013Smarcel break; 435115013Smarcel case 1: /* rp_gr */ 436115013Smarcel TRACE_I_DECODE_PROLOGUE_2("(P3) rp_gr", b0, b1) 437115013Smarcel newrstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_GR(reg)); 438115013Smarcel break; 439115013Smarcel case 2: /* pfs_gr */ 440115013Smarcel TRACE_I_DECODE_PROLOGUE_2("(P3) pfs_gr", b0, b1) 441115013Smarcel newrstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_GR(reg)); 442115013Smarcel break; 443115013Smarcel case 3: /* preds_gr */ 444115013Smarcel TRACE_I_DECODE_PROLOGUE_2("(P3) preds_gr", b0, b1) 445115013Smarcel newrstate[SBREG_PREDS] = 446115013Smarcel UWX_DISP_REG(UWX_REG_GR(reg)); 447115013Smarcel break; 448115013Smarcel case 4: /* unat_gr */ 449115013Smarcel TRACE_I_DECODE_PROLOGUE_2("(P3) unat_gr", b0, b1) 450115013Smarcel newrstate[SBREG_UNAT] = 451115013Smarcel UWX_DISP_REG(UWX_REG_GR(reg)); 452115013Smarcel break; 453115013Smarcel case 5: /* lc_gr */ 454115013Smarcel TRACE_I_DECODE_PROLOGUE_2("(P3) lc_gr", b0, b1) 455115013Smarcel newrstate[SBREG_LC] = 456115013Smarcel UWX_DISP_REG(UWX_REG_GR(reg)); 457115013Smarcel break; 458115013Smarcel case 6: /* rp_br */ 459115013Smarcel TRACE_I_DECODE_PROLOGUE_2("(P3) rp_br", b0, b1) 460115013Smarcel scoreboard->rstate[SBREG_RP] = 461115013Smarcel UWX_DISP_REG(UWX_REG_BR(reg)); 462160157Smarcel if (newrstate[SBREG_RP] == 463160157Smarcel UWX_DISP_REG(UWX_REG_BR(0))) 464160157Smarcel newrstate[SBREG_RP] = 465160157Smarcel UWX_DISP_REG(UWX_REG_BR(reg)); 466115013Smarcel break; 467115013Smarcel case 7: /* rnat_gr */ 468115013Smarcel TRACE_I_DECODE_PROLOGUE_2("(P3) rnat_gr", b0, b1) 469115013Smarcel newrstate[SBREG_RNAT] = 470115013Smarcel UWX_DISP_REG(UWX_REG_GR(reg)); 471115013Smarcel break; 472115013Smarcel case 8: /* bsp_gr */ 473115013Smarcel TRACE_I_DECODE_PROLOGUE_2("(P3) bsp_gr", b0, b1) 474115013Smarcel /* Don't track BSP yet */ 475115013Smarcel return UWX_ERR_CANTUNWIND; 476160157Smarcel /* break; */ 477115013Smarcel case 9: /* bspstore_gr */ 478115013Smarcel TRACE_I_DECODE_PROLOGUE_2("(P3) bspstore_gr", b0, b1) 479115013Smarcel /* Don't track BSPSTORE yet */ 480115013Smarcel return UWX_ERR_CANTUNWIND; 481160157Smarcel /* break; */ 482115013Smarcel case 10: /* fpsr_gr */ 483115013Smarcel TRACE_I_DECODE_PROLOGUE_2("(P3) fpsr_gr", b0, b1) 484115013Smarcel newrstate[SBREG_FPSR] = 485115013Smarcel UWX_DISP_REG(UWX_REG_GR(reg)); 486115013Smarcel break; 487115013Smarcel case 11: /* priunat_gr */ 488115013Smarcel TRACE_I_DECODE_PROLOGUE_2("(P3) priunat_gr", b0, b1) 489115013Smarcel newrstate[SBREG_PRIUNAT] = 490115013Smarcel UWX_DISP_REG(UWX_REG_GR(reg)); 491115013Smarcel break; 492115013Smarcel default: 493115013Smarcel TRACE_I_DECODE_PROLOGUE_2("(P3) ??", b0, b1) 494115013Smarcel return UWX_ERR_BADUDESC; 495115013Smarcel } 496115013Smarcel } 497115013Smarcel 498115013Smarcel /* Format P4 (spill_mask) */ 499115013Smarcel else if (b0 == 0xb8) { 500115013Smarcel TRACE_I_DECODE_PROLOGUE_1("(P4) spill_mask", b0) 501115013Smarcel /* The spill_mask descriptor is followed by */ 502115013Smarcel /* an imask field whose length is determined */ 503115013Smarcel /* by the region length: there are two mask */ 504115013Smarcel /* bits per instruction slot in the region. */ 505115013Smarcel /* We decode these bits two at a time, counting */ 506115013Smarcel /* the number of FRs, GRs, and BRs that are */ 507115013Smarcel /* saved up to the slot of interest. Other */ 508115013Smarcel /* descriptors describe which sets of these */ 509115013Smarcel /* registers are spilled, and we put those */ 510115013Smarcel /* two pieces of information together at the */ 511115013Smarcel /* end of the main loop. */ 512115013Smarcel t = 0; 513160157Smarcel nfr = 0; 514160157Smarcel ngr = 0; 515160157Smarcel nbr = 0; 516115013Smarcel while (t < rhdr->rlen) { 517115013Smarcel b1 = uwx_get_byte(bstream); 518115013Smarcel if (b1 < 0) 519115013Smarcel return UWX_ERR_BADUDESC; 520115013Smarcel for (i = 0; i < 4 && (t + i) < ip_slot; i++) { 521115013Smarcel switch (b1 & 0xc0) { 522115013Smarcel case 0x00: break; 523115013Smarcel case 0x40: nfr++; break; 524115013Smarcel case 0x80: ngr++; break; 525115013Smarcel case 0xc0: nbr++; break; 526115013Smarcel } 527115013Smarcel b1 = b1 << 2; 528115013Smarcel } 529115013Smarcel t += 4; 530115013Smarcel } 531115013Smarcel } 532115013Smarcel 533115013Smarcel /* Format P5 (frgr_mem) */ 534115013Smarcel else if (b0 == 0xb9) { 535115013Smarcel b1 = uwx_get_byte(bstream); 536115013Smarcel if (b1 < 0) 537115013Smarcel return UWX_ERR_BADUDESC; 538115013Smarcel b2 = uwx_get_byte(bstream); 539115013Smarcel if (b2 < 0) 540115013Smarcel return UWX_ERR_BADUDESC; 541115013Smarcel b3 = uwx_get_byte(bstream); 542115013Smarcel if (b3 < 0) 543115013Smarcel return UWX_ERR_BADUDESC; 544115013Smarcel TRACE_I_DECODE_PROLOGUE_4("(P5) frgr_mem", b0, b1, b2, b3) 545115013Smarcel gr_mem_mask = b1 >> 4; 546115013Smarcel fr_mem_mask = ((b1 & 0x0f) << 16) | (b2 << 8) | b3; 547115013Smarcel } 548115013Smarcel 549115013Smarcel /* Invalid descriptor record */ 550115013Smarcel else { 551115013Smarcel TRACE_I_DECODE_PROLOGUE_1("(?)", b0) 552115013Smarcel return UWX_ERR_BADUDESC; 553115013Smarcel } 554115013Smarcel 555115013Smarcel break; 556115013Smarcel 557115013Smarcel case 4: /* 1100 xxxx */ 558115013Smarcel /* Format P6 (fr_mem) */ 559115013Smarcel TRACE_I_DECODE_PROLOGUE_1("(P6) fr_mem", b0) 560115013Smarcel fr_mem_mask = b0 & 0x0f; 561115013Smarcel break; 562115013Smarcel 563115013Smarcel case 5: /* 1101 xxxx */ 564115013Smarcel /* Format P6 (gr_mem) */ 565115013Smarcel TRACE_I_DECODE_PROLOGUE_1("(P6) gr_mem", b0) 566115013Smarcel gr_mem_mask = b0 & 0x0f; 567115013Smarcel break; 568115013Smarcel 569115013Smarcel case 6: /* 1110 xxxx */ 570115013Smarcel /* Format P7 */ 571115013Smarcel r = b0 & 0xf; 572115013Smarcel status = uwx_get_uleb128(bstream, &parm1); 573115013Smarcel if (status != 0) 574115013Smarcel return UWX_ERR_BADUDESC; 575115013Smarcel switch (r) { 576115013Smarcel case 0: /* mem_stack_f */ 577115013Smarcel status = uwx_get_uleb128(bstream, &parm2); 578115013Smarcel if (status != 0) 579115013Smarcel return UWX_ERR_BADUDESC; 580115013Smarcel TRACE_I_DECODE_PROLOGUE_1LL("(P7) mem_stack_f", b0, parm1, parm2) 581115013Smarcel newrstate[SBREG_PSP] = UWX_DISP_SPPLUS(parm2 * 16); 582115013Smarcel tspill[SBREG_PSP] = (int) parm1; 583115013Smarcel break; 584115013Smarcel case 1: /* mem_stack_v */ 585115013Smarcel TRACE_I_DECODE_PROLOGUE_1L("(P7) mem_stack_v", b0, parm1) 586115013Smarcel tspill[SBREG_PSP] = (int) parm1; 587115013Smarcel break; 588115013Smarcel case 2: /* spill_base */ 589115013Smarcel TRACE_I_DECODE_PROLOGUE_1L("(P7) spill_base", b0, parm1) 590115013Smarcel spill_base = 4 * (unsigned int) parm1; 591115013Smarcel break; 592115013Smarcel case 3: /* psp_sprel */ 593115013Smarcel TRACE_I_DECODE_PROLOGUE_1L("(P7) psp_sprel", b0, parm1) 594115013Smarcel newrstate[SBREG_PSP] = UWX_DISP_SPREL(parm1 * 4); 595115013Smarcel break; 596115013Smarcel case 4: /* rp_when */ 597115013Smarcel TRACE_I_DECODE_PROLOGUE_1L("(P7) rp_when", b0, parm1) 598115013Smarcel tspill[SBREG_RP] = (int) parm1; 599115013Smarcel break; 600115013Smarcel case 5: /* rp_psprel */ 601115013Smarcel TRACE_I_DECODE_PROLOGUE_1L("(P7) rp_psprel", b0, parm1) 602115013Smarcel newrstate[SBREG_RP] = UWX_DISP_PSPREL(parm1 * 4); 603115013Smarcel break; 604115013Smarcel case 6: /* pfs_when */ 605115013Smarcel TRACE_I_DECODE_PROLOGUE_1L("(P7) pfs_when", b0, parm1) 606115013Smarcel tspill[SBREG_PFS] = (int) parm1; 607115013Smarcel break; 608115013Smarcel case 7: /* pfs_psprel */ 609115013Smarcel TRACE_I_DECODE_PROLOGUE_1L("(P7) pfs_psprel", b0, parm1) 610115013Smarcel newrstate[SBREG_PFS] = UWX_DISP_PSPREL(parm1 * 4); 611115013Smarcel break; 612115013Smarcel case 8: /* preds_when */ 613115013Smarcel TRACE_I_DECODE_PROLOGUE_1L("(P7) preds_when", b0, parm1) 614115013Smarcel tspill[SBREG_PREDS] = (int) parm1; 615115013Smarcel break; 616115013Smarcel case 9: /* preds_psprel */ 617115013Smarcel TRACE_I_DECODE_PROLOGUE_1L("(P7) preds_psprel", b0, parm1) 618115013Smarcel newrstate[SBREG_PREDS] = UWX_DISP_PSPREL(parm1 * 4); 619115013Smarcel break; 620115013Smarcel case 10: /* lc_when */ 621115013Smarcel TRACE_I_DECODE_PROLOGUE_1L("(P7) lc_when", b0, parm1) 622115013Smarcel tspill[SBREG_LC] = (int) parm1; 623115013Smarcel break; 624115013Smarcel case 11: /* lc_psprel */ 625115013Smarcel TRACE_I_DECODE_PROLOGUE_1L("(P7) lc_psprel", b0, parm1) 626115013Smarcel newrstate[SBREG_LC] = UWX_DISP_PSPREL(parm1 * 4); 627115013Smarcel break; 628115013Smarcel case 12: /* unat_when */ 629115013Smarcel TRACE_I_DECODE_PROLOGUE_1L("(P7) unat_when", b0, parm1) 630115013Smarcel tspill[SBREG_UNAT] = (int) parm1; 631115013Smarcel break; 632115013Smarcel case 13: /* unat_psprel */ 633115013Smarcel TRACE_I_DECODE_PROLOGUE_1L("(P7) unat_psprel", b0, parm1) 634115013Smarcel newrstate[SBREG_UNAT] = UWX_DISP_PSPREL(parm1 * 4); 635115013Smarcel break; 636115013Smarcel case 14: /* fpsr_when */ 637115013Smarcel TRACE_I_DECODE_PROLOGUE_1L("(P7) fpsr_when", b0, parm1) 638115013Smarcel tspill[SBREG_FPSR] = (int) parm1; 639115013Smarcel break; 640115013Smarcel case 15: /* fpsr_psprel */ 641115013Smarcel TRACE_I_DECODE_PROLOGUE_1L("(P7) fpsr_psprel", b0, parm1) 642115013Smarcel newrstate[SBREG_FPSR] = UWX_DISP_PSPREL(parm1 * 4); 643115013Smarcel break; 644115013Smarcel } 645115013Smarcel break; 646115013Smarcel 647115013Smarcel case 7: /* 1111 xxxx */ 648115013Smarcel /* Format P8 */ 649115013Smarcel if (b0 == 0xf0) { 650115013Smarcel b1 = uwx_get_byte(bstream); 651115013Smarcel if (b1 < 0) 652115013Smarcel return UWX_ERR_BADUDESC; 653115013Smarcel status = uwx_get_uleb128(bstream, &parm1); 654115013Smarcel if (status != 0) 655115013Smarcel return UWX_ERR_BADUDESC; 656115013Smarcel switch (b1) { 657115013Smarcel case 1: /* rp_sprel */ 658115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) rp_sprel", b0, b1, parm1) 659115013Smarcel newrstate[SBREG_RP] = UWX_DISP_SPREL(parm1 * 4); 660115013Smarcel break; 661115013Smarcel case 2: /* pfs_sprel */ 662115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) pfs_sprel", b0, b1, parm1) 663115013Smarcel newrstate[SBREG_PFS] = UWX_DISP_SPREL(parm1 * 4); 664115013Smarcel break; 665115013Smarcel case 3: /* preds_sprel */ 666115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) preds_sprel", b0, b1, parm1) 667115013Smarcel newrstate[SBREG_PREDS] = UWX_DISP_SPREL(parm1 * 4); 668115013Smarcel break; 669115013Smarcel case 4: /* lc_sprel */ 670115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) lc_sprel", b0, b1, parm1) 671115013Smarcel newrstate[SBREG_LC] = UWX_DISP_SPREL(parm1 * 4); 672115013Smarcel break; 673115013Smarcel case 5: /* unat_sprel */ 674115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) unat_sprel", b0, b1, parm1) 675115013Smarcel newrstate[SBREG_UNAT] = UWX_DISP_SPREL(parm1 * 4); 676115013Smarcel break; 677115013Smarcel case 6: /* fpsr_sprel */ 678115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) fpsr_sprel", b0, b1, parm1) 679115013Smarcel newrstate[SBREG_FPSR] = UWX_DISP_SPREL(parm1 * 4); 680115013Smarcel break; 681115013Smarcel case 7: /* bsp_when */ 682115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_when", b0, b1, parm1) 683115013Smarcel /* Don't track BSP yet */ 684115013Smarcel return UWX_ERR_CANTUNWIND; 685160157Smarcel /* break; */ 686115013Smarcel case 8: /* bsp_psprel */ 687115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_psprel", b0, b1, parm1) 688115013Smarcel /* Don't track BSP yet */ 689115013Smarcel return UWX_ERR_CANTUNWIND; 690160157Smarcel /* break; */ 691115013Smarcel case 9: /* bsp_sprel */ 692115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_sprel", b0, b1, parm1) 693115013Smarcel /* Don't track BSP yet */ 694115013Smarcel return UWX_ERR_CANTUNWIND; 695160157Smarcel /* break; */ 696115013Smarcel case 10: /* bspstore_when */ 697115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_when", b0, b1, parm1) 698115013Smarcel /* Don't track BSP yet */ 699115013Smarcel return UWX_ERR_CANTUNWIND; 700160157Smarcel /* break; */ 701115013Smarcel case 11: /* bspstore_psprel */ 702115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_psprel", b0, b1, parm1) 703115013Smarcel /* Don't track BSP yet */ 704115013Smarcel return UWX_ERR_CANTUNWIND; 705160157Smarcel /* break; */ 706115013Smarcel case 12: /* bspstore_sprel */ 707115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_sprel", b0, b1, parm1) 708115013Smarcel /* Don't track BSP yet */ 709115013Smarcel return UWX_ERR_CANTUNWIND; 710160157Smarcel /* break; */ 711115013Smarcel case 13: /* rnat_when */ 712115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_when", b0, b1, parm1) 713115013Smarcel tspill[SBREG_RNAT] = (int) parm1; 714115013Smarcel break; 715115013Smarcel case 14: /* rnat_psprel */ 716115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_psprel", b0, b1, parm1) 717115013Smarcel newrstate[SBREG_RNAT] = UWX_DISP_PSPREL(parm1 * 4); 718115013Smarcel break; 719115013Smarcel case 15: /* rnat_sprel */ 720115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_sprel", b0, b1, parm1) 721115013Smarcel newrstate[SBREG_RNAT] = UWX_DISP_SPREL(parm1 * 4); 722115013Smarcel break; 723115013Smarcel case 16: /* priunat_when_gr */ 724115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_when_gr", b0, b1, parm1) 725115013Smarcel tspill[SBREG_PRIUNAT] = (int) parm1; 726115013Smarcel break; 727115013Smarcel case 17: /* priunat_psprel */ 728115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_psprel", b0, b1, parm1) 729115013Smarcel priunat_mem_rstate = UWX_DISP_PSPREL(parm1 * 4); 730115013Smarcel break; 731115013Smarcel case 18: /* priunat_sprel */ 732115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_sprel", b0, b1, parm1) 733115013Smarcel priunat_mem_rstate = UWX_DISP_SPREL(parm1 * 4); 734115013Smarcel break; 735115013Smarcel case 19: /* priunat_when_mem */ 736115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_when_mem", b0, b1, parm1) 737115013Smarcel t_priunat_mem = (int) parm1; 738115013Smarcel break; 739115013Smarcel default: 740115013Smarcel TRACE_I_DECODE_PROLOGUE_2L("(P8) ??", b0, b1, parm1) 741115013Smarcel return UWX_ERR_BADUDESC; 742115013Smarcel } 743115013Smarcel } 744115013Smarcel 745115013Smarcel /* Format P9 (gr_gr) */ 746115013Smarcel else if (b0 == 0xf1) { 747115013Smarcel b1 = uwx_get_byte(bstream); 748115013Smarcel if (b1 < 0) 749115013Smarcel return UWX_ERR_BADUDESC; 750115013Smarcel b2 = uwx_get_byte(bstream); 751115013Smarcel if (b2 < 0) 752115013Smarcel return UWX_ERR_BADUDESC; 753115013Smarcel TRACE_I_DECODE_PROLOGUE_3("(P9) gr_gr", b0, b1, b2) 754115013Smarcel mask = b1 & 0x0f; 755115013Smarcel reg = b2 & 0x7f; 756115013Smarcel gr_gr_mask = mask; 757115013Smarcel for (i = 0; i < NSB_GR && mask != 0; i++) { 758115013Smarcel if (mask & 0x01) { 759115013Smarcel newrstate[SBREG_GR + i] = 760115013Smarcel UWX_DISP_REG(UWX_REG_GR(reg)); 761115013Smarcel reg++; 762115013Smarcel } 763115013Smarcel mask = mask >> 1; 764115013Smarcel } 765115013Smarcel } 766115013Smarcel 767115013Smarcel /* Format X1 */ 768115013Smarcel else if (b0 == 0xf9) { 769115013Smarcel TRACE_I_DECODE_PROLOGUE_1("(X1)", b0) 770115013Smarcel b1 = uwx_get_byte(bstream); 771115013Smarcel if (b1 < 0) 772115013Smarcel return UWX_ERR_BADUDESC; 773115013Smarcel /* Don't support X-format descriptors yet */ 774115013Smarcel return UWX_ERR_CANTUNWIND; 775115013Smarcel } 776115013Smarcel 777115013Smarcel /* Format X2 */ 778115013Smarcel else if (b0 == 0xfa) { 779115013Smarcel TRACE_I_DECODE_PROLOGUE_1("(X2)", b0) 780115013Smarcel b1 = uwx_get_byte(bstream); 781115013Smarcel if (b1 < 0) 782115013Smarcel return UWX_ERR_BADUDESC; 783115013Smarcel b2 = uwx_get_byte(bstream); 784115013Smarcel if (b2 < 0) 785115013Smarcel return UWX_ERR_BADUDESC; 786115013Smarcel /* Don't support X-format descriptors yet */ 787115013Smarcel return UWX_ERR_CANTUNWIND; 788115013Smarcel } 789115013Smarcel 790115013Smarcel /* Format X3 */ 791115013Smarcel else if (b0 == 0xfb) { 792115013Smarcel TRACE_I_DECODE_PROLOGUE_1("(X3)", b0) 793115013Smarcel b1 = uwx_get_byte(bstream); 794115013Smarcel if (b1 < 0) 795115013Smarcel return UWX_ERR_BADUDESC; 796115013Smarcel b2 = uwx_get_byte(bstream); 797115013Smarcel if (b2 < 0) 798115013Smarcel return UWX_ERR_BADUDESC; 799115013Smarcel /* Don't support X-format descriptors yet */ 800115013Smarcel return UWX_ERR_CANTUNWIND; 801115013Smarcel } 802115013Smarcel 803115013Smarcel /* Format X4 */ 804115013Smarcel else if (b0 == 0xfc) { 805115013Smarcel TRACE_I_DECODE_PROLOGUE_1("(X4)", b0) 806115013Smarcel b1 = uwx_get_byte(bstream); 807115013Smarcel if (b1 < 0) 808115013Smarcel return UWX_ERR_BADUDESC; 809115013Smarcel b2 = uwx_get_byte(bstream); 810115013Smarcel if (b2 < 0) 811115013Smarcel return UWX_ERR_BADUDESC; 812115013Smarcel b3 = uwx_get_byte(bstream); 813115013Smarcel if (b3 < 0) 814115013Smarcel return UWX_ERR_BADUDESC; 815115013Smarcel /* Don't support X-format descriptors yet */ 816115013Smarcel return UWX_ERR_CANTUNWIND; 817115013Smarcel } 818115013Smarcel 819115013Smarcel /* Format P10 */ 820115013Smarcel else if (b0 == 0xff) { 821115013Smarcel b1 = uwx_get_byte(bstream); 822115013Smarcel if (b1 < 0) 823115013Smarcel return UWX_ERR_BADUDESC; 824115013Smarcel b2 = uwx_get_byte(bstream); 825115013Smarcel if (b2 < 0) 826115013Smarcel return UWX_ERR_BADUDESC; 827115013Smarcel TRACE_I_DECODE_PROLOGUE_3("(P10) abi", b0, b1, b2) 828115013Smarcel env->abi_context = (b1 << 8) | b2; 829115013Smarcel return UWX_ABI_FRAME; 830115013Smarcel } 831115013Smarcel 832115013Smarcel /* Invalid descriptor record */ 833115013Smarcel else { 834115013Smarcel TRACE_I_DECODE_PROLOGUE_1("(?)", b0) 835115013Smarcel return UWX_ERR_BADUDESC; 836115013Smarcel } 837115013Smarcel break; 838115013Smarcel } 839115013Smarcel } 840115013Smarcel 841115013Smarcel /* Process the masks of spilled GRs, FRs, and BRs to */ 842115013Smarcel /* determine when and where each register was saved. */ 843115013Smarcel 844115013Smarcel fr_base = spill_base + 16 * uwx_count_ones(fr_mem_mask); 845115013Smarcel br_base = fr_base + 8 * uwx_count_ones(br_mem_mask); 846115013Smarcel gr_base = br_base + 8 * uwx_count_ones(gr_mem_mask); 847115013Smarcel TRACE_I_DECODE_PROLOGUE_SPILL_BASE(spill_base) 848115013Smarcel TRACE_I_DECODE_PROLOGUE_MASKS(gr_mem_mask, gr_gr_mask) 849115013Smarcel TRACE_I_DECODE_PROLOGUE_NSPILL(ngr) 850115013Smarcel for (i = 0; ngr > 0 && i <= NSB_GR; i++) { 851115013Smarcel if (gr_mem_mask & 1) { 852115013Smarcel newrstate[SBREG_GR + i] = UWX_DISP_PSPREL(gr_base); 853115013Smarcel tspill[SBREG_GR + i] = 0; 854115013Smarcel gr_base -= 8; 855115013Smarcel ngr--; 856115013Smarcel } 857115013Smarcel else if (gr_gr_mask & 1) { 858115013Smarcel tspill[SBREG_GR + i] = 0; 859115013Smarcel ngr--; 860115013Smarcel } 861115013Smarcel gr_gr_mask = gr_gr_mask >> 1; 862115013Smarcel gr_mem_mask = gr_mem_mask >> 1; 863115013Smarcel } 864115013Smarcel for (i = 0; nbr > 0 && i <= NSB_BR; i++) { 865115013Smarcel if (br_mem_mask & 1) { 866115013Smarcel newrstate[SBREG_BR + i] = UWX_DISP_PSPREL(br_base); 867115013Smarcel tspill[SBREG_BR + i] = 0; 868115013Smarcel br_base -= 8; 869115013Smarcel nbr--; 870115013Smarcel } 871115013Smarcel else if (br_gr_mask & 1) { 872115013Smarcel tspill[SBREG_BR + i] = 0; 873115013Smarcel nbr--; 874115013Smarcel } 875115013Smarcel br_gr_mask = br_gr_mask >> 1; 876115013Smarcel br_mem_mask = br_mem_mask >> 1; 877115013Smarcel } 878115013Smarcel for (i = 0; nfr > 0 && i <= NSB_FR; i++) { 879115013Smarcel if (fr_mem_mask & 1) { 880115013Smarcel newrstate[SBREG_FR + i] = UWX_DISP_PSPREL(fr_base); 881115013Smarcel tspill[SBREG_FR + i] = 0; 882120925Smarcel fr_base -= 16; 883115013Smarcel nfr--; 884115013Smarcel } 885115013Smarcel fr_mem_mask = fr_mem_mask >> 1; 886115013Smarcel } 887115013Smarcel 888115013Smarcel /* Update the scoreboard. */ 889115013Smarcel 890115013Smarcel for (i = 0; i < env->nsbreg; i++) { 891121642Smarcel if (ip_slot >= rhdr->rlen || ip_slot > tspill[i]) 892115013Smarcel scoreboard->rstate[i] = newrstate[i]; 893115013Smarcel } 894115013Smarcel if (priunat_mem_rstate != UWX_DISP_NONE && ip_slot > t_priunat_mem) 895115013Smarcel scoreboard->rstate[SBREG_PRIUNAT] = priunat_mem_rstate; 896115013Smarcel 897115013Smarcel return UWX_OK; 898115013Smarcel} 899115013Smarcel 900115013Smarcelint uwx_count_ones(unsigned int mask) 901115013Smarcel{ 902115013Smarcel mask = (mask & 0x55555555) + ((mask & 0xaaaaaaaa) >> 1); 903115013Smarcel mask = (mask & 0x33333333) + ((mask & 0xcccccccc) >> 2); 904115013Smarcel mask = (mask & 0x0f0f0f0f) + ((mask & 0xf0f0f0f0) >> 4); 905115013Smarcel mask = (mask & 0x00ff00ff) + ((mask & 0xff00ff00) >> 8); 906115013Smarcel return (mask & 0x0000ffff) + ((mask & 0xffff0000) >> 16); 907115013Smarcel} 908115013Smarcel 909115013Smarcel/* uwx_decode_body: Decodes a body region */ 910115013Smarcel 911115013Smarcelint uwx_decode_body( 912115013Smarcel struct uwx_env *env, 913115013Smarcel struct uwx_bstream *bstream, 914115013Smarcel struct uwx_scoreboard *scoreboard, 915115013Smarcel struct uwx_rhdr *rhdr, 916115013Smarcel int ip_slot) 917115013Smarcel{ 918115013Smarcel int status; 919115013Smarcel int b0; 920115013Smarcel int b1; 921115013Smarcel int b2; 922115013Smarcel int b3; 923115013Smarcel int label; 924115013Smarcel int ecount; 925115013Smarcel int i; 926115013Smarcel uint64_t parm1; 927115013Smarcel uint64_t parm2; 928115013Smarcel uint64_t newrstate[NSBREG]; 929115013Smarcel int tspill[NSBREG]; 930115013Smarcel int t_sp_restore; 931115013Smarcel 932115013Smarcel /* Initialize an array of register states from the current */ 933115013Smarcel /* scoreboard, along with a parallel array of spill times. */ 934115013Smarcel /* We use this as a temporary scoreboard, then update the */ 935115013Smarcel /* real scoreboard at the end of the procedure. */ 936115013Smarcel /* We initialize the spill time to (rhdr.rlen - 1) so that */ 937115013Smarcel /* spills without a "when" descriptor will take effect */ 938115013Smarcel /* at the end of the prologue region. */ 939115013Smarcel /* (Boundary condition: all actions in a zero-length prologue */ 940115013Smarcel /* will appear to have happened in the instruction slot */ 941115013Smarcel /* immediately preceding the prologue.) */ 942115013Smarcel 943115013Smarcel for (i = 0; i < env->nsbreg; i++) { 944115013Smarcel newrstate[i] = scoreboard->rstate[i]; 945115013Smarcel tspill[i] = rhdr->rlen - 1; 946115013Smarcel } 947115013Smarcel t_sp_restore = rhdr->rlen - 1; 948115013Smarcel 949115013Smarcel /* Read body descriptor records until */ 950115013Smarcel /* we hit another region header. */ 951115013Smarcel 952115013Smarcel for (;;) { 953115013Smarcel 954115013Smarcel b0 = uwx_get_byte(bstream); 955115013Smarcel 956115013Smarcel if (b0 < 0x80) { 957115013Smarcel /* Return the last byte read to the byte stream, since it's */ 958115013Smarcel /* really the first byte of the next region header record. */ 959115013Smarcel if (b0 >= 0) 960115013Smarcel (void) uwx_unget_byte(bstream, b0); 961115013Smarcel break; 962115013Smarcel } 963115013Smarcel 964115013Smarcel /* Format B1 (label_state) */ 965115013Smarcel if (b0 < 0xa0) { 966115013Smarcel TRACE_I_DECODE_BODY_1("(B1) label_state", b0) 967115013Smarcel label = b0 & 0x1f; 968115013Smarcel status = uwx_label_scoreboard(env, scoreboard, label); 969115013Smarcel if (status != UWX_OK) 970115013Smarcel return (status); 971115013Smarcel } 972115013Smarcel 973115013Smarcel /* Format B1 (copy_state) */ 974115013Smarcel else if (b0 < 0xc0) { 975115013Smarcel TRACE_I_DECODE_BODY_1("(B1) copy_state", b0) 976115013Smarcel label = b0 & 0x1f; 977115013Smarcel status = uwx_copy_scoreboard(env, scoreboard, label); 978115013Smarcel if (status != UWX_OK) 979115013Smarcel return (status); 980115013Smarcel for (i = 0; i < env->nsbreg; i++) { 981115013Smarcel newrstate[i] = scoreboard->rstate[i]; 982115013Smarcel tspill[i] = rhdr->rlen; 983115013Smarcel } 984115013Smarcel } 985115013Smarcel 986115013Smarcel /* Format B2 (epilogue) */ 987115013Smarcel else if (b0 < 0xe0) { 988115013Smarcel ecount = b0 & 0x1f; 989115013Smarcel status = uwx_get_uleb128(bstream, &parm1); 990115013Smarcel if (status != 0) 991115013Smarcel return UWX_ERR_BADUDESC; 992115013Smarcel TRACE_I_DECODE_BODY_1L("(B2) epilogue", b0, parm1) 993115013Smarcel rhdr->ecount = ecount + 1; 994115013Smarcel t_sp_restore = rhdr->rlen - (unsigned int) parm1; 995115013Smarcel } 996115013Smarcel 997115013Smarcel /* Format B3 (epilogue) */ 998115013Smarcel else if (b0 == 0xe0) { 999115013Smarcel status = uwx_get_uleb128(bstream, &parm1); 1000115013Smarcel if (status != 0) 1001115013Smarcel return UWX_ERR_BADUDESC; 1002115013Smarcel status = uwx_get_uleb128(bstream, &parm2); 1003115013Smarcel if (status != 0) 1004115013Smarcel return UWX_ERR_BADUDESC; 1005115013Smarcel TRACE_I_DECODE_BODY_1LL("(B3) epilogue", b0, parm1, parm2) 1006115013Smarcel t_sp_restore = rhdr->rlen - (unsigned int) parm1; 1007115013Smarcel rhdr->ecount = (unsigned int) parm2 + 1; 1008115013Smarcel } 1009115013Smarcel 1010115013Smarcel /* Format B4 (label_state) */ 1011115013Smarcel else if (b0 == 0xf0) { 1012115013Smarcel status = uwx_get_uleb128(bstream, &parm1); 1013115013Smarcel if (status != 0) 1014115013Smarcel return UWX_ERR_BADUDESC; 1015115013Smarcel TRACE_I_DECODE_BODY_1L("(B4) label_state", b0, parm1) 1016115013Smarcel label = (int) parm1; 1017115013Smarcel status = uwx_label_scoreboard(env, scoreboard, label); 1018115013Smarcel if (status != UWX_OK) 1019115013Smarcel return (status); 1020115013Smarcel } 1021115013Smarcel 1022115013Smarcel /* Format B4 (copy_state) */ 1023115013Smarcel else if (b0 == 0xf8) { 1024115013Smarcel status = uwx_get_uleb128(bstream, &parm1); 1025115013Smarcel if (status != 0) 1026115013Smarcel return UWX_ERR_BADUDESC; 1027115013Smarcel TRACE_I_DECODE_BODY_1L("(B4) copy_state", b0, parm1) 1028115013Smarcel label = (int) parm1; 1029115013Smarcel status = uwx_copy_scoreboard(env, scoreboard, label); 1030115013Smarcel if (status != UWX_OK) 1031115013Smarcel return (status); 1032115013Smarcel for (i = 0; i < env->nsbreg; i++) { 1033115013Smarcel newrstate[i] = scoreboard->rstate[i]; 1034115013Smarcel tspill[i] = rhdr->rlen; 1035115013Smarcel } 1036115013Smarcel } 1037115013Smarcel 1038115013Smarcel /* Format X1 */ 1039115013Smarcel else if (b0 == 0xf9) { 1040115013Smarcel TRACE_I_DECODE_BODY_1("(X1)", b0) 1041115013Smarcel b1 = uwx_get_byte(bstream); 1042115013Smarcel if (b1 < 0) 1043115013Smarcel return UWX_ERR_BADUDESC; 1044115013Smarcel /* Don't support X-format descriptors yet */ 1045115013Smarcel return UWX_ERR_CANTUNWIND; 1046115013Smarcel } 1047115013Smarcel 1048115013Smarcel /* Format X2 */ 1049115013Smarcel else if (b0 == 0xfa) { 1050115013Smarcel TRACE_I_DECODE_BODY_1("(X2)", b0) 1051115013Smarcel b1 = uwx_get_byte(bstream); 1052115013Smarcel if (b1 < 0) 1053115013Smarcel return UWX_ERR_BADUDESC; 1054115013Smarcel b2 = uwx_get_byte(bstream); 1055115013Smarcel if (b2 < 0) 1056115013Smarcel return UWX_ERR_BADUDESC; 1057115013Smarcel /* Don't support X-format descriptors yet */ 1058115013Smarcel return UWX_ERR_CANTUNWIND; 1059115013Smarcel } 1060115013Smarcel 1061115013Smarcel /* Format X3 */ 1062115013Smarcel else if (b0 == 0xfb) { 1063115013Smarcel TRACE_I_DECODE_BODY_1("(X3)", b0) 1064115013Smarcel b1 = uwx_get_byte(bstream); 1065115013Smarcel if (b1 < 0) 1066115013Smarcel return UWX_ERR_BADUDESC; 1067115013Smarcel b2 = uwx_get_byte(bstream); 1068115013Smarcel if (b2 < 0) 1069115013Smarcel return UWX_ERR_BADUDESC; 1070115013Smarcel /* Don't support X-format descriptors yet */ 1071115013Smarcel return UWX_ERR_CANTUNWIND; 1072115013Smarcel } 1073115013Smarcel 1074115013Smarcel /* Format X4 */ 1075115013Smarcel else if (b0 == 0xfc) { 1076115013Smarcel TRACE_I_DECODE_BODY_1("(X4)", b0) 1077115013Smarcel b1 = uwx_get_byte(bstream); 1078115013Smarcel if (b1 < 0) 1079115013Smarcel return UWX_ERR_BADUDESC; 1080115013Smarcel b2 = uwx_get_byte(bstream); 1081115013Smarcel if (b2 < 0) 1082115013Smarcel return UWX_ERR_BADUDESC; 1083115013Smarcel b3 = uwx_get_byte(bstream); 1084115013Smarcel if (b3 < 0) 1085115013Smarcel return UWX_ERR_BADUDESC; 1086115013Smarcel /* Don't support X-format descriptors yet */ 1087115013Smarcel return UWX_ERR_CANTUNWIND; 1088115013Smarcel } 1089115013Smarcel 1090115013Smarcel /* Invalid descriptor record */ 1091115013Smarcel else { 1092115013Smarcel TRACE_I_DECODE_BODY_1("(?)", b0) 1093115013Smarcel return UWX_ERR_BADUDESC; 1094115013Smarcel } 1095115013Smarcel } 1096115013Smarcel 1097115013Smarcel /* Update the scoreboard. */ 1098115013Smarcel 1099115013Smarcel for (i = 0; i < env->nsbreg; i++) { 1100115013Smarcel if (ip_slot > tspill[i]) 1101115013Smarcel scoreboard->rstate[i] = newrstate[i]; 1102115013Smarcel } 1103115013Smarcel 1104115013Smarcel /* If we've passed the point in the epilogue where sp */ 1105115013Smarcel /* is restored, update the scoreboard entry for PSP */ 1106115013Smarcel /* and reset any entries for registers saved in memory. */ 1107115013Smarcel 1108160157Smarcel if (rhdr->ecount > 0 && ip_slot > t_sp_restore) { 1109115013Smarcel scoreboard->rstate[SBREG_PSP] = UWX_DISP_SPPLUS(0); 1110115013Smarcel for (i = 0; i < env->nsbreg; i++) { 1111115013Smarcel if (UWX_GET_DISP_CODE(scoreboard->rstate[i]) == UWX_DISP_SPREL(0) || 1112115013Smarcel UWX_GET_DISP_CODE(scoreboard->rstate[i]) == UWX_DISP_PSPREL(0)) 1113115013Smarcel scoreboard->rstate[i] = UWX_DISP_NONE; 1114115013Smarcel } 1115115013Smarcel } 1116115013Smarcel 1117115013Smarcel return UWX_OK; 1118115013Smarcel} 1119115013Smarcel 1120