1 /* src/vm/jit/mips/disass.c - primitive disassembler for MIPS machine code
3 Copyright (C) 1996-2005, 2006 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 Contact: cacao@cacaojvm.org
27 Authors: Andreas Krall
29 Changes: Christian Thalinger
31 $Id: disass.c 4357 2006-01-22 23:33:38Z twisti $
42 /* The disassembler uses four tables for decoding the instructions. The first
43 table (ops) is used to classify the instructions based on the op code and
44 contains the instruction names for instructions which don't used the
45 function codes. This table is indexed by the op code (6 bit, 64 entries).
46 The other tables are either indexed by the function code or some special
47 format and branch codes.
50 #define ITYPE_UNDEF 0 /* undefined instructions (illegal opcode) */
51 #define ITYPE_JMP 1 /* jump instructions */
52 #define ITYPE_IMM 2 /* immediate instructions */
53 #define ITYPE_MEM 3 /* memory instructions */
54 #define ITYPE_FMEM 4 /* floating point memory instructions */
55 #define ITYPE_BRA 5 /* branch instructions */
56 #define ITYPE_RIMM 6 /* special/branch instructions */
57 #define ITYPE_OP 7 /* integer instructions */
58 #define ITYPE_TRAP 8 /* trap instructions */
59 #define ITYPE_DIVMUL 9 /* integer divide/multiply instructions */
60 #define ITYPE_MTOJR 10 /* move to and jump register instructions */
61 #define ITYPE_MFROM 11 /* move from instructions */
62 #define ITYPE_SYS 12 /* operating system instructions */
63 #define ITYPE_FOP 13 /* floating point instructions */
64 #define ITYPE_FOP2 14 /* 2 operand floating point instructions */
65 #define ITYPE_FCMP 15 /* floating point compare instructions */
68 /* instruction decode table for 6 bit op codes */
70 static struct {char *name; int itype;} ops[] = {
72 /* 0x00 */ {"special ", ITYPE_OP},
73 /* 0x01 */ {"regimm ", ITYPE_RIMM},
74 /* 0x02 */ {"j ", ITYPE_JMP},
75 /* 0x03 */ {"jal ", ITYPE_JMP},
76 /* 0x04 */ {"beq ", ITYPE_BRA},
77 /* 0x05 */ {"bne ", ITYPE_BRA},
78 /* 0x06 */ {"blez ", ITYPE_BRA},
79 /* 0x07 */ {"bgtz ", ITYPE_BRA},
81 /* 0x08 */ {"addi ", ITYPE_IMM},
82 /* 0x09 */ {"addiu ", ITYPE_IMM},
83 /* 0x0a */ {"slti ", ITYPE_IMM},
84 /* 0x0b */ {"sltiu ", ITYPE_IMM},
85 /* 0x0c */ {"andi ", ITYPE_IMM},
86 /* 0x0d */ {"ori ", ITYPE_IMM},
87 /* 0x0e */ {"xori ", ITYPE_IMM},
88 /* 0x0f */ {"lui ", ITYPE_IMM},
90 /* 0x10 */ {"cop0 ", ITYPE_OP},
91 /* 0x11 */ {"cop1 ", ITYPE_FOP},
92 /* 0x12 */ {"cop2 ", ITYPE_OP},
93 /* 0x13 */ {"", ITYPE_UNDEF},
94 /* 0x14 */ {"beql ", ITYPE_BRA},
95 /* 0x15 */ {"bnel ", ITYPE_BRA},
96 /* 0x16 */ {"blezl ", ITYPE_BRA},
97 /* 0x17 */ {"bgtzl ", ITYPE_BRA},
99 /* 0x18 */ {"daddi ", ITYPE_IMM},
100 /* 0x19 */ {"daddiu ", ITYPE_IMM},
101 /* 0x1a */ {"ldl ", ITYPE_MEM},
102 /* 0x1b */ {"ldr ", ITYPE_MEM},
103 /* 0x1c */ {"", ITYPE_UNDEF},
104 /* 0x1d */ {"", ITYPE_UNDEF},
105 /* 0x1e */ {"", ITYPE_UNDEF},
106 /* 0x1f */ {"", ITYPE_UNDEF},
108 /* 0x20 */ {"lb ", ITYPE_MEM},
109 /* 0x21 */ {"lh ", ITYPE_MEM},
110 /* 0x22 */ {"lwl ", ITYPE_MEM},
111 /* 0x23 */ {"lw ", ITYPE_MEM},
112 /* 0x24 */ {"lbu ", ITYPE_MEM},
113 /* 0x25 */ {"lhu ", ITYPE_MEM},
114 /* 0x26 */ {"lwr ", ITYPE_MEM},
115 /* 0x27 */ {"lwu ", ITYPE_MEM},
117 /* 0x28 */ {"sb ", ITYPE_MEM},
118 /* 0x29 */ {"sh ", ITYPE_MEM},
119 /* 0x2a */ {"swl ", ITYPE_MEM},
120 /* 0x2b */ {"sw ", ITYPE_MEM},
121 /* 0x2c */ {"sdl ", ITYPE_MEM},
122 /* 0x2d */ {"sdr ", ITYPE_MEM},
123 /* 0x2e */ {"swr ", ITYPE_MEM},
124 /* 0x2f */ {"cache ", ITYPE_MEM},
126 /* 0x30 */ {"ll ", ITYPE_MEM},
127 /* 0x31 */ {"lwc1 ", ITYPE_FMEM},
128 /* 0x32 */ {"lwc2 ", ITYPE_MEM},
129 /* 0x33 */ {"", ITYPE_UNDEF},
130 /* 0x34 */ {"lld ", ITYPE_MEM},
131 /* 0x35 */ {"ldc1 ", ITYPE_FMEM},
132 /* 0x36 */ {"ldc2 ", ITYPE_MEM},
133 /* 0x37 */ {"ld ", ITYPE_MEM},
135 /* 0x38 */ {"sc ", ITYPE_MEM},
136 /* 0x39 */ {"swc1 ", ITYPE_FMEM},
137 /* 0x3a */ {"swc2 ", ITYPE_MEM},
138 /* 0x3b */ {"", ITYPE_UNDEF},
139 /* 0x3c */ {"sld ", ITYPE_MEM},
140 /* 0x3d */ {"sdc1 ", ITYPE_FMEM},
141 /* 0x3e */ {"sdc2 ", ITYPE_MEM},
142 /* 0x3f */ {"sd ", ITYPE_MEM}
146 /* instruction decode table for 6 bit special function codes */
148 static struct {char *name; int ftype;} regops[] = {
150 /* 0x00 */ {"sll ", ITYPE_IMM},
151 /* 0x01 */ {"" , ITYPE_UNDEF},
152 /* 0x02 */ {"srl ", ITYPE_IMM},
153 /* 0x03 */ {"sra ", ITYPE_IMM},
154 /* 0x04 */ {"sllv ", ITYPE_OP},
155 /* 0x05 */ {"" , ITYPE_UNDEF},
156 /* 0x06 */ {"srlv ", ITYPE_OP},
157 /* 0x07 */ {"srav ", ITYPE_OP},
159 /* 0x08 */ {"jr ", ITYPE_MTOJR},
160 /* 0x09 */ {"jalr ", ITYPE_JMP},
161 /* 0x0a */ {"" , ITYPE_UNDEF},
162 /* 0x0b */ {"" , ITYPE_UNDEF},
163 /* 0x0c */ {"syscall ", ITYPE_SYS},
164 /* 0x0d */ {"break ", ITYPE_SYS},
165 /* 0x0e */ {"" , ITYPE_UNDEF},
166 /* 0x0f */ {"sync ", ITYPE_SYS},
168 /* 0x10 */ {"mfhi ", ITYPE_MFROM},
169 /* 0x11 */ {"mthi ", ITYPE_MTOJR},
170 /* 0x12 */ {"mflo ", ITYPE_MFROM},
171 /* 0x13 */ {"mtlo ", ITYPE_MTOJR},
172 /* 0x14 */ {"dsllv ", ITYPE_OP},
173 /* 0x15 */ {"" , ITYPE_UNDEF},
174 /* 0x16 */ {"dslrv ", ITYPE_OP},
175 /* 0x17 */ {"dsrav ", ITYPE_OP},
177 /* 0x18 */ {"mult ",ITYPE_DIVMUL},
178 /* 0x19 */ {"multu ",ITYPE_DIVMUL},
179 /* 0x1a */ {"div ",ITYPE_DIVMUL},
180 /* 0x1b */ {"divu ",ITYPE_DIVMUL},
181 /* 0x1c */ {"dmult ",ITYPE_DIVMUL},
182 /* 0x1d */ {"dmultu ",ITYPE_DIVMUL},
183 /* 0x1e */ {"ddiv ",ITYPE_DIVMUL},
184 /* 0x1f */ {"ddivu ",ITYPE_DIVMUL},
186 /* 0x20 */ {"add ", ITYPE_OP},
187 /* 0x21 */ {"addu ", ITYPE_OP},
188 /* 0x22 */ {"sub ", ITYPE_OP},
189 /* 0x23 */ {"subu ", ITYPE_OP},
190 /* 0x24 */ {"and ", ITYPE_OP},
191 /* 0x25 */ {"or ", ITYPE_OP},
192 /* 0x26 */ {"xor ", ITYPE_OP},
193 /* 0x27 */ {"nor ", ITYPE_OP},
195 /* 0x28 */ {"" , ITYPE_UNDEF},
196 /* 0x29 */ {"" , ITYPE_UNDEF},
197 /* 0x2a */ {"slt ", ITYPE_OP},
198 /* 0x2b */ {"sltu ", ITYPE_OP},
199 /* 0x2c */ {"dadd ", ITYPE_OP},
200 /* 0x2d */ {"daddu ", ITYPE_OP},
201 /* 0x2e */ {"dsub ", ITYPE_OP},
202 /* 0x2f */ {"dsubu ", ITYPE_OP},
204 /* 0x30 */ {"tge ", ITYPE_TRAP},
205 /* 0x31 */ {"tgeu ", ITYPE_TRAP},
206 /* 0x32 */ {"tlt ", ITYPE_TRAP},
207 /* 0x33 */ {"tltu ", ITYPE_TRAP},
208 /* 0x34 */ {"teq ", ITYPE_TRAP},
209 /* 0x35 */ {"" , ITYPE_UNDEF},
210 /* 0x36 */ {"tne ", ITYPE_TRAP},
211 /* 0x37 */ {"" , ITYPE_UNDEF},
213 /* 0x38 */ {"dsll ", ITYPE_IMM},
214 /* 0x39 */ {"" , ITYPE_UNDEF},
215 /* 0x3a */ {"dsrl ", ITYPE_IMM},
216 /* 0x3b */ {"dsra ", ITYPE_IMM},
217 /* 0x3c */ {"dsll32 ", ITYPE_IMM},
218 /* 0x3d */ {"" , ITYPE_UNDEF},
219 /* 0x3e */ {"dsrl32 ", ITYPE_IMM},
220 /* 0x3f */ {"dsra32 ", ITYPE_IMM}
224 /* instruction decode table for 5 bit reg immediate function codes */
226 static struct {char *name; int ftype;} regimms[] = {
228 /* 0x00 */ {"bltz ", ITYPE_BRA},
229 /* 0x01 */ {"bgez ", ITYPE_BRA},
230 /* 0x02 */ {"bltzl ", ITYPE_BRA},
231 /* 0x03 */ {"bgezl ", ITYPE_BRA},
232 /* 0x04 */ {"", ITYPE_UNDEF},
233 /* 0x05 */ {"", ITYPE_UNDEF},
234 /* 0x06 */ {"", ITYPE_UNDEF},
235 /* 0x07 */ {"", ITYPE_UNDEF},
237 /* 0x08 */ {"tgei ", ITYPE_IMM},
238 /* 0x09 */ {"dgeiu ", ITYPE_IMM},
239 /* 0x0a */ {"tlti ", ITYPE_IMM},
240 /* 0x0b */ {"tltiu ", ITYPE_IMM},
241 /* 0x0c */ {"teqi ", ITYPE_IMM},
242 /* 0x0d */ {"", ITYPE_UNDEF},
243 /* 0x0e */ {"tnei ", ITYPE_IMM},
244 /* 0x0f */ {"", ITYPE_UNDEF},
246 /* 0x10 */ {"bltzal ", ITYPE_BRA},
247 /* 0x11 */ {"bgezal ", ITYPE_BRA},
248 /* 0x12 */ {"bltzall ", ITYPE_BRA},
249 /* 0x13 */ {"bgezall ", ITYPE_BRA},
250 /* 0x14 */ {"", ITYPE_UNDEF},
251 /* 0x15 */ {"", ITYPE_UNDEF},
252 /* 0x16 */ {"", ITYPE_UNDEF},
253 /* 0x17 */ {"", ITYPE_UNDEF},
255 /* 0x18 */ {"", ITYPE_UNDEF},
256 /* 0x19 */ {"", ITYPE_UNDEF},
257 /* 0x1a */ {"", ITYPE_UNDEF},
258 /* 0x1b */ {"", ITYPE_UNDEF},
259 /* 0x1c */ {"", ITYPE_UNDEF},
260 /* 0x1d */ {"", ITYPE_UNDEF},
261 /* 0x1e */ {"", ITYPE_UNDEF},
262 /* 0x1f */ {"", ITYPE_UNDEF}
266 /* instruction decode table for 6 bit floating point op codes */
268 static struct {char *name; char *fill; int ftype;} fops[] = {
270 /* 0x00 */ {"add", " ", ITYPE_FOP},
271 /* 0x01 */ {"sub", " ", ITYPE_FOP},
272 /* 0x02 */ {"mul", " ", ITYPE_FOP},
273 /* 0x03 */ {"div", " ", ITYPE_FOP},
274 /* 0x04 */ {"sqrt", " ", ITYPE_FOP},
275 /* 0x05 */ {"abs", " ", ITYPE_FOP2},
276 /* 0x06 */ {"mov", " ", ITYPE_FOP2},
277 /* 0x07 */ {"neg", " ", ITYPE_FOP2},
279 /* 0x08 */ {"roundl", "", ITYPE_FOP2},
280 /* 0x09 */ {"truncl", "", ITYPE_FOP2},
281 /* 0x0a */ {"ceill", " ", ITYPE_FOP2},
282 /* 0x0b */ {"floorl", "", ITYPE_FOP2},
283 /* 0x0c */ {"round", " ", ITYPE_FOP2},
284 /* 0x0d */ {"trunc", " ", ITYPE_FOP2},
285 /* 0x0e */ {"ceil", " ", ITYPE_FOP2},
286 /* 0x0f */ {"floor", " ", ITYPE_FOP2},
288 /* 0x10 */ {"", "", ITYPE_UNDEF},
289 /* 0x11 */ {"", "", ITYPE_UNDEF},
290 /* 0x12 */ {"", "", ITYPE_UNDEF},
291 /* 0x13 */ {"", "", ITYPE_UNDEF},
292 /* 0x14 */ {"", "", ITYPE_UNDEF},
293 /* 0x15 */ {"", "", ITYPE_UNDEF},
294 /* 0x16 */ {"", "", ITYPE_UNDEF},
295 /* 0x17 */ {"", "", ITYPE_UNDEF},
297 /* 0x18 */ {"", "", ITYPE_UNDEF},
298 /* 0x19 */ {"recip", " ", ITYPE_FOP2},
299 /* 0x1a */ {"rsqrt", " ", ITYPE_FOP2},
300 /* 0x1b */ {"", "", ITYPE_UNDEF},
301 /* 0x1c */ {"", "", ITYPE_UNDEF},
302 /* 0x1d */ {"", "", ITYPE_UNDEF},
303 /* 0x1e */ {"", "", ITYPE_UNDEF},
304 /* 0x1f */ {"", "", ITYPE_UNDEF},
306 /* 0x20 */ {"cvts", " ", ITYPE_FOP2},
307 /* 0x21 */ {"cvtd", " ", ITYPE_FOP2},
308 /* 0x22 */ {"cvtx", " ", ITYPE_FOP2},
309 /* 0x23 */ {"cvtq", " ", ITYPE_FOP2},
310 /* 0x24 */ {"cvtw", " ", ITYPE_FOP2},
311 /* 0x25 */ {"cvtl", " ", ITYPE_FOP2},
312 /* 0x26 */ {"", "", ITYPE_UNDEF},
313 /* 0x27 */ {"", "", ITYPE_UNDEF},
315 /* 0x28 */ {"", "", ITYPE_UNDEF},
316 /* 0x29 */ {"", "", ITYPE_UNDEF},
317 /* 0x2a */ {"", "", ITYPE_UNDEF},
318 /* 0x2b */ {"", "", ITYPE_UNDEF},
319 /* 0x2c */ {"", "", ITYPE_UNDEF},
320 /* 0x2d */ {"", "", ITYPE_UNDEF},
321 /* 0x2e */ {"", "", ITYPE_UNDEF},
322 /* 0x2f */ {"", "", ITYPE_UNDEF},
324 /* 0x30 */ {"c.f", " ", ITYPE_FCMP},
325 /* 0x31 */ {"c.un", " ", ITYPE_FCMP},
326 /* 0x32 */ {"c.eq", " ", ITYPE_FCMP},
327 /* 0x33 */ {"c.ueq", " ", ITYPE_FCMP},
328 /* 0x34 */ {"c.olt", " ", ITYPE_FCMP},
329 /* 0x35 */ {"c.ult", " ", ITYPE_FCMP},
330 /* 0x36 */ {"c.ole", " ", ITYPE_FCMP},
331 /* 0x37 */ {"c.ule", " ", ITYPE_FCMP},
333 /* 0x38 */ {"c.sf", " ", ITYPE_FCMP},
334 /* 0x39 */ {"c.ngle", "", ITYPE_FCMP},
335 /* 0x3a */ {"c.seq", " ", ITYPE_FCMP},
336 /* 0x3b */ {"c.ngl", " ", ITYPE_FCMP},
337 /* 0x3c */ {"c.lt", " ", ITYPE_FCMP},
338 /* 0x3d */ {"c.nge", " ", ITYPE_FCMP},
339 /* 0x3e */ {"c.le", " ", ITYPE_FCMP},
340 /* 0x3f */ {"c.ngt", " ", ITYPE_FCMP}
344 /* format decode table for 3 bit floating point format codes */
346 static char *fmt[] = {
358 /* format decode table for 2 bit floating point branch codes */
360 static char *fbra[] = {
368 /* instruction decode table for 32 integer registers */
371 /* 0x00 */ "zero", /* "$0", */
372 /* 0x01 */ "at", /* "$1", */
373 /* 0x02 */ "v0", /* "$2", */
374 /* 0x03 */ "v1", /* "$3", */
375 /* 0x04 */ "a0", /* "$4", */
376 /* 0x05 */ "a1", /* "$5", */
377 /* 0x06 */ "a2", /* "$6", */
378 /* 0x07 */ "a3", /* "$7", */
380 /* 0x08 */ "a4", /* "$8", */
381 /* 0x09 */ "a5", /* "$9", */
382 /* 0x0a */ "a6", /* "$10", */
383 /* 0x0b */ "a7", /* "$11", */
384 /* 0x0c */ "t0", /* "$12", */
385 /* 0x0d */ "t1", /* "$13", */
386 /* 0x0e */ "t2", /* "$14", */
387 /* 0x0f */ "t3", /* "$15", */
389 /* 0x10 */ "s0", /* "$16", */
390 /* 0x11 */ "s1", /* "$17", */
391 /* 0x12 */ "s2", /* "$18", */
392 /* 0x13 */ "s3", /* "$19", */
393 /* 0x14 */ "s4", /* "$20", */
394 /* 0x15 */ "s5", /* "$21", */
395 /* 0x16 */ "s6", /* "$22", */
396 /* 0x17 */ "s7", /* "$23", */
398 /* 0x18 */ "t8", /* "$24", */
399 /* 0x19 */ "t9", /* "$25", */
400 /* 0x1a */ "k0", /* "$26", */
401 /* 0x1b */ "k1", /* "$27", */
402 /* 0x1c */ "gp", /* "$28", */
403 /* 0x1d */ "sp", /* "$29", */
404 /* 0x1e */ "s8", /* "$30", */
405 /* 0x1f */ "ra" /* "$31" */
409 /* instruction decode table for 32 floating point registers */
412 static char *fregs[] = {
414 /* 0x00 */ "fv0", /* "$f0", */
415 /* 0x01 */ "ft16", /* "$f1", */
416 /* 0x02 */ "fv1", /* "$f2", */
417 /* 0x03 */ "ft17", /* "$f3", */
418 /* 0x04 */ "ft0", /* "$f4", */
419 /* 0x05 */ "ft1", /* "$f5", */
420 /* 0x06 */ "ft2", /* "$f6", */
421 /* 0x07 */ "ft3", /* "$f7", */
423 /* 0x08 */ "ft4", /* "$f8", */
424 /* 0x09 */ "ft5", /* "$f9", */
425 /* 0x0a */ "ft6", /* "$f10", */
426 /* 0x0b */ "ft7", /* "$f11", */
427 /* 0x0c */ "fa0", /* "$f12", */
428 /* 0x0d */ "fa1", /* "$f13", */
429 /* 0x0e */ "fa2", /* "$f14", */
430 /* 0x0f */ "fa3", /* "$f15", */
432 /* 0x10 */ "fa4", /* "$f16", */
433 /* 0x11 */ "fa5", /* "$f17", */
434 /* 0x12 */ "fa6", /* "$f18", */
435 /* 0x13 */ "fa7", /* "$f19", */
436 /* 0x14 */ "ft8", /* "$f20", */
437 /* 0x15 */ "ft9", /* "$f21", */
438 /* 0x16 */ "ft10", /* "$f22", */
439 /* 0x17 */ "ft11", /* "$f23", */
441 /* 0x18 */ "fs0", /* "$f24", */
442 /* 0x19 */ "ft12", /* "$f25", */
443 /* 0x1a */ "fs1", /* "$f26", */
444 /* 0x1b */ "ft13", /* "$f27", */
445 /* 0x1c */ "fs2", /* "$f28", */
446 /* 0x1d */ "ft14", /* "$f29", */
447 /* 0x1e */ "fs3", /* "$f30", */
448 /* 0x1f */ "ft15" /* "$f31" */
453 /* disassinstr *****************************************************************
455 Outputs a disassembler listing of one machine code instruction on
458 code: pointer to instructions machine code
460 *******************************************************************************/
462 u1 *disassinstr(u1 *code)
464 s4 op; /* 6 bit op code */
465 s4 opfun; /* 6 bit function code */
466 s4 rs, rt, rd; /* 5 bit integer register specifiers */
467 s4 fs, ft, fd; /* 5 bit floating point register specifiers */
468 s4 shift; /* 5 bit unsigned shift amount */
473 op = (c >> 26) & 0x3f; /* 6 bit op code */
474 opfun = (c >> 0) & 0x3f; /* 6 bit function code */
475 rs = (c >> 21) & 0x1f; /* 5 bit source register specifier */
476 rt = (c >> 16) & 0x1f; /* 5 bit source/destination register specifier*/
477 rd = (c >> 11) & 0x1f; /* 5 bit destination register specifier */
478 shift = (c >> 6) & 0x1f; /* 5 bit unsigned shift amount */
480 #if SIZEOF_VOID_P == 8
481 printf("0x%016lx: %08x ", (u8) code, c);
483 printf("0x%08x: %08x ", (u4) code, c);
486 switch (ops[op].itype) {
487 case ITYPE_JMP: /* 26 bit unsigned jump offset */
488 printf("%s %#09x\n", ops[op].name, (c & 0x3ffffff) << 2);
491 case ITYPE_IMM: /* 16 bit signed immediate value */
492 printf("%s %s,%s,%d\n", ops[op].name, regs[rt],
493 regs[rs], (c << 16) >> 16);
496 case ITYPE_MEM: /* 16 bit signed memory offset */
497 printf("%s %s,%d(%s)\n", ops[op].name, regs[rt],
498 (c << 16) >> 16, regs[rs]);
501 case ITYPE_FMEM: /* 16 bit signed memory offset */
502 printf("%s $f%d,%d(%s)\n", ops[op].name, rt, (c << 16) >> 16, regs[rs]);
505 case ITYPE_BRA: /* 16 bit signed branch offset */
506 if (op == 0x04 && rs == 0 && rt == 0) {
507 #if SIZEOF_VOID_P == 8
508 printf("b 0x%016lx\n", (u8) code + 4 + ((c << 16) >> 14));
510 printf("b 0x%08x\n", (u4) code + 4 + ((c << 16) >> 14));
514 #if SIZEOF_VOID_P == 8
515 printf("%s %s,%s,0x%016lx\n", ops[op].name, regs[rs], regs[rt],
516 (u8) code + 4 + ((c << 16) >> 14));
518 printf("%s %s,%s,0x%08x\n", ops[op].name, regs[rs], regs[rt],
519 (u4) code + 4 + ((c << 16) >> 14));
524 if (regimms[rt].ftype == ITYPE_IMM)
525 printf("%s %s,%d\n", regimms[rt].name, regs[rs], (c << 16) >> 16);
526 else if (regimms[rt].ftype == ITYPE_BRA)
527 #if SIZEOF_VOID_P == 8
528 printf("%s %s,0x%016lx\n", regimms[rt].name, regs[rs],
529 (u8) code + 4 + ((c << 16) >> 14));
531 printf("%s %s,0x%08x\n", regimms[rt].name, regs[rs],
532 (u4) code + 4 + ((c << 16) >> 14));
535 printf("regimm %#04x,$%d,%d\n", rt, rs, (c << 16) >> 16);
543 if (opfun == 0x25 && rt == 0) {
545 printf("clr %s\n", regs[rd]);
547 printf("move %s,%s\n", regs[rd], regs[rs]);
550 switch (regops[opfun].ftype) {
552 printf("%s %s,%s,%s\n", regops[opfun].name, regs[rd],
555 case ITYPE_IMM: /* immediate instruction */
556 printf("%s %s,%s,%d\n",
557 regops[opfun].name, regs[rd], regs[rt], shift);
560 printf("%s %s,%s,%d\n", regops[opfun].name,
561 regs[rs], regs[rt], (c << 16) >> 22);
563 case ITYPE_DIVMUL: /* div/mul instruction */
564 printf("%s %s,%s\n", regops[opfun].name, regs[rs], regs[rt]);
568 printf("%s %s\n", regops[opfun].name, regs[rs]);
571 printf("%s %s,%s\n", regops[opfun].name, regs[rd], regs[rs]);
574 if (opfun == 8 && rs == 31) {
578 printf("%s %s\n", regops[opfun].name, regs[rs]);
581 printf("%s %s\n", regops[opfun].name, regs[rd]);
584 printf("%s\n", regops[opfun].name);
586 printf("special (%#04x) $%d,$%d,$%d\n", opfun, rd, rs, rt);
591 fs = (c >> 11) & 0x1f; /* 5 bit source register */
592 ft = (c >> 16) & 0x1f; /* 5 bit source/destination register */
593 fd = (c >> 6) & 0x1f; /* 5 bit destination register */
595 if (rs == 8) { /* floating point branch */
596 #if SIZEOF_VOID_P == 8
597 printf("%s 0x%016lx\n", fbra[ft & 3],
598 (u8) code + 4 + ((c << 16) >> 14));
600 printf("%s 0x%08x\n", fbra[ft & 3],
601 (u4) code + 4 + ((c << 16) >> 14));
606 if (rs == 0) { /* move from */
607 printf("mfc1 %s,$f%d\n", regs[rt], fs);
611 if (rs == 1) { /* double move from */
612 printf("dmfc1 %s,$f%d\n", regs[rt], fs);
616 if (rs == 4) { /* move to */
617 printf("mtc1 %s,$f%d\n", regs[rt], fs);
621 if (rs == 5) { /* double move to */
622 printf("dmtc1 %s,$f%d\n", regs[rt], fs);
626 rs = rs & 7; /* truncate to 3 bit format specifier */
628 if (fops[opfun].ftype == ITYPE_FOP)
629 printf("%s%s%s $f%d,$f%d,$f%d\n", fops[opfun].name, fmt[rs],
630 fops[opfun].fill, fd, fs, ft);
631 else if (fops[opfun].ftype == ITYPE_FOP2)
632 printf("%s%s%s $f%d,$f%d\n", fops[opfun].name, fmt[rs],
633 fops[opfun].fill, fd, fs);
634 else if (fops[opfun].ftype == ITYPE_FCMP)
635 printf("%s%s%s $f%d,$f%d\n", fops[opfun].name, fmt[rs],
636 fops[opfun].fill, fs, ft);
638 printf("cop1 (%#04x) $f%d,$f%d,$f%d\n", opfun, fd, fs, ft);
642 printf("undef %#04x(%#04x) $%d,$%d,$%d\n", op, opfun, rd, rs, rt);
649 /* disassemble *****************************************************************
651 Outputs a disassembler listing of some machine code on 'stdout'.
653 start: pointer to first instruction
654 end: pointer to last instruction
656 *******************************************************************************/
658 void disassemble(u1 *start, u1 *end)
660 printf(" --- disassembler listing ---\n");
661 for (; start < end; )
662 start = disassinstr(start);
667 * These are local overrides for various environment variables in Emacs.
668 * Please do not remove this and leave it at the end of the file, where
669 * Emacs will automagically detect them.
670 * ---------------------------------------------------------------------
673 * indent-tabs-mode: t