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