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 7351 2007-02-13 21:32:36Z 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, abi_registers_integer_name[rt],
449 abi_registers_integer_name[rs], (c << 16) >> 16);
452 case ITYPE_MEM: /* 16 bit signed memory offset */
453 printf("%s %s,%d(%s)\n", ops[op].name, abi_registers_integer_name[rt],
454 (c << 16) >> 16, abi_registers_integer_name[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,
459 abi_registers_integer_name[rs]);
462 case ITYPE_BRA: /* 16 bit signed branch offset */
463 if (op == 0x04 && rs == 0 && rt == 0) {
464 #if SIZEOF_VOID_P == 8
465 printf("b 0x%016lx\n", (u8) code + 4 + ((c << 16) >> 14));
467 printf("b 0x%08x\n", (u4) code + 4 + ((c << 16) >> 14));
471 #if SIZEOF_VOID_P == 8
472 printf("%s %s,%s,0x%016lx\n", ops[op].name,
473 abi_registers_integer_name[rs],
474 abi_registers_integer_name[rt],
475 (u8) code + 4 + ((c << 16) >> 14));
477 printf("%s %s,%s,0x%08x\n", ops[op].name,
478 abi_registers_integer_name[rs],
479 abi_registers_integer_name[rt],
480 (u4) code + 4 + ((c << 16) >> 14));
485 if (regimms[rt].ftype == ITYPE_IMM)
486 printf("%s %s,%d\n", regimms[rt].name,
487 abi_registers_integer_name[rs], (c << 16) >> 16);
488 else if (regimms[rt].ftype == ITYPE_BRA)
489 #if SIZEOF_VOID_P == 8
490 printf("%s %s,0x%016lx\n", regimms[rt].name,
491 abi_registers_integer_name[rs],
492 (u8) code + 4 + ((c << 16) >> 14));
494 printf("%s %s,0x%08x\n", regimms[rt].name,
495 abi_registers_integer_name[rs],
496 (u4) code + 4 + ((c << 16) >> 14));
499 printf("regimm %#04x,$%d,%d\n", rt, rs, (c << 16) >> 16);
507 if (opfun == 0x25 && rt == 0) {
509 printf("clr %s\n", abi_registers_integer_name[rd]);
511 printf("move %s,%s\n", abi_registers_integer_name[rd],
512 abi_registers_integer_name[rs]);
515 switch (regops[opfun].ftype) {
517 printf("%s %s,%s,%s\n", regops[opfun].name,
518 abi_registers_integer_name[rd],
519 abi_registers_integer_name[rs],
520 abi_registers_integer_name[rt]);
522 case ITYPE_IMM: /* immediate instruction */
523 printf("%s %s,%s,%d\n",
524 regops[opfun].name, abi_registers_integer_name[rd],
525 abi_registers_integer_name[rt], shift);
528 printf("%s %s,%s,%d\n", regops[opfun].name,
529 abi_registers_integer_name[rs],
530 abi_registers_integer_name[rt], (c << 16) >> 22);
532 case ITYPE_DIVMUL: /* div/mul instruction */
533 printf("%s %s,%s\n", regops[opfun].name,
534 abi_registers_integer_name[rs],
535 abi_registers_integer_name[rt]);
539 printf("%s %s\n", regops[opfun].name,
540 abi_registers_integer_name[rs]);
543 printf("%s %s,%s\n", regops[opfun].name,
544 abi_registers_integer_name[rd],
545 abi_registers_integer_name[rs]);
548 if (opfun == 8 && rs == 31) {
552 printf("%s %s\n", regops[opfun].name,
553 abi_registers_integer_name[rs]);
556 printf("%s %s\n", regops[opfun].name,
557 abi_registers_integer_name[rd]);
560 printf("%s\n", regops[opfun].name);
562 printf("special (%#04x) $%d,$%d,$%d\n", opfun, rd, rs, rt);
567 fs = (c >> 11) & 0x1f; /* 5 bit source register */
568 ft = (c >> 16) & 0x1f; /* 5 bit source/destination register */
569 fd = (c >> 6) & 0x1f; /* 5 bit destination register */
571 if (rs == 8) { /* floating point branch */
572 #if SIZEOF_VOID_P == 8
573 printf("%s 0x%016lx\n", fbra[ft & 3],
574 (u8) code + 4 + ((c << 16) >> 14));
576 printf("%s 0x%08x\n", fbra[ft & 3],
577 (u4) code + 4 + ((c << 16) >> 14));
582 if (rs == 0) { /* move from */
583 printf("mfc1 %s,$f%d\n", abi_registers_integer_name[rt], fs);
587 if (rs == 1) { /* double move from */
588 printf("dmfc1 %s,$f%d\n", abi_registers_integer_name[rt], fs);
592 if (rs == 4) { /* move to */
593 printf("mtc1 %s,$f%d\n", abi_registers_integer_name[rt], fs);
597 if (rs == 5) { /* double move to */
598 printf("dmtc1 %s,$f%d\n", abi_registers_integer_name[rt], fs);
602 rs = rs & 7; /* truncate to 3 bit format specifier */
604 if (fops[opfun].ftype == ITYPE_FOP)
605 printf("%s%s%s $f%d,$f%d,$f%d\n", fops[opfun].name, fmt[rs],
606 fops[opfun].fill, fd, fs, ft);
607 else if (fops[opfun].ftype == ITYPE_FOP2)
608 printf("%s%s%s $f%d,$f%d\n", fops[opfun].name, fmt[rs],
609 fops[opfun].fill, fd, fs);
610 else if (fops[opfun].ftype == ITYPE_FCMP)
611 printf("%s%s%s $f%d,$f%d\n", fops[opfun].name, fmt[rs],
612 fops[opfun].fill, fs, ft);
614 printf("cop1 (%#04x) $f%d,$f%d,$f%d\n", opfun, fd, fs, ft);
618 printf("undef %#04x(%#04x) $%d,$%d,$%d\n", op, opfun, rd, rs, rt);
625 /* disassemble *****************************************************************
627 Outputs a disassembler listing of some machine code on 'stdout'.
629 start: pointer to first instruction
630 end: pointer to last instruction
632 *******************************************************************************/
634 void disassemble(u1 *start, u1 *end)
636 printf(" --- disassembler listing ---\n");
637 for (; start < end; )
638 start = disassinstr(start);
643 * These are local overrides for various environment variables in Emacs.
644 * Please do not remove this and leave it at the end of the file, where
645 * Emacs will automagically detect them.
646 * ---------------------------------------------------------------------
649 * indent-tabs-mode: t