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