* Updated header: Added 2006. Changed address of FSF. Changed email
[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 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    Contact: cacao@cacaojvm.org
26
27    Authors: Andreas Krall
28
29    Changes: Christian Thalinger
30
31    $Id: disass.c 4357 2006-01-22 23:33:38Z twisti $
32
33 */
34
35
36 #include <stdio.h>
37
38 #include "config.h"
39 #include "vm/types.h"
40
41
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.
48 */
49
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        */
66
67
68 /* instruction decode table for 6 bit op codes                                */
69
70 static struct {char *name; int itype;} ops[] = {
71
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},
80
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},
89
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},
98
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},
107
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},
116
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},
125
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},
134
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}
143 };
144
145
146 /* instruction decode table for 6 bit special function codes                  */
147
148 static struct {char *name; int ftype;} regops[] = {
149
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},
158
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},
167
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},
176
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},
185
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},
194
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},
203
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},
212
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}
221 };
222
223
224 /* instruction decode table for 5 bit reg immediate function codes            */
225
226 static struct {char *name; int ftype;} regimms[] = {
227
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},
236
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},
245
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},
254
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}
263 };
264
265
266 /* instruction decode table for 6 bit floating point op codes                 */
267
268 static struct {char *name; char *fill; int ftype;} fops[] = {
269
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},
278
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},
287
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},
296
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},
305
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},
314
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},
323
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},
332
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}
341 };
342
343
344 /* format decode table for 3 bit floating point format codes                  */
345
346 static char *fmt[] = {
347         /* 0x00 */  ".s",
348         /* 0x01 */  ".d",
349         /* 0x02 */  ".x",
350         /* 0x03 */  ".q",
351         /* 0x04 */  ".w",
352         /* 0x05 */  ".l",
353         /* 0x06 */  ".?",
354         /* 0x07 */  ".?"
355 };
356
357
358 /* format decode table for 2 bit floating point branch codes                  */
359
360 static char *fbra[] = {
361         /* 0x00 */  "bc1f    ",
362         /* 0x01 */  "bc1t    ",
363         /* 0x02 */  "bc1fl   ",
364         /* 0x03 */  "bc1tl   "
365 };
366
367
368 /* instruction decode table for 32 integer registers                          */
369
370 char *regs[] = {
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", */
379
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", */
388
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", */
397
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"  */
406 };
407
408
409 /* instruction decode table for 32 floating point registers                   */
410
411 #if 0
412 static char *fregs[] = {
413
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", */
422
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", */
431
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", */
440
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"  */
449 };
450 #endif
451
452
453 /* disassinstr *****************************************************************
454
455    Outputs a disassembler listing of one machine code instruction on
456    'stdout'.
457
458    code: pointer to instructions machine code
459
460 *******************************************************************************/
461
462 u1 *disassinstr(u1 *code)
463 {
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                */
469         s4 c;
470
471         c = *((s4 *) code);
472
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                */
479
480 #if SIZEOF_VOID_P == 8
481         printf("0x%016lx:   %08x    ", (u8) code, c);
482 #else
483         printf("0x%08x:   %08x    ", (u4) code, c);
484 #endif
485
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); 
489                 break;
490
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); 
494                 break;
495
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]); 
499                 break;
500
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]);
503                 break;
504
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));
509 #else
510                         printf("b        0x%08x\n", (u4) code + 4 + ((c << 16) >> 14));
511 #endif
512                         break;
513                 }       
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));
517 #else
518                 printf("%s %s,%s,0x%08x\n", ops[op].name, regs[rs], regs[rt], 
519                            (u4) code + 4 + ((c << 16) >> 14));
520 #endif
521                 break;
522                         
523         case ITYPE_RIMM:
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));
530 #else
531                         printf("%s %s,0x%08x\n", regimms[rt].name, regs[rs],
532                                    (u4) code + 4 + ((c << 16) >> 14));
533 #endif
534                 else
535                         printf("regimm   %#04x,$%d,%d\n", rt, rs, (c << 16) >> 16);             
536                 break;
537
538         case ITYPE_OP:
539                 if (c == 0) {
540                         printf("nop\n");
541                         break;
542                 }
543                 if (opfun == 0x25 && rt == 0) {
544                         if (rs == 0)
545                                 printf("clr      %s\n", regs[rd]);
546                         else
547                                 printf("move     %s,%s\n", regs[rd], regs[rs]);
548                         break;
549                 }
550                 switch (regops[opfun].ftype) {
551                 case ITYPE_OP:
552                         printf("%s %s,%s,%s\n", regops[opfun].name, regs[rd],
553                                    regs[rs], regs[rt]);
554                         break;
555                 case ITYPE_IMM:  /* immediate instruction */
556                         printf("%s %s,%s,%d\n",
557                                    regops[opfun].name, regs[rd], regs[rt], shift);
558                         break;
559                 case ITYPE_TRAP:
560                         printf("%s %s,%s,%d\n", regops[opfun].name,
561                                    regs[rs], regs[rt], (c << 16) >> 22);
562                         break;
563                 case ITYPE_DIVMUL: /* div/mul instruction */
564                         printf("%s %s,%s\n", regops[opfun].name, regs[rs], regs[rt]);
565                         break;
566                 case ITYPE_JMP:
567                         if (rd == 31) {
568                                 printf("%s %s\n", regops[opfun].name, regs[rs]);
569                                 break;
570                         }
571                         printf("%s %s,%s\n", regops[opfun].name, regs[rd], regs[rs]);
572                         break;
573                 case ITYPE_MTOJR:
574                         if (opfun == 8 && rs == 31) {
575                                 printf("ret\n");
576                                 break;
577                         }
578                         printf("%s %s\n", regops[opfun].name, regs[rs]);
579                         break;
580                 case ITYPE_MFROM:
581                         printf("%s %s\n", regops[opfun].name, regs[rd]);
582                         break;
583                 case ITYPE_SYS:
584                         printf("%s\n", regops[opfun].name);
585                 default:
586                         printf("special  (%#04x) $%d,$%d,$%d\n", opfun, rd, rs, rt);
587                 }               
588                 break;
589
590         case ITYPE_FOP:
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         */
594
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));
599 #else
600                         printf("%s 0x%08x\n", fbra[ft & 3],
601                                    (u4) code + 4 + ((c << 16) >> 14));
602 #endif
603                         break;
604                 }
605
606                 if (rs == 0) {              /* move from                          */
607                         printf("mfc1     %s,$f%d\n", regs[rt], fs);             
608                         break;
609                 }
610
611                 if (rs == 1) {              /* double move from                   */
612                         printf("dmfc1    %s,$f%d\n", regs[rt], fs);             
613                         break;
614                 }
615
616                 if (rs == 4) {              /* move to                            */
617                         printf("mtc1     %s,$f%d\n", regs[rt], fs);             
618                         break;
619                 }
620
621                 if (rs == 5) {              /* double move to                     */
622                         printf("dmtc1    %s,$f%d\n", regs[rt], fs);             
623                         break;
624                 }
625
626                 rs    = rs & 7;             /* truncate to 3 bit format specifier */
627
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);
637                 else
638                         printf("cop1     (%#04x) $f%d,$f%d,$f%d\n", opfun, fd, fs, ft);
639                 break;
640
641         default:
642                 printf("undef    %#04x(%#04x) $%d,$%d,$%d\n", op, opfun, rd, rs, rt);
643         }
644
645         return code + 4;
646 }
647
648
649 /* disassemble *****************************************************************
650
651    Outputs a disassembler listing of some machine code on 'stdout'.
652
653    start: pointer to first instruction
654    end:   pointer to last instruction
655
656 *******************************************************************************/
657
658 void disassemble(u1 *start, u1 *end)
659 {
660         printf("  --- disassembler listing ---\n");     
661         for (; start < end; )
662                 start = disassinstr(start);
663 }
664
665
666 /*
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  * ---------------------------------------------------------------------
671  * Local variables:
672  * mode: c
673  * indent-tabs-mode: t
674  * c-basic-offset: 4
675  * tab-width: 4
676  * End:
677  */