]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/ia64/disasm/disasm_format.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / ia64 / disasm / disasm_format.c
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  */
39 static 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  */
80 static 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
109 void
110 asm_completer(const struct asm_cmpltr *c, char *buf)
111 {
112         strcpy(buf, asm_completers[c->c_type]);
113 }
114
115 void
116 asm_mnemonic(enum asm_op op, char *buf)
117 {
118         strcpy(buf, asm_mnemonics[(op < ASM_OP_INTERNAL_OPCODES) ? op : 0]);
119 }
120
121 void
122 asm_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
284 void
285 asm_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
292 void
293 asm_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 }