385023e70687c1599958dc6b6fdf58bec6838c09
[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    $Id: disass.c 7351 2007-02-13 21:32:36Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <stdio.h>
33
34 #include "vm/types.h"
35
36 #include "vm/jit/abi.h"
37
38
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.
45 */
46
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        */
63
64
65 /* instruction decode table for 6 bit op codes                                */
66
67 static struct {char *name; int itype;} ops[] = {
68
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},
77
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},
86
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},
95
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},
104
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},
113
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},
122
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},
131
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}
140 };
141
142
143 /* instruction decode table for 6 bit special function codes                  */
144
145 static struct {char *name; int ftype;} regops[] = {
146
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},
155
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},
164
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},
173
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},
182
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},
191
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},
200
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},
209
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}
218 };
219
220
221 /* instruction decode table for 5 bit reg immediate function codes            */
222
223 static struct {char *name; int ftype;} regimms[] = {
224
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},
233
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},
242
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},
251
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}
260 };
261
262
263 /* instruction decode table for 6 bit floating point op codes                 */
264
265 static struct {char *name; char *fill; int ftype;} fops[] = {
266
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},
275
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},
284
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},
293
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},
302
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},
311
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},
320
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},
329
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}
338 };
339
340
341 /* format decode table for 3 bit floating point format codes                  */
342
343 static char *fmt[] = {
344         /* 0x00 */  ".s",
345         /* 0x01 */  ".d",
346         /* 0x02 */  ".x",
347         /* 0x03 */  ".q",
348         /* 0x04 */  ".w",
349         /* 0x05 */  ".l",
350         /* 0x06 */  ".?",
351         /* 0x07 */  ".?"
352 };
353
354
355 /* format decode table for 2 bit floating point branch codes                  */
356
357 static char *fbra[] = {
358         /* 0x00 */  "bc1f    ",
359         /* 0x01 */  "bc1t    ",
360         /* 0x02 */  "bc1fl   ",
361         /* 0x03 */  "bc1tl   "
362 };
363
364
365 /* instruction decode table for 32 floating point registers                   */
366
367 #if 0
368 static char *fregs[] = {
369
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", */
378
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", */
387
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", */
396
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"  */
405 };
406 #endif
407
408
409 /* disassinstr *****************************************************************
410
411    Outputs a disassembler listing of one machine code instruction on
412    'stdout'.
413
414    code: pointer to instructions machine code
415
416 *******************************************************************************/
417
418 u1 *disassinstr(u1 *code)
419 {
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                */
425         s4 c;
426
427         c = *((s4 *) code);
428
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                */
435
436 #if SIZEOF_VOID_P == 8
437         printf("0x%016lx:   %08x    ", (u8) code, c);
438 #else
439         printf("0x%08x:   %08x    ", (u4) code, c);
440 #endif
441
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); 
445                 break;
446
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); 
450                 break;
451
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]); 
455                 break;
456
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]);
460                 break;
461
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));
466 #else
467                         printf("b        0x%08x\n", (u4) code + 4 + ((c << 16) >> 14));
468 #endif
469                         break;
470                 }       
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));
476 #else
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));
481 #endif
482                 break;
483                         
484         case ITYPE_RIMM:
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));
493 #else
494                         printf("%s %s,0x%08x\n", regimms[rt].name,
495                                    abi_registers_integer_name[rs],
496                                    (u4) code + 4 + ((c << 16) >> 14));
497 #endif
498                 else
499                         printf("regimm   %#04x,$%d,%d\n", rt, rs, (c << 16) >> 16);             
500                 break;
501
502         case ITYPE_OP:
503                 if (c == 0) {
504                         printf("nop\n");
505                         break;
506                 }
507                 if (opfun == 0x25 && rt == 0) {
508                         if (rs == 0)
509                                 printf("clr      %s\n", abi_registers_integer_name[rd]);
510                         else
511                                 printf("move     %s,%s\n", abi_registers_integer_name[rd],
512                                            abi_registers_integer_name[rs]);
513                         break;
514                 }
515                 switch (regops[opfun].ftype) {
516                 case ITYPE_OP:
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]);
521                         break;
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);
526                         break;
527                 case ITYPE_TRAP:
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);
531                         break;
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]);
536                         break;
537                 case ITYPE_JMP:
538                         if (rd == 31) {
539                                 printf("%s %s\n", regops[opfun].name,
540                                            abi_registers_integer_name[rs]);
541                                 break;
542                         }
543                         printf("%s %s,%s\n", regops[opfun].name,
544                                    abi_registers_integer_name[rd],
545                                    abi_registers_integer_name[rs]);
546                         break;
547                 case ITYPE_MTOJR:
548                         if (opfun == 8 && rs == 31) {
549                                 printf("ret\n");
550                                 break;
551                         }
552                         printf("%s %s\n", regops[opfun].name,
553                                    abi_registers_integer_name[rs]);
554                         break;
555                 case ITYPE_MFROM:
556                         printf("%s %s\n", regops[opfun].name,
557                                    abi_registers_integer_name[rd]);
558                         break;
559                 case ITYPE_SYS:
560                         printf("%s\n", regops[opfun].name);
561                 default:
562                         printf("special  (%#04x) $%d,$%d,$%d\n", opfun, rd, rs, rt);
563                 }               
564                 break;
565
566         case ITYPE_FOP:
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         */
570
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));
575 #else
576                         printf("%s 0x%08x\n", fbra[ft & 3],
577                                    (u4) code + 4 + ((c << 16) >> 14));
578 #endif
579                         break;
580                 }
581
582                 if (rs == 0) {              /* move from                          */
583                         printf("mfc1     %s,$f%d\n", abi_registers_integer_name[rt], fs);
584                         break;
585                 }
586
587                 if (rs == 1) {              /* double move from                   */
588                         printf("dmfc1    %s,$f%d\n", abi_registers_integer_name[rt], fs);
589                         break;
590                 }
591
592                 if (rs == 4) {              /* move to                            */
593                         printf("mtc1     %s,$f%d\n", abi_registers_integer_name[rt], fs);
594                         break;
595                 }
596
597                 if (rs == 5) {              /* double move to                     */
598                         printf("dmtc1    %s,$f%d\n", abi_registers_integer_name[rt], fs);
599                         break;
600                 }
601
602                 rs    = rs & 7;             /* truncate to 3 bit format specifier */
603
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);
613                 else
614                         printf("cop1     (%#04x) $f%d,$f%d,$f%d\n", opfun, fd, fs, ft);
615                 break;
616
617         default:
618                 printf("undef    %#04x(%#04x) $%d,$%d,$%d\n", op, opfun, rd, rs, rt);
619         }
620
621         return code + 4;
622 }
623
624
625 /* disassemble *****************************************************************
626
627    Outputs a disassembler listing of some machine code on 'stdout'.
628
629    start: pointer to first instruction
630    end:   pointer to last instruction
631
632 *******************************************************************************/
633
634 void disassemble(u1 *start, u1 *end)
635 {
636         printf("  --- disassembler listing ---\n");     
637         for (; start < end; )
638                 start = disassinstr(start);
639 }
640
641
642 /*
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  * ---------------------------------------------------------------------
647  * Local variables:
648  * mode: c
649  * indent-tabs-mode: t
650  * c-basic-offset: 4
651  * tab-width: 4
652  * End:
653  */