1139790Simp/*-
2159916Smarcel * Copyright (c) 2000-2006 Marcel Moolenaar
3121404Smarcel * All rights reserved.
4121404Smarcel *
5121404Smarcel * Redistribution and use in source and binary forms, with or without
6121404Smarcel * modification, are permitted provided that the following conditions
7121404Smarcel * are met:
8121404Smarcel *
9121404Smarcel * 1. Redistributions of source code must retain the above copyright
10121404Smarcel *    notice, this list of conditions and the following disclaimer.
11121404Smarcel * 2. Redistributions in binary form must reproduce the above copyright
12121404Smarcel *    notice, this list of conditions and the following disclaimer in the
13121404Smarcel *    documentation and/or other materials provided with the distribution.
14121404Smarcel *
15121404Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16121404Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17121404Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18121404Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19121404Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20121404Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21121404Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22121404Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23121404Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24121404Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25121404Smarcel */
26121404Smarcel
27121404Smarcel#include <sys/cdefs.h>
28121404Smarcel__FBSDID("$FreeBSD$");
29121404Smarcel
30121404Smarcel#include <sys/param.h>
31121404Smarcel#include <sys/systm.h>
32121404Smarcel
33121404Smarcel#include <ia64/disasm/disasm_int.h>
34121404Smarcel#include <ia64/disasm/disasm.h>
35121404Smarcel
36121404Smarcel/*
37121404Smarcel * Mnemonics (keep in sync with enum asm_op).
38121404Smarcel */
39121404Smarcelstatic const char *asm_mnemonics[] = {
40121404Smarcel	NULL,
41121404Smarcel	"add", "addl", "addp4", "adds", "alloc", "and", "andcm",
42121404Smarcel	"br", "break", "brl", "brp", "bsw",
43121404Smarcel	"chk", "clrrrb", "cmp", "cmp4", "cmp8xchg16", "cmpxchg1", "cmpxchg2",
44121404Smarcel	"cmpxchg4", "cmpxchg8", "cover", "czx1", "czx2",
45121404Smarcel	"dep",
46121404Smarcel	"epc", "extr",
47121404Smarcel	"famax", "famin", "fand", "fandcm", "fc", "fchkf", "fclass", "fclrf",
48121404Smarcel	"fcmp", "fcvt", "fetchadd4", "fetchadd8", "flushrs", "fma", "fmax",
49121404Smarcel	"fmerge", "fmin", "fmix", "fms", "fnma", "for", "fpack", "fpamax",
50121404Smarcel	"fpamin", "fpcmp", "fpcvt", "fpma", "fpmax", "fpmerge", "fpmin",
51121404Smarcel	"fpms", "fpnma", "fprcpa", "fprsqrta", "frcpa", "frsqrta", "fselect",
52121404Smarcel	"fsetc", "fswap", "fsxt", "fwb", "fxor",
53121404Smarcel	"getf",
54159909Smarcel	"hint",
55121404Smarcel	"invala", "itc", "itr",
56121404Smarcel	"ld1", "ld16", "ld2", "ld4", "ld8", "ldf", "ldf8", "ldfd", "ldfe",
57121404Smarcel	"ldfp8", "ldfpd", "ldfps", "ldfs", "lfetch", "loadrs",
58121404Smarcel	"mf", "mix1", "mix2", "mix4", "mov", "movl", "mux1", "mux2",
59121404Smarcel	"nop",
60121404Smarcel	"or",
61121404Smarcel	"pack2", "pack4", "padd1", "padd2", "padd4", "pavg1", "pavg2",
62121404Smarcel	"pavgsub1", "pavgsub2", "pcmp1", "pcmp2", "pcmp4", "pmax1", "pmax2",
63121404Smarcel	"pmin1", "pmin2", "pmpy2", "pmpyshr2", "popcnt", "probe", "psad1",
64121404Smarcel	"pshl2", "pshl4", "pshladd2", "pshr2", "pshr4", "pshradd2", "psub1",
65121404Smarcel	"psub2", "psub4", "ptc", "ptr",
66121404Smarcel	"rfi", "rsm", "rum",
67121404Smarcel	"setf", "shl", "shladd", "shladdp4", "shr", "shrp", "srlz", "ssm",
68121404Smarcel	"st1", "st16", "st2", "st4", "st8", "stf", "stf8", "stfd", "stfe",
69121404Smarcel	"stfs", "sub", "sum", "sxt1", "sxt2", "sxt4", "sync",
70159916Smarcel	"tak", "tbit", "tf", "thash", "tnat", "tpa", "ttag",
71121404Smarcel	"unpack1", "unpack2", "unpack4",
72159916Smarcel	"vmsw",
73121404Smarcel	"xchg1", "xchg2", "xchg4", "xchg8", "xma", "xor",
74121404Smarcel	"zxt1", "zxt2", "zxt4"
75121404Smarcel};
76121404Smarcel
77121404Smarcel/*
78121404Smarcel * Completers (keep in sync with enum asm_cmpltr_type).
79121404Smarcel */
80121404Smarcelstatic const char *asm_completers[] = {
81121404Smarcel	"",
82121404Smarcel	".0", ".1",
83121404Smarcel	".a", ".acq", ".and",
84121404Smarcel	".b", ".bias",
85121404Smarcel	".c.clr", ".c.clr.acq", ".c.nc", ".call", ".cexit", ".cloop", ".clr",
86121404Smarcel	".ctop",
87121404Smarcel	".d", ".dc.dc", ".dc.nt", ".dpnt", ".dptk",
88121404Smarcel	".e", ".eq", ".excl", ".exit", ".exp",
89121404Smarcel	".f", ".fault", ".few", ".fill", ".fx", ".fxu",
90121404Smarcel	".g", ".ga", ".ge", ".gt",
91121404Smarcel	".h", ".hu",
92121404Smarcel	".i", ".ia", ".imp",
93121404Smarcel	".l", ".le", ".loop", ".lr", ".lt", ".ltu",
94121404Smarcel	".m", ".many",
95121404Smarcel	".nc", ".ne", ".neq", ".nl", ".nle", ".nlt", ".nm", ".nr", ".ns",
96121404Smarcel	".nt.dc", ".nt.nt", ".nt.tk", ".nt1", ".nt2", ".nta", ".nz",
97121404Smarcel	".or", ".or.andcm", ".ord",
98121404Smarcel	".pr",
99121404Smarcel	".r", ".raz", ".rel", ".ret", ".rw",
100121404Smarcel	".s", ".s0", ".s1", ".s2", ".s3", ".sa", ".se", ".sig", ".spill",
101121404Smarcel	".spnt", ".sptk", ".sss",
102121404Smarcel	".tk.dc", ".tk.nt", ".tk.tk", ".trunc",
103121404Smarcel	".u", ".unc", ".unord", ".uss", ".uus", ".uuu",
104121404Smarcel	".w", ".wexit", ".wtop",
105121404Smarcel	".x", ".xf",
106121404Smarcel	".z"
107121404Smarcel};
108121404Smarcel
109121404Smarcelvoid
110121404Smarcelasm_completer(const struct asm_cmpltr *c, char *buf)
111121404Smarcel{
112121404Smarcel	strcpy(buf, asm_completers[c->c_type]);
113121404Smarcel}
114121404Smarcel
115121404Smarcelvoid
116121404Smarcelasm_mnemonic(enum asm_op op, char *buf)
117121404Smarcel{
118121404Smarcel	strcpy(buf, asm_mnemonics[(op < ASM_OP_INTERNAL_OPCODES) ? op : 0]);
119121404Smarcel}
120121404Smarcel
121121404Smarcelvoid
122121404Smarcelasm_operand(const struct asm_oper *o, char *buf, uint64_t ip)
123121404Smarcel{
124121404Smarcel	const char *n;
125121404Smarcel
126121404Smarcel	n = NULL;
127121404Smarcel	switch (o->o_type) {
128121404Smarcel	case ASM_OPER_AREG:
129121404Smarcel		switch ((int)o->o_value) {
130121404Smarcel		case AR_K0: n = "k0"; break;
131121404Smarcel		case AR_K1: n = "k1"; break;
132121404Smarcel		case AR_K2: n = "k2"; break;
133121404Smarcel		case AR_K3: n = "k3"; break;
134121404Smarcel		case AR_K4: n = "k4"; break;
135121404Smarcel		case AR_K5: n = "k5"; break;
136121404Smarcel		case AR_K6: n = "k6"; break;
137121404Smarcel		case AR_K7: n = "k7"; break;
138121404Smarcel		case AR_RSC: n = "rsc"; break;
139121404Smarcel		case AR_BSP: n = "bsp"; break;
140121404Smarcel		case AR_BSPSTORE: n = "bspstore"; break;
141121404Smarcel		case AR_RNAT: n = "rnat"; break;
142121404Smarcel		case AR_FCR: n = "fcr"; break;
143121404Smarcel		case AR_EFLAG: n = "eflag"; break;
144121404Smarcel		case AR_CSD: n = "csd"; break;
145121404Smarcel		case AR_SSD: n = "ssd"; break;
146121404Smarcel		case AR_CFLG: n = "cflg"; break;
147121404Smarcel		case AR_FSR: n = "fsr"; break;
148121404Smarcel		case AR_FIR: n = "fir"; break;
149121404Smarcel		case AR_FDR: n = "fdr"; break;
150121404Smarcel		case AR_CCV: n = "ccv"; break;
151121404Smarcel		case AR_UNAT: n = "unat"; break;
152121404Smarcel		case AR_FPSR: n = "fpsr"; break;
153121404Smarcel		case AR_ITC: n = "itc"; break;
154121404Smarcel		case AR_PFS: n = "pfs"; break;
155121404Smarcel		case AR_LC: n = "lc"; break;
156121404Smarcel		case AR_EC: n = "ec"; break;
157121404Smarcel		default:
158121404Smarcel			sprintf(buf, "ar%d", (int)o->o_value);
159121404Smarcel			return;
160121404Smarcel		}
161121404Smarcel		sprintf(buf, "ar.%s", n);
162121404Smarcel		return;
163121404Smarcel	case ASM_OPER_BREG:
164121404Smarcel		if (o->o_value != 0)
165121404Smarcel			sprintf(buf, "b%d", (int)o->o_value);
166121404Smarcel		else
167121404Smarcel			strcpy(buf, "rp");
168121404Smarcel		return;
169121404Smarcel	case ASM_OPER_CPUID:
170121404Smarcel		n = "cpuid";
171121404Smarcel		break;
172121404Smarcel	case ASM_OPER_CREG:
173121404Smarcel		switch ((int)o->o_value) {
174121404Smarcel		case CR_DCR: n = "dcr"; break;
175121404Smarcel		case CR_ITM: n = "itm"; break;
176121404Smarcel		case CR_IVA: n = "iva"; break;
177121404Smarcel		case CR_PTA: n = "pta"; break;
178121404Smarcel		case CR_IPSR: n = "ipsr"; break;
179121404Smarcel		case CR_ISR: n = "isr"; break;
180121404Smarcel		case CR_IIP: n = "iip"; break;
181121404Smarcel		case CR_IFA: n = "ifa"; break;
182121404Smarcel		case CR_ITIR: n = "itir"; break;
183121404Smarcel		case CR_IIPA: n = "iipa"; break;
184121404Smarcel		case CR_IFS: n = "ifs"; break;
185121404Smarcel		case CR_IIM: n = "iim"; break;
186121404Smarcel		case CR_IHA: n = "iha"; break;
187121404Smarcel		case CR_LID: n = "lid"; break;
188121404Smarcel		case CR_IVR: n = "ivr"; break;
189121404Smarcel		case CR_TPR: n = "tpr"; break;
190121404Smarcel		case CR_EOI: n = "eoi"; break;
191121404Smarcel		case CR_IRR0: n = "irr0"; break;
192121404Smarcel		case CR_IRR1: n = "irr1"; break;
193121404Smarcel		case CR_IRR2: n = "irr2"; break;
194121404Smarcel		case CR_IRR3: n = "irr3"; break;
195121404Smarcel		case CR_ITV: n = "itv"; break;
196121404Smarcel		case CR_PMV: n = "pmv"; break;
197121404Smarcel		case CR_CMCV: n = "cmcv"; break;
198121404Smarcel		case CR_LRR0: n = "lrr0"; break;
199121404Smarcel		case CR_LRR1: n = "lrr1"; break;
200121404Smarcel		default:
201121404Smarcel			sprintf(buf, "cr%d", (int)o->o_value);
202121404Smarcel			return;
203121404Smarcel		}
204121404Smarcel		sprintf(buf, "cr.%s", n);
205121404Smarcel		return;
206121404Smarcel	case ASM_OPER_DBR:
207121404Smarcel		n = "dbr";
208121404Smarcel		break;
209121404Smarcel	case ASM_OPER_DISP:
210121404Smarcel		sprintf(buf, "%lx", ip + o->o_value);
211121404Smarcel		return;
212121404Smarcel	case ASM_OPER_DTR:
213121404Smarcel		n = "dtr";
214121404Smarcel		break;
215121404Smarcel	case ASM_OPER_FREG:
216121404Smarcel		sprintf(buf, "f%d", (int)o->o_value);
217121404Smarcel		return;
218121404Smarcel	case ASM_OPER_GREG:
219121404Smarcel		break;
220121404Smarcel	case ASM_OPER_IBR:
221121404Smarcel		n = "ibr";
222121404Smarcel		break;
223121404Smarcel	case ASM_OPER_IMM:
224121404Smarcel		sprintf(buf, "0x%lx", o->o_value);
225121404Smarcel		return;
226121404Smarcel	case ASM_OPER_IP:
227121404Smarcel		strcpy(buf, "ip");
228121404Smarcel		return;
229121404Smarcel	case ASM_OPER_ITR:
230121404Smarcel		n = "itr";
231121404Smarcel		break;
232121404Smarcel	case ASM_OPER_MEM:
233121404Smarcel		n = "";
234121404Smarcel		break;
235121404Smarcel	case ASM_OPER_MSR:
236121404Smarcel		n = "msr";
237121404Smarcel		break;
238121404Smarcel	case ASM_OPER_PKR:
239121404Smarcel		n = "pkr";
240121404Smarcel		break;
241121404Smarcel	case ASM_OPER_PMC:
242121404Smarcel		n = "pmc";
243121404Smarcel		break;
244121404Smarcel	case ASM_OPER_PMD:
245121404Smarcel		n = "pmd";
246121404Smarcel		break;
247121404Smarcel	case ASM_OPER_PR:
248121404Smarcel		strcpy(buf, "pr");
249121404Smarcel                return;
250121404Smarcel	case ASM_OPER_PR_ROT:
251121404Smarcel		strcpy(buf, "pr.rot");
252121404Smarcel		return;
253121404Smarcel	case ASM_OPER_PREG:
254121404Smarcel		sprintf(buf, "p%d", (int)o->o_value);
255121404Smarcel		return;
256121404Smarcel	case ASM_OPER_PSR:
257121404Smarcel		strcpy(buf, "psr");
258121404Smarcel		return;
259121404Smarcel	case ASM_OPER_PSR_L:
260121404Smarcel		strcpy(buf, "psr.l");
261121404Smarcel		return;
262121404Smarcel	case ASM_OPER_PSR_UM:
263121404Smarcel		strcpy(buf, "psr.um");
264121404Smarcel		return;
265121404Smarcel	case ASM_OPER_RR:
266121404Smarcel		n = "rr";
267121404Smarcel		break;
268121404Smarcel	case ASM_OPER_NONE:
269121404Smarcel		KASSERT(0, ("foo"));
270121404Smarcel		break;
271121404Smarcel	}
272121404Smarcel	if (n != NULL)
273121404Smarcel		buf += sprintf(buf, "%s[", n);
274121404Smarcel	switch ((int)o->o_value) {
275121404Smarcel	case 1:	strcpy(buf, "gp"); buf += 2; break;
276121404Smarcel	case 12: strcpy(buf, "sp"); buf += 2; break;
277121404Smarcel	case 13: strcpy(buf, "tp"); buf += 2; break;
278121404Smarcel	default: buf += sprintf(buf, "r%d", (int)o->o_value); break;
279121404Smarcel	}
280121404Smarcel	if (n != NULL)
281121404Smarcel		strcpy(buf, "]");
282121404Smarcel}
283121404Smarcel
284121404Smarcelvoid
285121404Smarcelasm_print_bundle(const struct asm_bundle *b, uint64_t ip)
286121404Smarcel{
287121404Smarcel	asm_print_inst(b, 0, ip);
288121404Smarcel	asm_print_inst(b, 1, ip);
289121404Smarcel	asm_print_inst(b, 2, ip);
290121404Smarcel}
291121404Smarcel
292121404Smarcelvoid
293121404Smarcelasm_print_inst(const struct asm_bundle *b, int slot, uint64_t ip)
294121404Smarcel{
295121404Smarcel	char buf[32];
296121404Smarcel	const struct asm_inst *i;
297121404Smarcel	const char *tmpl;
298121404Smarcel	int n, w;
299121404Smarcel
300121404Smarcel	tmpl = b->b_templ + slot;
301121404Smarcel	if (*tmpl == ';' || (slot == 2 && b->b_templ[1] == ';'))
302121404Smarcel		tmpl++;
303121404Smarcel	i = b->b_inst + slot;
304121404Smarcel	if (*tmpl == 'L' || i->i_op == ASM_OP_NONE)
305121404Smarcel		return;
306121404Smarcel
307121404Smarcel	/* Address + slot. */
308121404Smarcel	printf("%lx[%c] ", ip + slot, *tmpl);
309121404Smarcel
310121404Smarcel	/* Predicate. */
311121404Smarcel	if (i->i_oper[0].o_value != 0) {
312121404Smarcel		asm_operand(i->i_oper+0, buf, ip);
313121404Smarcel		w = printf("(%s)", buf);
314121404Smarcel	} else
315121404Smarcel		w = 0;
316121404Smarcel	while (w++ < 8)
317121404Smarcel		printf(" ");
318121404Smarcel
319121404Smarcel	/* Mnemonic & completers. */
320121404Smarcel	asm_mnemonic(i->i_op, buf);
321121404Smarcel	w = printf(buf);
322121404Smarcel	n = 0;
323121404Smarcel	while (n < i->i_ncmpltrs) {
324121404Smarcel		asm_completer(i->i_cmpltr + n, buf);
325121404Smarcel		w += printf(buf);
326121404Smarcel		n++;
327121404Smarcel	}
328121404Smarcel	while (w++ < 15)
329121404Smarcel		printf(" ");
330121404Smarcel	printf(" ");
331121404Smarcel
332121404Smarcel	/* Operands. */
333121404Smarcel	n = 1;
334121404Smarcel	while (n < 7 && i->i_oper[n].o_type != ASM_OPER_NONE) {
335121404Smarcel		if (n > 1) {
336121404Smarcel			if (n == i->i_srcidx)
337121404Smarcel				printf(" = ");
338121404Smarcel			else
339121404Smarcel				printf(", ");
340121404Smarcel		}
341121404Smarcel		asm_operand(i->i_oper + n, buf, ip);
342121404Smarcel		printf(buf);
343121404Smarcel		n++;
344121404Smarcel	}
345121404Smarcel	printf("\n");
346121404Smarcel}
347