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