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