]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - 6/sys/contrib/ia64/libuwx/src/uwx_uinfo.c
Clone Kip's Xen on stable/6 tree so that I can work on improving FreeBSD/amd64
[FreeBSD/FreeBSD.git] / 6 / sys / contrib / ia64 / libuwx / src / uwx_uinfo.c
1 /*
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
10 conditions:
11
12 The above copyright notice and this permission notice shall be
13 included in all copies or substantial portions of the Software.
14
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.
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
33 int 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 *)(dest) = *(uint32_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 *)(dest) = *(uint64_t *)(src), DWORDSZ) )
61
62
63 /* uwx_default_rstate: Returns the default register state for a leaf routine */
64
65 int 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
77 int 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     TRACE_R_UIB(uentry, ulen)
125
126     /* Create an initial scoreboard for tracking the unwind state. */
127
128     scoreboard = uwx_init_scoreboards(env);
129
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. */
134
135     cur_slot = 0;
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);
140
141     /* Loop over the regions in the unwind info block. */
142
143     for (;;) {
144
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 */
149         /* header record. */
150
151         status = uwx_decode_rhdr(env, &bstream, &rhdr);
152         if (status != UWX_OK)
153             return status;
154
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. */
158
159         if (rhdr.is_prologue) {
160             scoreboard = uwx_new_scoreboard(env, scoreboard);
161             if (scoreboard == 0)
162                 return UWX_ERR_NOMEM;
163             status = uwx_decode_prologue(env, &bstream,
164                                             scoreboard, &rhdr, ip_slot);
165         }
166
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. */
171
172         else {
173             status = uwx_decode_body(env, &bstream, scoreboard, &rhdr, ip_slot);
174         }
175
176         if (status != UWX_OK)
177             return status;
178
179         TRACE_R_DUMP_SB(scoreboard, rhdr, cur_slot, ip_slot)
180
181         /* If the target ip slot is within this region, we're done. */
182         /* Return the scoreboard's register state array. */
183
184         if (ip_slot < rhdr.rlen) {
185             *rstatep = scoreboard->rstate;
186             return UWX_OK;
187         }
188
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. */
192
193         cur_slot += rhdr.rlen;
194         ip_slot -= rhdr.rlen;
195         if (rhdr.ecount > 0) {
196             scoreboard = uwx_pop_scoreboards(env, scoreboard, rhdr.ecount);
197             if (scoreboard == 0)
198                 return UWX_ERR_PROLOG_UF;
199         }
200     }
201     /*NOTREACHED*/
202 }
203
204
205 /* uwx_decode_rhdr: Decodes a region header record */
206
207 int uwx_decode_rhdr(
208     struct uwx_env *env,
209     struct uwx_bstream *bstream,
210     struct uwx_rhdr *rhdr)
211 {
212     int b0;
213     int b1;
214     uint64_t val;
215     int status;
216
217     /* Get the first byte of the next descriptor record. */
218     b0 = uwx_get_byte(bstream);
219     if (b0 < 0)
220         return UWX_ERR_NOUDESC;
221
222     /* Initialize region header record. */
223
224     rhdr->is_prologue = 0;
225     rhdr->rlen = 0;
226     rhdr->mask = 0;
227     rhdr->grsave = 0;
228     rhdr->ecount = 0;
229
230     /* Format R1 */
231
232     if (b0 < 0x40) {
233         if ((b0 & 0x20) == 0) {
234             TRACE_I_DECODE_RHDR_1("(R1) prologue", b0)
235             rhdr->is_prologue = 1;
236         }
237         else {
238             TRACE_I_DECODE_RHDR_1("(R1) body", b0)
239         }
240         rhdr->rlen = b0 & 0x1f;
241     }
242
243     /* Format R2 */
244
245     else if (b0 < 0x60) {
246         b1 = uwx_get_byte(bstream);
247         if (b1 < 0)
248             return UWX_ERR_BADUDESC;
249         status = uwx_get_uleb128(bstream, &val);
250         if (status != 0)
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;
257     }
258
259     /* Format R3 */
260
261     else if (b0 < 0x80) {
262         status = uwx_get_uleb128(bstream, &val);
263         if (status != 0)
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;
268         }
269         else {
270             TRACE_I_DECODE_RHDR_1L("(R3) body", b0, val)
271         }
272         rhdr->rlen = (unsigned int) val;
273     }
274
275     /* Otherwise, not a region header record. */
276
277     else {
278         TRACE_I_DECODE_RHDR_1("(?)", b0)
279         return UWX_ERR_BADUDESC;
280     }
281
282     return UWX_OK;
283 }
284
285
286 /* uwx_decode_prologue: Decodes a prologue region */
287
288 int uwx_decode_prologue(
289     struct uwx_env *env,
290     struct uwx_bstream *bstream,
291     struct uwx_scoreboard *scoreboard,
292     struct uwx_rhdr *rhdr,
293     int ip_slot)
294 {
295     int status;
296     int reg;
297     int mask;
298     int b0;
299     int b1;
300     int b2;
301     int b3;
302     int r;
303     int t;
304     int i;
305     uint64_t parm1;
306     uint64_t parm2;
307     uint64_t newrstate[NSBREG];
308     int tspill[NSBREG];
309     int priunat_mem_rstate;
310     int t_priunat_mem;
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;
316     int ngr;
317     int nbr;
318     int nfr;
319     unsigned int spill_base;
320     unsigned int gr_base;
321     unsigned int br_base;
322     unsigned int fr_base;
323
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.) */
334
335     for (i = 0; i < env->nsbreg; i++) {
336         newrstate[i] = scoreboard->rstate[i];
337         tspill[i] = rhdr->rlen - 1;
338     }
339     priunat_mem_rstate = UWX_DISP_NONE;
340     t_priunat_mem = rhdr->rlen - 1;
341
342     fr_mem_mask = 0;
343     gr_mem_mask = 0;
344     br_mem_mask = 0;
345     gr_gr_mask = 0;
346     br_gr_mask = 0;
347     nfr = 0;
348     ngr = 0;
349     nbr = 0;
350     spill_base = 0;
351
352     /* If prologue_gr header record supplied mask and grsave, */
353     /* record these in the scoreboard. */
354
355     reg = rhdr->grsave;
356     mask = rhdr->mask;
357     if (mask & 0x8) {
358         newrstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_GR(reg));
359         reg++;
360     }
361     if (mask & 0x4) {
362         newrstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_GR(reg));
363         reg++;
364     }
365     if (mask & 0x2) {
366         newrstate[SBREG_PSP] = UWX_DISP_REG(UWX_REG_GR(reg));
367         reg++;
368     }
369     if (mask & 0x1) {
370         newrstate[SBREG_PREDS] = UWX_DISP_REG(UWX_REG_GR(reg));
371         reg++;
372     }
373
374     /* Read prologue descriptor records until */
375     /* we hit another region header. */
376
377     for (;;) {
378
379         b0 = uwx_get_byte(bstream);
380
381         if (b0 < 0x80) {
382             /* Return the last byte read to the byte stream, since it's */
383             /* really the first byte of the next region header record. */
384             if (b0 >= 0)
385                 (void) uwx_unget_byte(bstream, b0);
386             break;
387         }
388
389         switch ((b0 & 0x70) >> 4) {
390
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;
396                 break;
397
398             case 2:                     /* 1010 xxxx */
399                 /* Format P2 (br_gr) */
400                 b1 = uwx_get_byte(bstream);
401                 if (b1 < 0)
402                     return UWX_ERR_BADUDESC;
403                 TRACE_I_DECODE_PROLOGUE_2("(P2) br_gr", b0, b1)
404                 mask = ((b0 & 0x0f) << 1) | (b1 >> 7);
405                 reg = b1 & 0x7f;
406                 br_gr_mask = mask;
407                 for (i = 0; i < NSB_BR && mask != 0; i++) {
408                     if (mask & 0x01) {
409                         newrstate[SBREG_BR + i] = UWX_DISP_REG(UWX_REG_GR(reg));
410                         reg++;
411                     }
412                     mask = mask >> 1;
413                 }
414                 break;
415
416             case 3:                     /* 1011 xxxx */
417                 /* Format P3 */
418                 if (b0 < 0xb8) {
419                     b1 = uwx_get_byte(bstream);
420                     if (b1 < 0)
421                         return UWX_ERR_BADUDESC;
422                     r = ((b0 & 0x7) << 1) | (b1 >> 7);
423                     reg = b1 & 0x7f;
424                     switch (r) {
425                         case 0:         /* psp_gr */
426                             TRACE_I_DECODE_PROLOGUE_2("(P3) psp_gr", b0, b1)
427                             newrstate[SBREG_PSP] = UWX_DISP_REG(UWX_REG_GR(reg));
428                             break;
429                         case 1:         /* rp_gr */
430                             TRACE_I_DECODE_PROLOGUE_2("(P3) rp_gr", b0, b1)
431                             newrstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_GR(reg));
432                             break;
433                         case 2:         /* pfs_gr */
434                             TRACE_I_DECODE_PROLOGUE_2("(P3) pfs_gr", b0, b1)
435                             newrstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_GR(reg));
436                             break;
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));
441                             break;
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));
446                             break;
447                         case 5:         /* lc_gr */
448                             TRACE_I_DECODE_PROLOGUE_2("(P3) lc_gr", b0, b1)
449                             newrstate[SBREG_LC] =
450                                         UWX_DISP_REG(UWX_REG_GR(reg));
451                             break;
452                         case 6:         /* rp_br */
453                             TRACE_I_DECODE_PROLOGUE_2("(P3) rp_br", b0, b1)
454                             scoreboard->rstate[SBREG_RP] =
455                                         UWX_DISP_REG(UWX_REG_BR(reg));
456                             break;
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));
461                             break;
462                         case 8:         /* bsp_gr */
463                             TRACE_I_DECODE_PROLOGUE_2("(P3) bsp_gr", b0, b1)
464                             /* Don't track BSP yet */
465                             return UWX_ERR_CANTUNWIND;
466                             break;
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;
471                             break;
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));
476                             break;
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));
481                             break;
482                         default:
483                             TRACE_I_DECODE_PROLOGUE_2("(P3) ??", b0, b1)
484                             return UWX_ERR_BADUDESC;
485                     }
486                 }
487
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. */
502                     t = 0;
503                     while (t < rhdr->rlen) {
504                         b1 = uwx_get_byte(bstream);
505                         if (b1 < 0)
506                             return UWX_ERR_BADUDESC;
507                         for (i = 0; i < 4 && (t + i) < ip_slot; i++) {
508                             switch (b1 & 0xc0) {
509                                 case 0x00: break;
510                                 case 0x40: nfr++; break;
511                                 case 0x80: ngr++; break;
512                                 case 0xc0: nbr++; break;
513                             }
514                             b1 = b1 << 2;
515                         }
516                         t += 4;
517                     }
518                 }
519
520                 /* Format P5 (frgr_mem) */
521                 else if (b0 == 0xb9) {
522                     b1 = uwx_get_byte(bstream);
523                     if (b1 < 0)
524                         return UWX_ERR_BADUDESC;
525                     b2 = uwx_get_byte(bstream);
526                     if (b2 < 0)
527                         return UWX_ERR_BADUDESC;
528                     b3 = uwx_get_byte(bstream);
529                     if (b3 < 0)
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;
534                 }
535
536                 /* Invalid descriptor record */
537                 else {
538                     TRACE_I_DECODE_PROLOGUE_1("(?)", b0)
539                     return UWX_ERR_BADUDESC;
540                 }
541
542                 break;
543
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;
548                 break;
549
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;
554                 break;
555
556             case 6:                     /* 1110 xxxx */
557                 /* Format P7 */
558                 r = b0 & 0xf;
559                 status = uwx_get_uleb128(bstream, &parm1);
560                 if (status != 0)
561                     return UWX_ERR_BADUDESC;
562                 switch (r) {
563                     case 0:             /* mem_stack_f */
564                         status = uwx_get_uleb128(bstream, &parm2);
565                         if (status != 0)
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;
570                         break;
571                     case 1:             /* mem_stack_v */
572                         TRACE_I_DECODE_PROLOGUE_1L("(P7) mem_stack_v", b0, parm1)
573                         tspill[SBREG_PSP] = (int) parm1;
574                         break;
575                     case 2:             /* spill_base */
576                         TRACE_I_DECODE_PROLOGUE_1L("(P7) spill_base", b0, parm1)
577                         spill_base = 4 * (unsigned int) parm1;
578                         break;
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);
582                         break;
583                     case 4:             /* rp_when */
584                         TRACE_I_DECODE_PROLOGUE_1L("(P7) rp_when", b0, parm1)
585                         tspill[SBREG_RP] = (int) parm1;
586                         break;
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);
590                         break;
591                     case 6:             /* pfs_when */
592                         TRACE_I_DECODE_PROLOGUE_1L("(P7) pfs_when", b0, parm1)
593                         tspill[SBREG_PFS] = (int) parm1;
594                         break;
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);
598                         break;
599                     case 8:             /* preds_when */
600                         TRACE_I_DECODE_PROLOGUE_1L("(P7) preds_when", b0, parm1)
601                         tspill[SBREG_PREDS] = (int) parm1;
602                         break;
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);
606                         break;
607                     case 10:    /* lc_when */
608                         TRACE_I_DECODE_PROLOGUE_1L("(P7) lc_when", b0, parm1)
609                         tspill[SBREG_LC] = (int) parm1;
610                         break;
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);
614                         break;
615                     case 12:    /* unat_when */
616                         TRACE_I_DECODE_PROLOGUE_1L("(P7) unat_when", b0, parm1)
617                         tspill[SBREG_UNAT] = (int) parm1;
618                         break;
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);
622                         break;
623                     case 14:    /* fpsr_when */
624                         TRACE_I_DECODE_PROLOGUE_1L("(P7) fpsr_when", b0, parm1)
625                         tspill[SBREG_FPSR] = (int) parm1;
626                         break;
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);
630                         break;
631                 }
632                 break;
633
634             case 7:                     /* 1111 xxxx */
635                 /* Format P8 */
636                 if (b0 == 0xf0) {
637                     b1 = uwx_get_byte(bstream);
638                     if (b1 < 0)
639                         return UWX_ERR_BADUDESC;
640                     status = uwx_get_uleb128(bstream, &parm1);
641                     if (status != 0)
642                         return UWX_ERR_BADUDESC;
643                     switch (b1) {
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);
647                             break;
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);
651                             break;
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);
655                             break;
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);
659                             break;
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);
663                             break;
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);
667                             break;
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;
672                             break;
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;
677                             break;
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;
682                             break;
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;
687                             break;
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;
692                             break;
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;
697                             break;
698                         case 13:        /* rnat_when */
699                             TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_when", b0, b1, parm1)
700                             tspill[SBREG_RNAT] = (int) parm1;
701                             break;
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);
705                             break;
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);
709                             break;
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;
713                             break;
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);
717                             break;
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);
721                             break;
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;
725                             break;
726                         default:
727                             TRACE_I_DECODE_PROLOGUE_2L("(P8) ??", b0, b1, parm1)
728                             return UWX_ERR_BADUDESC;
729                     }
730                 }
731
732                 /* Format P9 (gr_gr) */
733                 else if (b0 == 0xf1) {
734                     b1 = uwx_get_byte(bstream);
735                     if (b1 < 0)
736                         return UWX_ERR_BADUDESC;
737                     b2 = uwx_get_byte(bstream);
738                     if (b2 < 0)
739                         return UWX_ERR_BADUDESC;
740                     TRACE_I_DECODE_PROLOGUE_3("(P9) gr_gr", b0, b1, b2)
741                     mask = b1 & 0x0f;
742                     reg = b2 & 0x7f;
743                     gr_gr_mask = mask;
744                     for (i = 0; i < NSB_GR && mask != 0; i++) {
745                         if (mask & 0x01) {
746                             newrstate[SBREG_GR + i] =
747                                         UWX_DISP_REG(UWX_REG_GR(reg));
748                             reg++;
749                         }
750                         mask = mask >> 1;
751                     }
752                 }
753
754                 /* Format X1 */
755                 else if (b0 == 0xf9) {
756                     TRACE_I_DECODE_PROLOGUE_1("(X1)", b0)
757                     b1 = uwx_get_byte(bstream);
758                     if (b1 < 0)
759                         return UWX_ERR_BADUDESC;
760                     /* Don't support X-format descriptors yet */
761                     return UWX_ERR_CANTUNWIND;
762                 }
763
764                 /* Format X2 */
765                 else if (b0 == 0xfa) {
766                     TRACE_I_DECODE_PROLOGUE_1("(X2)", b0)
767                     b1 = uwx_get_byte(bstream);
768                     if (b1 < 0)
769                         return UWX_ERR_BADUDESC;
770                     b2 = uwx_get_byte(bstream);
771                     if (b2 < 0)
772                         return UWX_ERR_BADUDESC;
773                     /* Don't support X-format descriptors yet */
774                     return UWX_ERR_CANTUNWIND;
775                 }
776
777                 /* Format X3 */
778                 else if (b0 == 0xfb) {
779                     TRACE_I_DECODE_PROLOGUE_1("(X3)", 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 X4 */
791                 else if (b0 == 0xfc) {
792                     TRACE_I_DECODE_PROLOGUE_1("(X4)", 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                     b3 = uwx_get_byte(bstream);
800                     if (b3 < 0)
801                         return UWX_ERR_BADUDESC;
802                     /* Don't support X-format descriptors yet */
803                     return UWX_ERR_CANTUNWIND;
804                 }
805
806                 /* Format P10 */
807                 else if (b0 == 0xff) {
808                     b1 = uwx_get_byte(bstream);
809                     if (b1 < 0)
810                         return UWX_ERR_BADUDESC;
811                     b2 = uwx_get_byte(bstream);
812                     if (b2 < 0)
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;
817                 }
818
819                 /* Invalid descriptor record */
820                 else {
821                     TRACE_I_DECODE_PROLOGUE_1("(?)", b0)
822                     return UWX_ERR_BADUDESC;
823                 }
824                 break;
825         }
826     }
827
828     /* Process the masks of spilled GRs, FRs, and BRs to */
829     /* determine when and where each register was saved. */
830
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;
841             gr_base -= 8;
842             ngr--;
843         }
844         else if (gr_gr_mask & 1) {
845             tspill[SBREG_GR + i] = 0;
846             ngr--;
847         }
848         gr_gr_mask = gr_gr_mask >> 1;
849         gr_mem_mask = gr_mem_mask >> 1;
850     }
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;
855             br_base -= 8;
856             nbr--;
857         }
858         else if (br_gr_mask & 1) {
859             tspill[SBREG_BR + i] = 0;
860             nbr--;
861         }
862         br_gr_mask = br_gr_mask >> 1;
863         br_mem_mask = br_mem_mask >> 1;
864     }
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;
869             fr_base -= 16;
870             nfr--;
871         }
872         fr_mem_mask = fr_mem_mask >> 1;
873     }
874
875     /* Update the scoreboard. */
876
877     for (i = 0; i < env->nsbreg; i++) {
878         if (ip_slot >= rhdr->rlen || ip_slot > tspill[i])
879             scoreboard->rstate[i] = newrstate[i];
880     }
881     if (priunat_mem_rstate != UWX_DISP_NONE && ip_slot > t_priunat_mem)
882         scoreboard->rstate[SBREG_PRIUNAT] = priunat_mem_rstate;
883
884     return UWX_OK;
885 }
886
887 int uwx_count_ones(unsigned int mask)
888 {
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);
894 }
895
896 /* uwx_decode_body: Decodes a body region */
897
898 int uwx_decode_body(
899     struct uwx_env *env,
900     struct uwx_bstream *bstream,
901     struct uwx_scoreboard *scoreboard,
902     struct uwx_rhdr *rhdr,
903     int ip_slot)
904 {
905     int status;
906     int b0;
907     int b1;
908     int b2;
909     int b3;
910     int label;
911     int ecount;
912     int i;
913     uint64_t parm1;
914     uint64_t parm2;
915     uint64_t newrstate[NSBREG];
916     int tspill[NSBREG];
917     int t_sp_restore;
918
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.) */
929
930     for (i = 0; i < env->nsbreg; i++) {
931         newrstate[i] = scoreboard->rstate[i];
932         tspill[i] = rhdr->rlen - 1;
933     }
934     t_sp_restore = rhdr->rlen - 1;
935
936     /* Read body descriptor records until */
937     /* we hit another region header. */
938
939     for (;;) {
940
941         b0 = uwx_get_byte(bstream);
942
943         if (b0 < 0x80) {
944             /* Return the last byte read to the byte stream, since it's */
945             /* really the first byte of the next region header record. */
946             if (b0 >= 0)
947                 (void) uwx_unget_byte(bstream, b0);
948             break;
949         }
950
951         /* Format B1 (label_state) */
952         if (b0 < 0xa0) {
953             TRACE_I_DECODE_BODY_1("(B1) label_state", b0)
954             label = b0 & 0x1f;
955             status = uwx_label_scoreboard(env, scoreboard, label);
956             if (status != UWX_OK)
957                 return (status);
958         }
959
960         /* Format B1 (copy_state)  */
961         else if (b0 < 0xc0) {
962             TRACE_I_DECODE_BODY_1("(B1) copy_state", b0)
963             label = b0 & 0x1f;
964             status = uwx_copy_scoreboard(env, scoreboard, label);
965             if (status != UWX_OK)
966                 return (status);
967             for (i = 0; i < env->nsbreg; i++) {
968                 newrstate[i] = scoreboard->rstate[i];
969                 tspill[i] = rhdr->rlen;
970             }
971         }
972
973         /* Format B2 (epilogue) */
974         else if (b0 < 0xe0) {
975             ecount = b0 & 0x1f;
976             status = uwx_get_uleb128(bstream, &parm1);
977             if (status != 0)
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;
982         }
983
984         /* Format B3 (epilogue) */
985         else if (b0 == 0xe0) {
986             status = uwx_get_uleb128(bstream, &parm1);
987             if (status != 0)
988                 return UWX_ERR_BADUDESC;
989             status = uwx_get_uleb128(bstream, &parm2);
990             if (status != 0)
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;
995         }
996
997         /* Format B4 (label_state) */
998         else if (b0 == 0xf0) {
999             status = uwx_get_uleb128(bstream, &parm1);
1000             if (status != 0)
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)
1006                 return (status);
1007         }
1008
1009         /* Format B4 (copy_state) */
1010         else if (b0 == 0xf8) {
1011             status = uwx_get_uleb128(bstream, &parm1);
1012             if (status != 0)
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)
1018                 return (status);
1019             for (i = 0; i < env->nsbreg; i++) {
1020                 newrstate[i] = scoreboard->rstate[i];
1021                 tspill[i] = rhdr->rlen;
1022             }
1023         }
1024
1025         /* Format X1 */
1026         else if (b0 == 0xf9) {
1027             TRACE_I_DECODE_BODY_1("(X1)", b0)
1028             b1 = uwx_get_byte(bstream);
1029             if (b1 < 0)
1030                 return UWX_ERR_BADUDESC;
1031             /* Don't support X-format descriptors yet */
1032             return UWX_ERR_CANTUNWIND;
1033         }
1034
1035         /* Format X2 */
1036         else if (b0 == 0xfa) {
1037             TRACE_I_DECODE_BODY_1("(X2)", b0)
1038             b1 = uwx_get_byte(bstream);
1039             if (b1 < 0)
1040                 return UWX_ERR_BADUDESC;
1041             b2 = uwx_get_byte(bstream);
1042             if (b2 < 0)
1043                 return UWX_ERR_BADUDESC;
1044             /* Don't support X-format descriptors yet */
1045             return UWX_ERR_CANTUNWIND;
1046         }
1047
1048         /* Format X3 */
1049         else if (b0 == 0xfb) {
1050             TRACE_I_DECODE_BODY_1("(X3)", 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 X4 */
1062         else if (b0 == 0xfc) {
1063             TRACE_I_DECODE_BODY_1("(X4)", 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             b3 = uwx_get_byte(bstream);
1071             if (b3 < 0)
1072                 return UWX_ERR_BADUDESC;
1073             /* Don't support X-format descriptors yet */
1074             return UWX_ERR_CANTUNWIND;
1075         }
1076
1077         /* Invalid descriptor record */
1078         else {
1079             TRACE_I_DECODE_BODY_1("(?)", b0)
1080             return UWX_ERR_BADUDESC;
1081         }
1082     }
1083
1084     /* Update the scoreboard. */
1085
1086     for (i = 0; i < env->nsbreg; i++) {
1087         if (ip_slot > tspill[i])
1088             scoreboard->rstate[i] = newrstate[i];
1089     }
1090
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. */
1094
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;
1101         }
1102     }
1103
1104     return UWX_OK;
1105 }
1106