* src/vm/jit/mips/emit.c: Include fixes for cacaoh-changes.
[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 7252 2007-01-29 21:09:01Z 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, regs[rt],
449                            regs[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, regs[rt],
454                            (c << 16) >> 16, regs[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, regs[rs]);
459                 break;
460
461         case ITYPE_BRA:                      /* 16 bit signed branch offset   */
462                 if (op == 0x04 && rs == 0 && rt == 0) {
463 #if SIZEOF_VOID_P == 8
464                         printf("b        0x%016lx\n", (u8) code + 4 + ((c << 16) >> 14));
465 #else
466                         printf("b        0x%08x\n", (u4) code + 4 + ((c << 16) >> 14));
467 #endif
468                         break;
469                 }       
470 #if SIZEOF_VOID_P == 8
471                 printf("%s %s,%s,0x%016lx\n", ops[op].name, regs[rs], regs[rt], 
472                            (u8) code + 4 + ((c << 16) >> 14));
473 #else
474                 printf("%s %s,%s,0x%08x\n", ops[op].name, regs[rs], regs[rt], 
475                            (u4) code + 4 + ((c << 16) >> 14));
476 #endif
477                 break;
478                         
479         case ITYPE_RIMM:
480                 if (regimms[rt].ftype == ITYPE_IMM)
481                         printf("%s %s,%d\n", regimms[rt].name, regs[rs], (c << 16) >> 16);
482                 else if (regimms[rt].ftype == ITYPE_BRA)
483 #if SIZEOF_VOID_P == 8
484                         printf("%s %s,0x%016lx\n", regimms[rt].name, regs[rs],
485                                    (u8) code + 4 + ((c << 16) >> 14));
486 #else
487                         printf("%s %s,0x%08x\n", regimms[rt].name, regs[rs],
488                                    (u4) code + 4 + ((c << 16) >> 14));
489 #endif
490                 else
491                         printf("regimm   %#04x,$%d,%d\n", rt, rs, (c << 16) >> 16);             
492                 break;
493
494         case ITYPE_OP:
495                 if (c == 0) {
496                         printf("nop\n");
497                         break;
498                 }
499                 if (opfun == 0x25 && rt == 0) {
500                         if (rs == 0)
501                                 printf("clr      %s\n", regs[rd]);
502                         else
503                                 printf("move     %s,%s\n", regs[rd], regs[rs]);
504                         break;
505                 }
506                 switch (regops[opfun].ftype) {
507                 case ITYPE_OP:
508                         printf("%s %s,%s,%s\n", regops[opfun].name, regs[rd],
509                                    regs[rs], regs[rt]);
510                         break;
511                 case ITYPE_IMM:  /* immediate instruction */
512                         printf("%s %s,%s,%d\n",
513                                    regops[opfun].name, regs[rd], regs[rt], shift);
514                         break;
515                 case ITYPE_TRAP:
516                         printf("%s %s,%s,%d\n", regops[opfun].name,
517                                    regs[rs], regs[rt], (c << 16) >> 22);
518                         break;
519                 case ITYPE_DIVMUL: /* div/mul instruction */
520                         printf("%s %s,%s\n", regops[opfun].name, regs[rs], regs[rt]);
521                         break;
522                 case ITYPE_JMP:
523                         if (rd == 31) {
524                                 printf("%s %s\n", regops[opfun].name, regs[rs]);
525                                 break;
526                         }
527                         printf("%s %s,%s\n", regops[opfun].name, regs[rd], regs[rs]);
528                         break;
529                 case ITYPE_MTOJR:
530                         if (opfun == 8 && rs == 31) {
531                                 printf("ret\n");
532                                 break;
533                         }
534                         printf("%s %s\n", regops[opfun].name, regs[rs]);
535                         break;
536                 case ITYPE_MFROM:
537                         printf("%s %s\n", regops[opfun].name, regs[rd]);
538                         break;
539                 case ITYPE_SYS:
540                         printf("%s\n", regops[opfun].name);
541                 default:
542                         printf("special  (%#04x) $%d,$%d,$%d\n", opfun, rd, rs, rt);
543                 }               
544                 break;
545
546         case ITYPE_FOP:
547                 fs    = (c >> 11) & 0x1f;   /* 5 bit source register              */
548                 ft    = (c >> 16) & 0x1f;   /* 5 bit source/destination register  */
549                 fd    = (c >>  6) & 0x1f;   /* 5 bit destination register         */
550
551                 if (rs == 8) {              /* floating point branch              */
552 #if SIZEOF_VOID_P == 8
553                         printf("%s 0x%016lx\n", fbra[ft & 3],
554                                    (u8) code + 4 + ((c << 16) >> 14));
555 #else
556                         printf("%s 0x%08x\n", fbra[ft & 3],
557                                    (u4) code + 4 + ((c << 16) >> 14));
558 #endif
559                         break;
560                 }
561
562                 if (rs == 0) {              /* move from                          */
563                         printf("mfc1     %s,$f%d\n", regs[rt], fs);             
564                         break;
565                 }
566
567                 if (rs == 1) {              /* double move from                   */
568                         printf("dmfc1    %s,$f%d\n", regs[rt], fs);             
569                         break;
570                 }
571
572                 if (rs == 4) {              /* move to                            */
573                         printf("mtc1     %s,$f%d\n", regs[rt], fs);             
574                         break;
575                 }
576
577                 if (rs == 5) {              /* double move to                     */
578                         printf("dmtc1    %s,$f%d\n", regs[rt], fs);             
579                         break;
580                 }
581
582                 rs    = rs & 7;             /* truncate to 3 bit format specifier */
583
584                 if (fops[opfun].ftype == ITYPE_FOP)
585                         printf("%s%s%s $f%d,$f%d,$f%d\n", fops[opfun].name, fmt[rs],
586                                    fops[opfun].fill, fd, fs, ft);
587                 else if (fops[opfun].ftype == ITYPE_FOP2)
588                         printf("%s%s%s $f%d,$f%d\n", fops[opfun].name, fmt[rs],
589                                    fops[opfun].fill, fd, fs);
590                 else if (fops[opfun].ftype == ITYPE_FCMP)
591                         printf("%s%s%s $f%d,$f%d\n", fops[opfun].name, fmt[rs],
592                                    fops[opfun].fill, fs, ft);
593                 else
594                         printf("cop1     (%#04x) $f%d,$f%d,$f%d\n", opfun, fd, fs, ft);
595                 break;
596
597         default:
598                 printf("undef    %#04x(%#04x) $%d,$%d,$%d\n", op, opfun, rd, rs, rt);
599         }
600
601         return code + 4;
602 }
603
604
605 /* disassemble *****************************************************************
606
607    Outputs a disassembler listing of some machine code on 'stdout'.
608
609    start: pointer to first instruction
610    end:   pointer to last instruction
611
612 *******************************************************************************/
613
614 void disassemble(u1 *start, u1 *end)
615 {
616         printf("  --- disassembler listing ---\n");     
617         for (; start < end; )
618                 start = disassinstr(start);
619 }
620
621
622 /*
623  * These are local overrides for various environment variables in Emacs.
624  * Please do not remove this and leave it at the end of the file, where
625  * Emacs will automagically detect them.
626  * ---------------------------------------------------------------------
627  * Local variables:
628  * mode: c
629  * indent-tabs-mode: t
630  * c-basic-offset: 4
631  * tab-width: 4
632  * End:
633  */