• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <cutils/log.h>
47 
48 static char *sprintf_buffer;
49 static int sprintf_buf_len;
50 
51 
52 typedef uint64_t db_addr_t;
53 static void db_printf(const char* fmt, ...);
54 
55 static const char * const op_name[64] = {
56 /* 0 */ "spec", "bcond", "j", "jal", "beq", "bne", "blez", "bgtz",
57 /* 8 */ "pop10", "addiu", "slti", "sltiu", "andi", "ori", "xori", "aui",
58 /*16 */ "cop0", "cop1", "cop2", "?", "?", "?", "pop26", "pop27",
59 /*24 */ "pop30", "daddiu", "?", "?", "?", "daui", "msa", "op37",
60 /*32 */ "lb", "lh", "?",  "lw", "lbu", "lhu", "?", "lwu",
61 /*40 */ "sb", "sh", "?", "sw", "?", "?", "?", "?",
62 /*48 */ "?", "lwc1", "bc", "?", "?",  "ldc1", "pop66", "ld",
63 /*56 */ "?", "swc1", "balc", "pcrel", "?", "sdc1", "pop76", "sd"
64 };
65 
66 static const char * const spec_name[64] = {
67 /* 0 */ "sll", "?", "srl", "sra", "sllv", "?", "srlv", "srav",
68 /* 8 */ "?", "jalr", "?", "?", "syscall", "break", "sdbpp", "sync",
69 /*16 */ "clz", "clo", "dclz", "dclo", "dsllv", "dlsa", "dsrlv", "dsrav",
70 /*24 */ "sop30", "sop31", "sop32", "sop33", "sop34", "sop35", "sop36", "sop37",
71 /*32 */ "add", "addu", "sub", "subu", "and", "or", "xor", "nor",
72 /*40 */ "?", "?", "slt", "sltu", "dadd", "daddu", "dsub", "dsubu",
73 /*48 */ "tge", "tgeu", "tlt", "tltu", "teq", "seleqz", "tne", "selnez",
74 /*56 */ "dsll", "?", "dsrl", "dsra", "dsll32", "?", "dsrl32", "dsra32"
75 };
76 
77 static const char * const bcond_name[32] = {
78 /* 0 */ "bltz", "bgez", "?", "?", "?", "?", "dahi", "?",
79 /* 8 */ "?", "?", "?", "?", "?", "?", "?", "?",
80 /*16 */ "nal", "bal", "?", "?", "?", "?", "?", "sigrie",
81 /*24 */ "?", "?", "?", "?", "?", "?", "dati", "synci",
82 };
83 
84 static const char * const cop1_name[64] = {
85 /* 0 */ "fadd",  "fsub", "fmpy", "fdiv", "fsqrt","fabs", "fmov", "fneg",
86 /* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
87 /*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
88 /*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
89 /*32 */ "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
90 /*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
91 /*48 */ "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
92     "fcmp.ole","fcmp.ule",
93 /*56 */ "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
94     "fcmp.le","fcmp.ngt"
95 };
96 
97 static const char * const fmt_name[16] = {
98     "s",    "d",    "e",    "fmt3",
99     "w",    "fmt5", "fmt6", "fmt7",
100     "fmt8", "fmt9", "fmta", "fmtb",
101     "fmtc", "fmtd", "fmte", "fmtf"
102 };
103 
104 static char * const mips_reg_name[32] = {
105     "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3",
106     "a4",   "a5",   "a6",   "a7",   "t0",   "t1",   "t2",   "t3",
107     "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7",
108     "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra"
109 };
110 
111 static char * alt_arm_reg_name[32] = {  // hacked names for comparison with ARM code
112     "zero", "at",   "r0",   "r1",   "r2",   "r3",   "r4",   "r5",
113     "r6",   "r7",   "r8",   "r9",   "r10",  "r11",  "r12",  "r13",
114     "r14",  "r15",  "at2",  "cmp",  "s4",   "s5",   "s6",   "s7",
115     "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra"
116 };
117 
118 static char ** reg_name =  &mips_reg_name[0];
119 
120 static const char * const c0_opname[64] = {
121     "c0op00","tlbr",  "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
122     "tlbp",  "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
123     "rfe",   "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
124     "eret",  "c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
125     "c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
126     "c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
127     "c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
128     "c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
129 };
130 
131 static const char * const c0_reg[32] = {
132     "index",    "random",   "tlblo0",  "tlblo1",
133     "context",  "pagemask", "wired",   "cp0r7",
134     "badvaddr", "count",    "tlbhi",   "compare",
135     "status",   "cause",    "epc",     "prid",
136     "config",   "lladdr",   "watchlo", "watchhi",
137     "xcontext", "cp0r21",   "cp0r22",  "debug",
138     "depc",     "perfcnt",  "ecc",     "cacheerr",
139     "taglo",    "taghi",    "errepc",  "desave"
140 };
141 
142 static void print_addr(db_addr_t);
143 db_addr_t mips_disassem(db_addr_t loc, char *di_buffer, int alt_dis_format);
144 
145 
146 /*
147  * Disassemble instruction 'insn' nominally at 'loc'.
148  * 'loc' may in fact contain a breakpoint instruction.
149  */
150 static db_addr_t
db_disasm_insn(int insn,db_addr_t loc,bool altfmt)151 db_disasm_insn(int insn, db_addr_t loc, bool altfmt)
152 {
153     bool bdslot = false;
154     InstFmt i;
155 
156     i.word = insn;
157 
158     switch (i.JType.op) {
159     case OP_SPECIAL:
160         if (i.word == 0) {
161             db_printf("nop");
162             break;
163         }
164         if (i.word == 0x0080) {
165             db_printf("NIY");
166             break;
167         }
168         if (i.word == 0x00c0) {
169             db_printf("NOT IMPL");
170             break;
171         }
172         /* Special cases --------------------------------------------------
173          * "addu" is a "move" only in 32-bit mode.  What's the correct
174          * answer - never decode addu/daddu as "move"?
175          */
176         if ( (i.RType.func == OP_ADDU && i.RType.rt == 0)  ||
177              (i.RType.func == OP_OR   && i.RType.rt == 0) ) {
178             db_printf("move\t%s,%s",
179                 reg_name[i.RType.rd],
180                 reg_name[i.RType.rs]);
181             break;
182         }
183 
184         if (i.RType.func == OP_SRL && (i.RType.rs & 1) == 1) {
185             db_printf("rotr\t%s,%s,%d", reg_name[i.RType.rd],
186                 reg_name[i.RType.rt], i.RType.shamt);
187             break;
188         }
189         if (i.RType.func == OP_SRLV && (i.RType.shamt & 1) == 1) {
190             db_printf("rotrv\t%s,%s,%s", reg_name[i.RType.rd],
191                 reg_name[i.RType.rt], reg_name[i.RType.rs]);
192             break;
193         }
194 
195         if (i.RType.func == OP_SOP30) {
196             if (i.RType.shamt == OP_MUL) {
197                 db_printf("mul");
198             } else if (i.RType.shamt == OP_MUH) {
199                 db_printf("muh");
200             }
201             db_printf("\t%s,%s,%s", reg_name[i.RType.rd],
202                 reg_name[i.RType.rs], reg_name[i.RType.rt]);
203             break;
204         }
205         if (i.RType.func == OP_SOP31) {
206             if (i.RType.shamt == OP_MUL) {
207                 db_printf("mulu");
208             } else if (i.RType.shamt == OP_MUH) {
209                 db_printf("muhu");
210             }
211             db_printf("\t%s,%s,%s", reg_name[i.RType.rd],
212                 reg_name[i.RType.rs], reg_name[i.RType.rt]);
213             break;
214         }
215 
216         if (i.RType.func == OP_JALR && i.RType.rd == 0) {
217             db_printf("jr\t%s", reg_name[i.RType.rs]);
218             bdslot = true;
219             break;
220         }
221 
222         db_printf("%s", spec_name[i.RType.func]);
223         switch (i.RType.func) {
224         case OP_SLL:
225         case OP_SRL:
226         case OP_SRA:
227         case OP_DSLL:
228 
229         case OP_DSRL:
230         case OP_DSRA:
231         case OP_DSLL32:
232         case OP_DSRL32:
233         case OP_DSRA32:
234             db_printf("\t%s,%s,%d",
235                 reg_name[i.RType.rd],
236                 reg_name[i.RType.rt],
237                 i.RType.shamt);
238             break;
239 
240         case OP_SLLV:
241         case OP_SRLV:
242         case OP_SRAV:
243         case OP_DSLLV:
244         case OP_DSRLV:
245         case OP_DSRAV:
246             db_printf("\t%s,%s,%s",
247                 reg_name[i.RType.rd],
248                 reg_name[i.RType.rt],
249                 reg_name[i.RType.rs]);
250             break;
251 
252         case OP_CLZ:
253         case OP_CLO:
254         case OP_DCLZ:
255         case OP_DCLO:
256             db_printf("\t%s,%s",
257                 reg_name[i.RType.rd],
258                 reg_name[i.RType.rs]);
259             break;
260 
261         case OP_JALR:
262             db_printf("\t");
263             if (i.RType.rd != 31) {
264                 db_printf("%s,", reg_name[i.RType.rd]);
265             }
266             db_printf("%s", reg_name[i.RType.rs]);
267             bdslot = true;
268             break;
269 
270         case OP_SYSCALL:
271         case OP_SYNC:
272             break;
273 
274         case OP_BREAK:
275             db_printf("\t%d", (i.RType.rs << 5) | i.RType.rt);
276             break;
277 
278         default:
279             db_printf("\t%s,%s,%s",
280                 reg_name[i.RType.rd],
281                 reg_name[i.RType.rs],
282                 reg_name[i.RType.rt]);
283         }
284         break;
285 
286     case OP_SPECIAL3:
287         if (i.RType.func == OP_EXT)
288             db_printf("ext\t%s,%s,%d,%d",
289                     reg_name[i.RType.rt],
290                     reg_name[i.RType.rs],
291                     i.RType.shamt,
292                     i.RType.rd+1);
293         else if (i.RType.func == OP_DEXT)
294             db_printf("dext\t%s,%s,%d,%d",
295                     reg_name[i.RType.rt],
296                     reg_name[i.RType.rs],
297                     i.RType.shamt,
298                     i.RType.rd+1);
299         else if (i.RType.func == OP_DEXTM)
300             db_printf("dextm\t%s,%s,%d,%d",
301                     reg_name[i.RType.rt],
302                     reg_name[i.RType.rs],
303                     i.RType.shamt,
304                     i.RType.rd+33);
305         else if (i.RType.func == OP_DEXTU)
306             db_printf("dextu\t%s,%s,%d,%d",
307                     reg_name[i.RType.rt],
308                     reg_name[i.RType.rs],
309                     i.RType.shamt+32,
310                     i.RType.rd+1);
311         else if (i.RType.func == OP_INS)
312             db_printf("ins\t%s,%s,%d,%d",
313                     reg_name[i.RType.rt],
314                     reg_name[i.RType.rs],
315                     i.RType.shamt,
316                     i.RType.rd-i.RType.shamt+1);
317         else if (i.RType.func == OP_DINS)
318             db_printf("dins\t%s,%s,%d,%d",
319                     reg_name[i.RType.rt],
320                     reg_name[i.RType.rs],
321                     i.RType.shamt,
322                     i.RType.rd-i.RType.shamt+1);
323         else if (i.RType.func == OP_DINSM)
324             db_printf("dinsm\t%s,%s,%d,%d",
325                     reg_name[i.RType.rt],
326                     reg_name[i.RType.rs],
327                     i.RType.shamt,
328                     i.RType.rd-i.RType.shamt+33);
329         else if (i.RType.func == OP_DINSU)
330             db_printf("dinsu\t%s,%s,%d,%d",
331                     reg_name[i.RType.rt],
332                     reg_name[i.RType.rs],
333                     i.RType.shamt+32,
334                     i.RType.rd-i.RType.shamt+1);
335         else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_WSBH)
336             db_printf("wsbh\t%s,%s",
337                 reg_name[i.RType.rd],
338                 reg_name[i.RType.rt]);
339         else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_SEB)
340             db_printf("seb\t%s,%s",
341                 reg_name[i.RType.rd],
342                 reg_name[i.RType.rt]);
343         else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_SEH)
344             db_printf("seh\t%s,%s",
345                 reg_name[i.RType.rd],
346                 reg_name[i.RType.rt]);
347         else if (i.RType.func == OP_RDHWR)
348             db_printf("rdhwr\t%s,%s",
349                 reg_name[i.RType.rd],
350                 reg_name[i.RType.rt]);
351         else
352             db_printf("Unknown");
353         break;
354 
355     case OP_BCOND:
356         db_printf("%s\t%s,", bcond_name[i.IType.rt],
357             reg_name[i.IType.rs]);
358         goto pr_displ;
359 
360     case OP_BLEZ:
361     case OP_BGTZ:
362         db_printf("%s\t%s,", op_name[i.IType.op],
363             reg_name[i.IType.rs]);
364         goto pr_displ;
365 
366     case OP_BEQ:
367         if (i.IType.rs == 0 && i.IType.rt == 0) {
368             db_printf("b\t");
369             goto pr_displ;
370         }
371         /* FALLTHROUGH */
372     case OP_BNE:
373         db_printf("%s\t%s,%s,", op_name[i.IType.op],
374             reg_name[i.IType.rs],
375             reg_name[i.IType.rt]);
376     pr_displ:
377         print_addr(loc + 4 + ((short)i.IType.imm << 2));
378         bdslot = true;
379         break;
380 
381     case OP_COP0:
382         switch (i.RType.rs) {
383         case OP_BCx:
384         case OP_BCy:
385 
386             db_printf("bc0%c\t",
387                 "ft"[i.RType.rt & COPz_BC_TF_MASK]);
388             goto pr_displ;
389 
390         case OP_MT:
391             db_printf("mtc0\t%s,%s",
392                 reg_name[i.RType.rt],
393                 c0_reg[i.RType.rd]);
394             break;
395 
396         case OP_DMT:
397             db_printf("dmtc0\t%s,%s",
398                 reg_name[i.RType.rt],
399                 c0_reg[i.RType.rd]);
400             break;
401 
402         case OP_MF:
403             db_printf("mfc0\t%s,%s",
404                 reg_name[i.RType.rt],
405                 c0_reg[i.RType.rd]);
406             break;
407 
408         case OP_DMF:
409             db_printf("dmfc0\t%s,%s",
410                 reg_name[i.RType.rt],
411                 c0_reg[i.RType.rd]);
412             break;
413 
414         default:
415             db_printf("%s", c0_opname[i.FRType.func]);
416         }
417         break;
418 
419     case OP_COP1:
420         switch (i.RType.rs) {
421         case OP_BCx:
422         case OP_BCy:
423             db_printf("bc1%c\t",
424                 "ft"[i.RType.rt & COPz_BC_TF_MASK]);
425             goto pr_displ;
426 
427         case OP_MT:
428             db_printf("mtc1\t%s,f%d",
429                 reg_name[i.RType.rt],
430                 i.RType.rd);
431             break;
432 
433         case OP_MF:
434             db_printf("mfc1\t%s,f%d",
435                 reg_name[i.RType.rt],
436                 i.RType.rd);
437             break;
438 
439         case OP_CT:
440             db_printf("ctc1\t%s,f%d",
441                 reg_name[i.RType.rt],
442                 i.RType.rd);
443             break;
444 
445         case OP_CF:
446             db_printf("cfc1\t%s,f%d",
447                 reg_name[i.RType.rt],
448                 i.RType.rd);
449             break;
450 
451         default:
452             db_printf("%s.%s\tf%d,f%d,f%d",
453                 cop1_name[i.FRType.func],
454                 fmt_name[i.FRType.fmt],
455                 i.FRType.fd, i.FRType.fs, i.FRType.ft);
456         }
457         break;
458 
459     case OP_J:
460     case OP_JAL:
461         db_printf("%s\t", op_name[i.JType.op]);
462         print_addr((loc & 0xFFFFFFFFF0000000) | (i.JType.target << 2));
463         bdslot = true;
464         break;
465 
466     case OP_LWC1:
467     case OP_SWC1:
468         db_printf("%s\tf%d,", op_name[i.IType.op],
469             i.IType.rt);
470         goto loadstore;
471 
472     case OP_LB:
473     case OP_LH:
474     case OP_LW:
475     case OP_LD:
476     case OP_LBU:
477     case OP_LHU:
478     case OP_LWU:
479     case OP_SB:
480     case OP_SH:
481     case OP_SW:
482     case OP_SD:
483         db_printf("%s\t%s,", op_name[i.IType.op],
484             reg_name[i.IType.rt]);
485     loadstore:
486         db_printf("%d(%s)", (short)i.IType.imm,
487             reg_name[i.IType.rs]);
488         break;
489 
490     case OP_ORI:
491     case OP_XORI:
492         if (i.IType.rs == 0) {
493             db_printf("li\t%s,0x%x",
494                 reg_name[i.IType.rt],
495                 i.IType.imm);
496             break;
497         }
498         /* FALLTHROUGH */
499     case OP_ANDI:
500         db_printf("%s\t%s,%s,0x%x", op_name[i.IType.op],
501             reg_name[i.IType.rt],
502             reg_name[i.IType.rs],
503             i.IType.imm);
504         break;
505 
506     case OP_AUI:
507         if (i.IType.rs == 0) {
508             db_printf("lui\t%s,0x%x", reg_name[i.IType.rt],
509                 i.IType.imm);
510         } else {
511             db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
512             reg_name[i.IType.rt], reg_name[i.IType.rs],
513             (short)i.IType.imm);
514         }
515         break;
516 
517     case OP_ADDIU:
518     case OP_DADDIU:
519         if (i.IType.rs == 0) {
520             db_printf("li\t%s,%d",
521                 reg_name[i.IType.rt],
522                 (short)i.IType.imm);
523             break;
524         }
525         /* FALLTHROUGH */
526     default:
527         db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
528             reg_name[i.IType.rt],
529             reg_name[i.IType.rs],
530             (short)i.IType.imm);
531     }
532     // db_printf("\n");
533     // if (bdslot) {
534     //     db_printf("   bd: ");
535     //     mips_disassem(loc+4);
536     //     return (loc + 8);
537     // }
538     return (loc + 4);
539 }
540 
541 static void
print_addr(db_addr_t loc)542 print_addr(db_addr_t loc)
543 {
544     db_printf("0x%08lx", loc);
545 }
546 
db_printf(const char * fmt,...)547 static void db_printf(const char* fmt, ...)
548 {
549     int cnt;
550     va_list argp;
551     va_start(argp, fmt);
552     if (sprintf_buffer) {
553         cnt = vsnprintf(sprintf_buffer, sprintf_buf_len, fmt, argp);
554         sprintf_buffer += cnt;
555         sprintf_buf_len -= cnt;
556     } else {
557         vprintf(fmt, argp);
558     }
559 }
560 
561 /*
562  * Disassemble instruction at 'loc'.
563  * Return address of start of next instruction.
564  * Since this function is used by 'examine' and by 'step'
565  * "next instruction" does NOT mean the next instruction to
566  * be executed but the 'linear' next instruction.
567  */
568 db_addr_t
mips_disassem(db_addr_t loc,char * di_buffer,int alt_dis_format)569 mips_disassem(db_addr_t loc, char *di_buffer, int alt_dis_format)
570 {
571     u_int32_t instr;
572 
573     if (alt_dis_format) {   // use ARM register names for disassembly
574         reg_name = &alt_arm_reg_name[0];
575     }
576 
577     sprintf_buffer = di_buffer;     // quick 'n' dirty printf() vs sprintf()
578     sprintf_buf_len = 39;           // should be passed in
579 
580     instr =  *(u_int32_t *)loc;
581     return (db_disasm_insn(instr, loc, false));
582 }
583