1/* 2Copyright (c) 2003-2006 Hewlett-Packard Development Company, L.P. 3Permission is hereby granted, free of charge, to any person 4obtaining a copy of this software and associated documentation 5files (the "Software"), to deal in the Software without 6restriction, including without limitation the rights to use, 7copy, modify, merge, publish, distribute, sublicense, and/or sell 8copies of the Software, and to permit persons to whom the 9Software is furnished to do so, subject to the following 10conditions: 11 12The above copyright notice and this permission notice shall be 13included in all copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22OTHER DEALINGS IN THE SOFTWARE. 23*/ 24 25#include "uwx_env.h" 26#include "uwx_uinfo.h" 27#include "uwx_utable.h" 28#include "uwx_scoreboard.h" 29#include "uwx_bstream.h" 30#include "uwx_trace.h" 31#include "uwx_swap.h" 32 33int uwx_count_ones(unsigned int mask); 34 35/* 36 * uwx_uinfo.c 37 * 38 * This file contains the routines for reading and decoding 39 * the unwind information block. 40 * 41 * The main entry point, uwx_decode_uinfo(), is given a pointer 42 * to an unwind table entry and a pointer (passed by reference) 43 * to be filled in with a pointer to an update vector. It will 44 * read and decode the unwind descriptors contained in the 45 * unwind information block, then build the register state array, 46 * which describes the actions necessary to step from the current 47 * frame to the previous one. 48 */ 49 50#define COPYIN_UINFO_4(dest, src) \ 51 (env->remote? \ 52 (*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \ 53 WORDSZ, env->cb_token) : \ 54 (*(uint32_t *)(intptr_t)(dest) = *(uint32_t *)(intptr_t)(src), WORDSZ) ) 55 56#define COPYIN_UINFO_8(dest, src) \ 57 (env->remote? \ 58 (*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \ 59 DWORDSZ, env->cb_token) : \ 60 (*(uint64_t *)(intptr_t)(dest) = *(uint64_t *)(intptr_t)(src), DWORDSZ) ) 61 62 63/* uwx_default_rstate: Returns the default register state for a leaf routine */ 64 65int uwx_default_rstate(struct uwx_env *env, uint64_t **rstatep) 66{ 67 struct uwx_scoreboard *sb; 68 69 sb = uwx_init_scoreboards(env); 70 *rstatep = sb->rstate; 71 return UWX_OK; 72} 73 74 75/* uwx_decode_uinfo: Decodes unwind info region */ 76 77int uwx_decode_uinfo( 78 struct uwx_env *env, 79 struct uwx_utable_entry *uentry, 80 uint64_t **rstatep) 81{ 82 uint64_t uinfohdr; 83 unsigned int ulen; 84 int len; 85 struct uwx_bstream bstream; 86 struct uwx_scoreboard *scoreboard; 87 int ip_slot; 88 int cur_slot; 89 int status; 90 struct uwx_rhdr rhdr; 91 92 /* Remember the offset from the start of the function */ 93 /* to the current IP. This helps the client find */ 94 /* the symbolic information. */ 95 96 env->function_offset = env->remapped_ip - uentry->code_start; 97 98 /* Read the unwind info header using the copyin callback. */ 99 /* (If we're reading a 32-bit unwind table, we need to */ 100 /* read the header as two 32-bit pieces to preserve the */ 101 /* guarantee that we always call copyin for aligned */ 102 /* 4-byte or 8-byte chunks.) */ 103 /* Then compute the length of the unwind descriptor */ 104 /* region and initialize a byte stream to read it. */ 105 106 if (uentry->unwind_flags & UNWIND_TBL_32BIT) { 107 len = COPYIN_UINFO_4((char *)&uinfohdr, uentry->unwind_info); 108 len += COPYIN_UINFO_4((char *)&uinfohdr + WORDSZ, 109 uentry->unwind_info + WORDSZ); 110 } 111 else 112 len = COPYIN_UINFO_8((char *)&uinfohdr, uentry->unwind_info); 113 if (len != DWORDSZ) 114 return UWX_ERR_COPYIN_UINFO; 115 if (env->byte_swap) 116 uwx_swap8(&uinfohdr); 117 if (uentry->unwind_flags & UNWIND_TBL_32BIT) 118 ulen = UNW_LENGTH(uinfohdr) * WORDSZ; 119 else 120 ulen = UNW_LENGTH(uinfohdr) * DWORDSZ; 121 uwx_init_bstream(&bstream, env, 122 uentry->unwind_info + DWORDSZ, ulen, UWX_COPYIN_UINFO); 123 124 /* Save the header and a pointer to the personality routine ptr */ 125 /* for later use in exception handling. */ 126 127 env->uinfo_hdr = uinfohdr; 128 env->uinfo_end = uentry->unwind_info + DWORDSZ + ulen; 129 130 TRACE_R_UIB(uentry, ulen) 131 132 /* Create an initial scoreboard for tracking the unwind state. */ 133 134 scoreboard = uwx_init_scoreboards(env); 135 136 /* Prepare to read and decode the unwind regions described */ 137 /* by the unwind info block. Find the target "ip" slot */ 138 /* relative to the beginning of the region. The lower 4 bits */ 139 /* of the actual IP encode the slot number within a bundle. */ 140 141 cur_slot = 0; 142 ip_slot = (int) ((env->context.special[UWX_REG_IP] & ~0x0fLL) 143 - uentry->code_start) 144 / BUNDLESZ * SLOTSPERBUNDLE 145 + (unsigned int) (env->context.special[UWX_REG_IP] & 0x0f); 146 147 /* Loop over the regions in the unwind info block. */ 148 149 for (;;) { 150 151 /* Decode the next region header. */ 152 /* We have an error if we reach the end of the info block, */ 153 /* since we should have found our target ip slot by then. */ 154 /* We also have an error if the next byte isn't a region */ 155 /* header record. */ 156 157 status = uwx_decode_rhdr(env, &bstream, &rhdr); 158 if (status != UWX_OK) 159 return status; 160 161 /* If a prologue region, get a new scoreboard, pushing */ 162 /* the previous one onto the prologue stack. Then read */ 163 /* and decode the prologue region records. */ 164 165 if (rhdr.is_prologue) { 166 scoreboard = uwx_new_scoreboard(env, scoreboard); 167 if (scoreboard == 0) 168 return UWX_ERR_NOMEM; 169 status = uwx_decode_prologue(env, &bstream, 170 scoreboard, &rhdr, ip_slot); 171 } 172 173 /* If a body region, read and decode the body region */ 174 /* records. If the body has an epilogue count, */ 175 /* uwx_decode_body will note that in the region header */ 176 /* record for use at the bottom of the loop. */ 177 178 else { 179 status = uwx_decode_body(env, &bstream, scoreboard, &rhdr, ip_slot); 180 } 181 182 if (status != UWX_OK) 183 return status; 184 185 TRACE_R_DUMP_SB(scoreboard, rhdr, cur_slot, ip_slot) 186 187 /* If the target ip slot is within this region, we're done. */ 188 /* Return the scoreboard's register state array. */ 189 190 if (ip_slot < rhdr.rlen) { 191 *rstatep = scoreboard->rstate; 192 return UWX_OK; 193 } 194 195 /* Otherwise, update the current ip slot, pop the */ 196 /* scoreboard stack based on the epilogue count, */ 197 /* and loop back around for the next region. */ 198 199 cur_slot += rhdr.rlen; 200 ip_slot -= rhdr.rlen; 201 if (rhdr.ecount > 0) { 202 scoreboard = uwx_pop_scoreboards(env, scoreboard, rhdr.ecount); 203 if (scoreboard == 0) 204 return UWX_ERR_PROLOG_UF; 205 } 206 } 207 /*NOTREACHED*/ 208} 209 210 211/* uwx_decode_rhdr: Decodes a region header record */ 212 213int uwx_decode_rhdr( 214 struct uwx_env *env, 215 struct uwx_bstream *bstream, 216 struct uwx_rhdr *rhdr) 217{ 218 int b0; 219 int b1; 220 uint64_t val; 221 int status; 222 223 /* Get the first byte of the next descriptor record. */ 224 b0 = uwx_get_byte(bstream); 225 if (b0 < 0) 226 return UWX_ERR_NOUDESC; 227 228 /* Initialize region header record. */ 229 230 rhdr->is_prologue = 0; 231 rhdr->rlen = 0; 232 rhdr->mask = 0; 233 rhdr->grsave = 0; 234 rhdr->ecount = 0; 235 236 /* Format R1 */ 237 238 if (b0 < 0x40) { 239 if ((b0 & 0x20) == 0) { 240 TRACE_I_DECODE_RHDR_1("(R1) prologue", b0) 241 rhdr->is_prologue = 1; 242 } 243 else { 244 TRACE_I_DECODE_RHDR_1("(R1) body", b0) 245 } 246 rhdr->rlen = b0 & 0x1f; 247 } 248 249 /* Format R2 */ 250 251 else if (b0 < 0x60) { 252 b1 = uwx_get_byte(bstream); 253 if (b1 < 0) 254 return UWX_ERR_BADUDESC; 255 status = uwx_get_uleb128(bstream, &val); 256 if (status != 0) 257 return UWX_ERR_BADUDESC; 258 TRACE_I_DECODE_RHDR_2L("(R2) prologue_gr", b0, b1, val) 259 rhdr->is_prologue = 1; 260 rhdr->rlen = (unsigned int) val; 261 rhdr->mask = ((b0 & 0x07) << 1) | (b1 >> 7); 262 rhdr->grsave = b1 & 0x7f; 263 } 264 265 /* Format R3 */ 266 267 else if (b0 < 0x80) { 268 status = uwx_get_uleb128(bstream, &val); 269 if (status != 0) 270 return UWX_ERR_BADUDESC; 271 if ((b0 & 0x03) == 0) { 272 TRACE_I_DECODE_RHDR_1L("(R3) prologue", b0, val) 273 rhdr->is_prologue = 1; 274 } 275 else { 276 TRACE_I_DECODE_RHDR_1L("(R3) body", b0, val) 277 } 278 rhdr->rlen = (unsigned int) val; 279 } 280 281 /* Otherwise, not a region header record. */ 282 283 else { 284 TRACE_I_DECODE_RHDR_1("(?)", b0) 285 return UWX_ERR_BADUDESC; 286 } 287 288 return UWX_OK; 289} 290 291 292/* uwx_decode_prologue: Decodes a prologue region */ 293 294int uwx_decode_prologue( 295 struct uwx_env *env, 296 struct uwx_bstream *bstream, 297 struct uwx_scoreboard *scoreboard, 298 struct uwx_rhdr *rhdr, 299 int ip_slot) 300{ 301 int status; 302 int reg; 303 int mask; 304 int b0; 305 int b1; 306 int b2; 307 int b3; 308 int r; 309 int t; 310 int i; 311 uint64_t parm1; 312 uint64_t parm2; 313 uint64_t newrstate[NSBREG]; 314 int tspill[NSBREG]; 315 int priunat_mem_rstate; 316 int t_priunat_mem; 317 unsigned int gr_mem_mask; 318 unsigned int br_mem_mask; 319 unsigned int fr_mem_mask; 320 unsigned int gr_gr_mask; 321 unsigned int br_gr_mask; 322 int ngr; 323 int nbr; 324 int nfr; 325 unsigned int spill_base; 326 unsigned int gr_base; 327 unsigned int br_base; 328 unsigned int fr_base; 329 330 /* Initialize an array of register states from the current */ 331 /* scoreboard, along with a parallel array of spill times. */ 332 /* We use this as a temporary scoreboard, then update the */ 333 /* real scoreboard at the end of the procedure. */ 334 /* We initialize the spill time to (rhdr.rlen - 1) so that */ 335 /* spills without a "when" descriptor will take effect */ 336 /* at the end of the prologue region. */ 337 /* (Boundary condition: all actions in a zero-length prologue */ 338 /* will appear to have happened in the instruction slot */ 339 /* immediately preceding the prologue.) */ 340 341 for (i = 0; i < env->nsbreg; i++) { 342 newrstate[i] = scoreboard->rstate[i]; 343 tspill[i] = rhdr->rlen - 1; 344 } 345 priunat_mem_rstate = UWX_DISP_NONE; 346 t_priunat_mem = rhdr->rlen - 1; 347 348 fr_mem_mask = 0; 349 gr_mem_mask = 0; 350 br_mem_mask = 0; 351 gr_gr_mask = 0; 352 br_gr_mask = 0; 353 nfr = 127; 354 ngr = 127; 355 nbr = 127; 356 spill_base = 0; 357 358 /* If prologue_gr header record supplied mask and grsave, */ 359 /* record these in the scoreboard. */ 360 361 reg = rhdr->grsave; 362 mask = rhdr->mask; 363 if (mask & 0x8) { 364 newrstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_GR(reg)); 365 reg++; 366 } 367 if (mask & 0x4) { 368 newrstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_GR(reg)); 369 reg++; 370 } 371 if (mask & 0x2) { 372 newrstate[SBREG_PSP] = UWX_DISP_REG(UWX_REG_GR(reg)); 373 reg++; 374 } 375 if (mask & 0x1) { 376 newrstate[SBREG_PREDS] = UWX_DISP_REG(UWX_REG_GR(reg)); 377 reg++; 378 } 379 380 /* Read prologue descriptor records until */ 381 /* we hit another region header. */ 382 383 for (;;) { 384 385 b0 = uwx_get_byte(bstream); 386 387 if (b0 < 0x80) { 388 /* Return the last byte read to the byte stream, since it's */ 389 /* really the first byte of the next region header record. */ 390 if (b0 >= 0) 391 (void) uwx_unget_byte(bstream, b0); 392 break; 393 } 394 395 switch ((b0 & 0x70) >> 4) { 396 397 case 0: /* 1000 xxxx */ 398 case 1: /* 1001 xxxx */ 399 /* Format P1 (br_mem) */ 400 TRACE_I_DECODE_PROLOGUE_1("(P1) br_mem", b0) 401 br_mem_mask = b0 & 0x1f; 402 break; 403 404 case 2: /* 1010 xxxx */ 405 /* Format P2 (br_gr) */ 406 b1 = uwx_get_byte(bstream); 407 if (b1 < 0) 408 return UWX_ERR_BADUDESC; 409 TRACE_I_DECODE_PROLOGUE_2("(P2) br_gr", b0, b1) 410 mask = ((b0 & 0x0f) << 1) | (b1 >> 7); 411 reg = b1 & 0x7f; 412 br_gr_mask = mask; 413 for (i = 0; i < NSB_BR && mask != 0; i++) { 414 if (mask & 0x01) { 415 newrstate[SBREG_BR + i] = UWX_DISP_REG(UWX_REG_GR(reg)); 416 reg++; 417 } 418 mask = mask >> 1; 419 } 420 break; 421 422 case 3: /* 1011 xxxx */ 423 /* Format P3 */ 424 if (b0 < 0xb8) { 425 b1 = uwx_get_byte(bstream); 426 if (b1 < 0) 427 return UWX_ERR_BADUDESC; 428 r = ((b0 & 0x7) << 1) | (b1 >> 7); 429 reg = b1 & 0x7f; 430 switch (r) { 431 case 0: /* psp_gr */ 432 TRACE_I_DECODE_PROLOGUE_2("(P3) psp_gr", b0, b1) 433 newrstate[SBREG_PSP] = UWX_DISP_REG(UWX_REG_GR(reg)); 434 break; 435 case 1: /* rp_gr */ 436 TRACE_I_DECODE_PROLOGUE_2("(P3) rp_gr", b0, b1) 437 newrstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_GR(reg)); 438 break; 439 case 2: /* pfs_gr */ 440 TRACE_I_DECODE_PROLOGUE_2("(P3) pfs_gr", b0, b1) 441 newrstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_GR(reg)); 442 break; 443 case 3: /* preds_gr */ 444 TRACE_I_DECODE_PROLOGUE_2("(P3) preds_gr", b0, b1) 445 newrstate[SBREG_PREDS] = 446 UWX_DISP_REG(UWX_REG_GR(reg)); 447 break; 448 case 4: /* unat_gr */ 449 TRACE_I_DECODE_PROLOGUE_2("(P3) unat_gr", b0, b1) 450 newrstate[SBREG_UNAT] = 451 UWX_DISP_REG(UWX_REG_GR(reg)); 452 break; 453 case 5: /* lc_gr */ 454 TRACE_I_DECODE_PROLOGUE_2("(P3) lc_gr", b0, b1) 455 newrstate[SBREG_LC] = 456 UWX_DISP_REG(UWX_REG_GR(reg)); 457 break; 458 case 6: /* rp_br */ 459 TRACE_I_DECODE_PROLOGUE_2("(P3) rp_br", b0, b1) 460 scoreboard->rstate[SBREG_RP] = 461 UWX_DISP_REG(UWX_REG_BR(reg)); 462 if (newrstate[SBREG_RP] == 463 UWX_DISP_REG(UWX_REG_BR(0))) 464 newrstate[SBREG_RP] = 465 UWX_DISP_REG(UWX_REG_BR(reg)); 466 break; 467 case 7: /* rnat_gr */ 468 TRACE_I_DECODE_PROLOGUE_2("(P3) rnat_gr", b0, b1) 469 newrstate[SBREG_RNAT] = 470 UWX_DISP_REG(UWX_REG_GR(reg)); 471 break; 472 case 8: /* bsp_gr */ 473 TRACE_I_DECODE_PROLOGUE_2("(P3) bsp_gr", b0, b1) 474 /* Don't track BSP yet */ 475 return UWX_ERR_CANTUNWIND; 476 /* break; */ 477 case 9: /* bspstore_gr */ 478 TRACE_I_DECODE_PROLOGUE_2("(P3) bspstore_gr", b0, b1) 479 /* Don't track BSPSTORE yet */ 480 return UWX_ERR_CANTUNWIND; 481 /* break; */ 482 case 10: /* fpsr_gr */ 483 TRACE_I_DECODE_PROLOGUE_2("(P3) fpsr_gr", b0, b1) 484 newrstate[SBREG_FPSR] = 485 UWX_DISP_REG(UWX_REG_GR(reg)); 486 break; 487 case 11: /* priunat_gr */ 488 TRACE_I_DECODE_PROLOGUE_2("(P3) priunat_gr", b0, b1) 489 newrstate[SBREG_PRIUNAT] = 490 UWX_DISP_REG(UWX_REG_GR(reg)); 491 break; 492 default: 493 TRACE_I_DECODE_PROLOGUE_2("(P3) ??", b0, b1) 494 return UWX_ERR_BADUDESC; 495 } 496 } 497 498 /* Format P4 (spill_mask) */ 499 else if (b0 == 0xb8) { 500 TRACE_I_DECODE_PROLOGUE_1("(P4) spill_mask", b0) 501 /* The spill_mask descriptor is followed by */ 502 /* an imask field whose length is determined */ 503 /* by the region length: there are two mask */ 504 /* bits per instruction slot in the region. */ 505 /* We decode these bits two at a time, counting */ 506 /* the number of FRs, GRs, and BRs that are */ 507 /* saved up to the slot of interest. Other */ 508 /* descriptors describe which sets of these */ 509 /* registers are spilled, and we put those */ 510 /* two pieces of information together at the */ 511 /* end of the main loop. */ 512 t = 0; 513 nfr = 0; 514 ngr = 0; 515 nbr = 0; 516 while (t < rhdr->rlen) { 517 b1 = uwx_get_byte(bstream); 518 if (b1 < 0) 519 return UWX_ERR_BADUDESC; 520 for (i = 0; i < 4 && (t + i) < ip_slot; i++) { 521 switch (b1 & 0xc0) { 522 case 0x00: break; 523 case 0x40: nfr++; break; 524 case 0x80: ngr++; break; 525 case 0xc0: nbr++; break; 526 } 527 b1 = b1 << 2; 528 } 529 t += 4; 530 } 531 } 532 533 /* Format P5 (frgr_mem) */ 534 else if (b0 == 0xb9) { 535 b1 = uwx_get_byte(bstream); 536 if (b1 < 0) 537 return UWX_ERR_BADUDESC; 538 b2 = uwx_get_byte(bstream); 539 if (b2 < 0) 540 return UWX_ERR_BADUDESC; 541 b3 = uwx_get_byte(bstream); 542 if (b3 < 0) 543 return UWX_ERR_BADUDESC; 544 TRACE_I_DECODE_PROLOGUE_4("(P5) frgr_mem", b0, b1, b2, b3) 545 gr_mem_mask = b1 >> 4; 546 fr_mem_mask = ((b1 & 0x0f) << 16) | (b2 << 8) | b3; 547 } 548 549 /* Invalid descriptor record */ 550 else { 551 TRACE_I_DECODE_PROLOGUE_1("(?)", b0) 552 return UWX_ERR_BADUDESC; 553 } 554 555 break; 556 557 case 4: /* 1100 xxxx */ 558 /* Format P6 (fr_mem) */ 559 TRACE_I_DECODE_PROLOGUE_1("(P6) fr_mem", b0) 560 fr_mem_mask = b0 & 0x0f; 561 break; 562 563 case 5: /* 1101 xxxx */ 564 /* Format P6 (gr_mem) */ 565 TRACE_I_DECODE_PROLOGUE_1("(P6) gr_mem", b0) 566 gr_mem_mask = b0 & 0x0f; 567 break; 568 569 case 6: /* 1110 xxxx */ 570 /* Format P7 */ 571 r = b0 & 0xf; 572 status = uwx_get_uleb128(bstream, &parm1); 573 if (status != 0) 574 return UWX_ERR_BADUDESC; 575 switch (r) { 576 case 0: /* mem_stack_f */ 577 status = uwx_get_uleb128(bstream, &parm2); 578 if (status != 0) 579 return UWX_ERR_BADUDESC; 580 TRACE_I_DECODE_PROLOGUE_1LL("(P7) mem_stack_f", b0, parm1, parm2) 581 newrstate[SBREG_PSP] = UWX_DISP_SPPLUS(parm2 * 16); 582 tspill[SBREG_PSP] = (int) parm1; 583 break; 584 case 1: /* mem_stack_v */ 585 TRACE_I_DECODE_PROLOGUE_1L("(P7) mem_stack_v", b0, parm1) 586 tspill[SBREG_PSP] = (int) parm1; 587 break; 588 case 2: /* spill_base */ 589 TRACE_I_DECODE_PROLOGUE_1L("(P7) spill_base", b0, parm1) 590 spill_base = 4 * (unsigned int) parm1; 591 break; 592 case 3: /* psp_sprel */ 593 TRACE_I_DECODE_PROLOGUE_1L("(P7) psp_sprel", b0, parm1) 594 newrstate[SBREG_PSP] = UWX_DISP_SPREL(parm1 * 4); 595 break; 596 case 4: /* rp_when */ 597 TRACE_I_DECODE_PROLOGUE_1L("(P7) rp_when", b0, parm1) 598 tspill[SBREG_RP] = (int) parm1; 599 break; 600 case 5: /* rp_psprel */ 601 TRACE_I_DECODE_PROLOGUE_1L("(P7) rp_psprel", b0, parm1) 602 newrstate[SBREG_RP] = UWX_DISP_PSPREL(parm1 * 4); 603 break; 604 case 6: /* pfs_when */ 605 TRACE_I_DECODE_PROLOGUE_1L("(P7) pfs_when", b0, parm1) 606 tspill[SBREG_PFS] = (int) parm1; 607 break; 608 case 7: /* pfs_psprel */ 609 TRACE_I_DECODE_PROLOGUE_1L("(P7) pfs_psprel", b0, parm1) 610 newrstate[SBREG_PFS] = UWX_DISP_PSPREL(parm1 * 4); 611 break; 612 case 8: /* preds_when */ 613 TRACE_I_DECODE_PROLOGUE_1L("(P7) preds_when", b0, parm1) 614 tspill[SBREG_PREDS] = (int) parm1; 615 break; 616 case 9: /* preds_psprel */ 617 TRACE_I_DECODE_PROLOGUE_1L("(P7) preds_psprel", b0, parm1) 618 newrstate[SBREG_PREDS] = UWX_DISP_PSPREL(parm1 * 4); 619 break; 620 case 10: /* lc_when */ 621 TRACE_I_DECODE_PROLOGUE_1L("(P7) lc_when", b0, parm1) 622 tspill[SBREG_LC] = (int) parm1; 623 break; 624 case 11: /* lc_psprel */ 625 TRACE_I_DECODE_PROLOGUE_1L("(P7) lc_psprel", b0, parm1) 626 newrstate[SBREG_LC] = UWX_DISP_PSPREL(parm1 * 4); 627 break; 628 case 12: /* unat_when */ 629 TRACE_I_DECODE_PROLOGUE_1L("(P7) unat_when", b0, parm1) 630 tspill[SBREG_UNAT] = (int) parm1; 631 break; 632 case 13: /* unat_psprel */ 633 TRACE_I_DECODE_PROLOGUE_1L("(P7) unat_psprel", b0, parm1) 634 newrstate[SBREG_UNAT] = UWX_DISP_PSPREL(parm1 * 4); 635 break; 636 case 14: /* fpsr_when */ 637 TRACE_I_DECODE_PROLOGUE_1L("(P7) fpsr_when", b0, parm1) 638 tspill[SBREG_FPSR] = (int) parm1; 639 break; 640 case 15: /* fpsr_psprel */ 641 TRACE_I_DECODE_PROLOGUE_1L("(P7) fpsr_psprel", b0, parm1) 642 newrstate[SBREG_FPSR] = UWX_DISP_PSPREL(parm1 * 4); 643 break; 644 } 645 break; 646 647 case 7: /* 1111 xxxx */ 648 /* Format P8 */ 649 if (b0 == 0xf0) { 650 b1 = uwx_get_byte(bstream); 651 if (b1 < 0) 652 return UWX_ERR_BADUDESC; 653 status = uwx_get_uleb128(bstream, &parm1); 654 if (status != 0) 655 return UWX_ERR_BADUDESC; 656 switch (b1) { 657 case 1: /* rp_sprel */ 658 TRACE_I_DECODE_PROLOGUE_2L("(P8) rp_sprel", b0, b1, parm1) 659 newrstate[SBREG_RP] = UWX_DISP_SPREL(parm1 * 4); 660 break; 661 case 2: /* pfs_sprel */ 662 TRACE_I_DECODE_PROLOGUE_2L("(P8) pfs_sprel", b0, b1, parm1) 663 newrstate[SBREG_PFS] = UWX_DISP_SPREL(parm1 * 4); 664 break; 665 case 3: /* preds_sprel */ 666 TRACE_I_DECODE_PROLOGUE_2L("(P8) preds_sprel", b0, b1, parm1) 667 newrstate[SBREG_PREDS] = UWX_DISP_SPREL(parm1 * 4); 668 break; 669 case 4: /* lc_sprel */ 670 TRACE_I_DECODE_PROLOGUE_2L("(P8) lc_sprel", b0, b1, parm1) 671 newrstate[SBREG_LC] = UWX_DISP_SPREL(parm1 * 4); 672 break; 673 case 5: /* unat_sprel */ 674 TRACE_I_DECODE_PROLOGUE_2L("(P8) unat_sprel", b0, b1, parm1) 675 newrstate[SBREG_UNAT] = UWX_DISP_SPREL(parm1 * 4); 676 break; 677 case 6: /* fpsr_sprel */ 678 TRACE_I_DECODE_PROLOGUE_2L("(P8) fpsr_sprel", b0, b1, parm1) 679 newrstate[SBREG_FPSR] = UWX_DISP_SPREL(parm1 * 4); 680 break; 681 case 7: /* bsp_when */ 682 TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_when", b0, b1, parm1) 683 /* Don't track BSP yet */ 684 return UWX_ERR_CANTUNWIND; 685 /* break; */ 686 case 8: /* bsp_psprel */ 687 TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_psprel", b0, b1, parm1) 688 /* Don't track BSP yet */ 689 return UWX_ERR_CANTUNWIND; 690 /* break; */ 691 case 9: /* bsp_sprel */ 692 TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_sprel", b0, b1, parm1) 693 /* Don't track BSP yet */ 694 return UWX_ERR_CANTUNWIND; 695 /* break; */ 696 case 10: /* bspstore_when */ 697 TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_when", b0, b1, parm1) 698 /* Don't track BSP yet */ 699 return UWX_ERR_CANTUNWIND; 700 /* break; */ 701 case 11: /* bspstore_psprel */ 702 TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_psprel", b0, b1, parm1) 703 /* Don't track BSP yet */ 704 return UWX_ERR_CANTUNWIND; 705 /* break; */ 706 case 12: /* bspstore_sprel */ 707 TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_sprel", b0, b1, parm1) 708 /* Don't track BSP yet */ 709 return UWX_ERR_CANTUNWIND; 710 /* break; */ 711 case 13: /* rnat_when */ 712 TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_when", b0, b1, parm1) 713 tspill[SBREG_RNAT] = (int) parm1; 714 break; 715 case 14: /* rnat_psprel */ 716 TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_psprel", b0, b1, parm1) 717 newrstate[SBREG_RNAT] = UWX_DISP_PSPREL(parm1 * 4); 718 break; 719 case 15: /* rnat_sprel */ 720 TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_sprel", b0, b1, parm1) 721 newrstate[SBREG_RNAT] = UWX_DISP_SPREL(parm1 * 4); 722 break; 723 case 16: /* priunat_when_gr */ 724 TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_when_gr", b0, b1, parm1) 725 tspill[SBREG_PRIUNAT] = (int) parm1; 726 break; 727 case 17: /* priunat_psprel */ 728 TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_psprel", b0, b1, parm1) 729 priunat_mem_rstate = UWX_DISP_PSPREL(parm1 * 4); 730 break; 731 case 18: /* priunat_sprel */ 732 TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_sprel", b0, b1, parm1) 733 priunat_mem_rstate = UWX_DISP_SPREL(parm1 * 4); 734 break; 735 case 19: /* priunat_when_mem */ 736 TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_when_mem", b0, b1, parm1) 737 t_priunat_mem = (int) parm1; 738 break; 739 default: 740 TRACE_I_DECODE_PROLOGUE_2L("(P8) ??", b0, b1, parm1) 741 return UWX_ERR_BADUDESC; 742 } 743 } 744 745 /* Format P9 (gr_gr) */ 746 else if (b0 == 0xf1) { 747 b1 = uwx_get_byte(bstream); 748 if (b1 < 0) 749 return UWX_ERR_BADUDESC; 750 b2 = uwx_get_byte(bstream); 751 if (b2 < 0) 752 return UWX_ERR_BADUDESC; 753 TRACE_I_DECODE_PROLOGUE_3("(P9) gr_gr", b0, b1, b2) 754 mask = b1 & 0x0f; 755 reg = b2 & 0x7f; 756 gr_gr_mask = mask; 757 for (i = 0; i < NSB_GR && mask != 0; i++) { 758 if (mask & 0x01) { 759 newrstate[SBREG_GR + i] = 760 UWX_DISP_REG(UWX_REG_GR(reg)); 761 reg++; 762 } 763 mask = mask >> 1; 764 } 765 } 766 767 /* Format X1 */ 768 else if (b0 == 0xf9) { 769 TRACE_I_DECODE_PROLOGUE_1("(X1)", b0) 770 b1 = uwx_get_byte(bstream); 771 if (b1 < 0) 772 return UWX_ERR_BADUDESC; 773 /* Don't support X-format descriptors yet */ 774 return UWX_ERR_CANTUNWIND; 775 } 776 777 /* Format X2 */ 778 else if (b0 == 0xfa) { 779 TRACE_I_DECODE_PROLOGUE_1("(X2)", b0) 780 b1 = uwx_get_byte(bstream); 781 if (b1 < 0) 782 return UWX_ERR_BADUDESC; 783 b2 = uwx_get_byte(bstream); 784 if (b2 < 0) 785 return UWX_ERR_BADUDESC; 786 /* Don't support X-format descriptors yet */ 787 return UWX_ERR_CANTUNWIND; 788 } 789 790 /* Format X3 */ 791 else if (b0 == 0xfb) { 792 TRACE_I_DECODE_PROLOGUE_1("(X3)", b0) 793 b1 = uwx_get_byte(bstream); 794 if (b1 < 0) 795 return UWX_ERR_BADUDESC; 796 b2 = uwx_get_byte(bstream); 797 if (b2 < 0) 798 return UWX_ERR_BADUDESC; 799 /* Don't support X-format descriptors yet */ 800 return UWX_ERR_CANTUNWIND; 801 } 802 803 /* Format X4 */ 804 else if (b0 == 0xfc) { 805 TRACE_I_DECODE_PROLOGUE_1("(X4)", b0) 806 b1 = uwx_get_byte(bstream); 807 if (b1 < 0) 808 return UWX_ERR_BADUDESC; 809 b2 = uwx_get_byte(bstream); 810 if (b2 < 0) 811 return UWX_ERR_BADUDESC; 812 b3 = uwx_get_byte(bstream); 813 if (b3 < 0) 814 return UWX_ERR_BADUDESC; 815 /* Don't support X-format descriptors yet */ 816 return UWX_ERR_CANTUNWIND; 817 } 818 819 /* Format P10 */ 820 else if (b0 == 0xff) { 821 b1 = uwx_get_byte(bstream); 822 if (b1 < 0) 823 return UWX_ERR_BADUDESC; 824 b2 = uwx_get_byte(bstream); 825 if (b2 < 0) 826 return UWX_ERR_BADUDESC; 827 TRACE_I_DECODE_PROLOGUE_3("(P10) abi", b0, b1, b2) 828 env->abi_context = (b1 << 8) | b2; 829 return UWX_ABI_FRAME; 830 } 831 832 /* Invalid descriptor record */ 833 else { 834 TRACE_I_DECODE_PROLOGUE_1("(?)", b0) 835 return UWX_ERR_BADUDESC; 836 } 837 break; 838 } 839 } 840 841 /* Process the masks of spilled GRs, FRs, and BRs to */ 842 /* determine when and where each register was saved. */ 843 844 fr_base = spill_base + 16 * uwx_count_ones(fr_mem_mask); 845 br_base = fr_base + 8 * uwx_count_ones(br_mem_mask); 846 gr_base = br_base + 8 * uwx_count_ones(gr_mem_mask); 847 TRACE_I_DECODE_PROLOGUE_SPILL_BASE(spill_base) 848 TRACE_I_DECODE_PROLOGUE_MASKS(gr_mem_mask, gr_gr_mask) 849 TRACE_I_DECODE_PROLOGUE_NSPILL(ngr) 850 for (i = 0; ngr > 0 && i <= NSB_GR; i++) { 851 if (gr_mem_mask & 1) { 852 newrstate[SBREG_GR + i] = UWX_DISP_PSPREL(gr_base); 853 tspill[SBREG_GR + i] = 0; 854 gr_base -= 8; 855 ngr--; 856 } 857 else if (gr_gr_mask & 1) { 858 tspill[SBREG_GR + i] = 0; 859 ngr--; 860 } 861 gr_gr_mask = gr_gr_mask >> 1; 862 gr_mem_mask = gr_mem_mask >> 1; 863 } 864 for (i = 0; nbr > 0 && i <= NSB_BR; i++) { 865 if (br_mem_mask & 1) { 866 newrstate[SBREG_BR + i] = UWX_DISP_PSPREL(br_base); 867 tspill[SBREG_BR + i] = 0; 868 br_base -= 8; 869 nbr--; 870 } 871 else if (br_gr_mask & 1) { 872 tspill[SBREG_BR + i] = 0; 873 nbr--; 874 } 875 br_gr_mask = br_gr_mask >> 1; 876 br_mem_mask = br_mem_mask >> 1; 877 } 878 for (i = 0; nfr > 0 && i <= NSB_FR; i++) { 879 if (fr_mem_mask & 1) { 880 newrstate[SBREG_FR + i] = UWX_DISP_PSPREL(fr_base); 881 tspill[SBREG_FR + i] = 0; 882 fr_base -= 16; 883 nfr--; 884 } 885 fr_mem_mask = fr_mem_mask >> 1; 886 } 887 888 /* Update the scoreboard. */ 889 890 for (i = 0; i < env->nsbreg; i++) { 891 if (ip_slot >= rhdr->rlen || ip_slot > tspill[i]) 892 scoreboard->rstate[i] = newrstate[i]; 893 } 894 if (priunat_mem_rstate != UWX_DISP_NONE && ip_slot > t_priunat_mem) 895 scoreboard->rstate[SBREG_PRIUNAT] = priunat_mem_rstate; 896 897 return UWX_OK; 898} 899 900int uwx_count_ones(unsigned int mask) 901{ 902 mask = (mask & 0x55555555) + ((mask & 0xaaaaaaaa) >> 1); 903 mask = (mask & 0x33333333) + ((mask & 0xcccccccc) >> 2); 904 mask = (mask & 0x0f0f0f0f) + ((mask & 0xf0f0f0f0) >> 4); 905 mask = (mask & 0x00ff00ff) + ((mask & 0xff00ff00) >> 8); 906 return (mask & 0x0000ffff) + ((mask & 0xffff0000) >> 16); 907} 908 909/* uwx_decode_body: Decodes a body region */ 910 911int uwx_decode_body( 912 struct uwx_env *env, 913 struct uwx_bstream *bstream, 914 struct uwx_scoreboard *scoreboard, 915 struct uwx_rhdr *rhdr, 916 int ip_slot) 917{ 918 int status; 919 int b0; 920 int b1; 921 int b2; 922 int b3; 923 int label; 924 int ecount; 925 int i; 926 uint64_t parm1; 927 uint64_t parm2; 928 uint64_t newrstate[NSBREG]; 929 int tspill[NSBREG]; 930 int t_sp_restore; 931 932 /* Initialize an array of register states from the current */ 933 /* scoreboard, along with a parallel array of spill times. */ 934 /* We use this as a temporary scoreboard, then update the */ 935 /* real scoreboard at the end of the procedure. */ 936 /* We initialize the spill time to (rhdr.rlen - 1) so that */ 937 /* spills without a "when" descriptor will take effect */ 938 /* at the end of the prologue region. */ 939 /* (Boundary condition: all actions in a zero-length prologue */ 940 /* will appear to have happened in the instruction slot */ 941 /* immediately preceding the prologue.) */ 942 943 for (i = 0; i < env->nsbreg; i++) { 944 newrstate[i] = scoreboard->rstate[i]; 945 tspill[i] = rhdr->rlen - 1; 946 } 947 t_sp_restore = rhdr->rlen - 1; 948 949 /* Read body descriptor records until */ 950 /* we hit another region header. */ 951 952 for (;;) { 953 954 b0 = uwx_get_byte(bstream); 955 956 if (b0 < 0x80) { 957 /* Return the last byte read to the byte stream, since it's */ 958 /* really the first byte of the next region header record. */ 959 if (b0 >= 0) 960 (void) uwx_unget_byte(bstream, b0); 961 break; 962 } 963 964 /* Format B1 (label_state) */ 965 if (b0 < 0xa0) { 966 TRACE_I_DECODE_BODY_1("(B1) label_state", b0) 967 label = b0 & 0x1f; 968 status = uwx_label_scoreboard(env, scoreboard, label); 969 if (status != UWX_OK) 970 return (status); 971 } 972 973 /* Format B1 (copy_state) */ 974 else if (b0 < 0xc0) { 975 TRACE_I_DECODE_BODY_1("(B1) copy_state", b0) 976 label = b0 & 0x1f; 977 status = uwx_copy_scoreboard(env, scoreboard, label); 978 if (status != UWX_OK) 979 return (status); 980 for (i = 0; i < env->nsbreg; i++) { 981 newrstate[i] = scoreboard->rstate[i]; 982 tspill[i] = rhdr->rlen; 983 } 984 } 985 986 /* Format B2 (epilogue) */ 987 else if (b0 < 0xe0) { 988 ecount = b0 & 0x1f; 989 status = uwx_get_uleb128(bstream, &parm1); 990 if (status != 0) 991 return UWX_ERR_BADUDESC; 992 TRACE_I_DECODE_BODY_1L("(B2) epilogue", b0, parm1) 993 rhdr->ecount = ecount + 1; 994 t_sp_restore = rhdr->rlen - (unsigned int) parm1; 995 } 996 997 /* Format B3 (epilogue) */ 998 else if (b0 == 0xe0) { 999 status = uwx_get_uleb128(bstream, &parm1); 1000 if (status != 0) 1001 return UWX_ERR_BADUDESC; 1002 status = uwx_get_uleb128(bstream, &parm2); 1003 if (status != 0) 1004 return UWX_ERR_BADUDESC; 1005 TRACE_I_DECODE_BODY_1LL("(B3) epilogue", b0, parm1, parm2) 1006 t_sp_restore = rhdr->rlen - (unsigned int) parm1; 1007 rhdr->ecount = (unsigned int) parm2 + 1; 1008 } 1009 1010 /* Format B4 (label_state) */ 1011 else if (b0 == 0xf0) { 1012 status = uwx_get_uleb128(bstream, &parm1); 1013 if (status != 0) 1014 return UWX_ERR_BADUDESC; 1015 TRACE_I_DECODE_BODY_1L("(B4) label_state", b0, parm1) 1016 label = (int) parm1; 1017 status = uwx_label_scoreboard(env, scoreboard, label); 1018 if (status != UWX_OK) 1019 return (status); 1020 } 1021 1022 /* Format B4 (copy_state) */ 1023 else if (b0 == 0xf8) { 1024 status = uwx_get_uleb128(bstream, &parm1); 1025 if (status != 0) 1026 return UWX_ERR_BADUDESC; 1027 TRACE_I_DECODE_BODY_1L("(B4) copy_state", b0, parm1) 1028 label = (int) parm1; 1029 status = uwx_copy_scoreboard(env, scoreboard, label); 1030 if (status != UWX_OK) 1031 return (status); 1032 for (i = 0; i < env->nsbreg; i++) { 1033 newrstate[i] = scoreboard->rstate[i]; 1034 tspill[i] = rhdr->rlen; 1035 } 1036 } 1037 1038 /* Format X1 */ 1039 else if (b0 == 0xf9) { 1040 TRACE_I_DECODE_BODY_1("(X1)", b0) 1041 b1 = uwx_get_byte(bstream); 1042 if (b1 < 0) 1043 return UWX_ERR_BADUDESC; 1044 /* Don't support X-format descriptors yet */ 1045 return UWX_ERR_CANTUNWIND; 1046 } 1047 1048 /* Format X2 */ 1049 else if (b0 == 0xfa) { 1050 TRACE_I_DECODE_BODY_1("(X2)", b0) 1051 b1 = uwx_get_byte(bstream); 1052 if (b1 < 0) 1053 return UWX_ERR_BADUDESC; 1054 b2 = uwx_get_byte(bstream); 1055 if (b2 < 0) 1056 return UWX_ERR_BADUDESC; 1057 /* Don't support X-format descriptors yet */ 1058 return UWX_ERR_CANTUNWIND; 1059 } 1060 1061 /* Format X3 */ 1062 else if (b0 == 0xfb) { 1063 TRACE_I_DECODE_BODY_1("(X3)", b0) 1064 b1 = uwx_get_byte(bstream); 1065 if (b1 < 0) 1066 return UWX_ERR_BADUDESC; 1067 b2 = uwx_get_byte(bstream); 1068 if (b2 < 0) 1069 return UWX_ERR_BADUDESC; 1070 /* Don't support X-format descriptors yet */ 1071 return UWX_ERR_CANTUNWIND; 1072 } 1073 1074 /* Format X4 */ 1075 else if (b0 == 0xfc) { 1076 TRACE_I_DECODE_BODY_1("(X4)", b0) 1077 b1 = uwx_get_byte(bstream); 1078 if (b1 < 0) 1079 return UWX_ERR_BADUDESC; 1080 b2 = uwx_get_byte(bstream); 1081 if (b2 < 0) 1082 return UWX_ERR_BADUDESC; 1083 b3 = uwx_get_byte(bstream); 1084 if (b3 < 0) 1085 return UWX_ERR_BADUDESC; 1086 /* Don't support X-format descriptors yet */ 1087 return UWX_ERR_CANTUNWIND; 1088 } 1089 1090 /* Invalid descriptor record */ 1091 else { 1092 TRACE_I_DECODE_BODY_1("(?)", b0) 1093 return UWX_ERR_BADUDESC; 1094 } 1095 } 1096 1097 /* Update the scoreboard. */ 1098 1099 for (i = 0; i < env->nsbreg; i++) { 1100 if (ip_slot > tspill[i]) 1101 scoreboard->rstate[i] = newrstate[i]; 1102 } 1103 1104 /* If we've passed the point in the epilogue where sp */ 1105 /* is restored, update the scoreboard entry for PSP */ 1106 /* and reset any entries for registers saved in memory. */ 1107 1108 if (rhdr->ecount > 0 && ip_slot > t_sp_restore) { 1109 scoreboard->rstate[SBREG_PSP] = UWX_DISP_SPPLUS(0); 1110 for (i = 0; i < env->nsbreg; i++) { 1111 if (UWX_GET_DISP_CODE(scoreboard->rstate[i]) == UWX_DISP_SPREL(0) || 1112 UWX_GET_DISP_CODE(scoreboard->rstate[i]) == UWX_DISP_PSPREL(0)) 1113 scoreboard->rstate[i] = UWX_DISP_NONE; 1114 } 1115 } 1116 1117 return UWX_OK; 1118} 1119 1120