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