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