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