1 /* src/vm/jit/alpha/disass.c - primitive disassembler for Alpha machine code
3 Copyright (C) 1996-2005, 2006 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
8 This file is part of CACAO.
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.
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.
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
25 Contact: cacao@cacaojvm.org
27 Authors: Andreas Krall
30 Changes: Christian Thalinger
32 $Id: disass.c 4357 2006-01-22 23:33:38Z twisti $
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.
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 */
61 /* instruction decode table for 6 bit op codes */
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}
131 /* instruction decode list for 6 bit op codes and 9 bit function codes */
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 " },
246 /* name table for 32 integer registers */
249 /* 0x00 */ "v0", /* "$0", */
250 /* 0x01 */ "t0", /* "$1", */
251 /* 0x02 */ "t1", /* "$2", */
252 /* 0x03 */ "t2", /* "$3", */
253 /* 0x04 */ "t3", /* "$4", */
254 /* 0x05 */ "t4", /* "$5", */
255 /* 0x06 */ "t5", /* "$6", */
256 /* 0x07 */ "t6", /* "$7", */
258 /* 0x08 */ "t7", /* "$8", */
259 /* 0x09 */ "s0", /* "$9", */
260 /* 0x0a */ "s1", /* "$10", */
261 /* 0x0b */ "s2", /* "$11", */
262 /* 0x0c */ "s3", /* "$12", */
263 /* 0x0d */ "s4", /* "$13", */
264 /* 0x0e */ "s5", /* "$14", */
265 /* 0x0f */ "s6", /* "$15", */
267 /* 0x10 */ "a0", /* "$16", */
268 /* 0x11 */ "a1", /* "$17", */
269 /* 0x12 */ "a2", /* "$18", */
270 /* 0x13 */ "a3", /* "$19", */
271 /* 0x14 */ "a4", /* "$20", */
272 /* 0x15 */ "a5", /* "$21", */
273 /* 0x16 */ "t8", /* "$22", */
274 /* 0x17 */ "t9", /* "$23", */
276 /* 0x18 */ "t10", /* "$24", */
277 /* 0x19 */ "t11", /* "$25", */
278 /* 0x1a */ "ra", /* "$26", */
279 /* 0x1b */ "pv", /* "$27", */
280 /* 0x1c */ "at", /* "$28", */
281 /* 0x1d */ "gp", /* "$29", */
282 /* 0x1e */ "sp", /* "$30", */
283 /* 0x1f */ "zero" /* "$31" */
287 /* disassinstr *****************************************************************
289 Outputs a disassembler listing of one machine code instruction on
292 code: pointer to instructions machine code
294 *******************************************************************************/
296 u1 *disassinstr(u1 *code)
298 s4 op; /* 6 bit op code */
299 s4 opfun; /* 7 bit function code */
300 s4 ra, rb, rc; /* 6 bit register specifiers */
301 s4 lit; /* 8 bit unsigned literal */
302 s4 i; /* loop counter */
307 op = (c >> 26) & 0x3f; /* 6 bit op code */
308 opfun = (c >> 5) & 0x7f; /* 7 bit function code */
309 ra = (c >> 21) & 0x1f; /* 6 bit source register specifier */
310 rb = (c >> 16) & 0x1f; /* 6 bit source register specifier */
311 rc = (c >> 0) & 0x1f; /* 6 bit destination register specifiers */
312 lit = (c >> 13) & 0xff; /* 8 bit unsigned literal */
314 printf("0x%016lx: %08x ", (u8) code, c);
316 switch (ops[op].itype) {
318 switch ((c >> 14) & 3) { /* branch hint */
321 printf("jmp (%s)\n", regs[rb]);
328 printf("jsr (%s)\n", regs[rb]);
334 if (ra == 31 && rb == 26) {
339 printf("ret (%s)\n", regs[rb]);
348 printf("%s,(%s)\n", regs[ra], regs[rb]);
352 s4 disp = (c << 16) >> 16; /* 16 bit signed displacement */
354 if (op == 0x18 && ra == 0 && ra == 0 && disp == 0)
357 printf("%s %s,%d(%s)\n", ops[op].name, regs[ra], disp, regs[rb]);
362 printf("%s $f%d,%d(%s)\n", ops[op].name, ra, (c << 16) >> 16, regs[rb]);
365 case ITYPE_BRA: /* 21 bit signed branch offset */
366 if (op == 0x30 && ra == 31)
367 printf("br 0x%016lx\n", (u8) code + 4 + ((c << 11) >> 9));
368 else if (op == 0x34 && ra == 26)
369 printf("brs 0x%016lx\n", (u8) code + 4 + ((c << 11) >> 9));
371 printf("%s %s,0x%016lx\n",
372 ops[op].name, regs[ra], (u8) code + 4 + ((c << 11) >> 9));
376 s4 fopfun = (c >> 5) & 0x7ff; /* 11 bit fp function code */
378 if (op == 0x17 && fopfun == 0x020 && ra == rb) {
379 if (ra == 31 && rc == 31)
382 printf("fmov $f%d,$f%d\n", ra, rc);
385 for (i = 0; op3s[i].name; i++)
386 if (op3s[i].op == op && op3s[i].fun == fopfun) {
387 printf("%s $f%d,$f%d,$f%d\n", op3s[i].name, ra, rb, rc);
390 printf("%s%x $f%d,$f%d,$f%d\n", ops[op].name, fopfun, ra, rb, rc);
395 if (op == 0x11 && opfun == 0x20 && ra == rb && ~(c&0x1000)) {
396 if (ra == 31 && rc == 31)
399 printf("clr %s\n", regs[rc]);
401 printf("mov %s,%s\n", regs[ra], regs[rc]);
404 for (i = 0; op3s[i].name; i++) {
405 if (op3s[i].op == op && op3s[i].fun == opfun) {
406 if (c & 0x1000) /* immediate instruction */
407 printf("%s %s,%d,%s\n",
408 op3s[i].name, regs[ra], lit, regs[rc]);
410 printf("%s %s,%s,%s\n",
411 op3s[i].name, regs[ra], regs[rb], regs[rc]);
417 if (c & 0x1000) /* immediate instruction */
418 printf("UNDEF %x(%x) $%d,%d,$%d\n", op, opfun, ra, lit, rc);
420 printf("UNDEF %x(%x) $%d,$%d,$%d\n", op, opfun, ra, rb, rc);
423 /* 1 instruction is 4-bytes long */
430 /* disassemble *****************************************************************
432 Outputs a disassembler listing of some machine code on 'stdout'.
434 start: pointer to first instruction
435 end: pointer to last instruction
437 *******************************************************************************/
439 void disassemble(u1 *start, u1 *end)
441 printf(" --- disassembler listing ---\n");
442 for (; start < end; )
443 start = disassinstr(start);
448 * These are local overrides for various environment variables in Emacs.
449 * Please do not remove this and leave it at the end of the file, where
450 * Emacs will automagically detect them.
451 * ---------------------------------------------------------------------
454 * indent-tabs-mode: t