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