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