1 /* $NetBSD: disasm_format.c,v 1.5 2016/08/05 16:45:50 scole Exp $ */
2
3 /*-
4 * Copyright (c) 2000-2006 Marcel Moolenaar
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "opt_ddb.h"
30
31 #include <sys/cdefs.h>
32 /* __FBSDID("$FreeBSD: releng/10.1/sys/ia64/disasm/disasm_format.c 159916 2006-06-24 19:21:11Z marcel $"); */
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36
37 #ifdef DDB
38
39 #include <ia64/disasm/disasm_int.h>
40 #include <ia64/disasm/disasm.h>
41
42 /*
43 * Mnemonics (keep in sync with enum asm_op).
44 */
45 static const char *asm_mnemonics[] = {
46 "",
47 "add", "addl", "addp4", "adds", "alloc", "and", "andcm",
48 "br", "break", "brl", "brp", "bsw",
49 "chk", "clrrrb", "cmp", "cmp4", "cmp8xchg16", "cmpxchg1", "cmpxchg2",
50 "cmpxchg4", "cmpxchg8", "cover", "czx1", "czx2",
51 "dep",
52 "epc", "extr",
53 "famax", "famin", "fand", "fandcm", "fc", "fchkf", "fclass", "fclrf",
54 "fcmp", "fcvt", "fetchadd4", "fetchadd8", "flushrs", "fma", "fmax",
55 "fmerge", "fmin", "fmix", "fms", "fnma", "for", "fpack", "fpamax",
56 "fpamin", "fpcmp", "fpcvt", "fpma", "fpmax", "fpmerge", "fpmin",
57 "fpms", "fpnma", "fprcpa", "fprsqrta", "frcpa", "frsqrta", "fselect",
58 "fsetc", "fswap", "fsxt", "fwb", "fxor",
59 "getf",
60 "hint",
61 "invala", "itc", "itr",
62 "ld1", "ld16", "ld2", "ld4", "ld8", "ldf", "ldf8", "ldfd", "ldfe",
63 "ldfp8", "ldfpd", "ldfps", "ldfs", "lfetch", "loadrs",
64 "mf", "mix1", "mix2", "mix4", "mov", "movl", "mux1", "mux2",
65 "nop",
66 "or",
67 "pack2", "pack4", "padd1", "padd2", "padd4", "pavg1", "pavg2",
68 "pavgsub1", "pavgsub2", "pcmp1", "pcmp2", "pcmp4", "pmax1", "pmax2",
69 "pmin1", "pmin2", "pmpy2", "pmpyshr2", "popcnt", "probe", "psad1",
70 "pshl2", "pshl4", "pshladd2", "pshr2", "pshr4", "pshradd2", "psub1",
71 "psub2", "psub4", "ptc", "ptr",
72 "rfi", "rsm", "rum",
73 "setf", "shl", "shladd", "shladdp4", "shr", "shrp", "srlz", "ssm",
74 "st1", "st16", "st2", "st4", "st8", "stf", "stf8", "stfd", "stfe",
75 "stfs", "sub", "sum", "sxt1", "sxt2", "sxt4", "sync",
76 "tak", "tbit", "tf", "thash", "tnat", "tpa", "ttag",
77 "unpack1", "unpack2", "unpack4",
78 "vmsw",
79 "xchg1", "xchg2", "xchg4", "xchg8", "xma", "xor",
80 "zxt1", "zxt2", "zxt4"
81 };
82
83 /*
84 * Completers (keep in sync with enum asm_cmpltr_type).
85 */
86 static const char *asm_completers[] = {
87 "",
88 ".0", ".1",
89 ".a", ".acq", ".and",
90 ".b", ".bias",
91 ".c.clr", ".c.clr.acq", ".c.nc", ".call", ".cexit", ".cloop", ".clr",
92 ".ctop",
93 ".d", ".dc.dc", ".dc.nt", ".dpnt", ".dptk",
94 ".e", ".eq", ".excl", ".exit", ".exp",
95 ".f", ".fault", ".few", ".fill", ".fx", ".fxu",
96 ".g", ".ga", ".ge", ".gt",
97 ".h", ".hu",
98 ".i", ".ia", ".imp",
99 ".l", ".le", ".loop", ".lr", ".lt", ".ltu",
100 ".m", ".many",
101 ".nc", ".ne", ".neq", ".nl", ".nle", ".nlt", ".nm", ".nr", ".ns",
102 ".nt.dc", ".nt.nt", ".nt.tk", ".nt1", ".nt2", ".nta", ".nz",
103 ".or", ".or.andcm", ".ord",
104 ".pr",
105 ".r", ".raz", ".rel", ".ret", ".rw",
106 ".s", ".s0", ".s1", ".s2", ".s3", ".sa", ".se", ".sig", ".spill",
107 ".spnt", ".sptk", ".sss",
108 ".tk.dc", ".tk.nt", ".tk.tk", ".trunc",
109 ".u", ".unc", ".unord", ".uss", ".uus", ".uuu",
110 ".w", ".wexit", ".wtop",
111 ".x", ".xf",
112 ".z"
113 };
114
115 void
asm_completer(const struct asm_cmpltr * c,char * buf,size_t buflen)116 asm_completer(const struct asm_cmpltr *c, char *buf, size_t buflen)
117 {
118 strlcpy(buf, asm_completers[c->c_type], buflen);
119 }
120
121 void
asm_mnemonic(enum asm_op op,char * buf,size_t buflen)122 asm_mnemonic(enum asm_op op, char *buf, size_t buflen)
123 {
124 strlcpy(buf, asm_mnemonics[(op < ASM_OP_INTERNAL_OPCODES) ? op : 0],
125 buflen);
126 }
127
128 void
asm_operand(const struct asm_oper * o,char * buf,size_t buflen,uint64_t ip)129 asm_operand(const struct asm_oper *o, char *buf, size_t buflen, uint64_t ip)
130 {
131 const char *n;
132 size_t l;
133
134 n = "";
135 switch (o->o_type) {
136 case ASM_OPER_AREG:
137 switch ((int)o->o_value) {
138 case AR_K0: n = "k0"; break;
139 case AR_K1: n = "k1"; break;
140 case AR_K2: n = "k2"; break;
141 case AR_K3: n = "k3"; break;
142 case AR_K4: n = "k4"; break;
143 case AR_K5: n = "k5"; break;
144 case AR_K6: n = "k6"; break;
145 case AR_K7: n = "k7"; break;
146 case AR_RSC: n = "rsc"; break;
147 case AR_BSP: n = "bsp"; break;
148 case AR_BSPSTORE: n = "bspstore"; break;
149 case AR_RNAT: n = "rnat"; break;
150 case AR_FCR: n = "fcr"; break;
151 case AR_EFLAG: n = "eflag"; break;
152 case AR_CSD: n = "csd"; break;
153 case AR_SSD: n = "ssd"; break;
154 case AR_CFLG: n = "cflg"; break;
155 case AR_FSR: n = "fsr"; break;
156 case AR_FIR: n = "fir"; break;
157 case AR_FDR: n = "fdr"; break;
158 case AR_CCV: n = "ccv"; break;
159 case AR_UNAT: n = "unat"; break;
160 case AR_FPSR: n = "fpsr"; break;
161 case AR_ITC: n = "itc"; break;
162 case AR_PFS: n = "pfs"; break;
163 case AR_LC: n = "lc"; break;
164 case AR_EC: n = "ec"; break;
165 default:
166 snprintf(buf, buflen, "ar%d", (int)o->o_value);
167 return;
168 }
169 snprintf(buf, buflen, "ar.%s", n);
170 return;
171 case ASM_OPER_BREG:
172 if (o->o_value != 0)
173 snprintf(buf, buflen, "b%d", (int)o->o_value);
174 else
175 strlcpy(buf, "rp", buflen);
176 return;
177 case ASM_OPER_CPUID:
178 n = "cpuid";
179 break;
180 case ASM_OPER_CREG:
181 switch ((int)o->o_value) {
182 case CR_DCR: n = "dcr"; break;
183 case CR_ITM: n = "itm"; break;
184 case CR_IVA: n = "iva"; break;
185 case CR_PTA: n = "pta"; break;
186 case CR_IPSR: n = "ipsr"; break;
187 case CR_ISR: n = "isr"; break;
188 case CR_IIP: n = "iip"; break;
189 case CR_IFA: n = "ifa"; break;
190 case CR_ITIR: n = "itir"; break;
191 case CR_IIPA: n = "iipa"; break;
192 case CR_IFS: n = "ifs"; break;
193 case CR_IIM: n = "iim"; break;
194 case CR_IHA: n = "iha"; break;
195 case CR_LID: n = "lid"; break;
196 case CR_IVR: n = "ivr"; break;
197 case CR_TPR: n = "tpr"; break;
198 case CR_EOI: n = "eoi"; break;
199 case CR_IRR0: n = "irr0"; break;
200 case CR_IRR1: n = "irr1"; break;
201 case CR_IRR2: n = "irr2"; break;
202 case CR_IRR3: n = "irr3"; break;
203 case CR_ITV: n = "itv"; break;
204 case CR_PMV: n = "pmv"; break;
205 case CR_CMCV: n = "cmcv"; break;
206 case CR_LRR0: n = "lrr0"; break;
207 case CR_LRR1: n = "lrr1"; break;
208 default:
209 snprintf(buf, buflen, "cr%d", (int)o->o_value);
210 return;
211 }
212 snprintf(buf, buflen, "cr.%s", n);
213 return;
214 case ASM_OPER_DBR:
215 n = "dbr";
216 break;
217 case ASM_OPER_DISP:
218 snprintf(buf, buflen, "%lx", ip + o->o_value);
219 return;
220 case ASM_OPER_DTR:
221 n = "dtr";
222 break;
223 case ASM_OPER_FREG:
224 snprintf(buf, buflen, "f%d", (int)o->o_value);
225 return;
226 case ASM_OPER_GREG:
227 break;
228 case ASM_OPER_IBR:
229 n = "ibr";
230 break;
231 case ASM_OPER_IMM:
232 snprintf(buf, buflen, "0x%lx", o->o_value);
233 return;
234 case ASM_OPER_IP:
235 strlcpy(buf, "ip", buflen);
236 return;
237 case ASM_OPER_ITR:
238 n = "itr";
239 break;
240 case ASM_OPER_MEM:
241 n = "";
242 break;
243 case ASM_OPER_MSR:
244 n = "msr";
245 break;
246 case ASM_OPER_PKR:
247 n = "pkr";
248 break;
249 case ASM_OPER_PMC:
250 n = "pmc";
251 break;
252 case ASM_OPER_PMD:
253 n = "pmd";
254 break;
255 case ASM_OPER_PR:
256 strlcpy(buf, "pr", buflen);
257 return;
258 case ASM_OPER_PR_ROT:
259 strlcpy(buf, "pr.rot", buflen);
260 return;
261 case ASM_OPER_PREG:
262 snprintf(buf, buflen, "p%d", (int)o->o_value);
263 return;
264 case ASM_OPER_PSR:
265 strlcpy(buf, "psr", buflen);
266 return;
267 case ASM_OPER_PSR_L:
268 strlcpy(buf, "psr.l", buflen);
269 return;
270 case ASM_OPER_PSR_UM:
271 strlcpy(buf, "psr.um", buflen);
272 return;
273 case ASM_OPER_RR:
274 n = "rr";
275 break;
276 case ASM_OPER_NONE:
277 KASSERT(0);
278 break;
279 }
280 if (n[0] != '\0') {
281 l = snprintf(buf, buflen, "%s[", n);
282 if (l > buflen)
283 l = buflen;
284 buf += l;
285 buflen -= l;
286 }
287 switch ((int)o->o_value) {
288 case 1: l = strlcpy(buf, "gp", buflen); break;
289 case 12: l = strlcpy(buf, "sp", buflen); break;
290 case 13: l = strlcpy(buf, "tp", buflen); break;
291 default:
292 l = snprintf(buf, buflen, "r%d", (int)o->o_value);
293 if (l > buflen)
294 l = buflen;
295 break;
296 }
297 buf += l;
298 buflen -= l;
299 if (n[0] != '\0')
300 strlcpy(buf, "]", buflen);
301 }
302
303 void
asm_print_bundle(const struct asm_bundle * b,uint64_t ip)304 asm_print_bundle(const struct asm_bundle *b, uint64_t ip)
305 {
306 asm_print_inst(b, 0, ip);
307 asm_print_inst(b, 1, ip);
308 asm_print_inst(b, 2, ip);
309 }
310
311 void
asm_print_inst(const struct asm_bundle * b,int slot,uint64_t ip)312 asm_print_inst(const struct asm_bundle *b, int slot, uint64_t ip)
313 {
314 char buf[32];
315 const struct asm_inst *i;
316 const char *tmpl;
317 int n, w;
318
319 tmpl = b->b_templ + slot;
320 if (*tmpl == ';' || (slot == 2 && b->b_templ[1] == ';'))
321 tmpl++;
322 i = b->b_inst + slot;
323 if (*tmpl == 'L' || i->i_op == ASM_OP_NONE)
324 return;
325
326 /* Address + slot. */
327 printf("%lx[%c] ", ip + slot, *tmpl);
328
329 /* Predicate. */
330 if (i->i_oper[0].o_value != 0) {
331 asm_operand(i->i_oper+0, buf, sizeof(buf), ip);
332 printf("(%s)", buf);
333 w = strlen(buf);
334 } else
335 w = 0;
336 while (w++ < 8)
337 printf(" ");
338
339 /* Mnemonic & completers. */
340 asm_mnemonic(i->i_op, buf, sizeof(buf));
341 printf("%s", buf);
342 w = strlen(buf);
343 n = 0;
344 while (n < i->i_ncmpltrs) {
345 asm_completer(i->i_cmpltr + n, buf, sizeof(buf));
346 printf(buf);
347 w += strlen(buf);
348 n++;
349 }
350 while (w++ < 15)
351 printf(" ");
352 printf(" ");
353
354 /* Operands. */
355 n = 1;
356 while (n < 7 && i->i_oper[n].o_type != ASM_OPER_NONE) {
357 if (n > 1) {
358 if (n == i->i_srcidx)
359 printf(" = ");
360 else
361 printf(", ");
362 }
363 asm_operand(i->i_oper + n, buf, sizeof(buf), ip);
364 printf("%s", buf);
365 n++;
366 }
367 printf("\n");
368 }
369
370 #endif
371