Home | History | Annotate | Line # | Download | only in disasm
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