2 Copyright (c) 2003 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 *)(dest) = *(uint32_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 *)(dest) = *(uint64_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 TRACE_R_UIB(uentry, ulen)
126 /* Create an initial scoreboard for tracking the unwind state. */
128 scoreboard = uwx_init_scoreboards(env);
130 /* Prepare to read and decode the unwind regions described */
131 /* by the unwind info block. Find the target "ip" slot */
132 /* relative to the beginning of the region. The lower 4 bits */
133 /* of the actual IP encode the slot number within a bundle. */
136 ip_slot = (int) ((env->context.special[UWX_REG_IP] & ~0x0fLL)
137 - uentry->code_start)
138 / BUNDLESZ * SLOTSPERBUNDLE
139 + (unsigned int) (env->context.special[UWX_REG_IP] & 0x0f);
141 /* Loop over the regions in the unwind info block. */
145 /* Decode the next region header. */
146 /* We have an error if we reach the end of the info block, */
147 /* since we should have found our target ip slot by then. */
148 /* We also have an error if the next byte isn't a region */
151 status = uwx_decode_rhdr(env, &bstream, &rhdr);
152 if (status != UWX_OK)
155 /* If a prologue region, get a new scoreboard, pushing */
156 /* the previous one onto the prologue stack. Then read */
157 /* and decode the prologue region records. */
159 if (rhdr.is_prologue) {
160 scoreboard = uwx_new_scoreboard(env, scoreboard);
162 return UWX_ERR_NOMEM;
163 status = uwx_decode_prologue(env, &bstream,
164 scoreboard, &rhdr, ip_slot);
167 /* If a body region, read and decode the body region */
168 /* records. If the body has an epilogue count, */
169 /* uwx_decode_body will note that in the region header */
170 /* record for use at the bottom of the loop. */
173 status = uwx_decode_body(env, &bstream, scoreboard, &rhdr, ip_slot);
176 if (status != UWX_OK)
179 TRACE_R_DUMP_SB(scoreboard, rhdr, cur_slot, ip_slot)
181 /* If the target ip slot is within this region, we're done. */
182 /* Return the scoreboard's register state array. */
184 if (ip_slot < rhdr.rlen) {
185 *rstatep = scoreboard->rstate;
189 /* Otherwise, update the current ip slot, pop the */
190 /* scoreboard stack based on the epilogue count, */
191 /* and loop back around for the next region. */
193 cur_slot += rhdr.rlen;
194 ip_slot -= rhdr.rlen;
195 if (rhdr.ecount > 0) {
196 scoreboard = uwx_pop_scoreboards(env, scoreboard, rhdr.ecount);
198 return UWX_ERR_PROLOG_UF;
205 /* uwx_decode_rhdr: Decodes a region header record */
209 struct uwx_bstream *bstream,
210 struct uwx_rhdr *rhdr)
217 /* Get the first byte of the next descriptor record. */
218 b0 = uwx_get_byte(bstream);
220 return UWX_ERR_NOUDESC;
222 /* Initialize region header record. */
224 rhdr->is_prologue = 0;
233 if ((b0 & 0x20) == 0) {
234 TRACE_I_DECODE_RHDR_1("(R1) prologue", b0)
235 rhdr->is_prologue = 1;
238 TRACE_I_DECODE_RHDR_1("(R1) body", b0)
240 rhdr->rlen = b0 & 0x1f;
245 else if (b0 < 0x60) {
246 b1 = uwx_get_byte(bstream);
248 return UWX_ERR_BADUDESC;
249 status = uwx_get_uleb128(bstream, &val);
251 return UWX_ERR_BADUDESC;
252 TRACE_I_DECODE_RHDR_2L("(R2) prologue_gr", b0, b1, val)
253 rhdr->is_prologue = 1;
254 rhdr->rlen = (unsigned int) val;
255 rhdr->mask = ((b0 & 0x07) << 1) | (b1 >> 7);
256 rhdr->grsave = b1 & 0x7f;
261 else if (b0 < 0x80) {
262 status = uwx_get_uleb128(bstream, &val);
264 return UWX_ERR_BADUDESC;
265 if ((b0 & 0x03) == 0) {
266 TRACE_I_DECODE_RHDR_1L("(R3) prologue", b0, val)
267 rhdr->is_prologue = 1;
270 TRACE_I_DECODE_RHDR_1L("(R3) body", b0, val)
272 rhdr->rlen = (unsigned int) val;
275 /* Otherwise, not a region header record. */
278 TRACE_I_DECODE_RHDR_1("(?)", b0)
279 return UWX_ERR_BADUDESC;
286 /* uwx_decode_prologue: Decodes a prologue region */
288 int uwx_decode_prologue(
290 struct uwx_bstream *bstream,
291 struct uwx_scoreboard *scoreboard,
292 struct uwx_rhdr *rhdr,
307 uint64_t newrstate[NSBREG];
309 int priunat_mem_rstate;
311 unsigned int gr_mem_mask;
312 unsigned int br_mem_mask;
313 unsigned int fr_mem_mask;
314 unsigned int gr_gr_mask;
315 unsigned int br_gr_mask;
319 unsigned int spill_base;
320 unsigned int gr_base;
321 unsigned int br_base;
322 unsigned int fr_base;
324 /* Initialize an array of register states from the current */
325 /* scoreboard, along with a parallel array of spill times. */
326 /* We use this as a temporary scoreboard, then update the */
327 /* real scoreboard at the end of the procedure. */
328 /* We initialize the spill time to (rhdr.rlen - 1) so that */
329 /* spills without a "when" descriptor will take effect */
330 /* at the end of the prologue region. */
331 /* (Boundary condition: all actions in a zero-length prologue */
332 /* will appear to have happened in the instruction slot */
333 /* immediately preceding the prologue.) */
335 for (i = 0; i < env->nsbreg; i++) {
336 newrstate[i] = scoreboard->rstate[i];
337 tspill[i] = rhdr->rlen - 1;
339 priunat_mem_rstate = UWX_DISP_NONE;
340 t_priunat_mem = rhdr->rlen - 1;
352 /* If prologue_gr header record supplied mask and grsave, */
353 /* record these in the scoreboard. */
358 newrstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_GR(reg));
362 newrstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_GR(reg));
366 newrstate[SBREG_PSP] = UWX_DISP_REG(UWX_REG_GR(reg));
370 newrstate[SBREG_PREDS] = UWX_DISP_REG(UWX_REG_GR(reg));
374 /* Read prologue descriptor records until */
375 /* we hit another region header. */
379 b0 = uwx_get_byte(bstream);
382 /* Return the last byte read to the byte stream, since it's */
383 /* really the first byte of the next region header record. */
385 (void) uwx_unget_byte(bstream, b0);
389 switch ((b0 & 0x70) >> 4) {
391 case 0: /* 1000 xxxx */
392 case 1: /* 1001 xxxx */
393 /* Format P1 (br_mem) */
394 TRACE_I_DECODE_PROLOGUE_1("(P1) br_mem", b0)
395 br_mem_mask = b0 & 0x1f;
398 case 2: /* 1010 xxxx */
399 /* Format P2 (br_gr) */
400 b1 = uwx_get_byte(bstream);
402 return UWX_ERR_BADUDESC;
403 TRACE_I_DECODE_PROLOGUE_2("(P2) br_gr", b0, b1)
404 mask = ((b0 & 0x0f) << 1) | (b1 >> 7);
407 for (i = 0; i < NSB_BR && mask != 0; i++) {
409 newrstate[SBREG_BR + i] = UWX_DISP_REG(UWX_REG_GR(reg));
416 case 3: /* 1011 xxxx */
419 b1 = uwx_get_byte(bstream);
421 return UWX_ERR_BADUDESC;
422 r = ((b0 & 0x7) << 1) | (b1 >> 7);
426 TRACE_I_DECODE_PROLOGUE_2("(P3) psp_gr", b0, b1)
427 newrstate[SBREG_PSP] = UWX_DISP_REG(UWX_REG_GR(reg));
430 TRACE_I_DECODE_PROLOGUE_2("(P3) rp_gr", b0, b1)
431 newrstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_GR(reg));
434 TRACE_I_DECODE_PROLOGUE_2("(P3) pfs_gr", b0, b1)
435 newrstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_GR(reg));
437 case 3: /* preds_gr */
438 TRACE_I_DECODE_PROLOGUE_2("(P3) preds_gr", b0, b1)
439 newrstate[SBREG_PREDS] =
440 UWX_DISP_REG(UWX_REG_GR(reg));
442 case 4: /* unat_gr */
443 TRACE_I_DECODE_PROLOGUE_2("(P3) unat_gr", b0, b1)
444 newrstate[SBREG_UNAT] =
445 UWX_DISP_REG(UWX_REG_GR(reg));
448 TRACE_I_DECODE_PROLOGUE_2("(P3) lc_gr", b0, b1)
449 newrstate[SBREG_LC] =
450 UWX_DISP_REG(UWX_REG_GR(reg));
453 TRACE_I_DECODE_PROLOGUE_2("(P3) rp_br", b0, b1)
454 scoreboard->rstate[SBREG_RP] =
455 UWX_DISP_REG(UWX_REG_BR(reg));
457 case 7: /* rnat_gr */
458 TRACE_I_DECODE_PROLOGUE_2("(P3) rnat_gr", b0, b1)
459 newrstate[SBREG_RNAT] =
460 UWX_DISP_REG(UWX_REG_GR(reg));
463 TRACE_I_DECODE_PROLOGUE_2("(P3) bsp_gr", b0, b1)
464 /* Don't track BSP yet */
465 return UWX_ERR_CANTUNWIND;
467 case 9: /* bspstore_gr */
468 TRACE_I_DECODE_PROLOGUE_2("(P3) bspstore_gr", b0, b1)
469 /* Don't track BSPSTORE yet */
470 return UWX_ERR_CANTUNWIND;
472 case 10: /* fpsr_gr */
473 TRACE_I_DECODE_PROLOGUE_2("(P3) fpsr_gr", b0, b1)
474 newrstate[SBREG_FPSR] =
475 UWX_DISP_REG(UWX_REG_GR(reg));
477 case 11: /* priunat_gr */
478 TRACE_I_DECODE_PROLOGUE_2("(P3) priunat_gr", b0, b1)
479 newrstate[SBREG_PRIUNAT] =
480 UWX_DISP_REG(UWX_REG_GR(reg));
483 TRACE_I_DECODE_PROLOGUE_2("(P3) ??", b0, b1)
484 return UWX_ERR_BADUDESC;
488 /* Format P4 (spill_mask) */
489 else if (b0 == 0xb8) {
490 TRACE_I_DECODE_PROLOGUE_1("(P4) spill_mask", b0)
491 /* The spill_mask descriptor is followed by */
492 /* an imask field whose length is determined */
493 /* by the region length: there are two mask */
494 /* bits per instruction slot in the region. */
495 /* We decode these bits two at a time, counting */
496 /* the number of FRs, GRs, and BRs that are */
497 /* saved up to the slot of interest. Other */
498 /* descriptors describe which sets of these */
499 /* registers are spilled, and we put those */
500 /* two pieces of information together at the */
501 /* end of the main loop. */
503 while (t < rhdr->rlen) {
504 b1 = uwx_get_byte(bstream);
506 return UWX_ERR_BADUDESC;
507 for (i = 0; i < 4 && (t + i) < ip_slot; i++) {
510 case 0x40: nfr++; break;
511 case 0x80: ngr++; break;
512 case 0xc0: nbr++; break;
520 /* Format P5 (frgr_mem) */
521 else if (b0 == 0xb9) {
522 b1 = uwx_get_byte(bstream);
524 return UWX_ERR_BADUDESC;
525 b2 = uwx_get_byte(bstream);
527 return UWX_ERR_BADUDESC;
528 b3 = uwx_get_byte(bstream);
530 return UWX_ERR_BADUDESC;
531 TRACE_I_DECODE_PROLOGUE_4("(P5) frgr_mem", b0, b1, b2, b3)
532 gr_mem_mask = b1 >> 4;
533 fr_mem_mask = ((b1 & 0x0f) << 16) | (b2 << 8) | b3;
536 /* Invalid descriptor record */
538 TRACE_I_DECODE_PROLOGUE_1("(?)", b0)
539 return UWX_ERR_BADUDESC;
544 case 4: /* 1100 xxxx */
545 /* Format P6 (fr_mem) */
546 TRACE_I_DECODE_PROLOGUE_1("(P6) fr_mem", b0)
547 fr_mem_mask = b0 & 0x0f;
550 case 5: /* 1101 xxxx */
551 /* Format P6 (gr_mem) */
552 TRACE_I_DECODE_PROLOGUE_1("(P6) gr_mem", b0)
553 gr_mem_mask = b0 & 0x0f;
556 case 6: /* 1110 xxxx */
559 status = uwx_get_uleb128(bstream, &parm1);
561 return UWX_ERR_BADUDESC;
563 case 0: /* mem_stack_f */
564 status = uwx_get_uleb128(bstream, &parm2);
566 return UWX_ERR_BADUDESC;
567 TRACE_I_DECODE_PROLOGUE_1LL("(P7) mem_stack_f", b0, parm1, parm2)
568 newrstate[SBREG_PSP] = UWX_DISP_SPPLUS(parm2 * 16);
569 tspill[SBREG_PSP] = (int) parm1;
571 case 1: /* mem_stack_v */
572 TRACE_I_DECODE_PROLOGUE_1L("(P7) mem_stack_v", b0, parm1)
573 tspill[SBREG_PSP] = (int) parm1;
575 case 2: /* spill_base */
576 TRACE_I_DECODE_PROLOGUE_1L("(P7) spill_base", b0, parm1)
577 spill_base = 4 * (unsigned int) parm1;
579 case 3: /* psp_sprel */
580 TRACE_I_DECODE_PROLOGUE_1L("(P7) psp_sprel", b0, parm1)
581 newrstate[SBREG_PSP] = UWX_DISP_SPREL(parm1 * 4);
583 case 4: /* rp_when */
584 TRACE_I_DECODE_PROLOGUE_1L("(P7) rp_when", b0, parm1)
585 tspill[SBREG_RP] = (int) parm1;
587 case 5: /* rp_psprel */
588 TRACE_I_DECODE_PROLOGUE_1L("(P7) rp_psprel", b0, parm1)
589 newrstate[SBREG_RP] = UWX_DISP_PSPREL(parm1 * 4);
591 case 6: /* pfs_when */
592 TRACE_I_DECODE_PROLOGUE_1L("(P7) pfs_when", b0, parm1)
593 tspill[SBREG_PFS] = (int) parm1;
595 case 7: /* pfs_psprel */
596 TRACE_I_DECODE_PROLOGUE_1L("(P7) pfs_psprel", b0, parm1)
597 newrstate[SBREG_PFS] = UWX_DISP_PSPREL(parm1 * 4);
599 case 8: /* preds_when */
600 TRACE_I_DECODE_PROLOGUE_1L("(P7) preds_when", b0, parm1)
601 tspill[SBREG_PREDS] = (int) parm1;
603 case 9: /* preds_psprel */
604 TRACE_I_DECODE_PROLOGUE_1L("(P7) preds_psprel", b0, parm1)
605 newrstate[SBREG_PREDS] = UWX_DISP_PSPREL(parm1 * 4);
607 case 10: /* lc_when */
608 TRACE_I_DECODE_PROLOGUE_1L("(P7) lc_when", b0, parm1)
609 tspill[SBREG_LC] = (int) parm1;
611 case 11: /* lc_psprel */
612 TRACE_I_DECODE_PROLOGUE_1L("(P7) lc_psprel", b0, parm1)
613 newrstate[SBREG_LC] = UWX_DISP_PSPREL(parm1 * 4);
615 case 12: /* unat_when */
616 TRACE_I_DECODE_PROLOGUE_1L("(P7) unat_when", b0, parm1)
617 tspill[SBREG_UNAT] = (int) parm1;
619 case 13: /* unat_psprel */
620 TRACE_I_DECODE_PROLOGUE_1L("(P7) unat_psprel", b0, parm1)
621 newrstate[SBREG_UNAT] = UWX_DISP_PSPREL(parm1 * 4);
623 case 14: /* fpsr_when */
624 TRACE_I_DECODE_PROLOGUE_1L("(P7) fpsr_when", b0, parm1)
625 tspill[SBREG_FPSR] = (int) parm1;
627 case 15: /* fpsr_psprel */
628 TRACE_I_DECODE_PROLOGUE_1L("(P7) fpsr_psprel", b0, parm1)
629 newrstate[SBREG_FPSR] = UWX_DISP_PSPREL(parm1 * 4);
634 case 7: /* 1111 xxxx */
637 b1 = uwx_get_byte(bstream);
639 return UWX_ERR_BADUDESC;
640 status = uwx_get_uleb128(bstream, &parm1);
642 return UWX_ERR_BADUDESC;
644 case 1: /* rp_sprel */
645 TRACE_I_DECODE_PROLOGUE_2L("(P8) rp_sprel", b0, b1, parm1)
646 newrstate[SBREG_RP] = UWX_DISP_SPREL(parm1 * 4);
648 case 2: /* pfs_sprel */
649 TRACE_I_DECODE_PROLOGUE_2L("(P8) pfs_sprel", b0, b1, parm1)
650 newrstate[SBREG_PFS] = UWX_DISP_SPREL(parm1 * 4);
652 case 3: /* preds_sprel */
653 TRACE_I_DECODE_PROLOGUE_2L("(P8) preds_sprel", b0, b1, parm1)
654 newrstate[SBREG_PREDS] = UWX_DISP_SPREL(parm1 * 4);
656 case 4: /* lc_sprel */
657 TRACE_I_DECODE_PROLOGUE_2L("(P8) lc_sprel", b0, b1, parm1)
658 newrstate[SBREG_LC] = UWX_DISP_SPREL(parm1 * 4);
660 case 5: /* unat_sprel */
661 TRACE_I_DECODE_PROLOGUE_2L("(P8) unat_sprel", b0, b1, parm1)
662 newrstate[SBREG_UNAT] = UWX_DISP_SPREL(parm1 * 4);
664 case 6: /* fpsr_sprel */
665 TRACE_I_DECODE_PROLOGUE_2L("(P8) fpsr_sprel", b0, b1, parm1)
666 newrstate[SBREG_FPSR] = UWX_DISP_SPREL(parm1 * 4);
668 case 7: /* bsp_when */
669 TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_when", b0, b1, parm1)
670 /* Don't track BSP yet */
671 return UWX_ERR_CANTUNWIND;
673 case 8: /* bsp_psprel */
674 TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_psprel", b0, b1, parm1)
675 /* Don't track BSP yet */
676 return UWX_ERR_CANTUNWIND;
678 case 9: /* bsp_sprel */
679 TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_sprel", b0, b1, parm1)
680 /* Don't track BSP yet */
681 return UWX_ERR_CANTUNWIND;
683 case 10: /* bspstore_when */
684 TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_when", b0, b1, parm1)
685 /* Don't track BSP yet */
686 return UWX_ERR_CANTUNWIND;
688 case 11: /* bspstore_psprel */
689 TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_psprel", b0, b1, parm1)
690 /* Don't track BSP yet */
691 return UWX_ERR_CANTUNWIND;
693 case 12: /* bspstore_sprel */
694 TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_sprel", b0, b1, parm1)
695 /* Don't track BSP yet */
696 return UWX_ERR_CANTUNWIND;
698 case 13: /* rnat_when */
699 TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_when", b0, b1, parm1)
700 tspill[SBREG_RNAT] = (int) parm1;
702 case 14: /* rnat_psprel */
703 TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_psprel", b0, b1, parm1)
704 newrstate[SBREG_RNAT] = UWX_DISP_PSPREL(parm1 * 4);
706 case 15: /* rnat_sprel */
707 TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_sprel", b0, b1, parm1)
708 newrstate[SBREG_RNAT] = UWX_DISP_SPREL(parm1 * 4);
710 case 16: /* priunat_when_gr */
711 TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_when_gr", b0, b1, parm1)
712 tspill[SBREG_PRIUNAT] = (int) parm1;
714 case 17: /* priunat_psprel */
715 TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_psprel", b0, b1, parm1)
716 priunat_mem_rstate = UWX_DISP_PSPREL(parm1 * 4);
718 case 18: /* priunat_sprel */
719 TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_sprel", b0, b1, parm1)
720 priunat_mem_rstate = UWX_DISP_SPREL(parm1 * 4);
722 case 19: /* priunat_when_mem */
723 TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_when_mem", b0, b1, parm1)
724 t_priunat_mem = (int) parm1;
727 TRACE_I_DECODE_PROLOGUE_2L("(P8) ??", b0, b1, parm1)
728 return UWX_ERR_BADUDESC;
732 /* Format P9 (gr_gr) */
733 else if (b0 == 0xf1) {
734 b1 = uwx_get_byte(bstream);
736 return UWX_ERR_BADUDESC;
737 b2 = uwx_get_byte(bstream);
739 return UWX_ERR_BADUDESC;
740 TRACE_I_DECODE_PROLOGUE_3("(P9) gr_gr", b0, b1, b2)
744 for (i = 0; i < NSB_GR && mask != 0; i++) {
746 newrstate[SBREG_GR + i] =
747 UWX_DISP_REG(UWX_REG_GR(reg));
755 else if (b0 == 0xf9) {
756 TRACE_I_DECODE_PROLOGUE_1("(X1)", b0)
757 b1 = uwx_get_byte(bstream);
759 return UWX_ERR_BADUDESC;
760 /* Don't support X-format descriptors yet */
761 return UWX_ERR_CANTUNWIND;
765 else if (b0 == 0xfa) {
766 TRACE_I_DECODE_PROLOGUE_1("(X2)", b0)
767 b1 = uwx_get_byte(bstream);
769 return UWX_ERR_BADUDESC;
770 b2 = 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 == 0xfb) {
779 TRACE_I_DECODE_PROLOGUE_1("(X3)", 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 == 0xfc) {
792 TRACE_I_DECODE_PROLOGUE_1("(X4)", b0)
793 b1 = uwx_get_byte(bstream);
795 return UWX_ERR_BADUDESC;
796 b2 = uwx_get_byte(bstream);
798 return UWX_ERR_BADUDESC;
799 b3 = uwx_get_byte(bstream);
801 return UWX_ERR_BADUDESC;
802 /* Don't support X-format descriptors yet */
803 return UWX_ERR_CANTUNWIND;
807 else if (b0 == 0xff) {
808 b1 = uwx_get_byte(bstream);
810 return UWX_ERR_BADUDESC;
811 b2 = uwx_get_byte(bstream);
813 return UWX_ERR_BADUDESC;
814 TRACE_I_DECODE_PROLOGUE_3("(P10) abi", b0, b1, b2)
815 env->abi_context = (b1 << 8) | b2;
816 return UWX_ABI_FRAME;
819 /* Invalid descriptor record */
821 TRACE_I_DECODE_PROLOGUE_1("(?)", b0)
822 return UWX_ERR_BADUDESC;
828 /* Process the masks of spilled GRs, FRs, and BRs to */
829 /* determine when and where each register was saved. */
831 fr_base = spill_base + 16 * uwx_count_ones(fr_mem_mask);
832 br_base = fr_base + 8 * uwx_count_ones(br_mem_mask);
833 gr_base = br_base + 8 * uwx_count_ones(gr_mem_mask);
834 TRACE_I_DECODE_PROLOGUE_SPILL_BASE(spill_base)
835 TRACE_I_DECODE_PROLOGUE_MASKS(gr_mem_mask, gr_gr_mask)
836 TRACE_I_DECODE_PROLOGUE_NSPILL(ngr)
837 for (i = 0; ngr > 0 && i <= NSB_GR; i++) {
838 if (gr_mem_mask & 1) {
839 newrstate[SBREG_GR + i] = UWX_DISP_PSPREL(gr_base);
840 tspill[SBREG_GR + i] = 0;
844 else if (gr_gr_mask & 1) {
845 tspill[SBREG_GR + i] = 0;
848 gr_gr_mask = gr_gr_mask >> 1;
849 gr_mem_mask = gr_mem_mask >> 1;
851 for (i = 0; nbr > 0 && i <= NSB_BR; i++) {
852 if (br_mem_mask & 1) {
853 newrstate[SBREG_BR + i] = UWX_DISP_PSPREL(br_base);
854 tspill[SBREG_BR + i] = 0;
858 else if (br_gr_mask & 1) {
859 tspill[SBREG_BR + i] = 0;
862 br_gr_mask = br_gr_mask >> 1;
863 br_mem_mask = br_mem_mask >> 1;
865 for (i = 0; nfr > 0 && i <= NSB_FR; i++) {
866 if (fr_mem_mask & 1) {
867 newrstate[SBREG_FR + i] = UWX_DISP_PSPREL(fr_base);
868 tspill[SBREG_FR + i] = 0;
872 fr_mem_mask = fr_mem_mask >> 1;
875 /* Update the scoreboard. */
877 for (i = 0; i < env->nsbreg; i++) {
878 if (ip_slot >= rhdr->rlen || ip_slot > tspill[i])
879 scoreboard->rstate[i] = newrstate[i];
881 if (priunat_mem_rstate != UWX_DISP_NONE && ip_slot > t_priunat_mem)
882 scoreboard->rstate[SBREG_PRIUNAT] = priunat_mem_rstate;
887 int uwx_count_ones(unsigned int mask)
889 mask = (mask & 0x55555555) + ((mask & 0xaaaaaaaa) >> 1);
890 mask = (mask & 0x33333333) + ((mask & 0xcccccccc) >> 2);
891 mask = (mask & 0x0f0f0f0f) + ((mask & 0xf0f0f0f0) >> 4);
892 mask = (mask & 0x00ff00ff) + ((mask & 0xff00ff00) >> 8);
893 return (mask & 0x0000ffff) + ((mask & 0xffff0000) >> 16);
896 /* uwx_decode_body: Decodes a body region */
900 struct uwx_bstream *bstream,
901 struct uwx_scoreboard *scoreboard,
902 struct uwx_rhdr *rhdr,
915 uint64_t newrstate[NSBREG];
919 /* Initialize an array of register states from the current */
920 /* scoreboard, along with a parallel array of spill times. */
921 /* We use this as a temporary scoreboard, then update the */
922 /* real scoreboard at the end of the procedure. */
923 /* We initialize the spill time to (rhdr.rlen - 1) so that */
924 /* spills without a "when" descriptor will take effect */
925 /* at the end of the prologue region. */
926 /* (Boundary condition: all actions in a zero-length prologue */
927 /* will appear to have happened in the instruction slot */
928 /* immediately preceding the prologue.) */
930 for (i = 0; i < env->nsbreg; i++) {
931 newrstate[i] = scoreboard->rstate[i];
932 tspill[i] = rhdr->rlen - 1;
934 t_sp_restore = rhdr->rlen - 1;
936 /* Read body descriptor records until */
937 /* we hit another region header. */
941 b0 = uwx_get_byte(bstream);
944 /* Return the last byte read to the byte stream, since it's */
945 /* really the first byte of the next region header record. */
947 (void) uwx_unget_byte(bstream, b0);
951 /* Format B1 (label_state) */
953 TRACE_I_DECODE_BODY_1("(B1) label_state", b0)
955 status = uwx_label_scoreboard(env, scoreboard, label);
956 if (status != UWX_OK)
960 /* Format B1 (copy_state) */
961 else if (b0 < 0xc0) {
962 TRACE_I_DECODE_BODY_1("(B1) copy_state", b0)
964 status = uwx_copy_scoreboard(env, scoreboard, label);
965 if (status != UWX_OK)
967 for (i = 0; i < env->nsbreg; i++) {
968 newrstate[i] = scoreboard->rstate[i];
969 tspill[i] = rhdr->rlen;
973 /* Format B2 (epilogue) */
974 else if (b0 < 0xe0) {
976 status = uwx_get_uleb128(bstream, &parm1);
978 return UWX_ERR_BADUDESC;
979 TRACE_I_DECODE_BODY_1L("(B2) epilogue", b0, parm1)
980 rhdr->ecount = ecount + 1;
981 t_sp_restore = rhdr->rlen - (unsigned int) parm1;
984 /* Format B3 (epilogue) */
985 else if (b0 == 0xe0) {
986 status = uwx_get_uleb128(bstream, &parm1);
988 return UWX_ERR_BADUDESC;
989 status = uwx_get_uleb128(bstream, &parm2);
991 return UWX_ERR_BADUDESC;
992 TRACE_I_DECODE_BODY_1LL("(B3) epilogue", b0, parm1, parm2)
993 t_sp_restore = rhdr->rlen - (unsigned int) parm1;
994 rhdr->ecount = (unsigned int) parm2 + 1;
997 /* Format B4 (label_state) */
998 else if (b0 == 0xf0) {
999 status = uwx_get_uleb128(bstream, &parm1);
1001 return UWX_ERR_BADUDESC;
1002 TRACE_I_DECODE_BODY_1L("(B4) label_state", b0, parm1)
1003 label = (int) parm1;
1004 status = uwx_label_scoreboard(env, scoreboard, label);
1005 if (status != UWX_OK)
1009 /* Format B4 (copy_state) */
1010 else if (b0 == 0xf8) {
1011 status = uwx_get_uleb128(bstream, &parm1);
1013 return UWX_ERR_BADUDESC;
1014 TRACE_I_DECODE_BODY_1L("(B4) copy_state", b0, parm1)
1015 label = (int) parm1;
1016 status = uwx_copy_scoreboard(env, scoreboard, label);
1017 if (status != UWX_OK)
1019 for (i = 0; i < env->nsbreg; i++) {
1020 newrstate[i] = scoreboard->rstate[i];
1021 tspill[i] = rhdr->rlen;
1026 else if (b0 == 0xf9) {
1027 TRACE_I_DECODE_BODY_1("(X1)", b0)
1028 b1 = uwx_get_byte(bstream);
1030 return UWX_ERR_BADUDESC;
1031 /* Don't support X-format descriptors yet */
1032 return UWX_ERR_CANTUNWIND;
1036 else if (b0 == 0xfa) {
1037 TRACE_I_DECODE_BODY_1("(X2)", b0)
1038 b1 = uwx_get_byte(bstream);
1040 return UWX_ERR_BADUDESC;
1041 b2 = 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 == 0xfb) {
1050 TRACE_I_DECODE_BODY_1("(X3)", 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 == 0xfc) {
1063 TRACE_I_DECODE_BODY_1("(X4)", b0)
1064 b1 = uwx_get_byte(bstream);
1066 return UWX_ERR_BADUDESC;
1067 b2 = uwx_get_byte(bstream);
1069 return UWX_ERR_BADUDESC;
1070 b3 = uwx_get_byte(bstream);
1072 return UWX_ERR_BADUDESC;
1073 /* Don't support X-format descriptors yet */
1074 return UWX_ERR_CANTUNWIND;
1077 /* Invalid descriptor record */
1079 TRACE_I_DECODE_BODY_1("(?)", b0)
1080 return UWX_ERR_BADUDESC;
1084 /* Update the scoreboard. */
1086 for (i = 0; i < env->nsbreg; i++) {
1087 if (ip_slot > tspill[i])
1088 scoreboard->rstate[i] = newrstate[i];
1091 /* If we've passed the point in the epilogue where sp */
1092 /* is restored, update the scoreboard entry for PSP */
1093 /* and reset any entries for registers saved in memory. */
1095 if (ip_slot > t_sp_restore) {
1096 scoreboard->rstate[SBREG_PSP] = UWX_DISP_SPPLUS(0);
1097 for (i = 0; i < env->nsbreg; i++) {
1098 if (UWX_GET_DISP_CODE(scoreboard->rstate[i]) == UWX_DISP_SPREL(0) ||
1099 UWX_GET_DISP_CODE(scoreboard->rstate[i]) == UWX_DISP_PSPREL(0))
1100 scoreboard->rstate[i] = UWX_DISP_NONE;