xref: /netbsd/sys/arch/ia64/disasm/disasm_format.c (revision 273ac2a6)
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