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