Don't pass unused pos to disassintr.
[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 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    Changes: Christian Thalinger
30
31    $Id: disass.c 1975 2005-03-03 10:59:37Z twisti $
32
33 */
34
35
36 #include <stdio.h>
37 #include "types.h"
38 #include "disass.h"
39
40
41 /*  The disassembler uses four tables for decoding the instructions. The first
42         table (ops) is used to classify the instructions based on the op code and
43         contains the instruction names for instructions which don't used the
44         function codes. This table is indexed by the op code (6 bit, 64 entries).
45         The other tables are either indexed by the function code or some special
46         format and branch codes.
47 */
48
49 #define ITYPE_UNDEF  0          /* undefined instructions (illegal opcode)    */
50 #define ITYPE_JMP    1          /* jump instructions                          */
51 #define ITYPE_IMM    2          /* immediate instructions                     */
52 #define ITYPE_MEM    3          /* memory instructions                        */
53 #define ITYPE_FMEM   4          /* floating point memory instructions         */
54 #define ITYPE_BRA    5          /* branch instructions                        */
55 #define ITYPE_RIMM   6          /* special/branch instructions                */
56 #define ITYPE_OP     7          /* integer instructions                       */
57 #define ITYPE_TRAP   8          /* trap instructions                          */
58 #define ITYPE_DIVMUL 9          /* integer divide/multiply instructions       */
59 #define ITYPE_MTOJR 10          /* move to and jump register instructions     */
60 #define ITYPE_MFROM 11          /* move from instructions                     */
61 #define ITYPE_SYS   12          /* operating system instructions              */
62 #define ITYPE_FOP   13          /* floating point instructions                */
63 #define ITYPE_FOP2  14          /* 2 operand floating point instructions      */
64 #define ITYPE_FCMP  15          /* floating point compare instructions        */
65
66
67 /* instruction decode table for 6 bit op codes                                */
68
69 static struct {char *name; int itype;} ops[] = {
70
71         /* 0x00 */  {"special ",    ITYPE_OP},
72         /* 0x01 */  {"regimm  ",  ITYPE_RIMM},
73         /* 0x02 */  {"j       ",   ITYPE_JMP},
74         /* 0x03 */  {"jal     ",   ITYPE_JMP},
75         /* 0x04 */  {"beq     ",   ITYPE_BRA},
76         /* 0x05 */  {"bne     ",   ITYPE_BRA},
77         /* 0x06 */  {"blez    ",   ITYPE_BRA},
78         /* 0x07 */  {"bgtz    ",   ITYPE_BRA},
79
80         /* 0x08 */  {"addi    ",   ITYPE_IMM},
81         /* 0x09 */  {"addiu   ",   ITYPE_IMM},
82         /* 0x0a */  {"slti    ",   ITYPE_IMM},
83         /* 0x0b */  {"sltiu   ",   ITYPE_IMM},
84         /* 0x0c */  {"andi    ",   ITYPE_IMM},
85         /* 0x0d */  {"ori     ",   ITYPE_IMM},
86         /* 0x0e */  {"xori    ",   ITYPE_IMM},
87         /* 0x0f */  {"lui     ",   ITYPE_IMM},
88
89         /* 0x10 */  {"cop0    ",    ITYPE_OP},
90         /* 0x11 */  {"cop1    ",   ITYPE_FOP},
91         /* 0x12 */  {"cop2    ",    ITYPE_OP},
92         /* 0x13 */  {"",         ITYPE_UNDEF},
93         /* 0x14 */  {"beql    ",   ITYPE_BRA},
94         /* 0x15 */  {"bnel    ",   ITYPE_BRA},
95         /* 0x16 */  {"blezl   ",   ITYPE_BRA},
96         /* 0x17 */  {"bgtzl   ",   ITYPE_BRA},
97
98         /* 0x18 */  {"daddi   ",   ITYPE_IMM},
99         /* 0x19 */  {"daddiu  ",   ITYPE_IMM},
100         /* 0x1a */  {"ldl     ",   ITYPE_MEM},
101         /* 0x1b */  {"ldr     ",   ITYPE_MEM},
102         /* 0x1c */  {"",         ITYPE_UNDEF},
103         /* 0x1d */  {"",         ITYPE_UNDEF},
104         /* 0x1e */  {"",         ITYPE_UNDEF},
105         /* 0x1f */  {"",         ITYPE_UNDEF},
106
107         /* 0x20 */  {"lb      ",   ITYPE_MEM},
108         /* 0x21 */  {"lh      ",   ITYPE_MEM},
109         /* 0x22 */  {"lwl     ",   ITYPE_MEM},
110         /* 0x23 */  {"lw      ",   ITYPE_MEM},
111         /* 0x24 */  {"lbu     ",   ITYPE_MEM},
112         /* 0x25 */  {"lhu     ",   ITYPE_MEM},
113         /* 0x26 */  {"lwr     ",   ITYPE_MEM},
114         /* 0x27 */  {"lwu     ",   ITYPE_MEM},
115
116         /* 0x28 */  {"sb      ",   ITYPE_MEM},
117         /* 0x29 */  {"sh      ",   ITYPE_MEM},
118         /* 0x2a */  {"swl     ",   ITYPE_MEM},
119         /* 0x2b */  {"sw      ",   ITYPE_MEM},
120         /* 0x2c */  {"sdl     ",   ITYPE_MEM},
121         /* 0x2d */  {"sdr     ",   ITYPE_MEM},
122         /* 0x2e */  {"swr     ",   ITYPE_MEM},
123         /* 0x2f */  {"cache   ",   ITYPE_MEM},
124
125         /* 0x30 */  {"ll      ",   ITYPE_MEM},
126         /* 0x31 */  {"lwc1    ",  ITYPE_FMEM},
127         /* 0x32 */  {"lwc2    ",   ITYPE_MEM},
128         /* 0x33 */  {"",         ITYPE_UNDEF},
129         /* 0x34 */  {"lld     ",   ITYPE_MEM},
130         /* 0x35 */  {"ldc1    ",  ITYPE_FMEM},
131         /* 0x36 */  {"ldc2    ",   ITYPE_MEM},
132         /* 0x37 */  {"ld      ",   ITYPE_MEM},
133
134         /* 0x38 */  {"sc      ",   ITYPE_MEM},
135         /* 0x39 */  {"swc1    ",  ITYPE_FMEM},
136         /* 0x3a */  {"swc2    ",   ITYPE_MEM},
137         /* 0x3b */  {"",         ITYPE_UNDEF},
138         /* 0x3c */  {"sld     ",   ITYPE_MEM},
139         /* 0x3d */  {"sdc1    ",  ITYPE_FMEM},
140         /* 0x3e */  {"sdc2    ",   ITYPE_MEM},
141         /* 0x3f */  {"sd      ",   ITYPE_MEM}
142 };
143
144
145 /* instruction decode table for 6 bit special function codes                  */
146
147 static struct {char *name; int ftype;} regops[] = {
148
149         /* 0x00 */  {"sll     ",   ITYPE_IMM},
150         /* 0x01 */  {""        , ITYPE_UNDEF},
151         /* 0x02 */  {"srl     ",   ITYPE_IMM},
152         /* 0x03 */  {"sra     ",   ITYPE_IMM},
153         /* 0x04 */  {"sllv    ",    ITYPE_OP},
154         /* 0x05 */  {""        , ITYPE_UNDEF},
155         /* 0x06 */  {"srlv    ",    ITYPE_OP},
156         /* 0x07 */  {"srav    ",    ITYPE_OP},
157
158         /* 0x08 */  {"jr      ", ITYPE_MTOJR},
159         /* 0x09 */  {"jalr    ",   ITYPE_JMP},
160         /* 0x0a */  {""        , ITYPE_UNDEF},
161         /* 0x0b */  {""        , ITYPE_UNDEF},
162         /* 0x0c */  {"syscall ",   ITYPE_SYS},
163         /* 0x0d */  {"break   ",   ITYPE_SYS},
164         /* 0x0e */  {""        , ITYPE_UNDEF},
165         /* 0x0f */  {"sync    ",   ITYPE_SYS},
166
167         /* 0x10 */  {"mfhi    ", ITYPE_MFROM},
168         /* 0x11 */  {"mthi    ", ITYPE_MTOJR},
169         /* 0x12 */  {"mflo    ", ITYPE_MFROM},
170         /* 0x13 */  {"mtlo    ", ITYPE_MTOJR},
171         /* 0x14 */  {"dsllv   ",    ITYPE_OP},
172         /* 0x15 */  {""        , ITYPE_UNDEF},
173         /* 0x16 */  {"dslrv   ",    ITYPE_OP},
174         /* 0x17 */  {"dsrav   ",    ITYPE_OP},
175
176         /* 0x18 */  {"mult    ",ITYPE_DIVMUL},
177         /* 0x19 */  {"multu   ",ITYPE_DIVMUL},
178         /* 0x1a */  {"div     ",ITYPE_DIVMUL},
179         /* 0x1b */  {"divu    ",ITYPE_DIVMUL},
180         /* 0x1c */  {"dmult   ",ITYPE_DIVMUL},
181         /* 0x1d */  {"dmultu  ",ITYPE_DIVMUL},
182         /* 0x1e */  {"ddiv    ",ITYPE_DIVMUL},
183         /* 0x1f */  {"ddivu   ",ITYPE_DIVMUL},
184
185         /* 0x20 */  {"add     ",    ITYPE_OP},
186         /* 0x21 */  {"addu    ",    ITYPE_OP},
187         /* 0x22 */  {"sub     ",    ITYPE_OP},
188         /* 0x23 */  {"subu    ",    ITYPE_OP},
189         /* 0x24 */  {"and     ",    ITYPE_OP},
190         /* 0x25 */  {"or      ",    ITYPE_OP},
191         /* 0x26 */  {"xor     ",    ITYPE_OP},
192         /* 0x27 */  {"nor     ",    ITYPE_OP},
193
194         /* 0x28 */  {""        , ITYPE_UNDEF},
195         /* 0x29 */  {""        , ITYPE_UNDEF},
196         /* 0x2a */  {"slt     ",    ITYPE_OP},
197         /* 0x2b */  {"sltu    ",    ITYPE_OP},
198         /* 0x2c */  {"dadd    ",    ITYPE_OP},
199         /* 0x2d */  {"daddu   ",    ITYPE_OP},
200         /* 0x2e */  {"dsub    ",    ITYPE_OP},
201         /* 0x2f */  {"dsubu   ",    ITYPE_OP},
202
203         /* 0x30 */  {"tge     ",  ITYPE_TRAP},
204         /* 0x31 */  {"tgeu    ",  ITYPE_TRAP},
205         /* 0x32 */  {"tlt     ",  ITYPE_TRAP},
206         /* 0x33 */  {"tltu    ",  ITYPE_TRAP},
207         /* 0x34 */  {"teq     ",  ITYPE_TRAP},
208         /* 0x35 */  {""        , ITYPE_UNDEF},
209         /* 0x36 */  {"tne     ",  ITYPE_TRAP},
210         /* 0x37 */  {""        , ITYPE_UNDEF},
211
212         /* 0x38 */  {"dsll    ",   ITYPE_IMM},
213         /* 0x39 */  {""        , ITYPE_UNDEF},
214         /* 0x3a */  {"dsrl    ",   ITYPE_IMM},
215         /* 0x3b */  {"dsra    ",   ITYPE_IMM},
216         /* 0x3c */  {"dsll32  ",   ITYPE_IMM},
217         /* 0x3d */  {""        , ITYPE_UNDEF},
218         /* 0x3e */  {"dsrl32  ",   ITYPE_IMM},
219         /* 0x3f */  {"dsra32  ",   ITYPE_IMM}
220 };
221
222
223 /* instruction decode table for 5 bit reg immediate function codes            */
224
225 static struct {char *name; int ftype;} regimms[] = {
226
227         /* 0x00 */  {"bltz    ",   ITYPE_BRA},
228         /* 0x01 */  {"bgez    ",   ITYPE_BRA},
229         /* 0x02 */  {"bltzl   ",   ITYPE_BRA},
230         /* 0x03 */  {"bgezl   ",   ITYPE_BRA},
231         /* 0x04 */  {"",         ITYPE_UNDEF},
232         /* 0x05 */  {"",         ITYPE_UNDEF},
233         /* 0x06 */  {"",         ITYPE_UNDEF},
234         /* 0x07 */  {"",         ITYPE_UNDEF},
235
236         /* 0x08 */  {"tgei    ",   ITYPE_IMM},
237         /* 0x09 */  {"dgeiu   ",   ITYPE_IMM},
238         /* 0x0a */  {"tlti    ",   ITYPE_IMM},
239         /* 0x0b */  {"tltiu   ",   ITYPE_IMM},
240         /* 0x0c */  {"teqi    ",   ITYPE_IMM},
241         /* 0x0d */  {"",         ITYPE_UNDEF},
242         /* 0x0e */  {"tnei    ",   ITYPE_IMM},
243         /* 0x0f */  {"",         ITYPE_UNDEF},
244
245         /* 0x10 */  {"bltzal  ",   ITYPE_BRA},
246         /* 0x11 */  {"bgezal  ",   ITYPE_BRA},
247         /* 0x12 */  {"bltzall ",   ITYPE_BRA},
248         /* 0x13 */  {"bgezall ",   ITYPE_BRA},
249         /* 0x14 */  {"",         ITYPE_UNDEF},
250         /* 0x15 */  {"",         ITYPE_UNDEF},
251         /* 0x16 */  {"",         ITYPE_UNDEF},
252         /* 0x17 */  {"",         ITYPE_UNDEF},
253
254         /* 0x18 */  {"",         ITYPE_UNDEF},
255         /* 0x19 */  {"",         ITYPE_UNDEF},
256         /* 0x1a */  {"",         ITYPE_UNDEF},
257         /* 0x1b */  {"",         ITYPE_UNDEF},
258         /* 0x1c */  {"",         ITYPE_UNDEF},
259         /* 0x1d */  {"",         ITYPE_UNDEF},
260         /* 0x1e */  {"",         ITYPE_UNDEF},
261         /* 0x1f */  {"",         ITYPE_UNDEF}
262 };
263
264
265 /* instruction decode table for 6 bit floating point op codes                 */
266
267 static struct {char *name; char *fill; int ftype;} fops[] = {
268
269         /* 0x00 */  {"add", "   ",   ITYPE_FOP},
270         /* 0x01 */  {"sub", "   ",   ITYPE_FOP},
271         /* 0x02 */  {"mul", "   ",   ITYPE_FOP},
272         /* 0x03 */  {"div", "   ",   ITYPE_FOP},
273         /* 0x04 */  {"sqrt", "  ",   ITYPE_FOP},
274         /* 0x05 */  {"abs", "   ",  ITYPE_FOP2},
275         /* 0x06 */  {"mov", "   ",  ITYPE_FOP2},
276         /* 0x07 */  {"neg", "   ",  ITYPE_FOP2},
277
278         /* 0x08 */  {"roundl", "",  ITYPE_FOP2},
279         /* 0x09 */  {"truncl", "",  ITYPE_FOP2},
280         /* 0x0a */  {"ceill", " ",  ITYPE_FOP2},
281         /* 0x0b */  {"floorl", "",  ITYPE_FOP2},
282         /* 0x0c */  {"round", " ",  ITYPE_FOP2},
283         /* 0x0d */  {"trunc", " ",  ITYPE_FOP2},
284         /* 0x0e */  {"ceil", "  ",  ITYPE_FOP2},
285         /* 0x0f */  {"floor", " ",  ITYPE_FOP2},
286
287         /* 0x10 */  {"",       "", ITYPE_UNDEF},
288         /* 0x11 */  {"",       "", ITYPE_UNDEF},
289         /* 0x12 */  {"",       "", ITYPE_UNDEF},
290         /* 0x13 */  {"",       "", ITYPE_UNDEF},
291         /* 0x14 */  {"",       "", ITYPE_UNDEF},
292         /* 0x15 */  {"",       "", ITYPE_UNDEF},
293         /* 0x16 */  {"",       "", ITYPE_UNDEF},
294         /* 0x17 */  {"",       "", ITYPE_UNDEF},
295
296         /* 0x18 */  {"",       "", ITYPE_UNDEF},
297         /* 0x19 */  {"recip", " ",  ITYPE_FOP2},
298         /* 0x1a */  {"rsqrt", " ",  ITYPE_FOP2},
299         /* 0x1b */  {"",       "", ITYPE_UNDEF},
300         /* 0x1c */  {"",       "", ITYPE_UNDEF},
301         /* 0x1d */  {"",       "", ITYPE_UNDEF},
302         /* 0x1e */  {"",       "", ITYPE_UNDEF},
303         /* 0x1f */  {"",       "", ITYPE_UNDEF},
304
305         /* 0x20 */  {"cvts", "  ",  ITYPE_FOP2},
306         /* 0x21 */  {"cvtd", "  ",  ITYPE_FOP2},
307         /* 0x22 */  {"cvtx", "  ",  ITYPE_FOP2},
308         /* 0x23 */  {"cvtq", "  ",  ITYPE_FOP2},
309         /* 0x24 */  {"cvtw", "  ",  ITYPE_FOP2},
310         /* 0x25 */  {"cvtl", "  ",  ITYPE_FOP2},
311         /* 0x26 */  {"",       "", ITYPE_UNDEF},
312         /* 0x27 */  {"",       "", ITYPE_UNDEF},
313
314         /* 0x28 */  {"",       "", ITYPE_UNDEF},
315         /* 0x29 */  {"",       "", ITYPE_UNDEF},
316         /* 0x2a */  {"",       "", ITYPE_UNDEF},
317         /* 0x2b */  {"",       "", ITYPE_UNDEF},
318         /* 0x2c */  {"",       "", ITYPE_UNDEF},
319         /* 0x2d */  {"",       "", ITYPE_UNDEF},
320         /* 0x2e */  {"",       "", ITYPE_UNDEF},
321         /* 0x2f */  {"",       "", ITYPE_UNDEF},
322
323         /* 0x30 */  {"c.f", "   ",  ITYPE_FCMP},
324         /* 0x31 */  {"c.un", "  ",  ITYPE_FCMP},
325         /* 0x32 */  {"c.eq", "  ",  ITYPE_FCMP},
326         /* 0x33 */  {"c.ueq", " ",  ITYPE_FCMP},
327         /* 0x34 */  {"c.olt", " ",  ITYPE_FCMP},
328         /* 0x35 */  {"c.ult", " ",  ITYPE_FCMP},
329         /* 0x36 */  {"c.ole", " ",  ITYPE_FCMP},
330         /* 0x37 */  {"c.ule", " ",  ITYPE_FCMP},
331
332         /* 0x38 */  {"c.sf", "  ",  ITYPE_FCMP},
333         /* 0x39 */  {"c.ngle", "",  ITYPE_FCMP},
334         /* 0x3a */  {"c.seq", " ",  ITYPE_FCMP},
335         /* 0x3b */  {"c.ngl", " ",  ITYPE_FCMP},
336         /* 0x3c */  {"c.lt", "  ",  ITYPE_FCMP},
337         /* 0x3d */  {"c.nge", " ",  ITYPE_FCMP},
338         /* 0x3e */  {"c.le", "  ",  ITYPE_FCMP},
339         /* 0x3f */  {"c.ngt", " ",  ITYPE_FCMP}
340 };
341
342
343 /* format decode table for 3 bit floating point format codes                  */
344
345 static char *fmt[] = {
346         /* 0x00 */  ".s",
347         /* 0x01 */  ".d",
348         /* 0x02 */  ".x",
349         /* 0x03 */  ".q",
350         /* 0x04 */  ".w",
351         /* 0x05 */  ".l",
352         /* 0x06 */  ".?",
353         /* 0x07 */  ".?"
354 };
355
356
357 /* format decode table for 2 bit floating point branch codes                  */
358
359 static char *fbra[] = {
360         /* 0x00 */  "bc1f    ",
361         /* 0x01 */  "bc1t    ",
362         /* 0x02 */  "bc1fl   ",
363         /* 0x03 */  "bc1tl   "
364 };
365
366
367 /* instruction decode table for 32 integer registers                          */
368
369 char *regs[] = {
370         /* 0x00 */  "zero", /*  "$0", */
371         /* 0x01 */  "at",   /*  "$1", */
372         /* 0x02 */  "v0",   /*  "$2", */
373         /* 0x03 */  "v1",   /*  "$3", */
374         /* 0x04 */  "a0",   /*  "$4", */
375         /* 0x05 */  "a1",   /*  "$5", */
376         /* 0x06 */  "a2",   /*  "$6", */
377         /* 0x07 */  "a3",   /*  "$7", */
378
379         /* 0x08 */  "a4",   /*  "$8", */
380         /* 0x09 */  "a5",   /*  "$9", */
381         /* 0x0a */  "a6",   /* "$10", */
382         /* 0x0b */  "a7",   /* "$11", */
383         /* 0x0c */  "t0",   /* "$12", */
384         /* 0x0d */  "t1",   /* "$13", */
385         /* 0x0e */  "t2",   /* "$14", */
386         /* 0x0f */  "t3",   /* "$15", */
387
388         /* 0x10 */  "s0",   /* "$16", */
389         /* 0x11 */  "s1",   /* "$17", */
390         /* 0x12 */  "s2",   /* "$18", */
391         /* 0x13 */  "s3",   /* "$19", */
392         /* 0x14 */  "s4",   /* "$20", */
393         /* 0x15 */  "s5",   /* "$21", */
394         /* 0x16 */  "s6",   /* "$22", */
395         /* 0x17 */  "s7",   /* "$23", */
396
397         /* 0x18 */  "t8",   /* "$24", */
398         /* 0x19 */  "t9",   /* "$25", */
399         /* 0x1a */  "k0",   /* "$26", */
400         /* 0x1b */  "k1",   /* "$27", */
401         /* 0x1c */  "gp",   /* "$28", */
402         /* 0x1d */  "sp",   /* "$29", */
403         /* 0x1e */  "s8",   /* "$30", */
404         /* 0x1f */  "ra"    /* "$31"  */
405 };
406
407
408 /* instruction decode table for 32 floating point registers                   */
409
410 #if 0
411 static char *fregs[] = {
412
413         /* 0x00 */  "fv0",   /*  "$f0", */
414         /* 0x01 */  "ft16",  /*  "$f1", */
415         /* 0x02 */  "fv1",   /*  "$f2", */
416         /* 0x03 */  "ft17",  /*  "$f3", */
417         /* 0x04 */  "ft0",   /*  "$f4", */
418         /* 0x05 */  "ft1",   /*  "$f5", */
419         /* 0x06 */  "ft2",   /*  "$f6", */
420         /* 0x07 */  "ft3",   /*  "$f7", */
421
422         /* 0x08 */  "ft4",   /*  "$f8", */
423         /* 0x09 */  "ft5",   /*  "$f9", */
424         /* 0x0a */  "ft6",   /* "$f10", */
425         /* 0x0b */  "ft7",   /* "$f11", */
426         /* 0x0c */  "fa0",   /* "$f12", */
427         /* 0x0d */  "fa1",   /* "$f13", */
428         /* 0x0e */  "fa2",   /* "$f14", */
429         /* 0x0f */  "fa3",   /* "$f15", */
430
431         /* 0x10 */  "fa4",   /* "$f16", */
432         /* 0x11 */  "fa5",   /* "$f17", */
433         /* 0x12 */  "fa6",   /* "$f18", */
434         /* 0x13 */  "fa7",   /* "$f19", */
435         /* 0x14 */  "ft8",   /* "$f20", */
436         /* 0x15 */  "ft9",   /* "$f21", */
437         /* 0x16 */  "ft10",  /* "$f22", */
438         /* 0x17 */  "ft11",  /* "$f23", */
439
440         /* 0x18 */  "fs0",   /* "$f24", */
441         /* 0x19 */  "ft12",  /* "$f25", */
442         /* 0x1a */  "fs1",   /* "$f26", */
443         /* 0x1b */  "ft13",  /* "$f27", */
444         /* 0x1c */  "fs2",   /* "$f28", */
445         /* 0x1d */  "ft14",  /* "$f29", */
446         /* 0x1e */  "fs3",   /* "$f30", */
447         /* 0x1f */  "ft15"   /* "$f31"  */
448 };
449 #endif
450
451
452 /* disassinstr *****************************************************************
453
454         outputs a disassembler listing of one machine code instruction on 'stdout'
455         c:   instructions machine code
456
457 *******************************************************************************/
458
459 void disassinstr(s4 *code)
460 {
461         s4 op;                      /* 6 bit op code                              */
462         s4 opfun;                   /* 6 bit function code                        */
463         s4 rs, rt, rd;              /* 5 bit integer register specifiers          */
464         s4 fs, ft, fd;              /* 5 bit floating point register specifiers   */
465         s4 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 0x%016lx\n", fbra[ft&3], (u8) code + 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 /* 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, s4 len)
629 {
630         s4 i;
631
632         printf("  --- disassembler listing ---\n");     
633         for (i = 0; i < len; i += 4, code++)
634                 disassinstr(code);
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  */