Home | History | Annotate | Download | only in codeflinger
      1 /*  $NetBSD: db_disasm.c,v 1.19 2007/02/28 04:21:53 thorpej Exp $   */
      2 
      3 /*-
      4  * Copyright (c) 1991, 1993
      5  *  The Regents of the University of California.  All rights reserved.
      6  *
      7  * This code is derived from software contributed to Berkeley by
      8  * Ralph Campbell.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. Neither the name of the University nor the names of its contributors
     19  *    may be used to endorse or promote products derived from this software
     20  *    without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32  * SUCH DAMAGE.
     33  *
     34  *  from: @(#)kadb.c    8.1 (Berkeley) 6/10/93
     35  */
     36 
     37 #include <stdio.h>
     38 #include <stdint.h>
     39 #include <stdarg.h>
     40 #include <stdbool.h>
     41 #include <sys/cdefs.h>
     42 
     43 #include <sys/types.h>
     44 #include "mips_opcode.h"
     45 
     46 
     47 // #include <sys/systm.h>
     48 // #include <sys/param.h>
     49 
     50 // #include <machine/reg.h>
     51 // #include <machine/cpu.h>
     52 /*#include <machine/param.h>*/
     53 // #include <machine/db_machdep.h>
     54 
     55 // #include <ddb/db_interface.h>
     56 // #include <ddb/db_output.h>
     57 // #include <ddb/db_extern.h>
     58 // #include <ddb/db_sym.h>
     59 
     60 
     61 static char *sprintf_buffer;
     62 static int sprintf_buf_len;
     63 
     64 
     65 typedef uint32_t db_addr_t;
     66 static void db_printf(const char* fmt, ...);
     67 
     68 static const char * const op_name[64] = {
     69 /* 0 */ "spec", "bcond","j  ",    "jal",  "beq",  "bne",  "blez", "bgtz",
     70 /* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori",  "xori", "lui",
     71 /*16 */ "cop0", "cop1", "cop2", "cop3", "beql", "bnel", "blezl","bgtzl",
     72 /*24 */ "daddi","daddiu","ldl", "ldr",  "op34", "op35", "op36", "op37",
     73 /*32 */ "lb ",   "lh ",   "lwl",  "lw ",   "lbu",  "lhu",  "lwr",  "lwu",
     74 /*40 */ "sb ",   "sh ",   "swl",  "sw ",   "sdl",  "sdr",  "swr",  "cache",
     75 /*48 */ "ll ",   "lwc1", "lwc2", "lwc3", "lld",  "ldc1", "ldc2", "ld ",
     76 /*56 */ "sc ",   "swc1", "swc2", "swc3", "scd",  "sdc1", "sdc2", "sd "
     77 };
     78 
     79 static const char * const spec_name[64] = {
     80 /* 0 */ "sll",  "spec01","srl", "sra",  "sllv", "spec05","srlv","srav",
     81 /* 8 */ "jr",   "jalr", "movz","movn","syscall","break","spec16","sync",
     82 /*16 */ "mfhi", "mthi", "mflo", "mtlo", "dsllv","spec25","dsrlv","dsrav",
     83 /*24 */ "mult", "multu","div",  "divu", "dmult","dmultu","ddiv","ddivu",
     84 /*32 */ "add",  "addu", "sub",  "subu", "and",  "or ",   "xor",  "nor",
     85 /*40 */ "spec50","spec51","slt","sltu", "dadd","daddu","dsub","dsubu",
     86 /*48 */ "tge","tgeu","tlt","tltu","teq","spec65","tne","spec67",
     87 /*56 */ "dsll","spec71","dsrl","dsra","dsll32","spec75","dsrl32","dsra32"
     88 };
     89 
     90 static const char * const spec2_name[64] = {     /* QED RM4650, R5000, etc. */
     91 /* 0x00 */ "madd", "maddu", "mul", "spec3", "msub", "msubu", "rsrv6", "rsrv7",
     92 /* 0x08 */ "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv",
     93 /* 0x10 */ "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv",
     94 /* 0x18 */ "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv",
     95 /* 0x20 */ "clz",  "clo",  "rsrv", "rsrv", "dclz", "dclo", "rsrv", "rsrv",
     96 /* 0x28 */ "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv",
     97 /* 0x30 */ "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv",
     98 /* 0x38 */ "rsrv", "rsrv", "rsrv", "resv", "rsrv", "rsrv", "rsrv", "sdbbp"
     99 };
    100 
    101 static const char * const bcond_name[32] = {
    102 /* 0 */ "bltz", "bgez", "bltzl", "bgezl", "?", "?", "?", "?",
    103 /* 8 */ "tgei", "tgeiu", "tlti", "tltiu", "teqi", "?", "tnei", "?",
    104 /*16 */ "bltzal", "bgezal", "bltzall", "bgezall", "?", "?", "?", "?",
    105 /*24 */ "?", "?", "?", "?", "?", "?", "?", "?",
    106 };
    107 
    108 static const char * const cop1_name[64] = {
    109 /* 0 */ "fadd",  "fsub", "fmpy", "fdiv", "fsqrt","fabs", "fmov", "fneg",
    110 /* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
    111 /*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
    112 /*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
    113 /*32 */ "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
    114 /*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
    115 /*48 */ "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
    116     "fcmp.ole","fcmp.ule",
    117 /*56 */ "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
    118     "fcmp.le","fcmp.ngt"
    119 };
    120 
    121 static const char * const fmt_name[16] = {
    122     "s",    "d",    "e",    "fmt3",
    123     "w",    "fmt5", "fmt6", "fmt7",
    124     "fmt8", "fmt9", "fmta", "fmtb",
    125     "fmtc", "fmtd", "fmte", "fmtf"
    126 };
    127 
    128 #if defined(__mips_n32) || defined(__mips_n64)
    129 static char * const reg_name[32] = {
    130     "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3",
    131     "a4",   "a5",   "a6",   "a7",   "t0",   "t1",   "t2",   "t3",
    132     "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7",
    133     "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra"
    134 };
    135 #else
    136 
    137 static char * alt_arm_reg_name[32] = {  // hacked names for comparison with ARM code
    138     "zero", "at",   "r0",   "r1",   "r2",   "r3",   "r4",   "r5",
    139     "r6",   "r7",   "r8",   "r9",   "r10",  "r11",  "r12",  "r13",
    140     "r14",  "r15",  "at2",  "cmp",  "s4",   "s5",   "s6",   "s7",
    141     "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra"
    142 };
    143 
    144 static char * mips_reg_name[32] = {
    145     "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3",
    146     "t0",   "t1",   "t2",   "t3",   "t4",   "t5",   "t6",   "t7",
    147     "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7",
    148     "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra"
    149 };
    150 
    151 static char ** reg_name =  &mips_reg_name[0];
    152 
    153 #endif /* __mips_n32 || __mips_n64 */
    154 
    155 static const char * const c0_opname[64] = {
    156     "c0op00","tlbr",  "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
    157     "tlbp",  "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
    158     "rfe",   "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
    159     "eret",  "c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
    160     "c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
    161     "c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
    162     "c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
    163     "c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
    164 };
    165 
    166 static const char * const c0_reg[32] = {
    167     "index",    "random",   "tlblo0",  "tlblo1",
    168     "context",  "pagemask", "wired",   "cp0r7",
    169     "badvaddr", "count",    "tlbhi",   "compare",
    170     "status",   "cause",    "epc",     "prid",
    171     "config",   "lladdr",   "watchlo", "watchhi",
    172     "xcontext", "cp0r21",   "cp0r22",  "debug",
    173     "depc",     "perfcnt",  "ecc",     "cacheerr",
    174     "taglo",    "taghi",    "errepc",  "desave"
    175 };
    176 
    177 static void print_addr(db_addr_t);
    178 db_addr_t mips_disassem(db_addr_t loc, char *di_buffer, int alt_dis_format);
    179 
    180 
    181 /*
    182  * Disassemble instruction 'insn' nominally at 'loc'.
    183  * 'loc' may in fact contain a breakpoint instruction.
    184  */
    185 static db_addr_t
    186 db_disasm_insn(int insn, db_addr_t loc, bool altfmt)
    187 {
    188     bool bdslot = false;
    189     InstFmt i;
    190 
    191     i.word = insn;
    192 
    193     switch (i.JType.op) {
    194     case OP_SPECIAL:
    195         if (i.word == 0) {
    196             db_printf("nop");
    197             break;
    198         }
    199         if (i.word == 0x0080) {
    200             db_printf("NIY");
    201             break;
    202         }
    203         if (i.word == 0x00c0) {
    204             db_printf("NOT IMPL");
    205             break;
    206         }
    207         /* Special cases --------------------------------------------------
    208          * "addu" is a "move" only in 32-bit mode.  What's the correct
    209          * answer - never decode addu/daddu as "move"?
    210          */
    211         if ( (i.RType.func == OP_ADDU && i.RType.rt == 0)  ||
    212              (i.RType.func == OP_OR   && i.RType.rt == 0) ) {
    213             db_printf("move\t%s,%s",
    214                 reg_name[i.RType.rd],
    215                 reg_name[i.RType.rs]);
    216             break;
    217         }
    218         // mips32r2, rotr & rotrv
    219         if (i.RType.func == OP_SRL && (i.RType.rs & 1) == 1) {
    220             db_printf("rotr\t%s,%s,%d", reg_name[i.RType.rd],
    221                 reg_name[i.RType.rt], i.RType.shamt);
    222             break;
    223         }
    224         if (i.RType.func == OP_SRLV && (i.RType.shamt & 1) == 1) {
    225             db_printf("rotrv\t%s,%s,%s", reg_name[i.RType.rd],
    226                 reg_name[i.RType.rt], reg_name[i.RType.rs]);
    227             break;
    228         }
    229 
    230 
    231         db_printf("%s", spec_name[i.RType.func]);
    232         switch (i.RType.func) {
    233         case OP_SLL:
    234         case OP_SRL:
    235         case OP_SRA:
    236         case OP_DSLL:
    237 
    238         case OP_DSRL:
    239         case OP_DSRA:
    240         case OP_DSLL32:
    241         case OP_DSRL32:
    242         case OP_DSRA32:
    243             db_printf("\t%s,%s,%d",
    244                 reg_name[i.RType.rd],
    245                 reg_name[i.RType.rt],
    246                 i.RType.shamt);
    247             break;
    248 
    249         case OP_SLLV:
    250         case OP_SRLV:
    251         case OP_SRAV:
    252         case OP_DSLLV:
    253         case OP_DSRLV:
    254         case OP_DSRAV:
    255             db_printf("\t%s,%s,%s",
    256                 reg_name[i.RType.rd],
    257                 reg_name[i.RType.rt],
    258                 reg_name[i.RType.rs]);
    259             break;
    260 
    261         case OP_MFHI:
    262         case OP_MFLO:
    263             db_printf("\t%s", reg_name[i.RType.rd]);
    264             break;
    265 
    266         case OP_JR:
    267         case OP_JALR:
    268             db_printf("\t%s", reg_name[i.RType.rs]);
    269             bdslot = true;
    270             break;
    271         case OP_MTLO:
    272         case OP_MTHI:
    273             db_printf("\t%s", reg_name[i.RType.rs]);
    274             break;
    275 
    276         case OP_MULT:
    277         case OP_MULTU:
    278         case OP_DMULT:
    279         case OP_DMULTU:
    280         case OP_DIV:
    281         case OP_DIVU:
    282         case OP_DDIV:
    283         case OP_DDIVU:
    284             db_printf("\t%s,%s",
    285                 reg_name[i.RType.rs],
    286                 reg_name[i.RType.rt]);
    287             break;
    288 
    289 
    290         case OP_SYSCALL:
    291         case OP_SYNC:
    292             break;
    293 
    294         case OP_BREAK:
    295             db_printf("\t%d", (i.RType.rs << 5) | i.RType.rt);
    296             break;
    297 
    298         default:
    299             db_printf("\t%s,%s,%s",
    300                 reg_name[i.RType.rd],
    301                 reg_name[i.RType.rs],
    302                 reg_name[i.RType.rt]);
    303         }
    304         break;
    305 
    306     case OP_SPECIAL2:
    307         if (i.RType.func == OP_MUL)
    308             db_printf("%s\t%s,%s,%s",
    309                 spec2_name[i.RType.func & 0x3f],
    310                     reg_name[i.RType.rd],
    311                     reg_name[i.RType.rs],
    312                     reg_name[i.RType.rt]);
    313         else
    314             db_printf("%s\t%s,%s",
    315                 spec2_name[i.RType.func & 0x3f],
    316                     reg_name[i.RType.rs],
    317                     reg_name[i.RType.rt]);
    318 
    319         break;
    320 
    321     case OP_SPECIAL3:
    322         if (i.RType.func == OP_EXT)
    323             db_printf("ext\t%s,%s,%d,%d",
    324                     reg_name[i.RType.rt],
    325                     reg_name[i.RType.rs],
    326                     i.RType.rd+1,
    327                     i.RType.shamt);
    328         else if (i.RType.func == OP_INS)
    329             db_printf("ins\t%s,%s,%d,%d",
    330                     reg_name[i.RType.rt],
    331                     reg_name[i.RType.rs],
    332                     i.RType.rd+1,
    333                     i.RType.shamt);
    334         else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_WSBH)
    335             db_printf("wsbh\t%s,%s",
    336                 reg_name[i.RType.rd],
    337                 reg_name[i.RType.rt]);
    338         else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_SEB)
    339             db_printf("seb\t%s,%s",
    340                 reg_name[i.RType.rd],
    341                 reg_name[i.RType.rt]);
    342         else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_SEH)
    343             db_printf("seh\t%s,%s",
    344                 reg_name[i.RType.rd],
    345                 reg_name[i.RType.rt]);
    346         else
    347             db_printf("Unknown");
    348         break;
    349 
    350     case OP_BCOND:
    351         db_printf("%s\t%s,", bcond_name[i.IType.rt],
    352             reg_name[i.IType.rs]);
    353         goto pr_displ;
    354 
    355     case OP_BLEZ:
    356     case OP_BLEZL:
    357     case OP_BGTZ:
    358     case OP_BGTZL:
    359         db_printf("%s\t%s,", op_name[i.IType.op],
    360             reg_name[i.IType.rs]);
    361         goto pr_displ;
    362 
    363     case OP_BEQ:
    364     case OP_BEQL:
    365         if (i.IType.rs == 0 && i.IType.rt == 0) {
    366             db_printf("b  \t");
    367             goto pr_displ;
    368         }
    369         /* FALLTHROUGH */
    370     case OP_BNE:
    371     case OP_BNEL:
    372         db_printf("%s\t%s,%s,", op_name[i.IType.op],
    373             reg_name[i.IType.rs],
    374             reg_name[i.IType.rt]);
    375     pr_displ:
    376         print_addr(loc + 4 + ((short)i.IType.imm << 2));
    377         bdslot = true;
    378         break;
    379 
    380     case OP_COP0:
    381         switch (i.RType.rs) {
    382         case OP_BCx:
    383         case OP_BCy:
    384 
    385             db_printf("bc0%c\t",
    386                 "ft"[i.RType.rt & COPz_BC_TF_MASK]);
    387             goto pr_displ;
    388 
    389         case OP_MT:
    390             db_printf("mtc0\t%s,%s",
    391                 reg_name[i.RType.rt],
    392                 c0_reg[i.RType.rd]);
    393             break;
    394 
    395         case OP_DMT:
    396             db_printf("dmtc0\t%s,%s",
    397                 reg_name[i.RType.rt],
    398                 c0_reg[i.RType.rd]);
    399             break;
    400 
    401         case OP_MF:
    402             db_printf("mfc0\t%s,%s",
    403                 reg_name[i.RType.rt],
    404                 c0_reg[i.RType.rd]);
    405             break;
    406 
    407         case OP_DMF:
    408             db_printf("dmfc0\t%s,%s",
    409                 reg_name[i.RType.rt],
    410                 c0_reg[i.RType.rd]);
    411             break;
    412 
    413         default:
    414             db_printf("%s", c0_opname[i.FRType.func]);
    415         }
    416         break;
    417 
    418     case OP_COP1:
    419         switch (i.RType.rs) {
    420         case OP_BCx:
    421         case OP_BCy:
    422             db_printf("bc1%c\t",
    423                 "ft"[i.RType.rt & COPz_BC_TF_MASK]);
    424             goto pr_displ;
    425 
    426         case OP_MT:
    427             db_printf("mtc1\t%s,f%d",
    428                 reg_name[i.RType.rt],
    429                 i.RType.rd);
    430             break;
    431 
    432         case OP_MF:
    433             db_printf("mfc1\t%s,f%d",
    434                 reg_name[i.RType.rt],
    435                 i.RType.rd);
    436             break;
    437 
    438         case OP_CT:
    439             db_printf("ctc1\t%s,f%d",
    440                 reg_name[i.RType.rt],
    441                 i.RType.rd);
    442             break;
    443 
    444         case OP_CF:
    445             db_printf("cfc1\t%s,f%d",
    446                 reg_name[i.RType.rt],
    447                 i.RType.rd);
    448             break;
    449 
    450         default:
    451             db_printf("%s.%s\tf%d,f%d,f%d",
    452                 cop1_name[i.FRType.func],
    453                 fmt_name[i.FRType.fmt],
    454                 i.FRType.fd, i.FRType.fs, i.FRType.ft);
    455         }
    456         break;
    457 
    458     case OP_J:
    459     case OP_JAL:
    460         db_printf("%s\t", op_name[i.JType.op]);
    461         print_addr((loc & 0xF0000000) | (i.JType.target << 2));
    462         bdslot = true;
    463         break;
    464 
    465     case OP_LWC1:
    466     case OP_SWC1:
    467         db_printf("%s\tf%d,", op_name[i.IType.op],
    468             i.IType.rt);
    469         goto loadstore;
    470 
    471     case OP_LB:
    472     case OP_LH:
    473     case OP_LW:
    474     case OP_LD:
    475     case OP_LBU:
    476     case OP_LHU:
    477     case OP_LWU:
    478     case OP_SB:
    479     case OP_SH:
    480     case OP_SW:
    481     case OP_SD:
    482         db_printf("%s\t%s,", op_name[i.IType.op],
    483             reg_name[i.IType.rt]);
    484     loadstore:
    485         db_printf("%d(%s)", (short)i.IType.imm,
    486             reg_name[i.IType.rs]);
    487         break;
    488 
    489     case OP_ORI:
    490     case OP_XORI:
    491         if (i.IType.rs == 0) {
    492             db_printf("li\t%s,0x%x",
    493                 reg_name[i.IType.rt],
    494                 i.IType.imm);
    495             break;
    496         }
    497         /* FALLTHROUGH */
    498     case OP_ANDI:
    499         db_printf("%s\t%s,%s,0x%x", op_name[i.IType.op],
    500             reg_name[i.IType.rt],
    501             reg_name[i.IType.rs],
    502             i.IType.imm);
    503         break;
    504 
    505     case OP_LUI:
    506         db_printf("%s\t%s,0x%x", op_name[i.IType.op],
    507             reg_name[i.IType.rt],
    508             i.IType.imm);
    509         break;
    510 
    511     case OP_CACHE:
    512         db_printf("%s\t0x%x,0x%x(%s)",
    513             op_name[i.IType.op],
    514             i.IType.rt,
    515             i.IType.imm,
    516             reg_name[i.IType.rs]);
    517         break;
    518 
    519     case OP_ADDI:
    520     case OP_DADDI:
    521     case OP_ADDIU:
    522     case OP_DADDIU:
    523         if (i.IType.rs == 0) {
    524             db_printf("li\t%s,%d",
    525                 reg_name[i.IType.rt],
    526                 (short)i.IType.imm);
    527             break;
    528         }
    529         /* FALLTHROUGH */
    530     default:
    531         db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
    532             reg_name[i.IType.rt],
    533             reg_name[i.IType.rs],
    534             (short)i.IType.imm);
    535     }
    536     // db_printf("\n");
    537     // if (bdslot) {
    538     //     db_printf("   bd: ");
    539     //     mips_disassem(loc+4);
    540     //     return (loc + 8);
    541     // }
    542     return (loc + 4);
    543 }
    544 
    545 static void
    546 print_addr(db_addr_t loc)
    547 {
    548     db_printf("0x%08x", loc);
    549 }
    550 
    551 
    552 
    553 static void db_printf(const char* fmt, ...)
    554 {
    555     int cnt;
    556     va_list argp;
    557     va_start(argp, fmt);
    558     if (sprintf_buffer) {
    559         cnt = vsnprintf(sprintf_buffer, sprintf_buf_len, fmt, argp);
    560         sprintf_buffer += cnt;
    561         sprintf_buf_len -= cnt;
    562     } else {
    563         vprintf(fmt, argp);
    564     }
    565 }
    566 
    567 
    568 /*
    569  * Disassemble instruction at 'loc'.
    570  * Return address of start of next instruction.
    571  * Since this function is used by 'examine' and by 'step'
    572  * "next instruction" does NOT mean the next instruction to
    573  * be executed but the 'linear' next instruction.
    574  */
    575 db_addr_t
    576 mips_disassem(db_addr_t loc, char *di_buffer, int alt_dis_format)
    577 {
    578     u_int32_t instr;
    579 
    580     if (alt_dis_format) {   // use ARM register names for disassembly
    581         reg_name = &alt_arm_reg_name[0];
    582     }
    583 
    584     sprintf_buffer = di_buffer;     // quick 'n' dirty printf() vs sprintf()
    585     sprintf_buf_len = 39;           // should be passed in
    586 
    587     instr =  *(u_int32_t *)loc;
    588     return (db_disasm_insn(instr, loc, false));
    589 }
    590 
    591