*** empty log message ***
[cacao.git] / alpha / 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 Alpha machine code for easy debugging.
8
9         Authors: Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
10                  Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
11
12         Last Change: 1998/11/18
13
14 *******************************************************************************/
15
16 /*  The disassembler uses two tables for decoding the instructions. The first
17         table (ops) is used to classify the instructions based on the op code and
18         contains the instruction names for instructions which don't used the
19         function codes. This table is indexed by the op code (6 bit, 64 entries).
20         The second table (op3s) contains instructions which contain both an op
21         code and a function code. This table is an unsorted list of instructions
22         which is terminated by op code and function code zero. This list is
23         searched linearly for a matching pair of opcode and function code.
24 */
25
26 #define ITYPE_UNDEF 0           /* undefined instructions (illegal opcode)    */
27 #define ITYPE_JMP   1           /* jump instructions                          */
28 #define ITYPE_MEM   2           /* memory instructions                        */
29 #define ITYPE_FMEM  3           /* floating point memory instructions         */
30 #define ITYPE_BRA   4           /* branch instructions                        */
31 #define ITYPE_OP    5           /* integer instructions                       */
32 #define ITYPE_FOP   6           /* floating point instructions                */
33
34
35 /* instruction decode table for 6 bit op codes                                */
36
37 static struct {char *name; int itype;} ops[] = {
38
39         /* 0x00 */  {"",        ITYPE_UNDEF},
40         /* 0x01 */  {"",        ITYPE_UNDEF},
41         /* 0x02 */  {"",        ITYPE_UNDEF},
42         /* 0x03 */  {"",        ITYPE_UNDEF},
43         /* 0x04 */  {"",        ITYPE_UNDEF},
44         /* 0x05 */  {"",        ITYPE_UNDEF},
45         /* 0x06 */  {"",        ITYPE_UNDEF},
46         /* 0x07 */  {"",        ITYPE_UNDEF},
47         /* 0x08 */  {"lda    ",   ITYPE_MEM},
48         /* 0x09 */  {"ldah   ",   ITYPE_MEM},
49         /* 0x0a */  {"ldb    ",   ITYPE_MEM},
50         /* 0x0b */  {"ldq_u  ",   ITYPE_MEM},
51         /* 0x0c */  {"ldw    ",   ITYPE_MEM},
52         /* 0x0d */  {"stw    ",   ITYPE_MEM},
53         /* 0x0e */  {"stb    ",   ITYPE_MEM},
54         /* 0x0f */  {"stq_u  ",   ITYPE_MEM},
55         /* 0x10 */  {"op     ",    ITYPE_OP},
56         /* 0x11 */  {"op     ",    ITYPE_OP},
57         /* 0x12 */  {"op     ",    ITYPE_OP},
58         /* 0x13 */  {"op     ",    ITYPE_OP},
59         /* 0x14 */  {"",        ITYPE_UNDEF},
60         /* 0x15 */  {"",        ITYPE_UNDEF},
61         /* 0x16 */  {"fop    ",   ITYPE_FOP},
62         /* 0x17 */  {"fop    ",   ITYPE_FOP},
63         /* 0x18 */  {"memfmt ",   ITYPE_MEM},
64         /* 0x19 */  {"",        ITYPE_UNDEF},
65         /* 0x1a */  {"jmp    ",   ITYPE_JMP},
66         /* 0x1b */  {"",        ITYPE_UNDEF},
67         /* 0x1c */  {"op     ",    ITYPE_OP},
68         /* 0x1d */  {"",        ITYPE_UNDEF},
69         /* 0x1e */  {"",        ITYPE_UNDEF},
70         /* 0x1f */  {"",        ITYPE_UNDEF},
71         /* 0x20 */  {"ldf    ",  ITYPE_FMEM},
72         /* 0x21 */  {"ldg    ",  ITYPE_FMEM},
73         /* 0x22 */  {"lds    ",  ITYPE_FMEM},
74         /* 0x23 */  {"ldt    ",  ITYPE_FMEM},
75         /* 0x24 */  {"stf    ",  ITYPE_FMEM},
76         /* 0x25 */  {"stg    ",  ITYPE_FMEM},
77         /* 0x26 */  {"sts    ",  ITYPE_FMEM},
78         /* 0x27 */  {"stt    ",  ITYPE_FMEM},
79         /* 0x28 */  {"ldl    ",   ITYPE_MEM},
80         /* 0x29 */  {"ldq    ",   ITYPE_MEM},
81         /* 0x2a */  {"ldl_l  ",   ITYPE_MEM},
82         /* 0x2b */  {"ldq_l  ",   ITYPE_MEM},
83         /* 0x2c */  {"stl    ",   ITYPE_MEM},
84         /* 0x2d */  {"stq    ",   ITYPE_MEM},
85         /* 0x2e */  {"stl_c  ",   ITYPE_MEM},
86         /* 0x2f */  {"stq_c  ",   ITYPE_MEM},
87         /* 0x30 */  {"br     ",   ITYPE_BRA},
88         /* 0x31 */  {"fbeq   ",   ITYPE_BRA},
89         /* 0x32 */  {"fblt   ",   ITYPE_BRA},
90         /* 0x33 */  {"fble   ",   ITYPE_BRA},
91         /* 0x34 */  {"bsr    ",   ITYPE_BRA},
92         /* 0x35 */  {"fbne   ",   ITYPE_BRA},
93         /* 0x36 */  {"fbge   ",   ITYPE_BRA},
94         /* 0x37 */  {"fbgt   ",   ITYPE_BRA},
95         /* 0x38 */  {"blbc   ",   ITYPE_BRA},
96         /* 0x39 */  {"beq    ",   ITYPE_BRA},
97         /* 0x3a */  {"blt    ",   ITYPE_BRA},
98         /* 0x3b */  {"ble    ",   ITYPE_BRA},
99         /* 0x3c */  {"blbs   ",   ITYPE_BRA},
100         /* 0x3d */  {"bne    ",   ITYPE_BRA},
101         /* 0x3e */  {"bge    ",   ITYPE_BRA},
102         /* 0x3f */  {"bgt    ",   ITYPE_BRA}
103 };
104
105
106 /* instruction decode list for 6 bit op codes and 9 bit function codes        */
107  
108 static struct { u2 op, fun; char *name; }  op3s[] = {
109
110         { 0x10, 0x00,  "addl   " },
111         { 0x10, 0x40,  "addl/v " },
112         { 0x10, 0x20,  "addq   " },
113         { 0x10, 0x60,  "addq/v " },
114         { 0x10, 0x09,  "subl   " },
115         { 0x10, 0x49,  "subl/v " },
116         { 0x10, 0x29,  "subq   " },
117         { 0x10, 0x69,  "subq/v " },
118         { 0x10, 0x2D,  "cmpeq  " },
119         { 0x10, 0x4D,  "cmplt  " },
120         { 0x10, 0x6D,  "cmple  " },
121         { 0x10, 0x1D,  "cmpult " },
122         { 0x10, 0x3D,  "cmpule " },
123         { 0x10, 0x0F,  "cmpbge " },
124         { 0x10, 0x02,  "s4addl " },
125         { 0x10, 0x0b,  "s4subl " },
126         { 0x10, 0x22,  "s4addq " },
127         { 0x10, 0x2b,  "s4subq " },
128         { 0x10, 0x12,  "s8addl " },
129         { 0x10, 0x1b,  "s8subl " },
130         { 0x10, 0x32,  "s8addq " },
131         { 0x10, 0x3b,  "s8subq " },
132         { 0x11, 0x00,  "and    " },
133         { 0x11, 0x20,  "or     " },
134         { 0x11, 0x40,  "xor    " },
135         { 0x11, 0x08,  "andnot " },
136         { 0x11, 0x28,  "ornot  " },
137         { 0x11, 0x48,  "xornot " },
138         { 0x11, 0x24,  "cmoveq " },
139         { 0x11, 0x44,  "cmovlt " },
140         { 0x11, 0x64,  "cmovle " },
141         { 0x11, 0x26,  "cmovne " },
142         { 0x11, 0x46,  "cmovge " },
143         { 0x11, 0x66,  "cmovgt " },
144         { 0x11, 0x14,  "cmovlbs" },
145         { 0x11, 0x16,  "cmovlbc" },
146         { 0x12, 0x39,  "sll    " },
147         { 0x12, 0x3C,  "sra    " },
148         { 0x12, 0x34,  "srl    " },
149         { 0x12, 0x30,  "zap    " },
150         { 0x12, 0x31,  "zapnot " },
151         { 0x12, 0x06,  "extbl  " },
152         { 0x12, 0x16,  "extwl  " },
153         { 0x12, 0x26,  "extll  " },
154         { 0x12, 0x36,  "extql  " },
155         { 0x12, 0x5a,  "extwh  " },
156         { 0x12, 0x6a,  "extlh  " },
157         { 0x12, 0x7a,  "extqh  " },
158         { 0x12, 0x0b,  "insbl  " },
159         { 0x12, 0x1b,  "inswl  " },
160         { 0x12, 0x2b,  "insll  " },
161         { 0x12, 0x3b,  "insql  " },
162         { 0x12, 0x57,  "inswh  " },
163         { 0x12, 0x67,  "inslh  " },
164         { 0x12, 0x77,  "insqh  " },
165         { 0x12, 0x02,  "mskbl  " },
166         { 0x12, 0x12,  "mskwl  " },
167         { 0x12, 0x22,  "mskll  " },
168         { 0x12, 0x32,  "mskql  " },
169         { 0x12, 0x52,  "mskwh  " },
170         { 0x12, 0x62,  "msklh  " },
171         { 0x12, 0x72,  "mskqh  " },
172         { 0x13, 0x00,  "mull   " },
173         { 0x13, 0x20,  "mulq   " },
174         { 0x13, 0x40,  "mull/v " },
175         { 0x13, 0x60,  "mulq/v " },
176         { 0x13, 0x30,  "umulh  " },
177         { 0x16, 0x080, "fadd   " },
178         { 0x16, 0x0a0, "dadd   " },
179         { 0x16, 0x081, "fsub   " },
180         { 0x16, 0x0a1, "dsub   " },
181         { 0x16, 0x082, "fmul   " },
182         { 0x16, 0x0a2, "dmul   " },
183         { 0x16, 0x083, "fdiv   " },
184         { 0x16, 0x0a3, "ddiv   " },
185         { 0x16, 0x580, "fadds  " },
186         { 0x16, 0x5a0, "dadds  " },
187         { 0x16, 0x581, "fsubs  " },
188         { 0x16, 0x5a1, "dsubs  " },
189         { 0x16, 0x582, "fmuls  " },
190         { 0x16, 0x5a2, "dmuls  " },
191         { 0x16, 0x583, "fdivs  " },
192         { 0x16, 0x5a3, "ddivs  " },
193         { 0x16, 0x0ac, "cvtdf  " },
194         { 0x16, 0x0bc, "cvtlf  " },
195         { 0x16, 0x0be, "cvtld  " },
196         { 0x16, 0x0af, "cvtdl  " },
197         { 0x16, 0x02f, "cvtdlc " },
198         { 0x17, 0x030, "cvtli  " },
199         { 0x16, 0x1af, "cvtdlv " },
200         { 0x16, 0x12f, "cvtdlcv" },
201         { 0x17, 0x130, "cvtliv " },
202         { 0x16, 0x5ac, "cvtdfs " },
203         { 0x16, 0x5af, "cvtdls " },
204         { 0x16, 0x52f, "cvtdlcs" },
205         { 0x16, 0x0a4, "fcmpun " },
206         { 0x16, 0x0a5, "fcmpeq " },
207         { 0x16, 0x0a6, "fcmplt " },
208         { 0x16, 0x0a7, "fcmple " },
209         { 0x16, 0x5a4, "fcmpuns" },
210         { 0x16, 0x5a5, "fcmpeqs" },
211         { 0x16, 0x5a6, "fcmplts" },
212         { 0x16, 0x5a7, "fcmples" },
213         { 0x17, 0x020, "fmov   " },
214         { 0x17, 0x021, "fmovn  " },
215         { 0x1c, 0x0,   "bsext  " },
216         { 0x1c, 0x1,   "wsext  " },
217         
218         { 0x00, 0x00,  NULL }
219 };
220
221
222 /* name table for 32 integer registers                                        */
223
224 static char *regs[] = {
225
226         /* 0x00 */  "v0",   /*  "$0", */
227         /* 0x01 */  "t0",   /*  "$1", */
228         /* 0x02 */  "t1",   /*  "$2", */
229         /* 0x03 */  "t2",   /*  "$3", */
230         /* 0x04 */  "t3",   /*  "$4", */
231         /* 0x05 */  "t4",   /*  "$5", */
232         /* 0x06 */  "t5",   /*  "$6", */
233         /* 0x07 */  "t6",   /*  "$7", */
234
235         /* 0x08 */  "t7",   /*  "$8", */
236         /* 0x09 */  "s0",   /*  "$9", */
237         /* 0x0a */  "s1",   /* "$10", */
238         /* 0x0b */  "s2",   /* "$11", */
239         /* 0x0c */  "s3",   /* "$12", */
240         /* 0x0d */  "s4",   /* "$13", */
241         /* 0x0e */  "s5",   /* "$14", */
242         /* 0x0f */  "s6",   /* "$15", */
243
244         /* 0x10 */  "a0",   /* "$16", */
245         /* 0x11 */  "a1",   /* "$17", */
246         /* 0x12 */  "a2",   /* "$18", */
247         /* 0x13 */  "a3",   /* "$19", */
248         /* 0x14 */  "a4",   /* "$20", */
249         /* 0x15 */  "a5",   /* "$21", */
250         /* 0x16 */  "t8",   /* "$22", */
251         /* 0x17 */  "t9",   /* "$23", */
252
253         /* 0x18 */  "t10",  /* "$24", */
254         /* 0x19 */  "t11",  /* "$25", */
255         /* 0x1a */  "ra",   /* "$26", */
256         /* 0x1b */  "pv",   /* "$27", */
257         /* 0x1c */  "at",   /* "$28", */
258         /* 0x1d */  "gp",   /* "$29", */
259         /* 0x1e */  "sp",   /* "$30", */
260         /* 0x1f */  "zero"  /* "$31"  */
261 };
262
263
264 /* function disassinstr ********************************************************
265
266         outputs a disassembler listing of one machine code instruction on 'stdout'
267         c:   instructions machine code
268         pos: instructions address relative to method start
269
270 *******************************************************************************/
271
272 static void disassinstr(int c, int pos)
273 {
274         int op;                     /* 6 bit op code                              */
275         int opfun;                  /* 7 bit function code                        */
276         int ra, rb, rc;             /* 6 bit register specifiers                  */
277         int lit;                    /* 8 bit unsigned literal                     */
278         int i;                      /* loop counter                               */
279
280         op    = (c >> 26) & 0x3f;   /* 6 bit op code                              */
281         opfun = (c >> 5)  & 0x7f;   /* 7 bit function code                        */
282         ra    = (c >> 21) & 0x1f;   /* 6 bit source register specifier            */
283         rb    = (c >> 16) & 0x1f;   /* 6 bit source register specifier            */
284         rc    = (c >> 0)  & 0x1f;   /* 6 bit destination register specifiers      */
285         lit   = (c >> 13) & 0xff;   /* 8 bit unsigned literal                     */
286
287         printf ("%6x: %8x  ", pos, c);
288         
289         switch (ops[op].itype) {
290                 case ITYPE_JMP:
291                         switch ((c >> 14) & 3) {  /* branch hint */
292                                 case 0:
293                                         if (ra == 31) {
294                                                 printf ("jmp     (%s)\n", regs[rb]); 
295                                                 return;
296                                                 }
297                                         printf ("jmp     "); 
298                                         break;
299                                 case 1:
300                                         if (ra == 26) {
301                                                 printf ("jsr     (%s)\n", regs[rb]); 
302                                                 return;
303                                                 }
304                                         printf ("jsr     "); 
305                                         break;
306                                 case 2:
307                                         if (ra == 31 && rb == 26) {
308                                                 printf ("ret\n"); 
309                                                 return;
310                                                 }
311                                         if (ra == 31) {
312                                                 printf ("ret     (%s)\n", regs[rb]); 
313                                                 return;
314                                                 }
315                                         printf ("ret     ");
316                                         break;
317                                 case 3:
318                                         printf ("jsr_co  "); 
319                                         break;
320                                 }
321                         printf ("%s,(%s)\n", regs[ra], regs[rb]); 
322                         break;
323
324                 case ITYPE_MEM: {
325                         int disp = (c << 16) >> 16; /* 16 bit signed displacement         */
326
327                         if (op == 0x18 && ra == 0 && ra == 0 && disp == 0)
328                                 printf ("trapb\n"); 
329                         else
330                                 printf ("%s %s,%d(%s)\n", ops[op].name, regs[ra], disp, regs[rb]); 
331                         break;
332                         }
333
334                 case ITYPE_FMEM: {
335                         printf ("%s $f%d,%d(%s)\n", ops[op].name, ra, (c << 16) >> 16, regs[rb]); 
336                         break;
337                         }
338
339                 case ITYPE_BRA:             /* 21 bit signed branch offset */
340                         if (op == 0x30 && ra == 31)
341                                 printf("br      0x%x\n", pos + 4 + ((c << 11) >> 9));
342                         else if (op == 0x34 && ra == 26)
343                                 printf("brs     0x%x\n", pos + 4 + ((c << 11) >> 9));
344                         else
345                                 printf("%s %s,0x%x\n",
346                                        ops[op].name, regs[ra], pos + 4 + ((c << 11) >> 9));
347                         break;
348                         
349                 case ITYPE_FOP: {
350                         int fopfun = (c >> 5) & 0x7ff;  /* 11 bit fp function code        */
351
352                         if (op == 0x17 && fopfun == 0x020 && ra == rb) {
353                                 if (ra == 31 && rc == 31)
354                                         printf("fnop\n");
355                                 else
356                                         printf("fmov    $f%d,$f%d\n", ra, rc);
357                                 return;
358                                 }
359                         for (i = 0; op3s[i].name; i++)
360                                 if (op3s[i].op == op && op3s[i].fun == fopfun) {
361                                         printf("%s $f%d,$f%d,$f%d\n", op3s[i].name, ra, rb,  rc);
362                                         return;
363                                         }
364                         printf("%s%x $f%d,$f%d,$f%d\n", ops[op].name, fopfun, ra, rb, rc);
365                         break;
366                         }
367
368                 case ITYPE_OP:
369                         if (op == 0x11 && opfun == 0x20 && ra == rb && ~(c&0x1000)) {
370                                 if (ra == 31 && rc == 31)
371                                         printf("nop\n");
372                                 else if (ra == 31)
373                                         printf("clr     %s\n", regs[rc]);
374                                 else
375                                         printf("mov     %s,%s\n", regs[ra], regs[rc]);
376                                 return;
377                                 }
378                         for (i = 0; op3s[i].name; i++) {
379                                 if (op3s[i].op == op && op3s[i].fun == opfun) {
380                                         if (c & 0x1000)                  /* immediate instruction */
381                                                 printf("%s %s,%d,%s\n",
382                                                        op3s[i].name, regs[ra], lit, regs[rc]);
383                                         else
384                                                 printf("%s %s,%s,%s\n",
385                                                        op3s[i].name, regs[ra], regs[rb], regs[rc]);
386                                         return;
387                                         }
388                                 }
389                         /* fall through */
390                 default:
391                         if (c & 0x1000)                          /* immediate instruction */
392                                 printf("UNDEF  %x(%x) $%d,%d,$%d\n", op, opfun, ra, lit, rc);
393                         else
394                                 printf("UNDEF  %x(%x) $%d,$%d,$%d\n", op, opfun, ra, rb,  rc);          
395                 }
396 }
397
398
399 /* function disassemble ********************************************************
400
401         outputs a disassembler listing of some machine code on 'stdout'
402         code: pointer to first instruction
403         len:  code size (number of instructions * 4)
404
405 *******************************************************************************/
406
407 static void disassemble(int *code, int len)
408 {
409         int p;
410
411         printf ("  --- disassembler listing ---\n");    
412         for (p = 0; p < len; p += 4, code++)
413                 disassinstr(*code, p); 
414 }
415
416
417 /*
418  * These are local overrides for various environment variables in Emacs.
419  * Please do not remove this and leave it at the end of the file, where
420  * Emacs will automagically detect them.
421  * ---------------------------------------------------------------------
422  * Local variables:
423  * mode: c
424  * indent-tabs-mode: t
425  * c-basic-offset: 4
426  * tab-width: 4
427  * End:
428  */