1115013Smarcel/*
2160157SmarcelCopyright (c) 2003-2006 Hewlett-Packard Development Company, L.P.
3121642SmarcelPermission is hereby granted, free of charge, to any person
4121642Smarcelobtaining a copy of this software and associated documentation
5121642Smarcelfiles (the "Software"), to deal in the Software without
6121642Smarcelrestriction, including without limitation the rights to use,
7121642Smarcelcopy, modify, merge, publish, distribute, sublicense, and/or sell
8121642Smarcelcopies of the Software, and to permit persons to whom the
9121642SmarcelSoftware is furnished to do so, subject to the following
10121642Smarcelconditions:
11115013Smarcel
12121642SmarcelThe above copyright notice and this permission notice shall be
13121642Smarcelincluded in all copies or substantial portions of the Software.
14121642Smarcel
15121642SmarcelTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16121642SmarcelEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17121642SmarcelOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18121642SmarcelNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19121642SmarcelHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20121642SmarcelWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21121642SmarcelFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22121642SmarcelOTHER DEALINGS IN THE SOFTWARE.
23121642Smarcel*/
24121642Smarcel
25115013Smarcel#include "uwx_env.h"
26160157Smarcel#include "uwx_utable.h"
27115013Smarcel#include "uwx_uinfo.h"
28115013Smarcel#include "uwx_scoreboard.h"
29115013Smarcel#include "uwx_trace.h"
30115013Smarcel
31160163Smarcel#ifdef UWX_TRACE_ENABLE
32160163Smarcel
33115013Smarcelvoid uwx_trace_init(struct uwx_env *env)
34115013Smarcel{
35115013Smarcel    char *tstr;
36115013Smarcel
37115013Smarcel    tstr = getenv("UWX_TRACE");
38115013Smarcel    if (tstr != NULL) {
39115013Smarcel	while (*tstr != '\0') {
40160163Smarcel	    switch (*tstr) {
41115013Smarcel		case 'i': env->trace |= UWX_TRACE_UINFO; break;
42115013Smarcel		case 't': env->trace |= UWX_TRACE_UTABLE; break;
43115013Smarcel		case 'b': env->trace |= UWX_TRACE_SB; break;
44115013Smarcel		case 'r': env->trace |= UWX_TRACE_RSTATE; break;
45115013Smarcel		case 's': env->trace |= UWX_TRACE_STEP; break;
46115013Smarcel		case 'c': env->trace |= UWX_TRACE_CONTEXT; break;
47115013Smarcel		case 'C': env->trace |= UWX_TRACE_COPYIN; break;
48115013Smarcel		case 'L': env->trace |= UWX_TRACE_LOOKUPIP; break;
49115013Smarcel		case '?':
50160163Smarcel#ifdef _KERNEL
51160163Smarcel		    fprintf(stderr, "UWX_TRACE flag `%c' unknown.\n", *tstr);
52160163Smarcel#else
53115013Smarcel		    fprintf(stderr, "UWX_TRACE flags:\n");
54115013Smarcel		    fprintf(stderr, "  i: unwind info\n");
55115013Smarcel		    fprintf(stderr, "  t: unwind table searching\n");
56115013Smarcel		    fprintf(stderr, "  b: scoreboard management\n");
57115013Smarcel		    fprintf(stderr, "  r: register state vector\n");
58115013Smarcel		    fprintf(stderr, "  s: step\n");
59115013Smarcel		    fprintf(stderr, "  c: context\n");
60115013Smarcel		    fprintf(stderr, "  C: copyin callback\n");
61115013Smarcel		    fprintf(stderr, "  L: lookup ip callback\n");
62115013Smarcel		    exit(1);
63160163Smarcel#endif
64115013Smarcel	    }
65160163Smarcel	    tstr++;
66115013Smarcel	}
67115013Smarcel    }
68115013Smarcel}
69115013Smarcel
70115013Smarcelchar *uwx_sb_rnames[] = {
71115013Smarcel    "RP", "PSP", "PFS",
72115013Smarcel    "PREDS", "UNAT", "PRIUNAT", "RNAT", "LC", "FPSR",
73115013Smarcel    "GR4", "GR5", "GR6", "GR7",
74115013Smarcel    "BR1", "BR2", "BR3", "BR4", "BR5",
75115013Smarcel    "FR2", "FR3", "FR4", "FR5",
76115013Smarcel    "FR16", "FR17", "FR18", "FR19",
77115013Smarcel    "FR20", "FR21", "FR22", "FR23",
78115013Smarcel    "FR24", "FR25", "FR26", "FR27",
79115013Smarcel    "FR28", "FR29", "FR30", "FR31",
80115013Smarcel};
81115013Smarcel
82115013Smarcelvoid uwx_dump_rstate(int regid, uint64_t rstate)
83115013Smarcel{
84115013Smarcel    int reg;
85115013Smarcel
86115013Smarcel    if (rstate == UWX_DISP_NONE)
87115013Smarcel	return;
88160157Smarcel    fprintf(stderr, "    %-7s", uwx_sb_rnames[regid]);
89115013Smarcel    switch (UWX_GET_DISP_CODE(rstate)) {
90115013Smarcel	case UWX_DISP_NONE:
91160157Smarcel	    fprintf(stderr, "    unchanged\n");
92115013Smarcel	    break;
93115013Smarcel	case UWX_DISP_SPPLUS(0):
94160157Smarcel	    fprintf(stderr, "    SP + %d\n", (int)rstate & ~0x07);
95115013Smarcel	    break;
96115013Smarcel	case UWX_DISP_SPREL(0):
97160157Smarcel	    fprintf(stderr, "    [SP + %d]\n", (int)rstate & ~0x07);
98115013Smarcel	    break;
99115013Smarcel	case UWX_DISP_PSPREL(0):
100160157Smarcel	    fprintf(stderr, "    [PSP + 16 - %d]\n", (int)rstate & ~0x07);
101115013Smarcel	    break;
102115013Smarcel	case UWX_DISP_REG(0):
103115013Smarcel	    reg = UWX_GET_DISP_REGID(rstate);
104120925Smarcel	    if (reg == UWX_REG_AR_PFS)
105160157Smarcel		fprintf(stderr, "    AR.PFS\n");
106120925Smarcel	    else if (reg == UWX_REG_AR_UNAT)
107160157Smarcel		fprintf(stderr, "    AR.UNAT\n");
108115013Smarcel	    else if (reg >= UWX_REG_GR(0) && reg < UWX_REG_GR(128))
109160157Smarcel		fprintf(stderr, "    GR%d\n", reg - UWX_REG_GR(0));
110115013Smarcel	    else if (reg >= UWX_REG_FR(0) && reg < UWX_REG_FR(128))
111160157Smarcel		fprintf(stderr, "    FR%d\n", reg - UWX_REG_FR(0));
112115013Smarcel	    else if (reg >= UWX_REG_BR(0) && reg < UWX_REG_BR(8))
113160157Smarcel		fprintf(stderr, "    BR%d\n", reg - UWX_REG_BR(0));
114115013Smarcel	    else
115160157Smarcel		fprintf(stderr, "    <reg %d>\n", reg);
116115013Smarcel	    break;
117115013Smarcel	default:
118160163Smarcel	    fprintf(stderr, "    <%08lx>\n", (long)rstate);
119115013Smarcel	    break;
120115013Smarcel    }
121115013Smarcel}
122115013Smarcel
123115013Smarcelvoid uwx_dump_scoreboard(
124115013Smarcel    struct uwx_scoreboard *scoreboard,
125115013Smarcel    int nsbreg,
126115013Smarcel    struct uwx_rhdr *rhdr,
127115013Smarcel    int cur_slot,
128115013Smarcel    int ip_slot)
129115013Smarcel{
130115013Smarcel    int i;
131115013Smarcel
132115013Smarcel    if (rhdr->is_prologue)
133160157Smarcel	fprintf(stderr, "  Prologue region (start = %d, length = %d)\n",
134115013Smarcel		    (int)cur_slot, (int)rhdr->rlen);
135115013Smarcel    else
136160157Smarcel	fprintf(stderr, "  Body region (start = %d, length = %d, ecount = %d)\n",
137115013Smarcel		    cur_slot, (int)rhdr->rlen, rhdr->ecount);
138115013Smarcel    if (ip_slot < rhdr->rlen)
139160157Smarcel	fprintf(stderr, "    IP is in this region (offset = %d)\n", ip_slot);
140115013Smarcel    for (i = 0; i < nsbreg; i++)
141115013Smarcel	uwx_dump_rstate(i, scoreboard->rstate[i]);
142115013Smarcel}
143115013Smarcel
144160157Smarcelvoid uwx_dump_uinfo_block(
145160157Smarcel	struct uwx_utable_entry *uentry,
146160157Smarcel	unsigned int ulen)
147160157Smarcel{
148160157Smarcel    int i;
149160157Smarcel    uint32_t *uinfo = (uint32_t *)(intptr_t)uentry->unwind_info;
150160157Smarcel
151160157Smarcel    ulen += DWORDSZ;		/* Include unwind info header */
152160157Smarcel    if (uentry->unwind_flags & UNWIND_TBL_32BIT) /* and personality routine */
153160157Smarcel	ulen += WORDSZ;
154160157Smarcel    else
155160157Smarcel	ulen += DWORDSZ;
156160157Smarcel    while (ulen >= WORDSZ) {
157160157Smarcel	fprintf(stderr, "  %08lx: ", (unsigned long)uinfo);
158160157Smarcel	for (i = 0; i < 4 * WORDSZ && ulen >= WORDSZ; i += WORDSZ) {
159160163Smarcel	    fprintf(stderr, " %04x", *uinfo++);
160160157Smarcel	    ulen -= WORDSZ;
161160157Smarcel	}
162160157Smarcel	fprintf(stderr, "\n");
163160157Smarcel    }
164160157Smarcel}
165160163Smarcel
166160163Smarcel#endif /* UWX_TRACE_ENABLE */
167