2 Copyright (c) 2003-2006 Hewlett-Packard Development Company, L.P.
3 Permission is hereby granted, free of charge, to any person
4 obtaining a copy of this software and associated documentation
5 files (the "Software"), to deal in the Software without
6 restriction, including without limitation the rights to use,
7 copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following
12 The above copyright notice and this permission notice shall be
13 included in all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 OTHER DEALINGS IN THE SOFTWARE.
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"
33 int uwx_count_ones(unsigned int mask);
38 * This file contains the routines for reading and decoding
39 * the unwind information block.
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.
50 #define COPYIN_UINFO_4(dest, src) \
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) )
56 #define COPYIN_UINFO_8(dest, src) \
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) )
63 /* uwx_default_rstate: Returns the default register state for a leaf routine */
65 int uwx_default_rstate(struct uwx_env *env, uint64_t **rstatep)
67 struct uwx_scoreboard *sb;
69 sb = uwx_init_scoreboards(env);
70 *rstatep = sb->rstate;
75 /* uwx_decode_uinfo: Decodes unwind info region */
79 struct uwx_utable_entry *uentry,
85 struct uwx_bstream bstream;
86 struct uwx_scoreboard *scoreboard;
92 /* Remember the offset from the start of the function */
93 /* to the current IP. This helps the client find */
94 /* the symbolic information. */
96 env->function_offset = env->remapped_ip - uentry->code_start;
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. */
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);
112 len = COPYIN_UINFO_8((char *)&uinfohdr, uentry->unwind_info);
114 return UWX_ERR_COPYIN_UINFO;
116 uwx_swap8(&uinfohdr);
117 if (uentry->unwind_flags & UNWIND_TBL_32BIT)
118 ulen = UNW_LENGTH(uinfohdr) * WORDSZ;
120 ulen = UNW_LENGTH(uinfohdr) * DWORDSZ;
121 uwx_init_bstream(&bstream, env,
122 uentry->unwind_info + DWORDSZ, ulen, UWX_COPYIN_UINFO);
124 /* Save the header and a pointer to the personality routine ptr */
125 /* for later use in exception handling. */
127 env->uinfo_hdr = uinfohdr;
128 env->uinfo_end = uentry->unwind_info + DWORDSZ + ulen;
130 TRACE_R_UIB(uentry, ulen)
132 /* Create an initial scoreboard for tracking the unwind state. */
134 scoreboard = uwx_init_scoreboards(env);
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. */
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);
147 /* Loop over the regions in the unwind info block. */
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 */
157 status = uwx_decode_rhdr(env, &bstream, &rhdr);
158 if (status != UWX_OK)
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. */
165 if (rhdr.is_prologue) {
166 scoreboard = uwx_new_scoreboard(env, scoreboard);
168 return UWX_ERR_NOMEM;
169 status = uwx_decode_prologue(env, &bstream,
170 scoreboard, &rhdr, ip_slot);
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. */
179 status = uwx_decode_body(env, &bstream, scoreboard, &rhdr, ip_slot);
182 if (status != UWX_OK)
185 TRACE_R_DUMP_SB(scoreboard, rhdr, cur_slot, ip_slot)
187 /* If the target ip slot is within this region, we're done. */
188 /* Return the scoreboard's register state array. */
190 if (ip_slot < rhdr.rlen) {
191 *rstatep = scoreboard->rstate;
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. */
199 cur_slot += rhdr.rlen;
200 ip_slot -= rhdr.rlen;
201 if (rhdr.ecount > 0) {
202 scoreboard = uwx_pop_scoreboards(env, scoreboard, rhdr.ecount);
204 return UWX_ERR_PROLOG_UF;
211 /* uwx_decode_rhdr: Decodes a region header record */
215 struct uwx_bstream *bstream,
216 struct uwx_rhdr *rhdr)
223 /* Get the first byte of the next descriptor record. */
224 b0 = uwx_get_byte(bstream);
226 return UWX_ERR_NOUDESC;
228 /* Initialize region header record. */
230 rhdr->is_prologue = 0;
239 if ((b0 & 0x20) == 0) {
240 TRACE_I_DECODE_RHDR_1("(R1) prologue", b0)
241 rhdr->is_prologue = 1;
244 TRACE_I_DECODE_RHDR_1("(R1) body", b0)
246 rhdr->rlen = b0 & 0x1f;
251 else if (b0 < 0x60) {
252 b1 = uwx_get_byte(bstream);
254 return UWX_ERR_BADUDESC;
255 status = uwx_get_uleb128(bstream, &val);
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;
267 else if (b0 < 0x80) {
268 status = uwx_get_uleb128(bstream, &val);
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;
276 TRACE_I_DECODE_RHDR_1L("(R3) body", b0, val)
278 rhdr->rlen = (unsigned int) val;
281 /* Otherwise, not a region header record. */
284 TRACE_I_DECODE_RHDR_1("(?)", b0)
285 return UWX_ERR_BADUDESC;
292 /* uwx_decode_prologue: Decodes a prologue region */
294 int uwx_decode_prologue(
296 struct uwx_bstream *bstream,
297 struct uwx_scoreboard *scoreboard,
298 struct uwx_rhdr *rhdr,
313 uint64_t newrstate[NSBREG];
315 int priunat_mem_rstate;
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;
325 unsigned int spill_base;
326 unsigned int gr_base;
327 unsigned int br_base;
328 unsigned int fr_base;
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.) */
341 for (i = 0; i < env->nsbreg; i++) {
342 newrstate[i] = scoreboard->rstate[i];
343 tspill[i] = rhdr->rlen - 1;
345 priunat_mem_rstate = UWX_DISP_NONE;
346 t_priunat_mem = rhdr->rlen - 1;
358 /* If prologue_gr header record supplied mask and grsave, */
359 /* record these in the scoreboard. */
364 newrstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_GR(reg));
368 newrstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_GR(reg));
372 newrstate[SBREG_PSP] = UWX_DISP_REG(UWX_REG_GR(reg));
376 newrstate[SBREG_PREDS] = UWX_DISP_REG(UWX_REG_GR(reg));
380 /* Read prologue descriptor records until */
381 /* we hit another region header. */
385 b0 = uwx_get_byte(bstream);
388 /* Return the last byte read to the byte stream, since it's */
389 /* really the first byte of the next region header record. */
391 (void) uwx_unget_byte(bstream, b0);
395 switch ((b0 & 0x70) >> 4) {
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;
404 case 2: /* 1010 xxxx */
405 /* Format P2 (br_gr) */
406 b1 = uwx_get_byte(bstream);
408 return UWX_ERR_BADUDESC;
409 TRACE_I_DECODE_PROLOGUE_2("(P2) br_gr", b0, b1)
410 mask = ((b0 & 0x0f) << 1) | (b1 >> 7);
413 for (i = 0; i < NSB_BR && mask != 0; i++) {
415 newrstate[SBREG_BR + i] = UWX_DISP_REG(UWX_REG_GR(reg));
422 case 3: /* 1011 xxxx */
425 b1 = uwx_get_byte(bstream);
427 return UWX_ERR_BADUDESC;
428 r = ((b0 & 0x7) << 1) | (b1 >> 7);
432 TRACE_I_DECODE_PROLOGUE_2("(P3) psp_gr", b0, b1)
433 newrstate[SBREG_PSP] = UWX_DISP_REG(UWX_REG_GR(reg));
436 TRACE_I_DECODE_PROLOGUE_2("(P3) rp_gr", b0, b1)
437 newrstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_GR(reg));
440 TRACE_I_DECODE_PROLOGUE_2("(P3) pfs_gr", b0, b1)
441 newrstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_GR(reg));
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));
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));
454 TRACE_I_DECODE_PROLOGUE_2("(P3) lc_gr", b0, b1)
455 newrstate[SBREG_LC] =
456 UWX_DISP_REG(UWX_REG_GR(reg));
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));
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));
473 TRACE_I_DECODE_PROLOGUE_2("(P3) bsp_gr", b0, b1)
474 /* Don't track BSP yet */
475 return UWX_ERR_CANTUNWIND;
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;
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));
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));
493 TRACE_I_DECODE_PROLOGUE_2("(P3) ??", b0, b1)
494 return UWX_ERR_BADUDESC;
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. */
516 while (t < rhdr->rlen) {
517 b1 = uwx_get_byte(bstream);
519 return UWX_ERR_BADUDESC;
520 for (i = 0; i < 4 && (t + i) < ip_slot; i++) {
523 case 0x40: nfr++; break;
524 case 0x80: ngr++; break;
525 case 0xc0: nbr++; break;
533 /* Format P5 (frgr_mem) */
534 else if (b0 == 0xb9) {
535 b1 = uwx_get_byte(bstream);
537 return UWX_ERR_BADUDESC;
538 b2 = uwx_get_byte(bstream);
540 return UWX_ERR_BADUDESC;
541 b3 = uwx_get_byte(bstream);
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;
549 /* Invalid descriptor record */
551 TRACE_I_DECODE_PROLOGUE_1("(?)", b0)
552 return UWX_ERR_BADUDESC;
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;
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;
569 case 6: /* 1110 xxxx */
572 status = uwx_get_uleb128(bstream, &parm1);
574 return UWX_ERR_BADUDESC;
576 case 0: /* mem_stack_f */
577 status = uwx_get_uleb128(bstream, &parm2);
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;
584 case 1: /* mem_stack_v */
585 TRACE_I_DECODE_PROLOGUE_1L("(P7) mem_stack_v", b0, parm1)
586 tspill[SBREG_PSP] = (int) parm1;
588 case 2: /* spill_base */
589 TRACE_I_DECODE_PROLOGUE_1L("(P7) spill_base", b0, parm1)
590 spill_base = 4 * (unsigned int) parm1;
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);
596 case 4: /* rp_when */
597 TRACE_I_DECODE_PROLOGUE_1L("(P7) rp_when", b0, parm1)
598 tspill[SBREG_RP] = (int) parm1;
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);
604 case 6: /* pfs_when */
605 TRACE_I_DECODE_PROLOGUE_1L("(P7) pfs_when", b0, parm1)
606 tspill[SBREG_PFS] = (int) parm1;
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);
612 case 8: /* preds_when */
613 TRACE_I_DECODE_PROLOGUE_1L("(P7) preds_when", b0, parm1)
614 tspill[SBREG_PREDS] = (int) parm1;
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);
620 case 10: /* lc_when */
621 TRACE_I_DECODE_PROLOGUE_1L("(P7) lc_when", b0, parm1)
622 tspill[SBREG_LC] = (int) parm1;
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);
628 case 12: /* unat_when */
629 TRACE_I_DECODE_PROLOGUE_1L("(P7) unat_when", b0, parm1)
630 tspill[SBREG_UNAT] = (int) parm1;
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);
636 case 14: /* fpsr_when */
637 TRACE_I_DECODE_PROLOGUE_1L("(P7) fpsr_when", b0, parm1)
638 tspill[SBREG_FPSR] = (int) parm1;
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);
647 case 7: /* 1111 xxxx */
650 b1 = uwx_get_byte(bstream);
652 return UWX_ERR_BADUDESC;
653 status = uwx_get_uleb128(bstream, &parm1);
655 return UWX_ERR_BADUDESC;
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);
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);
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);
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);
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);
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);
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;
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;
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;
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;
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;
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;
711 case 13: /* rnat_when */
712 TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_when", b0, b1, parm1)
713 tspill[SBREG_RNAT] = (int) parm1;
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);
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);
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;
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);
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);
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;
740 TRACE_I_DECODE_PROLOGUE_2L("(P8) ??", b0, b1, parm1)
741 return UWX_ERR_BADUDESC;
745 /* Format P9 (gr_gr) */
746 else if (b0 == 0xf1) {
747 b1 = uwx_get_byte(bstream);
749 return UWX_ERR_BADUDESC;
750 b2 = uwx_get_byte(bstream);
752 return UWX_ERR_BADUDESC;
753 TRACE_I_DECODE_PROLOGUE_3("(P9) gr_gr", b0, b1, b2)
757 for (i = 0; i < NSB_GR && mask != 0; i++) {
759 newrstate[SBREG_GR + i] =
760 UWX_DISP_REG(UWX_REG_GR(reg));
768 else if (b0 == 0xf9) {
769 TRACE_I_DECODE_PROLOGUE_1("(X1)", b0)
770 b1 = uwx_get_byte(bstream);
772 return UWX_ERR_BADUDESC;
773 /* Don't support X-format descriptors yet */
774 return UWX_ERR_CANTUNWIND;
778 else if (b0 == 0xfa) {
779 TRACE_I_DECODE_PROLOGUE_1("(X2)", b0)
780 b1 = uwx_get_byte(bstream);
782 return UWX_ERR_BADUDESC;
783 b2 = uwx_get_byte(bstream);
785 return UWX_ERR_BADUDESC;
786 /* Don't support X-format descriptors yet */
787 return UWX_ERR_CANTUNWIND;
791 else if (b0 == 0xfb) {
792 TRACE_I_DECODE_PROLOGUE_1("(X3)", b0)
793 b1 = uwx_get_byte(bstream);
795 return UWX_ERR_BADUDESC;
796 b2 = uwx_get_byte(bstream);
798 return UWX_ERR_BADUDESC;
799 /* Don't support X-format descriptors yet */
800 return UWX_ERR_CANTUNWIND;
804 else if (b0 == 0xfc) {
805 TRACE_I_DECODE_PROLOGUE_1("(X4)", b0)
806 b1 = uwx_get_byte(bstream);
808 return UWX_ERR_BADUDESC;
809 b2 = uwx_get_byte(bstream);
811 return UWX_ERR_BADUDESC;
812 b3 = uwx_get_byte(bstream);
814 return UWX_ERR_BADUDESC;
815 /* Don't support X-format descriptors yet */
816 return UWX_ERR_CANTUNWIND;
820 else if (b0 == 0xff) {
821 b1 = uwx_get_byte(bstream);
823 return UWX_ERR_BADUDESC;
824 b2 = uwx_get_byte(bstream);
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;
832 /* Invalid descriptor record */
834 TRACE_I_DECODE_PROLOGUE_1("(?)", b0)
835 return UWX_ERR_BADUDESC;
841 /* Process the masks of spilled GRs, FRs, and BRs to */
842 /* determine when and where each register was saved. */
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;
857 else if (gr_gr_mask & 1) {
858 tspill[SBREG_GR + i] = 0;
861 gr_gr_mask = gr_gr_mask >> 1;
862 gr_mem_mask = gr_mem_mask >> 1;
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;
871 else if (br_gr_mask & 1) {
872 tspill[SBREG_BR + i] = 0;
875 br_gr_mask = br_gr_mask >> 1;
876 br_mem_mask = br_mem_mask >> 1;
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;
885 fr_mem_mask = fr_mem_mask >> 1;
888 /* Update the scoreboard. */
890 for (i = 0; i < env->nsbreg; i++) {
891 if (ip_slot >= rhdr->rlen || ip_slot > tspill[i])
892 scoreboard->rstate[i] = newrstate[i];
894 if (priunat_mem_rstate != UWX_DISP_NONE && ip_slot > t_priunat_mem)
895 scoreboard->rstate[SBREG_PRIUNAT] = priunat_mem_rstate;
900 int uwx_count_ones(unsigned int mask)
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);
909 /* uwx_decode_body: Decodes a body region */
913 struct uwx_bstream *bstream,
914 struct uwx_scoreboard *scoreboard,
915 struct uwx_rhdr *rhdr,
928 uint64_t newrstate[NSBREG];
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.) */
943 for (i = 0; i < env->nsbreg; i++) {
944 newrstate[i] = scoreboard->rstate[i];
945 tspill[i] = rhdr->rlen - 1;
947 t_sp_restore = rhdr->rlen - 1;
949 /* Read body descriptor records until */
950 /* we hit another region header. */
954 b0 = uwx_get_byte(bstream);
957 /* Return the last byte read to the byte stream, since it's */
958 /* really the first byte of the next region header record. */
960 (void) uwx_unget_byte(bstream, b0);
964 /* Format B1 (label_state) */
966 TRACE_I_DECODE_BODY_1("(B1) label_state", b0)
968 status = uwx_label_scoreboard(env, scoreboard, label);
969 if (status != UWX_OK)
973 /* Format B1 (copy_state) */
974 else if (b0 < 0xc0) {
975 TRACE_I_DECODE_BODY_1("(B1) copy_state", b0)
977 status = uwx_copy_scoreboard(env, scoreboard, label);
978 if (status != UWX_OK)
980 for (i = 0; i < env->nsbreg; i++) {
981 newrstate[i] = scoreboard->rstate[i];
982 tspill[i] = rhdr->rlen;
986 /* Format B2 (epilogue) */
987 else if (b0 < 0xe0) {
989 status = uwx_get_uleb128(bstream, &parm1);
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;
997 /* Format B3 (epilogue) */
998 else if (b0 == 0xe0) {
999 status = uwx_get_uleb128(bstream, &parm1);
1001 return UWX_ERR_BADUDESC;
1002 status = uwx_get_uleb128(bstream, &parm2);
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;
1010 /* Format B4 (label_state) */
1011 else if (b0 == 0xf0) {
1012 status = uwx_get_uleb128(bstream, &parm1);
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)
1022 /* Format B4 (copy_state) */
1023 else if (b0 == 0xf8) {
1024 status = uwx_get_uleb128(bstream, &parm1);
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)
1032 for (i = 0; i < env->nsbreg; i++) {
1033 newrstate[i] = scoreboard->rstate[i];
1034 tspill[i] = rhdr->rlen;
1039 else if (b0 == 0xf9) {
1040 TRACE_I_DECODE_BODY_1("(X1)", b0)
1041 b1 = uwx_get_byte(bstream);
1043 return UWX_ERR_BADUDESC;
1044 /* Don't support X-format descriptors yet */
1045 return UWX_ERR_CANTUNWIND;
1049 else if (b0 == 0xfa) {
1050 TRACE_I_DECODE_BODY_1("(X2)", b0)
1051 b1 = uwx_get_byte(bstream);
1053 return UWX_ERR_BADUDESC;
1054 b2 = uwx_get_byte(bstream);
1056 return UWX_ERR_BADUDESC;
1057 /* Don't support X-format descriptors yet */
1058 return UWX_ERR_CANTUNWIND;
1062 else if (b0 == 0xfb) {
1063 TRACE_I_DECODE_BODY_1("(X3)", b0)
1064 b1 = uwx_get_byte(bstream);
1066 return UWX_ERR_BADUDESC;
1067 b2 = uwx_get_byte(bstream);
1069 return UWX_ERR_BADUDESC;
1070 /* Don't support X-format descriptors yet */
1071 return UWX_ERR_CANTUNWIND;
1075 else if (b0 == 0xfc) {
1076 TRACE_I_DECODE_BODY_1("(X4)", b0)
1077 b1 = uwx_get_byte(bstream);
1079 return UWX_ERR_BADUDESC;
1080 b2 = uwx_get_byte(bstream);
1082 return UWX_ERR_BADUDESC;
1083 b3 = uwx_get_byte(bstream);
1085 return UWX_ERR_BADUDESC;
1086 /* Don't support X-format descriptors yet */
1087 return UWX_ERR_CANTUNWIND;
1090 /* Invalid descriptor record */
1092 TRACE_I_DECODE_BODY_1("(?)", b0)
1093 return UWX_ERR_BADUDESC;
1097 /* Update the scoreboard. */
1099 for (i = 0; i < env->nsbreg; i++) {
1100 if (ip_slot > tspill[i])
1101 scoreboard->rstate[i] = newrstate[i];
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. */
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;