28a953ee69909eb4366af48e97f64b5fbb0fe919
[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, 2007 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    $Id: disass.c 7335 2007-02-12 10:43:33Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <stdio.h>
33
34 #include "vm/types.h"
35
36 #include "vm/global.h"
37
38 #include "vm/jit/abi.h"
39 #include "vm/jit/disass.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 /* disassinstr *****************************************************************
247
248    Outputs a disassembler listing of one machine code instruction on
249    'stdout'.
250
251    code: pointer to instructions machine code
252
253 *******************************************************************************/
254
255 u1 *disassinstr(u1 *code)
256 {
257         s4 op;                      /* 6 bit op code                              */
258         s4 opfun;                   /* 7 bit function code                        */
259         s4 ra, rb, rc;              /* 6 bit register specifiers                  */
260         s4 lit;                     /* 8 bit unsigned literal                     */
261         s4 i;                       /* loop counter                               */
262         s4 c;
263
264         c = *((s4 *) code);
265
266         op    = (c >> 26) & 0x3f;   /* 6 bit op code                              */
267         opfun = (c >> 5)  & 0x7f;   /* 7 bit function code                        */
268         ra    = (c >> 21) & 0x1f;   /* 6 bit source register specifier            */
269         rb    = (c >> 16) & 0x1f;   /* 6 bit source register specifier            */
270         rc    = (c >> 0)  & 0x1f;   /* 6 bit destination register specifiers      */
271         lit   = (c >> 13) & 0xff;   /* 8 bit unsigned literal                     */
272
273         printf("0x%016lx:   %08x    ", (u8) code, c);
274         
275         switch (ops[op].itype) {
276         case ITYPE_JMP:
277                 switch ((c >> 14) & 3) {  /* branch hint */
278                 case 0:
279                         if (ra == 31) {
280                                 printf("jmp     (%s)\n", abi_registers_integer_name[rb]); 
281                                 goto _return;
282                         }
283                         printf("jmp     "); 
284                         break;
285                 case 1:
286                         if (ra == 26) {
287                                 printf("jsr     (%s)\n", abi_registers_integer_name[rb]); 
288                                 goto _return;
289                         }
290                         printf("jsr     "); 
291                         break;
292                 case 2:
293                         if (ra == 31 && rb == 26) {
294                                 printf("ret\n"); 
295                                 goto _return;
296                         }
297                         if (ra == 31) {
298                                 printf("ret     (%s)\n", abi_registers_integer_name[rb]); 
299                                 goto _return;
300                         }
301                         printf("ret     ");
302                         break;
303                 case 3:
304                         printf("jsr_co  "); 
305                         break;
306                 }
307                 printf("%s,(%s)\n", abi_registers_integer_name[ra],
308                            abi_registers_integer_name[rb]); 
309                 break;
310
311         case ITYPE_MEM: {
312                 s4 disp = (c << 16) >> 16;              /* 16 bit signed displacement */
313
314                 if (op == 0x18 && ra == 0 && ra == 0 && disp == 0)
315                         printf("trapb\n"); 
316                 else
317                         printf("%s %s,%d(%s)\n", ops[op].name,
318                                    abi_registers_integer_name[ra], disp,
319                                    abi_registers_integer_name[rb]); 
320                 break;
321         }
322
323         case ITYPE_FMEM:
324                 printf("%s $f%d,%d(%s)\n", ops[op].name, ra, (c << 16) >> 16,
325                            abi_registers_integer_name[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", ops[op].name,
335                                    abi_registers_integer_name[ra],
336                                    (u8) code + 4 + ((c << 11) >> 9));
337                 break;
338                         
339         case ITYPE_FOP: {
340                 s4 fopfun = (c >> 5) & 0x7ff;              /* 11 bit fp function code */
341
342                 if (op == 0x17 && fopfun == 0x020 && ra == rb) {
343                         if (ra == 31 && rc == 31)
344                                 printf("fnop\n");
345                         else
346                                 printf("fmov    $f%d,$f%d\n", ra, rc);
347                         goto _return;
348                 }
349                 for (i = 0; op3s[i].name; i++)
350                         if (op3s[i].op == op && op3s[i].fun == fopfun) {
351                                 printf("%s $f%d,$f%d,$f%d\n", op3s[i].name, ra, rb,  rc);
352                                 goto _return;
353                         }
354                 printf("%s%x $f%d,$f%d,$f%d\n", ops[op].name, fopfun, ra, rb, rc);
355                 break;
356         }
357
358         case ITYPE_OP:
359                 if (op == 0x11 && opfun == 0x20 && ra == rb && ~(c&0x1000)) {
360                         if (ra == 31 && rc == 31)
361                                 printf("nop\n");
362                         else if (ra == 31)
363                                 printf("clr     %s\n", abi_registers_integer_name[rc]);
364                         else
365                                 printf("mov     %s,%s\n", abi_registers_integer_name[ra],
366                                            abi_registers_integer_name[rc]);
367                         goto _return;
368                 }
369                 for (i = 0; op3s[i].name; i++) {
370                         if (op3s[i].op == op && op3s[i].fun == opfun) {
371                                 if (c & 0x1000)                      /* immediate instruction */
372                                         printf("%s %s,%d,%s\n", op3s[i].name,
373                                                    abi_registers_integer_name[ra], lit,
374                                                    abi_registers_integer_name[rc]);
375                                 else
376                                         printf("%s %s,%s,%s\n", op3s[i].name,
377                                                    abi_registers_integer_name[ra],
378                                                    abi_registers_integer_name[rb],
379                                                    abi_registers_integer_name[rc]);
380                                 goto _return;
381                         }
382                 }
383                 /* fall through */
384         default:
385                 if (c & 0x1000)                              /* immediate instruction */
386                         printf("UNDEF  %x(%x) $%d,%d,$%d\n", op, opfun, ra, lit, rc);
387                 else
388                         printf("UNDEF  %x(%x) $%d,$%d,$%d\n", op, opfun, ra, rb,  rc);          
389         }
390
391         /* 1 instruction is 4-bytes long */
392
393  _return:
394         return code + 4;
395 }
396
397
398 /* disassemble *****************************************************************
399
400    Outputs a disassembler listing of some machine code on 'stdout'.
401
402    start: pointer to first instruction
403    end:   pointer to last instruction
404
405 *******************************************************************************/
406
407 void disassemble(u1 *start, u1 *end)
408 {
409         printf("  --- disassembler listing ---\n");
410         for (; start < end; )
411                 start = disassinstr(start);
412 }
413
414
415 /*
416  * These are local overrides for various environment variables in Emacs.
417  * Please do not remove this and leave it at the end of the file, where
418  * Emacs will automagically detect them.
419  * ---------------------------------------------------------------------
420  * Local variables:
421  * mode: c
422  * indent-tabs-mode: t
423  * c-basic-offset: 4
424  * tab-width: 4
425  * End:
426  */