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