GNU header update.
[cacao.git] / src / vm / jit / mips / disass.c
1 /* jit/mips/disass.c - primitive disassembler for mips machine code
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    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., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Andreas Krall
28
29    $Id: disass.c 1735 2004-12-07 14:33:27Z twisti $
30
31 */
32
33
34 #include <stdio.h>
35 #include "types.h"
36 #include "disass.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 integer registers                          */
366
367 char *regs[] = {
368         /* 0x00 */  "zero", /*  "$0", */
369         /* 0x01 */  "at",   /*  "$1", */
370         /* 0x02 */  "v0",   /*  "$2", */
371         /* 0x03 */  "v1",   /*  "$3", */
372         /* 0x04 */  "a0",   /*  "$4", */
373         /* 0x05 */  "a1",   /*  "$5", */
374         /* 0x06 */  "a2",   /*  "$6", */
375         /* 0x07 */  "a3",   /*  "$7", */
376
377         /* 0x08 */  "a4",   /*  "$8", */
378         /* 0x09 */  "a5",   /*  "$9", */
379         /* 0x0a */  "a6",   /* "$10", */
380         /* 0x0b */  "a7",   /* "$11", */
381         /* 0x0c */  "t0",   /* "$12", */
382         /* 0x0d */  "t1",   /* "$13", */
383         /* 0x0e */  "t2",   /* "$14", */
384         /* 0x0f */  "t3",   /* "$15", */
385
386         /* 0x10 */  "s0",   /* "$16", */
387         /* 0x11 */  "s1",   /* "$17", */
388         /* 0x12 */  "s2",   /* "$18", */
389         /* 0x13 */  "s3",   /* "$19", */
390         /* 0x14 */  "s4",   /* "$20", */
391         /* 0x15 */  "s5",   /* "$21", */
392         /* 0x16 */  "s6",   /* "$22", */
393         /* 0x17 */  "s7",   /* "$23", */
394
395         /* 0x18 */  "t8",   /* "$24", */
396         /* 0x19 */  "t9",   /* "$25", */
397         /* 0x1a */  "k0",   /* "$26", */
398         /* 0x1b */  "k1",   /* "$27", */
399         /* 0x1c */  "gp",   /* "$28", */
400         /* 0x1d */  "sp",   /* "$29", */
401         /* 0x1e */  "s8",   /* "$30", */
402         /* 0x1f */  "ra"    /* "$31"  */
403 };
404
405
406 /* instruction decode table for 32 floating point registers                   */
407
408 #if 0
409 static char *fregs[] = {
410
411         /* 0x00 */  "fv0",   /*  "$f0", */
412         /* 0x01 */  "ft16",  /*  "$f1", */
413         /* 0x02 */  "fv1",   /*  "$f2", */
414         /* 0x03 */  "ft17",  /*  "$f3", */
415         /* 0x04 */  "ft0",   /*  "$f4", */
416         /* 0x05 */  "ft1",   /*  "$f5", */
417         /* 0x06 */  "ft2",   /*  "$f6", */
418         /* 0x07 */  "ft3",   /*  "$f7", */
419
420         /* 0x08 */  "ft4",   /*  "$f8", */
421         /* 0x09 */  "ft5",   /*  "$f9", */
422         /* 0x0a */  "ft6",   /* "$f10", */
423         /* 0x0b */  "ft7",   /* "$f11", */
424         /* 0x0c */  "fa0",   /* "$f12", */
425         /* 0x0d */  "fa1",   /* "$f13", */
426         /* 0x0e */  "fa2",   /* "$f14", */
427         /* 0x0f */  "fa3",   /* "$f15", */
428
429         /* 0x10 */  "fa4",   /* "$f16", */
430         /* 0x11 */  "fa5",   /* "$f17", */
431         /* 0x12 */  "fa6",   /* "$f18", */
432         /* 0x13 */  "fa7",   /* "$f19", */
433         /* 0x14 */  "ft8",   /* "$f20", */
434         /* 0x15 */  "ft9",   /* "$f21", */
435         /* 0x16 */  "ft10",  /* "$f22", */
436         /* 0x17 */  "ft11",  /* "$f23", */
437
438         /* 0x18 */  "fs0",   /* "$f24", */
439         /* 0x19 */  "ft12",  /* "$f25", */
440         /* 0x1a */  "fs1",   /* "$f26", */
441         /* 0x1b */  "ft13",  /* "$f27", */
442         /* 0x1c */  "fs2",   /* "$f28", */
443         /* 0x1d */  "ft14",  /* "$f29", */
444         /* 0x1e */  "fs3",   /* "$f30", */
445         /* 0x1f */  "ft15"   /* "$f31"  */
446 };
447 #endif
448
449
450 /* function disassinstr ********************************************************
451
452         outputs a disassembler listing of one machine code instruction on 'stdout'
453         c:   instructions machine code
454         pos: instructions address relative to method start
455
456 *******************************************************************************/
457
458 void disassinstr(s4 *code, int pos)
459 {
460         int op;                     /* 6 bit op code                              */
461         int opfun;                  /* 6 bit function code                        */
462         int rs, rt, rd;             /* 5 bit integer register specifiers          */
463         int fs, ft, fd;             /* 5 bit floating point register specifiers   */
464         int shift;                  /* 5 bit unsigned shift amount                */
465         s4 c = *code;
466
467         op    = (c >> 26) & 0x3f;   /* 6 bit op code                              */
468         opfun = (c >>  0) & 0x3f;   /* 6 bit function code                        */
469         rs    = (c >> 21) & 0x1f;   /* 5 bit source register specifier            */
470         rt    = (c >> 16) & 0x1f;   /* 5 bit source/destination register specifier*/
471         rd    = (c >> 11) & 0x1f;   /* 5 bit destination register specifier       */
472         shift = (c >>  6) & 0x1f;   /* 5 bit unsigned shift amount                */
473
474         printf("0x%016lx:   %08x    ", (u8) code, c);
475         
476         switch (ops[op].itype) {
477                 case ITYPE_JMP:                      /* 26 bit unsigned jump offset   */
478                         printf ("%s %#09x\n", ops[op].name, (c & 0x3ffffff) << 2); 
479                         break;
480
481                 case ITYPE_IMM:                      /* 16 bit signed immediate value */
482                         printf ("%s %s,%s,%d\n", ops[op].name, regs[rt],
483                                                  regs[rs], (c << 16) >> 16); 
484                         break;
485
486                 case ITYPE_MEM:                      /* 16 bit signed memory offset   */
487                         printf ("%s %s,%d(%s)\n", ops[op].name, regs[rt],
488                                                   (c << 16) >> 16, regs[rs]); 
489                         break;
490
491                 case ITYPE_FMEM:                     /* 16 bit signed memory offset   */
492                         printf ("%s $f%d,%d(%s)\n", ops[op].name, rt,
493                                                     (c << 16) >> 16, regs[rs]); 
494                         break;
495
496                 case ITYPE_BRA:                      /* 16 bit signed branch offset   */
497                         if (op == 0x04 && rs == 0 && rt == 0) {
498                                 printf("b        0x%016lx\n", (u8) code + 4 + ((c << 16) >> 14));
499                                 break;
500                                 }       
501                         printf("%s %s,%s,0x%016lx\n", ops[op].name, regs[rs], regs[rt], 
502                                    (u8) code + 4 + ((c << 16) >> 14));
503                         break;
504                         
505                 case ITYPE_RIMM:
506                         if (regimms[rt].ftype == ITYPE_IMM)
507                                 printf("%s %s,%d\n", regimms[rt].name, regs[rs],
508                                        (c << 16) >> 16);
509                         else if (regimms[rt].ftype == ITYPE_BRA)
510                                 printf("%s %s,0x%016lx\n", regimms[rt].name, regs[rs],
511                                        (u8) code + 4 + ((c << 16) >> 14));
512                         else
513                                 printf("regimm   %#04x,$%d,%d\n", rt, rs, (c << 16) >> 16);             
514                         break;
515
516                 case ITYPE_OP:
517                         if (c == 0) {
518                                 printf("nop\n");
519                                 return;
520                                 }
521                         if (opfun == 0x25 && rt == 0) {
522                                 if (rs == 0)
523                                         printf("clr      %s\n", regs[rd]);
524                                 else
525                                         printf("move     %s,%s\n", regs[rd], regs[rs]);
526                                 return;
527                                 }
528                         switch (regops[opfun].ftype) {
529                                 case ITYPE_OP:
530                                         printf("%s %s,%s,%s\n", regops[opfun].name, regs[rd],
531                                                regs[rs], regs[rt]);
532                                         break;
533                                 case ITYPE_IMM:  /* immediate instruction */
534                                         printf("%s %s,%s,%d\n",
535                                                regops[opfun].name, regs[rd], regs[rt], shift);
536                                         break;
537                                 case ITYPE_TRAP:
538                                         printf("%s %s,%s,%d\n", regops[opfun].name,
539                                                regs[rs], regs[rt], (c << 16) >> 22);
540                                         break;
541                                 case ITYPE_DIVMUL: /* div/mul instruction */
542                                         printf("%s %s,%s\n", regops[opfun].name, regs[rs], regs[rt]);
543                                         break;
544                                 case ITYPE_JMP:
545                                         if (rd == 31) {
546                                                 printf("%s %s\n", regops[opfun].name, regs[rs]);
547                                                 break;
548                                                 }
549                                         printf("%s %s,%s\n", regops[opfun].name, regs[rd], regs[rs]);
550                                         break;
551                                 case ITYPE_MTOJR:
552                                         if (opfun == 8 && rs == 31) {
553                                                 printf("ret\n");
554                                                 break;
555                                                 }
556                                         printf("%s %s\n", regops[opfun].name, regs[rs]);
557                                         break;
558                                 case ITYPE_MFROM:
559                                         printf("%s %s\n", regops[opfun].name, regs[rd]);
560                                         break;
561                                 case ITYPE_SYS:
562                                         printf("%s\n", regops[opfun].name);
563                                 default:
564                                         printf("special  (%#04x) $%d,$%d,$%d\n", opfun, rd, rs, rt);
565                                 }               
566                         break;
567                 case ITYPE_FOP:
568                         fs    = (c >> 11) & 0x1f;   /* 5 bit source register              */
569                         ft    = (c >> 16) & 0x1f;   /* 5 bit source/destination register  */
570                         fd    = (c >>  6) & 0x1f;   /* 5 bit destination register         */
571
572                         if (rs == 8) {              /* floating point branch              */
573                                 printf("%s %x\n", fbra[ft&3], pos + 4 + ((c << 16) >> 14));
574                                 break;
575                                 }
576
577                         if (rs == 0) {              /* move from                          */
578                                 printf("mfc1     %s,$f%d\n", regs[rt], fs);             
579                                 break;
580                                 }
581
582                         if (rs == 1) {              /* double move from                   */
583                                 printf("dmfc1    %s,$f%d\n", regs[rt], fs);             
584                                 break;
585                                 }
586
587                         if (rs == 4) {              /* move to                            */
588                                 printf("mtc1     %s,$f%d\n", regs[rt], fs);             
589                                 break;
590                                 }
591
592                         if (rs == 5) {              /* double move to                     */
593                                 printf("dmtc1    %s,$f%d\n", regs[rt], fs);             
594                                 break;
595                                 }
596
597                         rs    = rs & 7;             /* truncate to 3 bit format specifier */
598
599                         if (fops[opfun].ftype == ITYPE_FOP)
600                                 printf("%s%s%s $f%d,$f%d,$f%d\n", fops[opfun].name, fmt[rs],
601                                                                fops[opfun].fill, fd, fs, ft);
602                         else if (fops[opfun].ftype == ITYPE_FOP2)
603                                 printf("%s%s%s $f%d,$f%d\n", fops[opfun].name, fmt[rs],
604                                                            fops[opfun].fill, fd, fs);
605                         else if (fops[opfun].ftype == ITYPE_FCMP)
606                                 printf("%s%s%s $f%d,$f%d\n", fops[opfun].name, fmt[rs],
607                                                            fops[opfun].fill, fs, ft);
608                         else
609                                 printf("cop1     (%#04x) $f%d,$f%d,$f%d\n", opfun, fd, fs, ft);         
610
611                         break;
612
613                 default:
614                         printf("undef    %#04x(%#04x) $%d,$%d,$%d\n", op, opfun, rd, rs, rt);           
615                 }
616 }
617
618
619 /* function disassemble ********************************************************
620
621         outputs a disassembler listing of some machine code on 'stdout'
622         code: pointer to first instruction
623         len:  code size (number of instructions * 4)
624
625 *******************************************************************************/
626
627 void disassemble(s4 *code, int len)
628 {
629         int p;
630
631         printf("  --- disassembler listing ---\n");     
632         for (p = 0; p < len; p += 4, code++)
633                 disassinstr(code, p);
634 }
635
636
637 /*
638  * These are local overrides for various environment variables in Emacs.
639  * Please do not remove this and leave it at the end of the file, where
640  * Emacs will automagically detect them.
641  * ---------------------------------------------------------------------
642  * Local variables:
643  * mode: c
644  * indent-tabs-mode: t
645  * c-basic-offset: 4
646  * tab-width: 4
647  * End:
648  */