1178172Simp/* $OpenBSD: db_disasm.c,v 1.1 1998/03/16 09:03:24 pefo Exp $ */ 2178172Simp/*- 3178172Simp * Copyright (c) 1991, 1993 4178172Simp * The Regents of the University of California. All rights reserved. 5178172Simp * 6178172Simp * This code is derived from software contributed to Berkeley by 7178172Simp * Ralph Campbell. 8178172Simp * 9178172Simp * Redistribution and use in source and binary forms, with or without 10178172Simp * modification, are permitted provided that the following conditions 11178172Simp * are met: 12178172Simp * 1. Redistributions of source code must retain the above copyright 13178172Simp * notice, this list of conditions and the following disclaimer. 14178172Simp * 2. Redistributions in binary form must reproduce the above copyright 15178172Simp * notice, this list of conditions and the following disclaimer in the 16178172Simp * documentation and/or other materials provided with the distribution. 17178172Simp * 3. All advertising materials mentioning features or use of this software 18178172Simp * must display the following acknowledgement: 19178172Simp * This product includes software developed by the University of 20178172Simp * California, Berkeley and its contributors. 21178172Simp * 4. Neither the name of the University nor the names of its contributors 22178172Simp * may be used to endorse or promote products derived from this software 23178172Simp * without specific prior written permission. 24178172Simp * 25178172Simp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26178172Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27178172Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28178172Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29178172Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30178172Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31178172Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32178172Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33178172Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34178172Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35178172Simp * SUCH DAMAGE. 36178172Simp * 37178172Simp * from: @(#)kadb.c 8.1 (Berkeley) 6/10/93 38178172Simp * Id: db_disasm.c,v 1.1 1998/03/16 09:03:24 pefo Exp 39178172Simp * JNPR: db_disasm.c,v 1.1 2006/08/07 05:38:57 katta 40178172Simp */ 41178172Simp 42178172Simp#include <sys/cdefs.h> 43178172Simp__FBSDID("$FreeBSD$"); 44178172Simp 45178172Simp#include <sys/param.h> 46178172Simp#include <vm/vm_param.h> 47178172Simp#include <vm/vm.h> 48178172Simp#include <vm/pmap.h> 49178172Simp#include <sys/systm.h> 50178172Simp 51178172Simp#include <machine/mips_opcode.h> 52178172Simp#include <machine/db_machdep.h> 53178172Simp#include <ddb/ddb.h> 54178172Simp#include <ddb/db_output.h> 55178172Simp 56178172Simpstatic char *op_name[64] = { 57178172Simp/* 0 */ "spec", "bcond","j", "jal", "beq", "bne", "blez", "bgtz", 58178172Simp/* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori", "xori", "lui", 59178172Simp/*16 */ "cop0", "cop1", "cop2", "cop3", "beql", "bnel", "blezl","bgtzl", 60178172Simp/*24 */ "daddi","daddiu","ldl", "ldr", "op34", "op35", "op36", "op37", 61178172Simp/*32 */ "lb", "lh", "lwl", "lw", "lbu", "lhu", "lwr", "lwu", 62178172Simp/*40 */ "sb", "sh", "swl", "sw", "sdl", "sdr", "swr", "cache", 63178172Simp/*48 */ "ll", "lwc1", "lwc2", "lwc3", "lld", "ldc1", "ldc2", "ld", 64178172Simp/*56 */ "sc", "swc1", "swc2", "swc3", "scd", "sdc1", "sdc2", "sd" 65178172Simp}; 66178172Simp 67178172Simpstatic char *spec_name[64] = { 68178172Simp/* 0 */ "sll", "spec01","srl", "sra", "sllv", "spec05","srlv","srav", 69178172Simp/* 8 */ "jr", "jalr", "spec12","spec13","syscall","break","spec16","sync", 70178172Simp/*16 */ "mfhi", "mthi", "mflo", "mtlo", "dsllv","spec25","dsrlv","dsrav", 71178172Simp/*24 */ "mult", "multu","div", "divu", "dmult","dmultu","ddiv","ddivu", 72178172Simp/*32 */ "add", "addu", "sub", "subu", "and", "or", "xor", "nor", 73178172Simp/*40 */ "spec50","spec51","slt","sltu", "dadd","daddu","dsub","dsubu", 74178172Simp/*48 */ "tge","tgeu","tlt","tltu","teq","spec65","tne","spec67", 75178172Simp/*56 */ "dsll","spec71","dsrl","dsra","dsll32","spec75","dsrl32","dsra32" 76178172Simp}; 77178172Simp 78178172Simpstatic char *bcond_name[32] = { 79178172Simp/* 0 */ "bltz", "bgez", "bltzl", "bgezl", "?", "?", "?", "?", 80178172Simp/* 8 */ "tgei", "tgeiu", "tlti", "tltiu", "teqi", "?", "tnei", "?", 81178172Simp/*16 */ "bltzal", "bgezal", "bltzall", "bgezall", "?", "?", "?", "?", 82178172Simp/*24 */ "?", "?", "?", "?", "?", "?", "?", "?", 83178172Simp}; 84178172Simp 85178172Simpstatic char *cop1_name[64] = { 86178172Simp/* 0 */ "fadd", "fsub", "fmpy", "fdiv", "fsqrt","fabs", "fmov", "fneg", 87178172Simp/* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f", 88178172Simp/*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17", 89178172Simp/*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f", 90178172Simp/*32 */ "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27", 91178172Simp/*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f", 92178172Simp/*48 */ "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult", 93178172Simp "fcmp.ole","fcmp.ule", 94178172Simp/*56 */ "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge", 95178172Simp "fcmp.le","fcmp.ngt" 96178172Simp}; 97178172Simp 98178172Simpstatic char *fmt_name[16] = { 99178172Simp "s", "d", "e", "fmt3", 100178172Simp "w", "fmt5", "fmt6", "fmt7", 101178172Simp "fmt8", "fmt9", "fmta", "fmtb", 102178172Simp "fmtc", "fmtd", "fmte", "fmtf" 103178172Simp}; 104178172Simp 105178172Simpstatic char *reg_name[32] = { 106178172Simp "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", 107178172Simp "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", 108178172Simp "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", 109178172Simp "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" 110178172Simp}; 111178172Simp 112178172Simpstatic char *c0_opname[64] = { 113178172Simp "c0op00","tlbr", "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07", 114178172Simp "tlbp", "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17", 115178172Simp "rfe", "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27", 116178172Simp "eret","c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37", 117178172Simp "c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47", 118178172Simp "c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57", 119178172Simp "c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67", 120178172Simp "c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77", 121178172Simp}; 122178172Simp 123178172Simpstatic char *c0_reg[32] = { 124178172Simp "index","random","tlblo0","tlblo1","context","tlbmask","wired","c0r7", 125178172Simp "badvaddr","count","tlbhi","c0r11","sr","cause","epc", "prid", 126178172Simp "config","lladr","watchlo","watchhi","xcontext","c0r21","c0r22","c0r23", 127178172Simp "c0r24","c0r25","ecc","cacheerr","taglo","taghi","errepc","c0r31" 128178172Simp}; 129178172Simp 130178172Simpstatic int md_printins(int ins, int mdbdot); 131178172Simp 132178172Simpdb_addr_t 133178172Simpdb_disasm(db_addr_t loc, boolean_t altfmt) 134178172Simp 135178172Simp{ 136178172Simp int ins; 137178172Simp 138178172Simp if (vtophys((vm_offset_t)loc)) { 139178172Simp db_read_bytes((vm_offset_t)loc, (size_t)sizeof(int), 140178172Simp (char *)&ins); 141178172Simp md_printins(ins, loc); 142178172Simp } 143178172Simp 144178172Simp return (loc + sizeof(int)); 145178172Simp} 146178172Simp 147178172Simp/* ARGSUSED */ 148178172Simpstatic int 149178172Simpmd_printins(int ins, int mdbdot) 150178172Simp{ 151178172Simp InstFmt i; 152178172Simp int delay = 0; 153178172Simp 154178172Simp i.word = ins; 155178172Simp 156178172Simp switch (i.JType.op) { 157178172Simp case OP_SPECIAL: 158178172Simp if (i.word == 0) { 159178172Simp db_printf("nop"); 160178172Simp break; 161178172Simp } 162178172Simp if (i.RType.func == OP_ADDU && i.RType.rt == 0) { 163178172Simp db_printf("move\t%s,%s", 164178172Simp reg_name[i.RType.rd], reg_name[i.RType.rs]); 165178172Simp break; 166178172Simp } 167178172Simp db_printf("%s", spec_name[i.RType.func]); 168178172Simp switch (i.RType.func) { 169178172Simp case OP_SLL: 170178172Simp case OP_SRL: 171178172Simp case OP_SRA: 172178172Simp case OP_DSLL: 173178172Simp case OP_DSRL: 174178172Simp case OP_DSRA: 175178172Simp case OP_DSLL32: 176178172Simp case OP_DSRL32: 177178172Simp case OP_DSRA32: 178178172Simp db_printf("\t%s,%s,%d", reg_name[i.RType.rd], 179178172Simp reg_name[i.RType.rt], i.RType.shamt); 180178172Simp break; 181178172Simp 182178172Simp case OP_SLLV: 183178172Simp case OP_SRLV: 184178172Simp case OP_SRAV: 185178172Simp case OP_DSLLV: 186178172Simp case OP_DSRLV: 187178172Simp case OP_DSRAV: 188178172Simp db_printf("\t%s,%s,%s", reg_name[i.RType.rd], 189178172Simp reg_name[i.RType.rt], reg_name[i.RType.rs]); 190178172Simp break; 191178172Simp 192178172Simp case OP_MFHI: 193178172Simp case OP_MFLO: 194178172Simp db_printf("\t%s", reg_name[i.RType.rd]); 195178172Simp break; 196178172Simp 197178172Simp case OP_JR: 198178172Simp case OP_JALR: 199178172Simp delay = 1; 200178172Simp /* FALLTHROUGH */ 201178172Simp case OP_MTLO: 202178172Simp case OP_MTHI: 203178172Simp db_printf("\t%s", reg_name[i.RType.rs]); 204178172Simp break; 205178172Simp 206178172Simp case OP_MULT: 207178172Simp case OP_MULTU: 208178172Simp case OP_DMULT: 209178172Simp case OP_DMULTU: 210178172Simp case OP_DIV: 211178172Simp case OP_DIVU: 212178172Simp case OP_DDIV: 213178172Simp case OP_DDIVU: 214178172Simp db_printf("\t%s,%s", 215178172Simp reg_name[i.RType.rs], reg_name[i.RType.rt]); 216178172Simp break; 217178172Simp 218178172Simp case OP_SYSCALL: 219178172Simp case OP_SYNC: 220178172Simp break; 221178172Simp 222178172Simp case OP_BREAK: 223178172Simp db_printf("\t%d", (i.RType.rs << 5) | i.RType.rt); 224178172Simp break; 225178172Simp 226178172Simp default: 227178172Simp db_printf("\t%s,%s,%s", reg_name[i.RType.rd], 228178172Simp reg_name[i.RType.rs], reg_name[i.RType.rt]); 229178172Simp }; 230178172Simp break; 231178172Simp 232178172Simp case OP_BCOND: 233178172Simp db_printf("%s\t%s,", bcond_name[i.IType.rt], 234178172Simp reg_name[i.IType.rs]); 235178172Simp goto pr_displ; 236178172Simp 237178172Simp case OP_BLEZ: 238178172Simp case OP_BLEZL: 239178172Simp case OP_BGTZ: 240178172Simp case OP_BGTZL: 241178172Simp db_printf("%s\t%s,", op_name[i.IType.op], 242178172Simp reg_name[i.IType.rs]); 243178172Simp goto pr_displ; 244178172Simp 245178172Simp case OP_BEQ: 246178172Simp case OP_BEQL: 247178172Simp if (i.IType.rs == 0 && i.IType.rt == 0) { 248178172Simp db_printf("b\t"); 249178172Simp goto pr_displ; 250178172Simp } 251178172Simp /* FALLTHROUGH */ 252178172Simp case OP_BNE: 253178172Simp case OP_BNEL: 254178172Simp db_printf("%s\t%s,%s,", op_name[i.IType.op], 255178172Simp reg_name[i.IType.rs], reg_name[i.IType.rt]); 256178172Simp pr_displ: 257178172Simp delay = 1; 258178172Simp db_printf("0x%08x", mdbdot + 4 + ((short)i.IType.imm << 2)); 259178172Simp break; 260178172Simp 261178172Simp case OP_COP0: 262178172Simp switch (i.RType.rs) { 263178172Simp case OP_BCx: 264178172Simp case OP_BCy: 265178172Simp db_printf("bc0%c\t", 266178172Simp "ft"[i.RType.rt & COPz_BC_TF_MASK]); 267178172Simp goto pr_displ; 268178172Simp 269178172Simp case OP_MT: 270178172Simp db_printf("mtc0\t%s,%s", 271178172Simp reg_name[i.RType.rt], c0_reg[i.RType.rd]); 272178172Simp break; 273178172Simp 274178172Simp case OP_DMT: 275178172Simp db_printf("dmtc0\t%s,%s", 276178172Simp reg_name[i.RType.rt], c0_reg[i.RType.rd]); 277178172Simp break; 278178172Simp 279178172Simp case OP_MF: 280178172Simp db_printf("mfc0\t%s,%s", 281178172Simp reg_name[i.RType.rt], c0_reg[i.RType.rd]); 282178172Simp break; 283178172Simp 284178172Simp case OP_DMF: 285178172Simp db_printf("dmfc0\t%s,%s", 286178172Simp reg_name[i.RType.rt], c0_reg[i.RType.rd]); 287178172Simp break; 288178172Simp 289178172Simp default: 290178172Simp db_printf("%s", c0_opname[i.FRType.func]); 291178172Simp }; 292178172Simp break; 293178172Simp 294178172Simp case OP_COP1: 295178172Simp switch (i.RType.rs) { 296178172Simp case OP_BCx: 297178172Simp case OP_BCy: 298178172Simp db_printf("bc1%c\t", 299178172Simp "ft"[i.RType.rt & COPz_BC_TF_MASK]); 300178172Simp goto pr_displ; 301178172Simp 302178172Simp case OP_MT: 303178172Simp db_printf("mtc1\t%s,f%d", 304178172Simp reg_name[i.RType.rt], i.RType.rd); 305178172Simp break; 306178172Simp 307178172Simp case OP_MF: 308178172Simp db_printf("mfc1\t%s,f%d", 309178172Simp reg_name[i.RType.rt], i.RType.rd); 310178172Simp break; 311178172Simp 312178172Simp case OP_CT: 313178172Simp db_printf("ctc1\t%s,f%d", 314178172Simp reg_name[i.RType.rt], i.RType.rd); 315178172Simp break; 316178172Simp 317178172Simp case OP_CF: 318178172Simp db_printf("cfc1\t%s,f%d", 319178172Simp reg_name[i.RType.rt], i.RType.rd); 320178172Simp break; 321178172Simp 322178172Simp default: 323178172Simp db_printf("%s.%s\tf%d,f%d,f%d", 324178172Simp cop1_name[i.FRType.func], fmt_name[i.FRType.fmt], 325178172Simp i.FRType.fd, i.FRType.fs, i.FRType.ft); 326178172Simp }; 327178172Simp break; 328178172Simp 329178172Simp case OP_J: 330178172Simp case OP_JAL: 331178172Simp db_printf("%s\t", op_name[i.JType.op]); 332178172Simp db_printf("0x%8x",(mdbdot & 0xF0000000) | (i.JType.target << 2)); 333178172Simp delay = 1; 334178172Simp break; 335178172Simp 336178172Simp case OP_LWC1: 337178172Simp case OP_SWC1: 338178172Simp db_printf("%s\tf%d,", op_name[i.IType.op], i.IType.rt); 339178172Simp goto loadstore; 340178172Simp 341178172Simp case OP_LB: 342178172Simp case OP_LH: 343178172Simp case OP_LW: 344178172Simp case OP_LD: 345178172Simp case OP_LBU: 346178172Simp case OP_LHU: 347178172Simp case OP_LWU: 348178172Simp case OP_SB: 349178172Simp case OP_SH: 350178172Simp case OP_SW: 351178172Simp case OP_SD: 352178172Simp db_printf("%s\t%s,", op_name[i.IType.op], 353178172Simp reg_name[i.IType.rt]); 354178172Simp loadstore: 355178172Simp db_printf("%d(%s)", (short)i.IType.imm, reg_name[i.IType.rs]); 356178172Simp break; 357178172Simp 358178172Simp case OP_ORI: 359178172Simp case OP_XORI: 360178172Simp if (i.IType.rs == 0) { 361178172Simp db_printf("li\t%s,0x%x", 362178172Simp reg_name[i.IType.rt], i.IType.imm); 363178172Simp break; 364178172Simp } 365178172Simp /* FALLTHROUGH */ 366178172Simp case OP_ANDI: 367178172Simp db_printf("%s\t%s,%s,0x%x", op_name[i.IType.op], 368178172Simp reg_name[i.IType.rt], reg_name[i.IType.rs], i.IType.imm); 369178172Simp break; 370178172Simp 371178172Simp case OP_LUI: 372178172Simp db_printf("%s\t%s,0x%x", op_name[i.IType.op], 373178172Simp reg_name[i.IType.rt], i.IType.imm); 374178172Simp break; 375178172Simp 376178172Simp case OP_ADDI: 377178172Simp case OP_DADDI: 378178172Simp case OP_ADDIU: 379178172Simp case OP_DADDIU: 380178172Simp if (i.IType.rs == 0) { 381178172Simp db_printf("li\t%s,%d", reg_name[i.IType.rt], 382178172Simp (short)i.IType.imm); 383178172Simp break; 384178172Simp } 385178172Simp /* FALLTHROUGH */ 386178172Simp default: 387178172Simp db_printf("%s\t%s,%s,%d", op_name[i.IType.op], 388178172Simp reg_name[i.IType.rt], reg_name[i.IType.rs], 389178172Simp (short)i.IType.imm); 390178172Simp } 391178172Simp return (delay); 392178172Simp} 393