1 /* src/vm/jit/mips/disass.c - primitive disassembler for MIPS machine code
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 $Id: disass.c 7252 2007-01-29 21:09:01Z twisti $
36 #include "vm/jit/abi.h"
39 /* The disassembler uses four tables for decoding the instructions. The first
40 table (ops) is used to classify the instructions based on the op code and
41 contains the instruction names for instructions which don't used the
42 function codes. This table is indexed by the op code (6 bit, 64 entries).
43 The other tables are either indexed by the function code or some special
44 format and branch codes.
47 #define ITYPE_UNDEF 0 /* undefined instructions (illegal opcode) */
48 #define ITYPE_JMP 1 /* jump instructions */
49 #define ITYPE_IMM 2 /* immediate instructions */
50 #define ITYPE_MEM 3 /* memory instructions */
51 #define ITYPE_FMEM 4 /* floating point memory instructions */
52 #define ITYPE_BRA 5 /* branch instructions */
53 #define ITYPE_RIMM 6 /* special/branch instructions */
54 #define ITYPE_OP 7 /* integer instructions */
55 #define ITYPE_TRAP 8 /* trap instructions */
56 #define ITYPE_DIVMUL 9 /* integer divide/multiply instructions */
57 #define ITYPE_MTOJR 10 /* move to and jump register instructions */
58 #define ITYPE_MFROM 11 /* move from instructions */
59 #define ITYPE_SYS 12 /* operating system instructions */
60 #define ITYPE_FOP 13 /* floating point instructions */
61 #define ITYPE_FOP2 14 /* 2 operand floating point instructions */
62 #define ITYPE_FCMP 15 /* floating point compare instructions */
65 /* instruction decode table for 6 bit op codes */
67 static struct {char *name; int itype;} ops[] = {
69 /* 0x00 */ {"special ", ITYPE_OP},
70 /* 0x01 */ {"regimm ", ITYPE_RIMM},
71 /* 0x02 */ {"j ", ITYPE_JMP},
72 /* 0x03 */ {"jal ", ITYPE_JMP},
73 /* 0x04 */ {"beq ", ITYPE_BRA},
74 /* 0x05 */ {"bne ", ITYPE_BRA},
75 /* 0x06 */ {"blez ", ITYPE_BRA},
76 /* 0x07 */ {"bgtz ", ITYPE_BRA},
78 /* 0x08 */ {"addi ", ITYPE_IMM},
79 /* 0x09 */ {"addiu ", ITYPE_IMM},
80 /* 0x0a */ {"slti ", ITYPE_IMM},
81 /* 0x0b */ {"sltiu ", ITYPE_IMM},
82 /* 0x0c */ {"andi ", ITYPE_IMM},
83 /* 0x0d */ {"ori ", ITYPE_IMM},
84 /* 0x0e */ {"xori ", ITYPE_IMM},
85 /* 0x0f */ {"lui ", ITYPE_IMM},
87 /* 0x10 */ {"cop0 ", ITYPE_OP},
88 /* 0x11 */ {"cop1 ", ITYPE_FOP},
89 /* 0x12 */ {"cop2 ", ITYPE_OP},
90 /* 0x13 */ {"", ITYPE_UNDEF},
91 /* 0x14 */ {"beql ", ITYPE_BRA},
92 /* 0x15 */ {"bnel ", ITYPE_BRA},
93 /* 0x16 */ {"blezl ", ITYPE_BRA},
94 /* 0x17 */ {"bgtzl ", ITYPE_BRA},
96 /* 0x18 */ {"daddi ", ITYPE_IMM},
97 /* 0x19 */ {"daddiu ", ITYPE_IMM},
98 /* 0x1a */ {"ldl ", ITYPE_MEM},
99 /* 0x1b */ {"ldr ", ITYPE_MEM},
100 /* 0x1c */ {"", ITYPE_UNDEF},
101 /* 0x1d */ {"", ITYPE_UNDEF},
102 /* 0x1e */ {"", ITYPE_UNDEF},
103 /* 0x1f */ {"", ITYPE_UNDEF},
105 /* 0x20 */ {"lb ", ITYPE_MEM},
106 /* 0x21 */ {"lh ", ITYPE_MEM},
107 /* 0x22 */ {"lwl ", ITYPE_MEM},
108 /* 0x23 */ {"lw ", ITYPE_MEM},
109 /* 0x24 */ {"lbu ", ITYPE_MEM},
110 /* 0x25 */ {"lhu ", ITYPE_MEM},
111 /* 0x26 */ {"lwr ", ITYPE_MEM},
112 /* 0x27 */ {"lwu ", ITYPE_MEM},
114 /* 0x28 */ {"sb ", ITYPE_MEM},
115 /* 0x29 */ {"sh ", ITYPE_MEM},
116 /* 0x2a */ {"swl ", ITYPE_MEM},
117 /* 0x2b */ {"sw ", ITYPE_MEM},
118 /* 0x2c */ {"sdl ", ITYPE_MEM},
119 /* 0x2d */ {"sdr ", ITYPE_MEM},
120 /* 0x2e */ {"swr ", ITYPE_MEM},
121 /* 0x2f */ {"cache ", ITYPE_MEM},
123 /* 0x30 */ {"ll ", ITYPE_MEM},
124 /* 0x31 */ {"lwc1 ", ITYPE_FMEM},
125 /* 0x32 */ {"lwc2 ", ITYPE_MEM},
126 /* 0x33 */ {"", ITYPE_UNDEF},
127 /* 0x34 */ {"lld ", ITYPE_MEM},
128 /* 0x35 */ {"ldc1 ", ITYPE_FMEM},
129 /* 0x36 */ {"ldc2 ", ITYPE_MEM},
130 /* 0x37 */ {"ld ", ITYPE_MEM},
132 /* 0x38 */ {"sc ", ITYPE_MEM},
133 /* 0x39 */ {"swc1 ", ITYPE_FMEM},
134 /* 0x3a */ {"swc2 ", ITYPE_MEM},
135 /* 0x3b */ {"", ITYPE_UNDEF},
136 /* 0x3c */ {"sld ", ITYPE_MEM},
137 /* 0x3d */ {"sdc1 ", ITYPE_FMEM},
138 /* 0x3e */ {"sdc2 ", ITYPE_MEM},
139 /* 0x3f */ {"sd ", ITYPE_MEM}
143 /* instruction decode table for 6 bit special function codes */
145 static struct {char *name; int ftype;} regops[] = {
147 /* 0x00 */ {"sll ", ITYPE_IMM},
148 /* 0x01 */ {"" , ITYPE_UNDEF},
149 /* 0x02 */ {"srl ", ITYPE_IMM},
150 /* 0x03 */ {"sra ", ITYPE_IMM},
151 /* 0x04 */ {"sllv ", ITYPE_OP},
152 /* 0x05 */ {"" , ITYPE_UNDEF},
153 /* 0x06 */ {"srlv ", ITYPE_OP},
154 /* 0x07 */ {"srav ", ITYPE_OP},
156 /* 0x08 */ {"jr ", ITYPE_MTOJR},
157 /* 0x09 */ {"jalr ", ITYPE_JMP},
158 /* 0x0a */ {"" , ITYPE_UNDEF},
159 /* 0x0b */ {"" , ITYPE_UNDEF},
160 /* 0x0c */ {"syscall ", ITYPE_SYS},
161 /* 0x0d */ {"break ", ITYPE_SYS},
162 /* 0x0e */ {"" , ITYPE_UNDEF},
163 /* 0x0f */ {"sync ", ITYPE_SYS},
165 /* 0x10 */ {"mfhi ", ITYPE_MFROM},
166 /* 0x11 */ {"mthi ", ITYPE_MTOJR},
167 /* 0x12 */ {"mflo ", ITYPE_MFROM},
168 /* 0x13 */ {"mtlo ", ITYPE_MTOJR},
169 /* 0x14 */ {"dsllv ", ITYPE_OP},
170 /* 0x15 */ {"" , ITYPE_UNDEF},
171 /* 0x16 */ {"dslrv ", ITYPE_OP},
172 /* 0x17 */ {"dsrav ", ITYPE_OP},
174 /* 0x18 */ {"mult ",ITYPE_DIVMUL},
175 /* 0x19 */ {"multu ",ITYPE_DIVMUL},
176 /* 0x1a */ {"div ",ITYPE_DIVMUL},
177 /* 0x1b */ {"divu ",ITYPE_DIVMUL},
178 /* 0x1c */ {"dmult ",ITYPE_DIVMUL},
179 /* 0x1d */ {"dmultu ",ITYPE_DIVMUL},
180 /* 0x1e */ {"ddiv ",ITYPE_DIVMUL},
181 /* 0x1f */ {"ddivu ",ITYPE_DIVMUL},
183 /* 0x20 */ {"add ", ITYPE_OP},
184 /* 0x21 */ {"addu ", ITYPE_OP},
185 /* 0x22 */ {"sub ", ITYPE_OP},
186 /* 0x23 */ {"subu ", ITYPE_OP},
187 /* 0x24 */ {"and ", ITYPE_OP},
188 /* 0x25 */ {"or ", ITYPE_OP},
189 /* 0x26 */ {"xor ", ITYPE_OP},
190 /* 0x27 */ {"nor ", ITYPE_OP},
192 /* 0x28 */ {"" , ITYPE_UNDEF},
193 /* 0x29 */ {"" , ITYPE_UNDEF},
194 /* 0x2a */ {"slt ", ITYPE_OP},
195 /* 0x2b */ {"sltu ", ITYPE_OP},
196 /* 0x2c */ {"dadd ", ITYPE_OP},
197 /* 0x2d */ {"daddu ", ITYPE_OP},
198 /* 0x2e */ {"dsub ", ITYPE_OP},
199 /* 0x2f */ {"dsubu ", ITYPE_OP},
201 /* 0x30 */ {"tge ", ITYPE_TRAP},
202 /* 0x31 */ {"tgeu ", ITYPE_TRAP},
203 /* 0x32 */ {"tlt ", ITYPE_TRAP},
204 /* 0x33 */ {"tltu ", ITYPE_TRAP},
205 /* 0x34 */ {"teq ", ITYPE_TRAP},
206 /* 0x35 */ {"" , ITYPE_UNDEF},
207 /* 0x36 */ {"tne ", ITYPE_TRAP},
208 /* 0x37 */ {"" , ITYPE_UNDEF},
210 /* 0x38 */ {"dsll ", ITYPE_IMM},
211 /* 0x39 */ {"" , ITYPE_UNDEF},
212 /* 0x3a */ {"dsrl ", ITYPE_IMM},
213 /* 0x3b */ {"dsra ", ITYPE_IMM},
214 /* 0x3c */ {"dsll32 ", ITYPE_IMM},
215 /* 0x3d */ {"" , ITYPE_UNDEF},
216 /* 0x3e */ {"dsrl32 ", ITYPE_IMM},
217 /* 0x3f */ {"dsra32 ", ITYPE_IMM}
221 /* instruction decode table for 5 bit reg immediate function codes */
223 static struct {char *name; int ftype;} regimms[] = {
225 /* 0x00 */ {"bltz ", ITYPE_BRA},
226 /* 0x01 */ {"bgez ", ITYPE_BRA},
227 /* 0x02 */ {"bltzl ", ITYPE_BRA},
228 /* 0x03 */ {"bgezl ", ITYPE_BRA},
229 /* 0x04 */ {"", ITYPE_UNDEF},
230 /* 0x05 */ {"", ITYPE_UNDEF},
231 /* 0x06 */ {"", ITYPE_UNDEF},
232 /* 0x07 */ {"", ITYPE_UNDEF},
234 /* 0x08 */ {"tgei ", ITYPE_IMM},
235 /* 0x09 */ {"dgeiu ", ITYPE_IMM},
236 /* 0x0a */ {"tlti ", ITYPE_IMM},
237 /* 0x0b */ {"tltiu ", ITYPE_IMM},
238 /* 0x0c */ {"teqi ", ITYPE_IMM},
239 /* 0x0d */ {"", ITYPE_UNDEF},
240 /* 0x0e */ {"tnei ", ITYPE_IMM},
241 /* 0x0f */ {"", ITYPE_UNDEF},
243 /* 0x10 */ {"bltzal ", ITYPE_BRA},
244 /* 0x11 */ {"bgezal ", ITYPE_BRA},
245 /* 0x12 */ {"bltzall ", ITYPE_BRA},
246 /* 0x13 */ {"bgezall ", ITYPE_BRA},
247 /* 0x14 */ {"", ITYPE_UNDEF},
248 /* 0x15 */ {"", ITYPE_UNDEF},
249 /* 0x16 */ {"", ITYPE_UNDEF},
250 /* 0x17 */ {"", ITYPE_UNDEF},
252 /* 0x18 */ {"", ITYPE_UNDEF},
253 /* 0x19 */ {"", ITYPE_UNDEF},
254 /* 0x1a */ {"", ITYPE_UNDEF},
255 /* 0x1b */ {"", ITYPE_UNDEF},
256 /* 0x1c */ {"", ITYPE_UNDEF},
257 /* 0x1d */ {"", ITYPE_UNDEF},
258 /* 0x1e */ {"", ITYPE_UNDEF},
259 /* 0x1f */ {"", ITYPE_UNDEF}
263 /* instruction decode table for 6 bit floating point op codes */
265 static struct {char *name; char *fill; int ftype;} fops[] = {
267 /* 0x00 */ {"add", " ", ITYPE_FOP},
268 /* 0x01 */ {"sub", " ", ITYPE_FOP},
269 /* 0x02 */ {"mul", " ", ITYPE_FOP},
270 /* 0x03 */ {"div", " ", ITYPE_FOP},
271 /* 0x04 */ {"sqrt", " ", ITYPE_FOP},
272 /* 0x05 */ {"abs", " ", ITYPE_FOP2},
273 /* 0x06 */ {"mov", " ", ITYPE_FOP2},
274 /* 0x07 */ {"neg", " ", ITYPE_FOP2},
276 /* 0x08 */ {"roundl", "", ITYPE_FOP2},
277 /* 0x09 */ {"truncl", "", ITYPE_FOP2},
278 /* 0x0a */ {"ceill", " ", ITYPE_FOP2},
279 /* 0x0b */ {"floorl", "", ITYPE_FOP2},
280 /* 0x0c */ {"round", " ", ITYPE_FOP2},
281 /* 0x0d */ {"trunc", " ", ITYPE_FOP2},
282 /* 0x0e */ {"ceil", " ", ITYPE_FOP2},
283 /* 0x0f */ {"floor", " ", ITYPE_FOP2},
285 /* 0x10 */ {"", "", ITYPE_UNDEF},
286 /* 0x11 */ {"", "", ITYPE_UNDEF},
287 /* 0x12 */ {"", "", ITYPE_UNDEF},
288 /* 0x13 */ {"", "", ITYPE_UNDEF},
289 /* 0x14 */ {"", "", ITYPE_UNDEF},
290 /* 0x15 */ {"", "", ITYPE_UNDEF},
291 /* 0x16 */ {"", "", ITYPE_UNDEF},
292 /* 0x17 */ {"", "", ITYPE_UNDEF},
294 /* 0x18 */ {"", "", ITYPE_UNDEF},
295 /* 0x19 */ {"recip", " ", ITYPE_FOP2},
296 /* 0x1a */ {"rsqrt", " ", ITYPE_FOP2},
297 /* 0x1b */ {"", "", ITYPE_UNDEF},
298 /* 0x1c */ {"", "", ITYPE_UNDEF},
299 /* 0x1d */ {"", "", ITYPE_UNDEF},
300 /* 0x1e */ {"", "", ITYPE_UNDEF},
301 /* 0x1f */ {"", "", ITYPE_UNDEF},
303 /* 0x20 */ {"cvts", " ", ITYPE_FOP2},
304 /* 0x21 */ {"cvtd", " ", ITYPE_FOP2},
305 /* 0x22 */ {"cvtx", " ", ITYPE_FOP2},
306 /* 0x23 */ {"cvtq", " ", ITYPE_FOP2},
307 /* 0x24 */ {"cvtw", " ", ITYPE_FOP2},
308 /* 0x25 */ {"cvtl", " ", ITYPE_FOP2},
309 /* 0x26 */ {"", "", ITYPE_UNDEF},
310 /* 0x27 */ {"", "", ITYPE_UNDEF},
312 /* 0x28 */ {"", "", ITYPE_UNDEF},
313 /* 0x29 */ {"", "", ITYPE_UNDEF},
314 /* 0x2a */ {"", "", ITYPE_UNDEF},
315 /* 0x2b */ {"", "", ITYPE_UNDEF},
316 /* 0x2c */ {"", "", ITYPE_UNDEF},
317 /* 0x2d */ {"", "", ITYPE_UNDEF},
318 /* 0x2e */ {"", "", ITYPE_UNDEF},
319 /* 0x2f */ {"", "", ITYPE_UNDEF},
321 /* 0x30 */ {"c.f", " ", ITYPE_FCMP},
322 /* 0x31 */ {"c.un", " ", ITYPE_FCMP},
323 /* 0x32 */ {"c.eq", " ", ITYPE_FCMP},
324 /* 0x33 */ {"c.ueq", " ", ITYPE_FCMP},
325 /* 0x34 */ {"c.olt", " ", ITYPE_FCMP},
326 /* 0x35 */ {"c.ult", " ", ITYPE_FCMP},
327 /* 0x36 */ {"c.ole", " ", ITYPE_FCMP},
328 /* 0x37 */ {"c.ule", " ", ITYPE_FCMP},
330 /* 0x38 */ {"c.sf", " ", ITYPE_FCMP},
331 /* 0x39 */ {"c.ngle", "", ITYPE_FCMP},
332 /* 0x3a */ {"c.seq", " ", ITYPE_FCMP},
333 /* 0x3b */ {"c.ngl", " ", ITYPE_FCMP},
334 /* 0x3c */ {"c.lt", " ", ITYPE_FCMP},
335 /* 0x3d */ {"c.nge", " ", ITYPE_FCMP},
336 /* 0x3e */ {"c.le", " ", ITYPE_FCMP},
337 /* 0x3f */ {"c.ngt", " ", ITYPE_FCMP}
341 /* format decode table for 3 bit floating point format codes */
343 static char *fmt[] = {
355 /* format decode table for 2 bit floating point branch codes */
357 static char *fbra[] = {
365 /* instruction decode table for 32 floating point registers */
368 static char *fregs[] = {
370 /* 0x00 */ "fv0", /* "$f0", */
371 /* 0x01 */ "ft16", /* "$f1", */
372 /* 0x02 */ "fv1", /* "$f2", */
373 /* 0x03 */ "ft17", /* "$f3", */
374 /* 0x04 */ "ft0", /* "$f4", */
375 /* 0x05 */ "ft1", /* "$f5", */
376 /* 0x06 */ "ft2", /* "$f6", */
377 /* 0x07 */ "ft3", /* "$f7", */
379 /* 0x08 */ "ft4", /* "$f8", */
380 /* 0x09 */ "ft5", /* "$f9", */
381 /* 0x0a */ "ft6", /* "$f10", */
382 /* 0x0b */ "ft7", /* "$f11", */
383 /* 0x0c */ "fa0", /* "$f12", */
384 /* 0x0d */ "fa1", /* "$f13", */
385 /* 0x0e */ "fa2", /* "$f14", */
386 /* 0x0f */ "fa3", /* "$f15", */
388 /* 0x10 */ "fa4", /* "$f16", */
389 /* 0x11 */ "fa5", /* "$f17", */
390 /* 0x12 */ "fa6", /* "$f18", */
391 /* 0x13 */ "fa7", /* "$f19", */
392 /* 0x14 */ "ft8", /* "$f20", */
393 /* 0x15 */ "ft9", /* "$f21", */
394 /* 0x16 */ "ft10", /* "$f22", */
395 /* 0x17 */ "ft11", /* "$f23", */
397 /* 0x18 */ "fs0", /* "$f24", */
398 /* 0x19 */ "ft12", /* "$f25", */
399 /* 0x1a */ "fs1", /* "$f26", */
400 /* 0x1b */ "ft13", /* "$f27", */
401 /* 0x1c */ "fs2", /* "$f28", */
402 /* 0x1d */ "ft14", /* "$f29", */
403 /* 0x1e */ "fs3", /* "$f30", */
404 /* 0x1f */ "ft15" /* "$f31" */
409 /* disassinstr *****************************************************************
411 Outputs a disassembler listing of one machine code instruction on
414 code: pointer to instructions machine code
416 *******************************************************************************/
418 u1 *disassinstr(u1 *code)
420 s4 op; /* 6 bit op code */
421 s4 opfun; /* 6 bit function code */
422 s4 rs, rt, rd; /* 5 bit integer register specifiers */
423 s4 fs, ft, fd; /* 5 bit floating point register specifiers */
424 s4 shift; /* 5 bit unsigned shift amount */
429 op = (c >> 26) & 0x3f; /* 6 bit op code */
430 opfun = (c >> 0) & 0x3f; /* 6 bit function code */
431 rs = (c >> 21) & 0x1f; /* 5 bit source register specifier */
432 rt = (c >> 16) & 0x1f; /* 5 bit source/destination register specifier*/
433 rd = (c >> 11) & 0x1f; /* 5 bit destination register specifier */
434 shift = (c >> 6) & 0x1f; /* 5 bit unsigned shift amount */
436 #if SIZEOF_VOID_P == 8
437 printf("0x%016lx: %08x ", (u8) code, c);
439 printf("0x%08x: %08x ", (u4) code, c);
442 switch (ops[op].itype) {
443 case ITYPE_JMP: /* 26 bit unsigned jump offset */
444 printf("%s %#09x\n", ops[op].name, (c & 0x3ffffff) << 2);
447 case ITYPE_IMM: /* 16 bit signed immediate value */
448 printf("%s %s,%s,%d\n", ops[op].name, regs[rt],
449 regs[rs], (c << 16) >> 16);
452 case ITYPE_MEM: /* 16 bit signed memory offset */
453 printf("%s %s,%d(%s)\n", ops[op].name, regs[rt],
454 (c << 16) >> 16, regs[rs]);
457 case ITYPE_FMEM: /* 16 bit signed memory offset */
458 printf("%s $f%d,%d(%s)\n", ops[op].name, rt, (c << 16) >> 16, regs[rs]);
461 case ITYPE_BRA: /* 16 bit signed branch offset */
462 if (op == 0x04 && rs == 0 && rt == 0) {
463 #if SIZEOF_VOID_P == 8
464 printf("b 0x%016lx\n", (u8) code + 4 + ((c << 16) >> 14));
466 printf("b 0x%08x\n", (u4) code + 4 + ((c << 16) >> 14));
470 #if SIZEOF_VOID_P == 8
471 printf("%s %s,%s,0x%016lx\n", ops[op].name, regs[rs], regs[rt],
472 (u8) code + 4 + ((c << 16) >> 14));
474 printf("%s %s,%s,0x%08x\n", ops[op].name, regs[rs], regs[rt],
475 (u4) code + 4 + ((c << 16) >> 14));
480 if (regimms[rt].ftype == ITYPE_IMM)
481 printf("%s %s,%d\n", regimms[rt].name, regs[rs], (c << 16) >> 16);
482 else if (regimms[rt].ftype == ITYPE_BRA)
483 #if SIZEOF_VOID_P == 8
484 printf("%s %s,0x%016lx\n", regimms[rt].name, regs[rs],
485 (u8) code + 4 + ((c << 16) >> 14));
487 printf("%s %s,0x%08x\n", regimms[rt].name, regs[rs],
488 (u4) code + 4 + ((c << 16) >> 14));
491 printf("regimm %#04x,$%d,%d\n", rt, rs, (c << 16) >> 16);
499 if (opfun == 0x25 && rt == 0) {
501 printf("clr %s\n", regs[rd]);
503 printf("move %s,%s\n", regs[rd], regs[rs]);
506 switch (regops[opfun].ftype) {
508 printf("%s %s,%s,%s\n", regops[opfun].name, regs[rd],
511 case ITYPE_IMM: /* immediate instruction */
512 printf("%s %s,%s,%d\n",
513 regops[opfun].name, regs[rd], regs[rt], shift);
516 printf("%s %s,%s,%d\n", regops[opfun].name,
517 regs[rs], regs[rt], (c << 16) >> 22);
519 case ITYPE_DIVMUL: /* div/mul instruction */
520 printf("%s %s,%s\n", regops[opfun].name, regs[rs], regs[rt]);
524 printf("%s %s\n", regops[opfun].name, regs[rs]);
527 printf("%s %s,%s\n", regops[opfun].name, regs[rd], regs[rs]);
530 if (opfun == 8 && rs == 31) {
534 printf("%s %s\n", regops[opfun].name, regs[rs]);
537 printf("%s %s\n", regops[opfun].name, regs[rd]);
540 printf("%s\n", regops[opfun].name);
542 printf("special (%#04x) $%d,$%d,$%d\n", opfun, rd, rs, rt);
547 fs = (c >> 11) & 0x1f; /* 5 bit source register */
548 ft = (c >> 16) & 0x1f; /* 5 bit source/destination register */
549 fd = (c >> 6) & 0x1f; /* 5 bit destination register */
551 if (rs == 8) { /* floating point branch */
552 #if SIZEOF_VOID_P == 8
553 printf("%s 0x%016lx\n", fbra[ft & 3],
554 (u8) code + 4 + ((c << 16) >> 14));
556 printf("%s 0x%08x\n", fbra[ft & 3],
557 (u4) code + 4 + ((c << 16) >> 14));
562 if (rs == 0) { /* move from */
563 printf("mfc1 %s,$f%d\n", regs[rt], fs);
567 if (rs == 1) { /* double move from */
568 printf("dmfc1 %s,$f%d\n", regs[rt], fs);
572 if (rs == 4) { /* move to */
573 printf("mtc1 %s,$f%d\n", regs[rt], fs);
577 if (rs == 5) { /* double move to */
578 printf("dmtc1 %s,$f%d\n", regs[rt], fs);
582 rs = rs & 7; /* truncate to 3 bit format specifier */
584 if (fops[opfun].ftype == ITYPE_FOP)
585 printf("%s%s%s $f%d,$f%d,$f%d\n", fops[opfun].name, fmt[rs],
586 fops[opfun].fill, fd, fs, ft);
587 else if (fops[opfun].ftype == ITYPE_FOP2)
588 printf("%s%s%s $f%d,$f%d\n", fops[opfun].name, fmt[rs],
589 fops[opfun].fill, fd, fs);
590 else if (fops[opfun].ftype == ITYPE_FCMP)
591 printf("%s%s%s $f%d,$f%d\n", fops[opfun].name, fmt[rs],
592 fops[opfun].fill, fs, ft);
594 printf("cop1 (%#04x) $f%d,$f%d,$f%d\n", opfun, fd, fs, ft);
598 printf("undef %#04x(%#04x) $%d,$%d,$%d\n", op, opfun, rd, rs, rt);
605 /* disassemble *****************************************************************
607 Outputs a disassembler listing of some machine code on 'stdout'.
609 start: pointer to first instruction
610 end: pointer to last instruction
612 *******************************************************************************/
614 void disassemble(u1 *start, u1 *end)
616 printf(" --- disassembler listing ---\n");
617 for (; start < end; )
618 start = disassinstr(start);
623 * These are local overrides for various environment variables in Emacs.
624 * Please do not remove this and leave it at the end of the file, where
625 * Emacs will automagically detect them.
626 * ---------------------------------------------------------------------
629 * indent-tabs-mode: t