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