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