Initial revision
[cacao.git] / alpha / disass.c
1 /********************************* disass.c ************************************
2
3         Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
4
5         See file COPYRIGHT for information on usage and disclaimer of warranties
6
7         A very primitive disassembler for Alpha machine code for easy debugging.
8
9         Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
10                  Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
11
12         Last Change: 1997/10/22
13
14 *******************************************************************************/
15
16
17 #define ITYPE_UNDEF 0
18 #define ITYPE_JMP   1
19 #define ITYPE_MEM   2
20 #define ITYPE_BRA   3
21 #define ITYPE_OP    4
22 #define ITYPE_FOP   5
23
24 static struct { int op; char *name; int itype; } ops[] = {
25         { 0x00, "",      ITYPE_UNDEF},
26         { 0x01, "",      ITYPE_UNDEF},
27         { 0x02, "",      ITYPE_UNDEF},
28         { 0x03, "",      ITYPE_UNDEF},
29         { 0x04, "",      ITYPE_UNDEF},
30         { 0x05, "",      ITYPE_UNDEF},
31         { 0x06, "",      ITYPE_UNDEF},
32         { 0x07, "",      ITYPE_UNDEF},
33         { 0x08, "LDA    ", ITYPE_MEM},
34         { 0x09, "LDAH   ", ITYPE_MEM},
35         { 0x0a, "LDB    ", ITYPE_MEM},
36         { 0x0b, "LDQ_U  ", ITYPE_MEM},
37         { 0x0c, "LDW    ", ITYPE_MEM},
38         { 0x0d, "STW    ", ITYPE_MEM},
39         { 0x0e, "STB    ", ITYPE_MEM},
40         { 0x0f, "STQ_U  ", ITYPE_MEM},
41         { 0x10, "OP     ",  ITYPE_OP},
42         { 0x11, "OP     ",  ITYPE_OP},
43         { 0x12, "OP     ",  ITYPE_OP},
44         { 0x13, "OP     ",  ITYPE_OP},
45         { 0x14, "",      ITYPE_UNDEF},
46         { 0x15, "",      ITYPE_UNDEF},
47         { 0x16, "FOP    ", ITYPE_FOP},
48         { 0x17, "FOP    ", ITYPE_FOP},
49         { 0x18, "MEMFMT ", ITYPE_MEM},
50         { 0x19, "",      ITYPE_UNDEF},
51         { 0x1a, "JMP    ", ITYPE_JMP},
52         { 0x1b, "",      ITYPE_UNDEF},
53         { 0x1c, "OP     ",  ITYPE_OP},
54         { 0x1d, "",      ITYPE_UNDEF},
55         { 0x1e, "",      ITYPE_UNDEF},
56         { 0x1f, "",      ITYPE_UNDEF},
57         { 0x20, "LDF    ", ITYPE_MEM},
58         { 0x21, "LDG    ", ITYPE_MEM},
59         { 0x22, "LDS    ", ITYPE_MEM},
60         { 0x23, "LDT    ", ITYPE_MEM},
61         { 0x24, "STF    ", ITYPE_MEM},
62         { 0x25, "STG    ", ITYPE_MEM},
63         { 0x26, "STS    ", ITYPE_MEM},
64         { 0x27, "STT    ", ITYPE_MEM},
65         { 0x28, "LDL    ", ITYPE_MEM},
66         { 0x29, "LDQ    ", ITYPE_MEM},
67         { 0x2a, "LDL_L  ", ITYPE_MEM},
68         { 0x2b, "LDQ_L  ", ITYPE_MEM},
69         { 0x2c, "STL    ", ITYPE_MEM},
70         { 0x2d, "STQ    ", ITYPE_MEM},
71         { 0x2e, "STL_C  ", ITYPE_MEM},
72         { 0x2f, "STQ_C  ", ITYPE_MEM},
73         { 0x30, "BR     ", ITYPE_BRA},
74         { 0x31, "FBEQ   ", ITYPE_BRA},
75         { 0x32, "FBLT   ", ITYPE_BRA},
76         { 0x33, "FBLE   ", ITYPE_BRA},
77         { 0x34, "BSR    ", ITYPE_BRA},
78         { 0x35, "FBNE   ", ITYPE_BRA},
79         { 0x36, "FBGE   ", ITYPE_BRA},
80         { 0x37, "FBGT   ", ITYPE_BRA},
81         { 0x38, "BLBC   ", ITYPE_BRA},
82         { 0x39, "BEQ    ", ITYPE_BRA},
83         { 0x3a, "BLT    ", ITYPE_BRA},
84         { 0x3b, "BLE    ", ITYPE_BRA},
85         { 0x3c, "BLBS   ", ITYPE_BRA},
86         { 0x3d, "BNE    ", ITYPE_BRA},
87         { 0x3e, "BGE    ", ITYPE_BRA},
88         { 0x3f, "BGT    ", ITYPE_BRA}
89 };
90                 
91 static struct { u2 op,fun; char *name; }  op3s[] = {
92         { 0x10, 0x00,  "ADDL   " },
93         { 0x10, 0x40,  "ADDL/V " },
94         { 0x10, 0x20,  "ADDQ   " },
95         { 0x10, 0x60,  "ADDQ/V " },
96         { 0x10, 0x09,  "SUBL   " },
97         { 0x10, 0x49,  "SUBL/V " },
98         { 0x10, 0x29,  "SUBQ   " },
99         { 0x10, 0x69,  "SUBQ/V " },
100         { 0x10, 0x2D,  "CMPEQ  " },
101         { 0x10, 0x4D,  "CMPLT  " },
102         { 0x10, 0x6D,  "CMPLE  " },
103         { 0x10, 0x1D,  "CMPULT " },
104         { 0x10, 0x3D,  "CMPULE " },
105         { 0x10, 0x0F,  "CMPBGE " },
106         { 0x10, 0x02,  "S4ADDL " },
107         { 0x10, 0x0b,  "S4SUBL " },
108         { 0x10, 0x22,  "S4ADDQ " },
109         { 0x10, 0x2b,  "S4SUBQ " },
110         { 0x10, 0x12,  "S8ADDL " },
111         { 0x10, 0x1b,  "S8SUBL " },
112         { 0x10, 0x32,  "S8ADDQ " },
113         { 0x10, 0x3b,  "S8SUBQ " },
114         { 0x11, 0x00,  "AND    " },
115         { 0x11, 0x20,  "OR     " },
116         { 0x11, 0x40,  "XOR    " },
117         { 0x11, 0x08,  "ANDNOT " },
118         { 0x11, 0x28,  "ORNOT  " },
119         { 0x11, 0x48,  "XORNOT " },
120         { 0x11, 0x24,  "CMOVEQ " },
121         { 0x11, 0x44,  "CMOVLT " },
122         { 0x11, 0x64,  "CMOVLE " },
123         { 0x11, 0x26,  "CMOVNE " },
124         { 0x11, 0x46,  "CMOVGE " },
125         { 0x11, 0x66,  "CMOVGT " },
126         { 0x11, 0x14,  "CMOVLBS" },
127         { 0x11, 0x16,  "CMOVLBC" },
128         { 0x12, 0x39,  "SLL    " },
129         { 0x12, 0x3C,  "SRA    " },
130         { 0x12, 0x34,  "SRL    " },
131         { 0x12, 0x30,  "ZAP    " },
132         { 0x12, 0x31,  "ZAPNOT " },
133         { 0x12, 0x06,  "EXTBL  " },
134         { 0x12, 0x16,  "EXTWL  " },
135         { 0x12, 0x26,  "EXTLL  " },
136         { 0x12, 0x36,  "EXTQL  " },
137         { 0x12, 0x5a,  "EXTWH  " },
138         { 0x12, 0x6a,  "EXTLH  " },
139         { 0x12, 0x7a,  "EXTQH  " },
140         { 0x12, 0x0b,  "INSBL  " },
141         { 0x12, 0x1b,  "INSWL  " },
142         { 0x12, 0x2b,  "INSLL  " },
143         { 0x12, 0x3b,  "INSQL  " },
144         { 0x12, 0x57,  "INSWH  " },
145         { 0x12, 0x67,  "INSLH  " },
146         { 0x12, 0x77,  "INSQH  " },
147         { 0x12, 0x02,  "MSKBL  " },
148         { 0x12, 0x12,  "MSKWL  " },
149         { 0x12, 0x22,  "MSKLL  " },
150         { 0x12, 0x32,  "MSKQL  " },
151         { 0x12, 0x52,  "MSKWH  " },
152         { 0x12, 0x62,  "MSKLH  " },
153         { 0x12, 0x72,  "MSKQH  " },
154         { 0x13, 0x00,  "MULL   " },
155         { 0x13, 0x60,  "MULQ/V " },
156         { 0x13, 0x40,  "MULL/V " },
157         { 0x13, 0x30,  "UMULH  " },
158         { 0x16, 0x080, "FADD   " },
159         { 0x16, 0x0a0, "DADD   " },
160         { 0x16, 0x081, "FSUB   " },
161         { 0x16, 0x0a1, "DSUB   " },
162         { 0x16, 0x082, "FMUL   " },
163         { 0x16, 0x0a2, "DMUL   " },
164         { 0x16, 0x083, "FDIV   " },
165         { 0x16, 0x0a3, "DDIV   " },
166         { 0x16, 0x580, "FADDS  " },
167         { 0x16, 0x5a0, "DADDS  " },
168         { 0x16, 0x581, "FSUBS  " },
169         { 0x16, 0x5a1, "DSUBS  " },
170         { 0x16, 0x582, "FMULS  " },
171         { 0x16, 0x5a2, "DMULS  " },
172         { 0x16, 0x583, "FDIVS  " },
173         { 0x16, 0x5a3, "DDIVS  " },
174         { 0x16, 0x0ac, "CVTDF  " },
175         { 0x16, 0x0bc, "CVTLF  " },
176         { 0x16, 0x0be, "CVTLD  " },
177         { 0x16, 0x0af, "CVTDL  " },
178         { 0x16, 0x02f, "CVTDLC " },
179         { 0x16, 0x5ac, "CVTDFS " },
180         { 0x16, 0x5af, "CVTDLS " },
181         { 0x16, 0x52f, "CVTDLCS" },
182         { 0x16, 0x0a4, "FCMPUN " },
183         { 0x16, 0x0a5, "FCMPEQ " },
184         { 0x16, 0x0a6, "FCMPLT " },
185         { 0x16, 0x0a7, "FCMPLE " },
186         { 0x16, 0x5a4, "FCMPUNS" },
187         { 0x16, 0x5a5, "FCMPEQS" },
188         { 0x16, 0x5a6, "FCMPLTS" },
189         { 0x16, 0x5a7, "FCMPLES" },
190         { 0x17, 0x020, "FMOV   " },
191         { 0x17, 0x021, "FMOVN  " },
192         { 0x1c, 0x0,   "BSEXT  " },
193         { 0x1c, 0x1,   "WSEXT  " },
194         
195         { 0x00, 0x00,  NULL }
196 };
197
198
199 static void disasscmd (int c, int pos)
200 {
201         int op, opfun, fopfun, i;
202         int ra, rb, rc, lit, disp;
203
204         op     = (c>>26) & 0x3f;
205         opfun  = (c>>5)  & 0x7f;
206         fopfun = (c>>5)  & 0x7ff;
207         ra     = (c>>21) & 0x1f;
208         rb     = (c>>16) & 0x1f;
209         rc     = (c>>0)  & 0x1f;
210         lit    = (c>>13) & 0xff;
211         disp   = (c<<16) >> 16;
212
213         printf ("%6x: %8x  ", pos, c);
214         
215         switch ( ops[op].itype ) {
216         case ITYPE_JMP:
217                 switch ((c>>14) & 3) {
218                         case 0:
219                                 printf ("JMP     "); 
220                                 break;
221                         case 1:
222                                 printf ("JSR     "); 
223                                 break;
224                         case 2:
225                                 printf ("RET     "); 
226                                 break;
227                         case 3:
228                                 printf ("JSR_CO  "); 
229                                 break;
230                         }
231                 printf ("$%d,$%d\n", ra, rb); 
232                 break;
233
234         case ITYPE_MEM:
235                 if (op == 0x18 && ra == 0 && ra == 0 && disp == 0)
236                         printf ("TRAPB\n"); 
237                 else
238                         printf ("%s $%d,$%d,%d\n", ops[op].name, ra, rb, disp); 
239                 break;
240
241         case ITYPE_BRA:
242                 printf ("%s $%d,%x\n", ops[op].name, ra, pos + 4 + ((c << 11) >> 9));
243                 break;
244                 
245         case ITYPE_FOP:
246                 if (op == 0x17 && fopfun == 0x020 && ra == rb) {
247                         if (ra == 31 && rc == 31)
248                                 printf ("FNOP\n");
249                         else
250                                 printf ("FMOV    $f%d,$f%d\n", ra, rc);
251                         return;
252                         }
253                 for (i = 0; op3s[i].name; i++)
254                         if (op3s[i].op == op && op3s[i].fun == fopfun) {
255                                 printf ("%s $f%d,$f%d,$f%d\n", op3s[i].name, ra, rb,  rc);
256                                 return;
257                                 }
258                 printf ("%s%x $f%d,$f%d,$f%d\n", ops[op].name, fopfun, ra, rb, rc);
259                 break; 
260
261         case ITYPE_OP:
262                 if (op == 0x11 && opfun == 0x20 && ra == rb && ~(c&0x1000)) {
263                         if (ra == 31 && rc == 31)
264                                 printf ("NOP\n");
265                         else
266                                 printf ("MOV     $%d,$%d\n", ra, rc);
267                         return;
268                         }
269                 for (i = 0; op3s[i].name; i++) {
270                         if (op3s[i].op == op && op3s[i].fun == opfun) {
271                                 if (c&0x1000)
272                                         printf ("%s $%d,#%d,$%d\n", op3s[i].name, ra, lit, rc);
273                                 else
274                                         printf ("%s $%d,$%d,$%d\n", op3s[i].name, ra, rb,  rc);
275                                 return;
276                                 }
277                         }
278                 /* fall through */
279         default:
280                 if (c&0x1000)
281                         printf ("UNDEF  %x(%x) $%d,#%d,$%d\n", op, opfun, ra, lit, rc);
282                 else
283                         printf ("UNDEF  %x(%x) $%d,$%d,$%d\n", op, opfun, ra, rb,  rc);         
284         }
285 }
286
287
288 /*********************** funktion disassemble **********************************
289
290         outputs a disassembler listing of some machine code on 'stdout'
291
292 *******************************************************************************/
293
294 static void disassemble (int *code, int len)
295 {
296         int p;
297
298         printf ("  --- disassembler listing ---\n");    
299         for (p = 0; p < len; p += 4, code++)
300                 disasscmd (*code, p); 
301 }