* Removed all Id tags.
[cacao.git] / src / vm / jit / mips / disass.c
1 /* src/vm/jit/mips/disass.c - primitive disassembler for MIPS machine code
2
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
7
8    This file is part of CACAO.
9
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.
14
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.
19
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
23    02110-1301, USA.
24
25 */
26
27
28 #include "config.h"
29
30 #include <stdio.h>
31
32 #include "vm/types.h"
33
34 #include "vm/jit/abi.h"
35
36
37 /*  The disassembler uses four tables for decoding the instructions. The first
38         table (ops) is used to classify the instructions based on the op code and
39         contains the instruction names for instructions which don't used the
40         function codes. This table is indexed by the op code (6 bit, 64 entries).
41         The other tables are either indexed by the function code or some special
42         format and branch codes.
43 */
44
45 #define ITYPE_UNDEF  0          /* undefined instructions (illegal opcode)    */
46 #define ITYPE_JMP    1          /* jump instructions                          */
47 #define ITYPE_IMM    2          /* immediate instructions                     */
48 #define ITYPE_MEM    3          /* memory instructions                        */
49 #define ITYPE_FMEM   4          /* floating point memory instructions         */
50 #define ITYPE_BRA    5          /* branch instructions                        */
51 #define ITYPE_RIMM   6          /* special/branch instructions                */
52 #define ITYPE_OP     7          /* integer instructions                       */
53 #define ITYPE_TRAP   8          /* trap instructions                          */
54 #define ITYPE_DIVMUL 9          /* integer divide/multiply instructions       */
55 #define ITYPE_MTOJR 10          /* move to and jump register instructions     */
56 #define ITYPE_MFROM 11          /* move from instructions                     */
57 #define ITYPE_SYS   12          /* operating system instructions              */
58 #define ITYPE_FOP   13          /* floating point instructions                */
59 #define ITYPE_FOP2  14          /* 2 operand floating point instructions      */
60 #define ITYPE_FCMP  15          /* floating point compare instructions        */
61
62
63 /* instruction decode table for 6 bit op codes                                */
64
65 static struct {char *name; int itype;} ops[] = {
66
67         /* 0x00 */  {"special ",    ITYPE_OP},
68         /* 0x01 */  {"regimm  ",  ITYPE_RIMM},
69         /* 0x02 */  {"j       ",   ITYPE_JMP},
70         /* 0x03 */  {"jal     ",   ITYPE_JMP},
71         /* 0x04 */  {"beq     ",   ITYPE_BRA},
72         /* 0x05 */  {"bne     ",   ITYPE_BRA},
73         /* 0x06 */  {"blez    ",   ITYPE_BRA},
74         /* 0x07 */  {"bgtz    ",   ITYPE_BRA},
75
76         /* 0x08 */  {"addi    ",   ITYPE_IMM},
77         /* 0x09 */  {"addiu   ",   ITYPE_IMM},
78         /* 0x0a */  {"slti    ",   ITYPE_IMM},
79         /* 0x0b */  {"sltiu   ",   ITYPE_IMM},
80         /* 0x0c */  {"andi    ",   ITYPE_IMM},
81         /* 0x0d */  {"ori     ",   ITYPE_IMM},
82         /* 0x0e */  {"xori    ",   ITYPE_IMM},
83         /* 0x0f */  {"lui     ",   ITYPE_IMM},
84
85         /* 0x10 */  {"cop0    ",    ITYPE_OP},
86         /* 0x11 */  {"cop1    ",   ITYPE_FOP},
87         /* 0x12 */  {"cop2    ",    ITYPE_OP},
88         /* 0x13 */  {"",         ITYPE_UNDEF},
89         /* 0x14 */  {"beql    ",   ITYPE_BRA},
90         /* 0x15 */  {"bnel    ",   ITYPE_BRA},
91         /* 0x16 */  {"blezl   ",   ITYPE_BRA},
92         /* 0x17 */  {"bgtzl   ",   ITYPE_BRA},
93
94         /* 0x18 */  {"daddi   ",   ITYPE_IMM},
95         /* 0x19 */  {"daddiu  ",   ITYPE_IMM},
96         /* 0x1a */  {"ldl     ",   ITYPE_MEM},
97         /* 0x1b */  {"ldr     ",   ITYPE_MEM},
98         /* 0x1c */  {"",         ITYPE_UNDEF},
99         /* 0x1d */  {"",         ITYPE_UNDEF},
100         /* 0x1e */  {"",         ITYPE_UNDEF},
101         /* 0x1f */  {"",         ITYPE_UNDEF},
102
103         /* 0x20 */  {"lb      ",   ITYPE_MEM},
104         /* 0x21 */  {"lh      ",   ITYPE_MEM},
105         /* 0x22 */  {"lwl     ",   ITYPE_MEM},
106         /* 0x23 */  {"lw      ",   ITYPE_MEM},
107         /* 0x24 */  {"lbu     ",   ITYPE_MEM},
108         /* 0x25 */  {"lhu     ",   ITYPE_MEM},
109         /* 0x26 */  {"lwr     ",   ITYPE_MEM},
110         /* 0x27 */  {"lwu     ",   ITYPE_MEM},
111
112         /* 0x28 */  {"sb      ",   ITYPE_MEM},
113         /* 0x29 */  {"sh      ",   ITYPE_MEM},
114         /* 0x2a */  {"swl     ",   ITYPE_MEM},
115         /* 0x2b */  {"sw      ",   ITYPE_MEM},
116         /* 0x2c */  {"sdl     ",   ITYPE_MEM},
117         /* 0x2d */  {"sdr     ",   ITYPE_MEM},
118         /* 0x2e */  {"swr     ",   ITYPE_MEM},
119         /* 0x2f */  {"cache   ",   ITYPE_MEM},
120
121         /* 0x30 */  {"ll      ",   ITYPE_MEM},
122         /* 0x31 */  {"lwc1    ",  ITYPE_FMEM},
123         /* 0x32 */  {"lwc2    ",   ITYPE_MEM},
124         /* 0x33 */  {"",         ITYPE_UNDEF},
125         /* 0x34 */  {"lld     ",   ITYPE_MEM},
126         /* 0x35 */  {"ldc1    ",  ITYPE_FMEM},
127         /* 0x36 */  {"ldc2    ",   ITYPE_MEM},
128         /* 0x37 */  {"ld      ",   ITYPE_MEM},
129
130         /* 0x38 */  {"sc      ",   ITYPE_MEM},
131         /* 0x39 */  {"swc1    ",  ITYPE_FMEM},
132         /* 0x3a */  {"swc2    ",   ITYPE_MEM},
133         /* 0x3b */  {"",         ITYPE_UNDEF},
134         /* 0x3c */  {"sld     ",   ITYPE_MEM},
135         /* 0x3d */  {"sdc1    ",  ITYPE_FMEM},
136         /* 0x3e */  {"sdc2    ",   ITYPE_MEM},
137         /* 0x3f */  {"sd      ",   ITYPE_MEM}
138 };
139
140
141 /* instruction decode table for 6 bit special function codes                  */
142
143 static struct {char *name; int ftype;} regops[] = {
144
145         /* 0x00 */  {"sll     ",   ITYPE_IMM},
146         /* 0x01 */  {""        , ITYPE_UNDEF},
147         /* 0x02 */  {"srl     ",   ITYPE_IMM},
148         /* 0x03 */  {"sra     ",   ITYPE_IMM},
149         /* 0x04 */  {"sllv    ",    ITYPE_OP},
150         /* 0x05 */  {""        , ITYPE_UNDEF},
151         /* 0x06 */  {"srlv    ",    ITYPE_OP},
152         /* 0x07 */  {"srav    ",    ITYPE_OP},
153
154         /* 0x08 */  {"jr      ", ITYPE_MTOJR},
155         /* 0x09 */  {"jalr    ",   ITYPE_JMP},
156         /* 0x0a */  {""        , ITYPE_UNDEF},
157         /* 0x0b */  {""        , ITYPE_UNDEF},
158         /* 0x0c */  {"syscall ",   ITYPE_SYS},
159         /* 0x0d */  {"break   ",   ITYPE_SYS},
160         /* 0x0e */  {""        , ITYPE_UNDEF},
161         /* 0x0f */  {"sync    ",   ITYPE_SYS},
162
163         /* 0x10 */  {"mfhi    ", ITYPE_MFROM},
164         /* 0x11 */  {"mthi    ", ITYPE_MTOJR},
165         /* 0x12 */  {"mflo    ", ITYPE_MFROM},
166         /* 0x13 */  {"mtlo    ", ITYPE_MTOJR},
167         /* 0x14 */  {"dsllv   ",    ITYPE_OP},
168         /* 0x15 */  {""        , ITYPE_UNDEF},
169         /* 0x16 */  {"dslrv   ",    ITYPE_OP},
170         /* 0x17 */  {"dsrav   ",    ITYPE_OP},
171
172         /* 0x18 */  {"mult    ",ITYPE_DIVMUL},
173         /* 0x19 */  {"multu   ",ITYPE_DIVMUL},
174         /* 0x1a */  {"div     ",ITYPE_DIVMUL},
175         /* 0x1b */  {"divu    ",ITYPE_DIVMUL},
176         /* 0x1c */  {"dmult   ",ITYPE_DIVMUL},
177         /* 0x1d */  {"dmultu  ",ITYPE_DIVMUL},
178         /* 0x1e */  {"ddiv    ",ITYPE_DIVMUL},
179         /* 0x1f */  {"ddivu   ",ITYPE_DIVMUL},
180
181         /* 0x20 */  {"add     ",    ITYPE_OP},
182         /* 0x21 */  {"addu    ",    ITYPE_OP},
183         /* 0x22 */  {"sub     ",    ITYPE_OP},
184         /* 0x23 */  {"subu    ",    ITYPE_OP},
185         /* 0x24 */  {"and     ",    ITYPE_OP},
186         /* 0x25 */  {"or      ",    ITYPE_OP},
187         /* 0x26 */  {"xor     ",    ITYPE_OP},
188         /* 0x27 */  {"nor     ",    ITYPE_OP},
189
190         /* 0x28 */  {""        , ITYPE_UNDEF},
191         /* 0x29 */  {""        , ITYPE_UNDEF},
192         /* 0x2a */  {"slt     ",    ITYPE_OP},
193         /* 0x2b */  {"sltu    ",    ITYPE_OP},
194         /* 0x2c */  {"dadd    ",    ITYPE_OP},
195         /* 0x2d */  {"daddu   ",    ITYPE_OP},
196         /* 0x2e */  {"dsub    ",    ITYPE_OP},
197         /* 0x2f */  {"dsubu   ",    ITYPE_OP},
198
199         /* 0x30 */  {"tge     ",  ITYPE_TRAP},
200         /* 0x31 */  {"tgeu    ",  ITYPE_TRAP},
201         /* 0x32 */  {"tlt     ",  ITYPE_TRAP},
202         /* 0x33 */  {"tltu    ",  ITYPE_TRAP},
203         /* 0x34 */  {"teq     ",  ITYPE_TRAP},
204         /* 0x35 */  {""        , ITYPE_UNDEF},
205         /* 0x36 */  {"tne     ",  ITYPE_TRAP},
206         /* 0x37 */  {""        , ITYPE_UNDEF},
207
208         /* 0x38 */  {"dsll    ",   ITYPE_IMM},
209         /* 0x39 */  {""        , ITYPE_UNDEF},
210         /* 0x3a */  {"dsrl    ",   ITYPE_IMM},
211         /* 0x3b */  {"dsra    ",   ITYPE_IMM},
212         /* 0x3c */  {"dsll32  ",   ITYPE_IMM},
213         /* 0x3d */  {""        , ITYPE_UNDEF},
214         /* 0x3e */  {"dsrl32  ",   ITYPE_IMM},
215         /* 0x3f */  {"dsra32  ",   ITYPE_IMM}
216 };
217
218
219 /* instruction decode table for 5 bit reg immediate function codes            */
220
221 static struct {char *name; int ftype;} regimms[] = {
222
223         /* 0x00 */  {"bltz    ",   ITYPE_BRA},
224         /* 0x01 */  {"bgez    ",   ITYPE_BRA},
225         /* 0x02 */  {"bltzl   ",   ITYPE_BRA},
226         /* 0x03 */  {"bgezl   ",   ITYPE_BRA},
227         /* 0x04 */  {"",         ITYPE_UNDEF},
228         /* 0x05 */  {"",         ITYPE_UNDEF},
229         /* 0x06 */  {"",         ITYPE_UNDEF},
230         /* 0x07 */  {"",         ITYPE_UNDEF},
231
232         /* 0x08 */  {"tgei    ",   ITYPE_IMM},
233         /* 0x09 */  {"dgeiu   ",   ITYPE_IMM},
234         /* 0x0a */  {"tlti    ",   ITYPE_IMM},
235         /* 0x0b */  {"tltiu   ",   ITYPE_IMM},
236         /* 0x0c */  {"teqi    ",   ITYPE_IMM},
237         /* 0x0d */  {"",         ITYPE_UNDEF},
238         /* 0x0e */  {"tnei    ",   ITYPE_IMM},
239         /* 0x0f */  {"",         ITYPE_UNDEF},
240
241         /* 0x10 */  {"bltzal  ",   ITYPE_BRA},
242         /* 0x11 */  {"bgezal  ",   ITYPE_BRA},
243         /* 0x12 */  {"bltzall ",   ITYPE_BRA},
244         /* 0x13 */  {"bgezall ",   ITYPE_BRA},
245         /* 0x14 */  {"",         ITYPE_UNDEF},
246         /* 0x15 */  {"",         ITYPE_UNDEF},
247         /* 0x16 */  {"",         ITYPE_UNDEF},
248         /* 0x17 */  {"",         ITYPE_UNDEF},
249
250         /* 0x18 */  {"",         ITYPE_UNDEF},
251         /* 0x19 */  {"",         ITYPE_UNDEF},
252         /* 0x1a */  {"",         ITYPE_UNDEF},
253         /* 0x1b */  {"",         ITYPE_UNDEF},
254         /* 0x1c */  {"",         ITYPE_UNDEF},
255         /* 0x1d */  {"",         ITYPE_UNDEF},
256         /* 0x1e */  {"",         ITYPE_UNDEF},
257         /* 0x1f */  {"",         ITYPE_UNDEF}
258 };
259
260
261 /* instruction decode table for 6 bit floating point op codes                 */
262
263 static struct {char *name; char *fill; int ftype;} fops[] = {
264
265         /* 0x00 */  {"add", "   ",   ITYPE_FOP},
266         /* 0x01 */  {"sub", "   ",   ITYPE_FOP},
267         /* 0x02 */  {"mul", "   ",   ITYPE_FOP},
268         /* 0x03 */  {"div", "   ",   ITYPE_FOP},
269         /* 0x04 */  {"sqrt", "  ",   ITYPE_FOP},
270         /* 0x05 */  {"abs", "   ",  ITYPE_FOP2},
271         /* 0x06 */  {"mov", "   ",  ITYPE_FOP2},
272         /* 0x07 */  {"neg", "   ",  ITYPE_FOP2},
273
274         /* 0x08 */  {"roundl", "",  ITYPE_FOP2},
275         /* 0x09 */  {"truncl", "",  ITYPE_FOP2},
276         /* 0x0a */  {"ceill", " ",  ITYPE_FOP2},
277         /* 0x0b */  {"floorl", "",  ITYPE_FOP2},
278         /* 0x0c */  {"round", " ",  ITYPE_FOP2},
279         /* 0x0d */  {"trunc", " ",  ITYPE_FOP2},
280         /* 0x0e */  {"ceil", "  ",  ITYPE_FOP2},
281         /* 0x0f */  {"floor", " ",  ITYPE_FOP2},
282
283         /* 0x10 */  {"",       "", ITYPE_UNDEF},
284         /* 0x11 */  {"",       "", ITYPE_UNDEF},
285         /* 0x12 */  {"",       "", ITYPE_UNDEF},
286         /* 0x13 */  {"",       "", ITYPE_UNDEF},
287         /* 0x14 */  {"",       "", ITYPE_UNDEF},
288         /* 0x15 */  {"",       "", ITYPE_UNDEF},
289         /* 0x16 */  {"",       "", ITYPE_UNDEF},
290         /* 0x17 */  {"",       "", ITYPE_UNDEF},
291
292         /* 0x18 */  {"",       "", ITYPE_UNDEF},
293         /* 0x19 */  {"recip", " ",  ITYPE_FOP2},
294         /* 0x1a */  {"rsqrt", " ",  ITYPE_FOP2},
295         /* 0x1b */  {"",       "", ITYPE_UNDEF},
296         /* 0x1c */  {"",       "", ITYPE_UNDEF},
297         /* 0x1d */  {"",       "", ITYPE_UNDEF},
298         /* 0x1e */  {"",       "", ITYPE_UNDEF},
299         /* 0x1f */  {"",       "", ITYPE_UNDEF},
300
301         /* 0x20 */  {"cvts", "  ",  ITYPE_FOP2},
302         /* 0x21 */  {"cvtd", "  ",  ITYPE_FOP2},
303         /* 0x22 */  {"cvtx", "  ",  ITYPE_FOP2},
304         /* 0x23 */  {"cvtq", "  ",  ITYPE_FOP2},
305         /* 0x24 */  {"cvtw", "  ",  ITYPE_FOP2},
306         /* 0x25 */  {"cvtl", "  ",  ITYPE_FOP2},
307         /* 0x26 */  {"",       "", ITYPE_UNDEF},
308         /* 0x27 */  {"",       "", ITYPE_UNDEF},
309
310         /* 0x28 */  {"",       "", ITYPE_UNDEF},
311         /* 0x29 */  {"",       "", ITYPE_UNDEF},
312         /* 0x2a */  {"",       "", ITYPE_UNDEF},
313         /* 0x2b */  {"",       "", ITYPE_UNDEF},
314         /* 0x2c */  {"",       "", ITYPE_UNDEF},
315         /* 0x2d */  {"",       "", ITYPE_UNDEF},
316         /* 0x2e */  {"",       "", ITYPE_UNDEF},
317         /* 0x2f */  {"",       "", ITYPE_UNDEF},
318
319         /* 0x30 */  {"c.f", "   ",  ITYPE_FCMP},
320         /* 0x31 */  {"c.un", "  ",  ITYPE_FCMP},
321         /* 0x32 */  {"c.eq", "  ",  ITYPE_FCMP},
322         /* 0x33 */  {"c.ueq", " ",  ITYPE_FCMP},
323         /* 0x34 */  {"c.olt", " ",  ITYPE_FCMP},
324         /* 0x35 */  {"c.ult", " ",  ITYPE_FCMP},
325         /* 0x36 */  {"c.ole", " ",  ITYPE_FCMP},
326         /* 0x37 */  {"c.ule", " ",  ITYPE_FCMP},
327
328         /* 0x38 */  {"c.sf", "  ",  ITYPE_FCMP},
329         /* 0x39 */  {"c.ngle", "",  ITYPE_FCMP},
330         /* 0x3a */  {"c.seq", " ",  ITYPE_FCMP},
331         /* 0x3b */  {"c.ngl", " ",  ITYPE_FCMP},
332         /* 0x3c */  {"c.lt", "  ",  ITYPE_FCMP},
333         /* 0x3d */  {"c.nge", " ",  ITYPE_FCMP},
334         /* 0x3e */  {"c.le", "  ",  ITYPE_FCMP},
335         /* 0x3f */  {"c.ngt", " ",  ITYPE_FCMP}
336 };
337
338
339 /* format decode table for 3 bit floating point format codes                  */
340
341 static char *fmt[] = {
342         /* 0x00 */  ".s",
343         /* 0x01 */  ".d",
344         /* 0x02 */  ".x",
345         /* 0x03 */  ".q",
346         /* 0x04 */  ".w",
347         /* 0x05 */  ".l",
348         /* 0x06 */  ".?",
349         /* 0x07 */  ".?"
350 };
351
352
353 /* format decode table for 2 bit floating point branch codes                  */
354
355 static char *fbra[] = {
356         /* 0x00 */  "bc1f    ",
357         /* 0x01 */  "bc1t    ",
358         /* 0x02 */  "bc1fl   ",
359         /* 0x03 */  "bc1tl   "
360 };
361
362
363 /* instruction decode table for 32 floating point registers                   */
364
365 #if 0
366 static char *fregs[] = {
367
368         /* 0x00 */  "fv0",   /*  "$f0", */
369         /* 0x01 */  "ft16",  /*  "$f1", */
370         /* 0x02 */  "fv1",   /*  "$f2", */
371         /* 0x03 */  "ft17",  /*  "$f3", */
372         /* 0x04 */  "ft0",   /*  "$f4", */
373         /* 0x05 */  "ft1",   /*  "$f5", */
374         /* 0x06 */  "ft2",   /*  "$f6", */
375         /* 0x07 */  "ft3",   /*  "$f7", */
376
377         /* 0x08 */  "ft4",   /*  "$f8", */
378         /* 0x09 */  "ft5",   /*  "$f9", */
379         /* 0x0a */  "ft6",   /* "$f10", */
380         /* 0x0b */  "ft7",   /* "$f11", */
381         /* 0x0c */  "fa0",   /* "$f12", */
382         /* 0x0d */  "fa1",   /* "$f13", */
383         /* 0x0e */  "fa2",   /* "$f14", */
384         /* 0x0f */  "fa3",   /* "$f15", */
385
386         /* 0x10 */  "fa4",   /* "$f16", */
387         /* 0x11 */  "fa5",   /* "$f17", */
388         /* 0x12 */  "fa6",   /* "$f18", */
389         /* 0x13 */  "fa7",   /* "$f19", */
390         /* 0x14 */  "ft8",   /* "$f20", */
391         /* 0x15 */  "ft9",   /* "$f21", */
392         /* 0x16 */  "ft10",  /* "$f22", */
393         /* 0x17 */  "ft11",  /* "$f23", */
394
395         /* 0x18 */  "fs0",   /* "$f24", */
396         /* 0x19 */  "ft12",  /* "$f25", */
397         /* 0x1a */  "fs1",   /* "$f26", */
398         /* 0x1b */  "ft13",  /* "$f27", */
399         /* 0x1c */  "fs2",   /* "$f28", */
400         /* 0x1d */  "ft14",  /* "$f29", */
401         /* 0x1e */  "fs3",   /* "$f30", */
402         /* 0x1f */  "ft15"   /* "$f31"  */
403 };
404 #endif
405
406
407 /* disassinstr *****************************************************************
408
409    Outputs a disassembler listing of one machine code instruction on
410    'stdout'.
411
412    code: pointer to instructions machine code
413
414 *******************************************************************************/
415
416 u1 *disassinstr(u1 *code)
417 {
418         s4 op;                      /* 6 bit op code                              */
419         s4 opfun;                   /* 6 bit function code                        */
420         s4 rs, rt, rd;              /* 5 bit integer register specifiers          */
421         s4 fs, ft, fd;              /* 5 bit floating point register specifiers   */
422         s4 shift;                   /* 5 bit unsigned shift amount                */
423         s4 c;
424
425         c = *((s4 *) code);
426
427         op    = (c >> 26) & 0x3f;   /* 6 bit op code                              */
428         opfun = (c >>  0) & 0x3f;   /* 6 bit function code                        */
429         rs    = (c >> 21) & 0x1f;   /* 5 bit source register specifier            */
430         rt    = (c >> 16) & 0x1f;   /* 5 bit source/destination register specifier*/
431         rd    = (c >> 11) & 0x1f;   /* 5 bit destination register specifier       */
432         shift = (c >>  6) & 0x1f;   /* 5 bit unsigned shift amount                */
433
434 #if SIZEOF_VOID_P == 8
435         printf("0x%016lx:   %08x    ", (u8) code, c);
436 #else
437         printf("0x%08x:   %08x    ", (u4) code, c);
438 #endif
439
440         switch (ops[op].itype) {
441         case ITYPE_JMP:                      /* 26 bit unsigned jump offset   */
442                 printf("%s %#09x\n", ops[op].name, (c & 0x3ffffff) << 2); 
443                 break;
444
445         case ITYPE_IMM:                      /* 16 bit signed immediate value */
446                 printf("%s %s,%s,%d\n", ops[op].name, abi_registers_integer_name[rt],
447                            abi_registers_integer_name[rs], (c << 16) >> 16); 
448                 break;
449
450         case ITYPE_MEM:                      /* 16 bit signed memory offset   */
451                 printf("%s %s,%d(%s)\n", ops[op].name, abi_registers_integer_name[rt],
452                            (c << 16) >> 16, abi_registers_integer_name[rs]); 
453                 break;
454
455         case ITYPE_FMEM:                     /* 16 bit signed memory offset   */
456                 printf("%s $f%d,%d(%s)\n", ops[op].name, rt, (c << 16) >> 16,
457                            abi_registers_integer_name[rs]);
458                 break;
459
460         case ITYPE_BRA:                      /* 16 bit signed branch offset   */
461                 if (op == 0x04 && rs == 0 && rt == 0) {
462 #if SIZEOF_VOID_P == 8
463                         printf("b        0x%016lx\n", (u8) code + 4 + ((c << 16) >> 14));
464 #else
465                         printf("b        0x%08x\n", (u4) code + 4 + ((c << 16) >> 14));
466 #endif
467                         break;
468                 }       
469 #if SIZEOF_VOID_P == 8
470                 printf("%s %s,%s,0x%016lx\n", ops[op].name,
471                            abi_registers_integer_name[rs],
472                            abi_registers_integer_name[rt], 
473                            (u8) code + 4 + ((c << 16) >> 14));
474 #else
475                 printf("%s %s,%s,0x%08x\n", ops[op].name,
476                            abi_registers_integer_name[rs],
477                            abi_registers_integer_name[rt], 
478                            (u4) code + 4 + ((c << 16) >> 14));
479 #endif
480                 break;
481                         
482         case ITYPE_RIMM:
483                 if (regimms[rt].ftype == ITYPE_IMM)
484                         printf("%s %s,%d\n", regimms[rt].name,
485                                    abi_registers_integer_name[rs], (c << 16) >> 16);
486                 else if (regimms[rt].ftype == ITYPE_BRA)
487 #if SIZEOF_VOID_P == 8
488                         printf("%s %s,0x%016lx\n", regimms[rt].name,
489                                    abi_registers_integer_name[rs],
490                                    (u8) code + 4 + ((c << 16) >> 14));
491 #else
492                         printf("%s %s,0x%08x\n", regimms[rt].name,
493                                    abi_registers_integer_name[rs],
494                                    (u4) code + 4 + ((c << 16) >> 14));
495 #endif
496                 else
497                         printf("regimm   %#04x,$%d,%d\n", rt, rs, (c << 16) >> 16);             
498                 break;
499
500         case ITYPE_OP:
501                 if (c == 0) {
502                         printf("nop\n");
503                         break;
504                 }
505                 if (opfun == 0x25 && rt == 0) {
506                         if (rs == 0)
507                                 printf("clr      %s\n", abi_registers_integer_name[rd]);
508                         else
509                                 printf("move     %s,%s\n", abi_registers_integer_name[rd],
510                                            abi_registers_integer_name[rs]);
511                         break;
512                 }
513                 switch (regops[opfun].ftype) {
514                 case ITYPE_OP:
515                         printf("%s %s,%s,%s\n", regops[opfun].name,
516                                    abi_registers_integer_name[rd],
517                                    abi_registers_integer_name[rs],
518                                    abi_registers_integer_name[rt]);
519                         break;
520                 case ITYPE_IMM:  /* immediate instruction */
521                         printf("%s %s,%s,%d\n",
522                                    regops[opfun].name, abi_registers_integer_name[rd],
523                                    abi_registers_integer_name[rt], shift);
524                         break;
525                 case ITYPE_TRAP:
526                         printf("%s %s,%s,%d\n", regops[opfun].name,
527                                    abi_registers_integer_name[rs],
528                                    abi_registers_integer_name[rt], (c << 16) >> 22);
529                         break;
530                 case ITYPE_DIVMUL: /* div/mul instruction */
531                         printf("%s %s,%s\n", regops[opfun].name,
532                                    abi_registers_integer_name[rs],
533                                    abi_registers_integer_name[rt]);
534                         break;
535                 case ITYPE_JMP:
536                         if (rd == 31) {
537                                 printf("%s %s\n", regops[opfun].name,
538                                            abi_registers_integer_name[rs]);
539                                 break;
540                         }
541                         printf("%s %s,%s\n", regops[opfun].name,
542                                    abi_registers_integer_name[rd],
543                                    abi_registers_integer_name[rs]);
544                         break;
545                 case ITYPE_MTOJR:
546                         if (opfun == 8 && rs == 31) {
547                                 printf("ret\n");
548                                 break;
549                         }
550                         printf("%s %s\n", regops[opfun].name,
551                                    abi_registers_integer_name[rs]);
552                         break;
553                 case ITYPE_MFROM:
554                         printf("%s %s\n", regops[opfun].name,
555                                    abi_registers_integer_name[rd]);
556                         break;
557                 case ITYPE_SYS:
558                         printf("%s\n", regops[opfun].name);
559                 default:
560                         printf("special  (%#04x) $%d,$%d,$%d\n", opfun, rd, rs, rt);
561                 }               
562                 break;
563
564         case ITYPE_FOP:
565                 fs    = (c >> 11) & 0x1f;   /* 5 bit source register              */
566                 ft    = (c >> 16) & 0x1f;   /* 5 bit source/destination register  */
567                 fd    = (c >>  6) & 0x1f;   /* 5 bit destination register         */
568
569                 if (rs == 8) {              /* floating point branch              */
570 #if SIZEOF_VOID_P == 8
571                         printf("%s 0x%016lx\n", fbra[ft & 3],
572                                    (u8) code + 4 + ((c << 16) >> 14));
573 #else
574                         printf("%s 0x%08x\n", fbra[ft & 3],
575                                    (u4) code + 4 + ((c << 16) >> 14));
576 #endif
577                         break;
578                 }
579
580                 if (rs == 0) {              /* move from                          */
581                         printf("mfc1     %s,$f%d\n", abi_registers_integer_name[rt], fs);
582                         break;
583                 }
584
585                 if (rs == 1) {              /* double move from                   */
586                         printf("dmfc1    %s,$f%d\n", abi_registers_integer_name[rt], fs);
587                         break;
588                 }
589
590                 if (rs == 4) {              /* move to                            */
591                         printf("mtc1     %s,$f%d\n", abi_registers_integer_name[rt], fs);
592                         break;
593                 }
594
595                 if (rs == 5) {              /* double move to                     */
596                         printf("dmtc1    %s,$f%d\n", abi_registers_integer_name[rt], fs);
597                         break;
598                 }
599
600                 rs    = rs & 7;             /* truncate to 3 bit format specifier */
601
602                 if (fops[opfun].ftype == ITYPE_FOP)
603                         printf("%s%s%s $f%d,$f%d,$f%d\n", fops[opfun].name, fmt[rs],
604                                    fops[opfun].fill, fd, fs, ft);
605                 else if (fops[opfun].ftype == ITYPE_FOP2)
606                         printf("%s%s%s $f%d,$f%d\n", fops[opfun].name, fmt[rs],
607                                    fops[opfun].fill, fd, fs);
608                 else if (fops[opfun].ftype == ITYPE_FCMP)
609                         printf("%s%s%s $f%d,$f%d\n", fops[opfun].name, fmt[rs],
610                                    fops[opfun].fill, fs, ft);
611                 else
612                         printf("cop1     (%#04x) $f%d,$f%d,$f%d\n", opfun, fd, fs, ft);
613                 break;
614
615         default:
616                 printf("undef    %#04x(%#04x) $%d,$%d,$%d\n", op, opfun, rd, rs, rt);
617         }
618
619         return code + 4;
620 }
621
622
623 /* disassemble *****************************************************************
624
625    Outputs a disassembler listing of some machine code on 'stdout'.
626
627    start: pointer to first instruction
628    end:   pointer to last instruction
629
630 *******************************************************************************/
631
632 void disassemble(u1 *start, u1 *end)
633 {
634         printf("  --- disassembler listing ---\n");     
635         for (; start < end; )
636                 start = disassinstr(start);
637 }
638
639
640 /*
641  * These are local overrides for various environment variables in Emacs.
642  * Please do not remove this and leave it at the end of the file, where
643  * Emacs will automagically detect them.
644  * ---------------------------------------------------------------------
645  * Local variables:
646  * mode: c
647  * indent-tabs-mode: t
648  * c-basic-offset: 4
649  * tab-width: 4
650  * End:
651  */