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