1/*
2Copyright (c) 2003-2006 Hewlett-Packard Development Company, L.P.
3Permission is hereby granted, free of charge, to any person
4obtaining a copy of this software and associated documentation
5files (the "Software"), to deal in the Software without
6restriction, including without limitation the rights to use,
7copy, modify, merge, publish, distribute, sublicense, and/or sell
8copies of the Software, and to permit persons to whom the
9Software is furnished to do so, subject to the following
10conditions:
11
12The above copyright notice and this permission notice shall be
13included in all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22OTHER DEALINGS IN THE SOFTWARE.
23*/
24
25#include "uwx_env.h"
26#include "uwx_uinfo.h"
27#include "uwx_utable.h"
28#include "uwx_scoreboard.h"
29#include "uwx_bstream.h"
30#include "uwx_trace.h"
31#include "uwx_swap.h"
32
33int 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
65int 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
77int 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
213int 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
294int 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
900int 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
911int 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
1120