disasm_format.c revision 1.4 1 /* $NetBSD: disasm_format.c,v 1.4 2014/04/03 17:02:34 martin Exp $ */
2
3 /*-
4 * Copyright (c) 2000-2003 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: src/sys/ia64/disasm/disasm_format.c,v 1.2 2005/01/06 22:18:22 imp Exp $"); */
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 "invala", "itc", "itr",
61 "ld1", "ld16", "ld2", "ld4", "ld8", "ldf", "ldf8", "ldfd", "ldfe",
62 "ldfp8", "ldfpd", "ldfps", "ldfs", "lfetch", "loadrs",
63 "mf", "mix1", "mix2", "mix4", "mov", "movl", "mux1", "mux2",
64 "nop",
65 "or",
66 "pack2", "pack4", "padd1", "padd2", "padd4", "pavg1", "pavg2",
67 "pavgsub1", "pavgsub2", "pcmp1", "pcmp2", "pcmp4", "pmax1", "pmax2",
68 "pmin1", "pmin2", "pmpy2", "pmpyshr2", "popcnt", "probe", "psad1",
69 "pshl2", "pshl4", "pshladd2", "pshr2", "pshr4", "pshradd2", "psub1",
70 "psub2", "psub4", "ptc", "ptr",
71 "rfi", "rsm", "rum",
72 "setf", "shl", "shladd", "shladdp4", "shr", "shrp", "srlz", "ssm",
73 "st1", "st16", "st2", "st4", "st8", "stf", "stf8", "stfd", "stfe",
74 "stfs", "sub", "sum", "sxt1", "sxt2", "sxt4", "sync",
75 "tak", "tbit", "thash", "tnat", "tpa", "ttag",
76 "unpack1", "unpack2", "unpack4",
77 "xchg1", "xchg2", "xchg4", "xchg8", "xma", "xor",
78 "zxt1", "zxt2", "zxt4"
79 };
80
81 /*
82 * Completers (keep in sync with enum asm_cmpltr_type).
83 */
84 static const char *asm_completers[] = {
85 "",
86 ".0", ".1",
87 ".a", ".acq", ".and",
88 ".b", ".bias",
89 ".c.clr", ".c.clr.acq", ".c.nc", ".call", ".cexit", ".cloop", ".clr",
90 ".ctop",
91 ".d", ".dc.dc", ".dc.nt", ".dpnt", ".dptk",
92 ".e", ".eq", ".excl", ".exit", ".exp",
93 ".f", ".fault", ".few", ".fill", ".fx", ".fxu",
94 ".g", ".ga", ".ge", ".gt",
95 ".h", ".hu",
96 ".i", ".ia", ".imp",
97 ".l", ".le", ".loop", ".lr", ".lt", ".ltu",
98 ".m", ".many",
99 ".nc", ".ne", ".neq", ".nl", ".nle", ".nlt", ".nm", ".nr", ".ns",
100 ".nt.dc", ".nt.nt", ".nt.tk", ".nt1", ".nt2", ".nta", ".nz",
101 ".or", ".or.andcm", ".ord",
102 ".pr",
103 ".r", ".raz", ".rel", ".ret", ".rw",
104 ".s", ".s0", ".s1", ".s2", ".s3", ".sa", ".se", ".sig", ".spill",
105 ".spnt", ".sptk", ".sss",
106 ".tk.dc", ".tk.nt", ".tk.tk", ".trunc",
107 ".u", ".unc", ".unord", ".uss", ".uus", ".uuu",
108 ".w", ".wexit", ".wtop",
109 ".x", ".xf",
110 ".z"
111 };
112
113 void
114 asm_completer(const struct asm_cmpltr *c, char *buf, size_t buflen)
115 {
116 strlcpy(buf, asm_completers[c->c_type], buflen);
117 }
118
119 void
120 asm_mnemonic(enum asm_op op, char *buf, size_t buflen)
121 {
122 strlcpy(buf, asm_mnemonics[(op < ASM_OP_INTERNAL_OPCODES) ? op : 0],
123 buflen);
124 }
125
126 void
127 asm_operand(const struct asm_oper *o, char *buf, size_t buflen, uint64_t ip)
128 {
129 const char *n;
130 size_t l;
131
132 n = "";
133 switch (o->o_type) {
134 case ASM_OPER_AREG:
135 switch ((int)o->o_value) {
136 case AR_K0: n = "k0"; break;
137 case AR_K1: n = "k1"; break;
138 case AR_K2: n = "k2"; break;
139 case AR_K3: n = "k3"; break;
140 case AR_K4: n = "k4"; break;
141 case AR_K5: n = "k5"; break;
142 case AR_K6: n = "k6"; break;
143 case AR_K7: n = "k7"; break;
144 case AR_RSC: n = "rsc"; break;
145 case AR_BSP: n = "bsp"; break;
146 case AR_BSPSTORE: n = "bspstore"; break;
147 case AR_RNAT: n = "rnat"; break;
148 case AR_FCR: n = "fcr"; break;
149 case AR_EFLAG: n = "eflag"; break;
150 case AR_CSD: n = "csd"; break;
151 case AR_SSD: n = "ssd"; break;
152 case AR_CFLG: n = "cflg"; break;
153 case AR_FSR: n = "fsr"; break;
154 case AR_FIR: n = "fir"; break;
155 case AR_FDR: n = "fdr"; break;
156 case AR_CCV: n = "ccv"; break;
157 case AR_UNAT: n = "unat"; break;
158 case AR_FPSR: n = "fpsr"; break;
159 case AR_ITC: n = "itc"; break;
160 case AR_PFS: n = "pfs"; break;
161 case AR_LC: n = "lc"; break;
162 case AR_EC: n = "ec"; break;
163 default:
164 snprintf(buf, buflen, "ar%d", (int)o->o_value);
165 return;
166 }
167 snprintf(buf, buflen, "ar.%s", n);
168 return;
169 case ASM_OPER_BREG:
170 if (o->o_value != 0)
171 snprintf(buf, buflen, "b%d", (int)o->o_value);
172 else
173 strlcpy(buf, "rp", buflen);
174 return;
175 case ASM_OPER_CPUID:
176 n = "cpuid";
177 break;
178 case ASM_OPER_CREG:
179 switch ((int)o->o_value) {
180 case CR_DCR: n = "dcr"; break;
181 case CR_ITM: n = "itm"; break;
182 case CR_IVA: n = "iva"; break;
183 case CR_PTA: n = "pta"; break;
184 case CR_IPSR: n = "ipsr"; break;
185 case CR_ISR: n = "isr"; break;
186 case CR_IIP: n = "iip"; break;
187 case CR_IFA: n = "ifa"; break;
188 case CR_ITIR: n = "itir"; break;
189 case CR_IIPA: n = "iipa"; break;
190 case CR_IFS: n = "ifs"; break;
191 case CR_IIM: n = "iim"; break;
192 case CR_IHA: n = "iha"; break;
193 case CR_LID: n = "lid"; break;
194 case CR_IVR: n = "ivr"; break;
195 case CR_TPR: n = "tpr"; break;
196 case CR_EOI: n = "eoi"; break;
197 case CR_IRR0: n = "irr0"; break;
198 case CR_IRR1: n = "irr1"; break;
199 case CR_IRR2: n = "irr2"; break;
200 case CR_IRR3: n = "irr3"; break;
201 case CR_ITV: n = "itv"; break;
202 case CR_PMV: n = "pmv"; break;
203 case CR_CMCV: n = "cmcv"; break;
204 case CR_LRR0: n = "lrr0"; break;
205 case CR_LRR1: n = "lrr1"; break;
206 default:
207 snprintf(buf, buflen, "cr%d", (int)o->o_value);
208 return;
209 }
210 snprintf(buf, buflen, "cr.%s", n);
211 return;
212 case ASM_OPER_DBR:
213 n = "dbr";
214 break;
215 case ASM_OPER_DISP:
216 snprintf(buf, buflen, "%lx", ip + o->o_value);
217 return;
218 case ASM_OPER_DTR:
219 n = "dtr";
220 break;
221 case ASM_OPER_FREG:
222 snprintf(buf, buflen, "f%d", (int)o->o_value);
223 return;
224 case ASM_OPER_GREG:
225 break;
226 case ASM_OPER_IBR:
227 n = "ibr";
228 break;
229 case ASM_OPER_IMM:
230 snprintf(buf, buflen, "0x%lx", o->o_value);
231 return;
232 case ASM_OPER_IP:
233 strlcpy(buf, "ip", buflen);
234 return;
235 case ASM_OPER_ITR:
236 n = "itr";
237 break;
238 case ASM_OPER_MEM:
239 n = "";
240 break;
241 case ASM_OPER_MSR:
242 n = "msr";
243 break;
244 case ASM_OPER_PKR:
245 n = "pkr";
246 break;
247 case ASM_OPER_PMC:
248 n = "pmc";
249 break;
250 case ASM_OPER_PMD:
251 n = "pmd";
252 break;
253 case ASM_OPER_PR:
254 strlcpy(buf, "pr", buflen);
255 return;
256 case ASM_OPER_PR_ROT:
257 strlcpy(buf, "pr.rot", buflen);
258 return;
259 case ASM_OPER_PREG:
260 snprintf(buf, buflen, "p%d", (int)o->o_value);
261 return;
262 case ASM_OPER_PSR:
263 strlcpy(buf, "psr", buflen);
264 return;
265 case ASM_OPER_PSR_L:
266 strlcpy(buf, "psr.l", buflen);
267 return;
268 case ASM_OPER_PSR_UM:
269 strlcpy(buf, "psr.um", buflen);
270 return;
271 case ASM_OPER_RR:
272 n = "rr";
273 break;
274 case ASM_OPER_NONE:
275 KASSERT(0);
276 break;
277 }
278 if (n[0] != '\0') {
279 l = snprintf(buf, buflen, "%s[", n);
280 if (l > buflen)
281 l = buflen;
282 buf += l;
283 buflen -= l;
284 }
285 switch ((int)o->o_value) {
286 case 1: l = strlcpy(buf, "gp", buflen); break;
287 case 12: l = strlcpy(buf, "sp", buflen); break;
288 case 13: l = strlcpy(buf, "tp", buflen); break;
289 default:
290 l = snprintf(buf, buflen, "r%d", (int)o->o_value);
291 if (l > buflen)
292 l = buflen;
293 break;
294 }
295 buf += l;
296 buflen -= l;
297 if (n[0] != '\0')
298 strlcpy(buf, "]", buflen);
299 }
300
301 void
302 asm_print_bundle(const struct asm_bundle *b, uint64_t ip)
303 {
304 asm_print_inst(b, 0, ip);
305 asm_print_inst(b, 1, ip);
306 asm_print_inst(b, 2, ip);
307 }
308
309 void
310 asm_print_inst(const struct asm_bundle *b, int slot, uint64_t ip)
311 {
312 char buf[32];
313 const struct asm_inst *i;
314 const char *tmpl;
315 int n, w;
316
317 tmpl = b->b_templ + slot;
318 if (*tmpl == ';' || (slot == 2 && b->b_templ[1] == ';'))
319 tmpl++;
320 i = b->b_inst + slot;
321 if (*tmpl == 'L' || i->i_op == ASM_OP_NONE)
322 return;
323
324 /* Address + slot. */
325 printf("%lx[%c] ", ip + slot, *tmpl);
326
327 /* Predicate. */
328 if (i->i_oper[0].o_value != 0) {
329 asm_operand(i->i_oper+0, buf, sizeof(buf), ip);
330 printf("(%s)", buf);
331 w = strlen(buf);
332 } else
333 w = 0;
334 while (w++ < 8)
335 printf(" ");
336
337 /* Mnemonic & completers. */
338 asm_mnemonic(i->i_op, buf, sizeof(buf));
339 printf("%s", buf);
340 w = strlen(buf);
341 n = 0;
342 while (n < i->i_ncmpltrs) {
343 asm_completer(i->i_cmpltr + n, buf, sizeof(buf));
344 printf(buf);
345 w += strlen(buf);
346 n++;
347 }
348 while (w++ < 15)
349 printf(" ");
350 printf(" ");
351
352 /* Operands. */
353 n = 1;
354 while (n < 7 && i->i_oper[n].o_type != ASM_OPER_NONE) {
355 if (n > 1) {
356 if (n == i->i_srcidx)
357 printf(" = ");
358 else
359 printf(", ");
360 }
361 asm_operand(i->i_oper + n, buf, sizeof(buf), ip);
362 printf("%s", buf);
363 n++;
364 }
365 printf("\n");
366 }
367
368 #endif
369