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