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
31 $Id: disass.c 6261 2006-12-28 21:21:08Z twisti $
42 #include "vm/global.h"
43 #include "vm/jit/disass.h"
46 /* The disassembler uses two tables for decoding the instructions. The first
47 table (ops) is used to classify the instructions based on the op code and
48 contains the instruction names for instructions which don't used the
49 function codes. This table is indexed by the op code (6 bit, 64 entries).
50 The second table (op3s) contains instructions which contain both an op
51 code and a function code. This table is an unsorted list of instructions
52 which is terminated by op code and function code zero. This list is
53 searched linearly for a matching pair of opcode and function code.
56 #define ITYPE_UNDEF 0 /* undefined instructions (illegal opcode) */
57 #define ITYPE_JMP 1 /* jump instructions */
58 #define ITYPE_MEM 2 /* memory instructions */
59 #define ITYPE_FMEM 3 /* floating point memory instructions */
60 #define ITYPE_BRA 4 /* branch instructions */
61 #define ITYPE_OP 5 /* integer instructions */
62 #define ITYPE_FOP 6 /* floating point instructions */
65 /* instruction decode table for 6 bit op codes */
67 static struct {char *name; int itype;} ops[] = {
68 /* 0x00 */ {"", ITYPE_UNDEF},
69 /* 0x01 */ {"", ITYPE_UNDEF},
70 /* 0x02 */ {"", ITYPE_UNDEF},
71 /* 0x03 */ {"", ITYPE_UNDEF},
72 /* 0x04 */ {"", ITYPE_UNDEF},
73 /* 0x05 */ {"", ITYPE_UNDEF},
74 /* 0x06 */ {"", ITYPE_UNDEF},
75 /* 0x07 */ {"", ITYPE_UNDEF},
76 /* 0x08 */ {"lda ", ITYPE_MEM},
77 /* 0x09 */ {"ldah ", ITYPE_MEM},
78 /* 0x0a */ {"ldb ", ITYPE_MEM},
79 /* 0x0b */ {"ldq_u ", ITYPE_MEM},
80 /* 0x0c */ {"ldw ", ITYPE_MEM},
81 /* 0x0d */ {"stw ", ITYPE_MEM},
82 /* 0x0e */ {"stb ", ITYPE_MEM},
83 /* 0x0f */ {"stq_u ", ITYPE_MEM},
84 /* 0x10 */ {"op ", ITYPE_OP},
85 /* 0x11 */ {"op ", ITYPE_OP},
86 /* 0x12 */ {"op ", ITYPE_OP},
87 /* 0x13 */ {"op ", ITYPE_OP},
88 /* 0x14 */ {"", ITYPE_UNDEF},
89 /* 0x15 */ {"", ITYPE_UNDEF},
90 /* 0x16 */ {"fop ", ITYPE_FOP},
91 /* 0x17 */ {"fop ", ITYPE_FOP},
92 /* 0x18 */ {"memfmt ", ITYPE_MEM},
93 /* 0x19 */ {"", ITYPE_UNDEF},
94 /* 0x1a */ {"jmp ", ITYPE_JMP},
95 /* 0x1b */ {"", ITYPE_UNDEF},
96 /* 0x1c */ {"op ", ITYPE_OP},
97 /* 0x1d */ {"", ITYPE_UNDEF},
98 /* 0x1e */ {"", ITYPE_UNDEF},
99 /* 0x1f */ {"", ITYPE_UNDEF},
100 /* 0x20 */ {"ldf ", ITYPE_FMEM},
101 /* 0x21 */ {"ldg ", ITYPE_FMEM},
102 /* 0x22 */ {"lds ", ITYPE_FMEM},
103 /* 0x23 */ {"ldt ", ITYPE_FMEM},
104 /* 0x24 */ {"stf ", ITYPE_FMEM},
105 /* 0x25 */ {"stg ", ITYPE_FMEM},
106 /* 0x26 */ {"sts ", ITYPE_FMEM},
107 /* 0x27 */ {"stt ", ITYPE_FMEM},
108 /* 0x28 */ {"ldl ", ITYPE_MEM},
109 /* 0x29 */ {"ldq ", ITYPE_MEM},
110 /* 0x2a */ {"ldl_l ", ITYPE_MEM},
111 /* 0x2b */ {"ldq_l ", ITYPE_MEM},
112 /* 0x2c */ {"stl ", ITYPE_MEM},
113 /* 0x2d */ {"stq ", ITYPE_MEM},
114 /* 0x2e */ {"stl_c ", ITYPE_MEM},
115 /* 0x2f */ {"stq_c ", ITYPE_MEM},
116 /* 0x30 */ {"br ", ITYPE_BRA},
117 /* 0x31 */ {"fbeq ", ITYPE_BRA},
118 /* 0x32 */ {"fblt ", ITYPE_BRA},
119 /* 0x33 */ {"fble ", ITYPE_BRA},
120 /* 0x34 */ {"bsr ", ITYPE_BRA},
121 /* 0x35 */ {"fbne ", ITYPE_BRA},
122 /* 0x36 */ {"fbge ", ITYPE_BRA},
123 /* 0x37 */ {"fbgt ", ITYPE_BRA},
124 /* 0x38 */ {"blbc ", ITYPE_BRA},
125 /* 0x39 */ {"beq ", ITYPE_BRA},
126 /* 0x3a */ {"blt ", ITYPE_BRA},
127 /* 0x3b */ {"ble ", ITYPE_BRA},
128 /* 0x3c */ {"blbs ", ITYPE_BRA},
129 /* 0x3d */ {"bne ", ITYPE_BRA},
130 /* 0x3e */ {"bge ", ITYPE_BRA},
131 /* 0x3f */ {"bgt ", ITYPE_BRA}
135 /* instruction decode list for 6 bit op codes and 9 bit function codes */
137 static struct { u2 op, fun; char *name; } op3s[] = {
138 { 0x10, 0x00, "addl " },
139 { 0x10, 0x40, "addl/v " },
140 { 0x10, 0x20, "addq " },
141 { 0x10, 0x60, "addq/v " },
142 { 0x10, 0x09, "subl " },
143 { 0x10, 0x49, "subl/v " },
144 { 0x10, 0x29, "subq " },
145 { 0x10, 0x69, "subq/v " },
146 { 0x10, 0x2D, "cmpeq " },
147 { 0x10, 0x4D, "cmplt " },
148 { 0x10, 0x6D, "cmple " },
149 { 0x10, 0x1D, "cmpult " },
150 { 0x10, 0x3D, "cmpule " },
151 { 0x10, 0x0F, "cmpbge " },
152 { 0x10, 0x02, "s4addl " },
153 { 0x10, 0x0b, "s4subl " },
154 { 0x10, 0x22, "s4addq " },
155 { 0x10, 0x2b, "s4subq " },
156 { 0x10, 0x12, "s8addl " },
157 { 0x10, 0x1b, "s8subl " },
158 { 0x10, 0x32, "s8addq " },
159 { 0x10, 0x3b, "s8subq " },
160 { 0x11, 0x00, "and " },
161 { 0x11, 0x20, "or " },
162 { 0x11, 0x40, "xor " },
163 { 0x11, 0x08, "andnot " },
164 { 0x11, 0x28, "ornot " },
165 { 0x11, 0x48, "xornot " },
166 { 0x11, 0x24, "cmoveq " },
167 { 0x11, 0x44, "cmovlt " },
168 { 0x11, 0x64, "cmovle " },
169 { 0x11, 0x26, "cmovne " },
170 { 0x11, 0x46, "cmovge " },
171 { 0x11, 0x66, "cmovgt " },
172 { 0x11, 0x14, "cmovlbs" },
173 { 0x11, 0x16, "cmovlbc" },
174 { 0x12, 0x39, "sll " },
175 { 0x12, 0x3C, "sra " },
176 { 0x12, 0x34, "srl " },
177 { 0x12, 0x30, "zap " },
178 { 0x12, 0x31, "zapnot " },
179 { 0x12, 0x06, "extbl " },
180 { 0x12, 0x16, "extwl " },
181 { 0x12, 0x26, "extll " },
182 { 0x12, 0x36, "extql " },
183 { 0x12, 0x5a, "extwh " },
184 { 0x12, 0x6a, "extlh " },
185 { 0x12, 0x7a, "extqh " },
186 { 0x12, 0x0b, "insbl " },
187 { 0x12, 0x1b, "inswl " },
188 { 0x12, 0x2b, "insll " },
189 { 0x12, 0x3b, "insql " },
190 { 0x12, 0x57, "inswh " },
191 { 0x12, 0x67, "inslh " },
192 { 0x12, 0x77, "insqh " },
193 { 0x12, 0x02, "mskbl " },
194 { 0x12, 0x12, "mskwl " },
195 { 0x12, 0x22, "mskll " },
196 { 0x12, 0x32, "mskql " },
197 { 0x12, 0x52, "mskwh " },
198 { 0x12, 0x62, "msklh " },
199 { 0x12, 0x72, "mskqh " },
200 { 0x13, 0x00, "mull " },
201 { 0x13, 0x20, "mulq " },
202 { 0x13, 0x40, "mull/v " },
203 { 0x13, 0x60, "mulq/v " },
204 { 0x13, 0x30, "umulh " },
205 { 0x16, 0x080, "fadd " },
206 { 0x16, 0x0a0, "dadd " },
207 { 0x16, 0x081, "fsub " },
208 { 0x16, 0x0a1, "dsub " },
209 { 0x16, 0x082, "fmul " },
210 { 0x16, 0x0a2, "dmul " },
211 { 0x16, 0x083, "fdiv " },
212 { 0x16, 0x0a3, "ddiv " },
213 { 0x16, 0x580, "fadds " },
214 { 0x16, 0x5a0, "dadds " },
215 { 0x16, 0x581, "fsubs " },
216 { 0x16, 0x5a1, "dsubs " },
217 { 0x16, 0x582, "fmuls " },
218 { 0x16, 0x5a2, "dmuls " },
219 { 0x16, 0x583, "fdivs " },
220 { 0x16, 0x5a3, "ddivs " },
221 { 0x16, 0x0ac, "cvtdf " },
222 { 0x16, 0x0bc, "cvtlf " },
223 { 0x16, 0x0be, "cvtld " },
224 { 0x16, 0x0af, "cvtdl " },
225 { 0x16, 0x02f, "cvtdlc " },
226 { 0x17, 0x030, "cvtli " },
227 { 0x16, 0x1af, "cvtdlv " },
228 { 0x16, 0x12f, "cvtdlcv" },
229 { 0x17, 0x130, "cvtliv " },
230 { 0x16, 0x5ac, "cvtdfs " },
231 { 0x16, 0x5af, "cvtdls " },
232 { 0x16, 0x52f, "cvtdlcs" },
233 { 0x16, 0x0a4, "fcmpun " },
234 { 0x16, 0x0a5, "fcmpeq " },
235 { 0x16, 0x0a6, "fcmplt " },
236 { 0x16, 0x0a7, "fcmple " },
237 { 0x16, 0x5a4, "fcmpuns" },
238 { 0x16, 0x5a5, "fcmpeqs" },
239 { 0x16, 0x5a6, "fcmplts" },
240 { 0x16, 0x5a7, "fcmples" },
241 { 0x17, 0x020, "fmov " },
242 { 0x17, 0x021, "fmovn " },
243 { 0x1c, 0x0, "bsext " },
244 { 0x1c, 0x1, "wsext " },
250 /* disassinstr *****************************************************************
252 Outputs a disassembler listing of one machine code instruction on
255 code: pointer to instructions machine code
257 *******************************************************************************/
259 u1 *disassinstr(u1 *code)
261 s4 op; /* 6 bit op code */
262 s4 opfun; /* 7 bit function code */
263 s4 ra, rb, rc; /* 6 bit register specifiers */
264 s4 lit; /* 8 bit unsigned literal */
265 s4 i; /* loop counter */
270 op = (c >> 26) & 0x3f; /* 6 bit op code */
271 opfun = (c >> 5) & 0x7f; /* 7 bit function code */
272 ra = (c >> 21) & 0x1f; /* 6 bit source register specifier */
273 rb = (c >> 16) & 0x1f; /* 6 bit source register specifier */
274 rc = (c >> 0) & 0x1f; /* 6 bit destination register specifiers */
275 lit = (c >> 13) & 0xff; /* 8 bit unsigned literal */
277 printf("0x%016lx: %08x ", (u8) code, c);
279 switch (ops[op].itype) {
281 switch ((c >> 14) & 3) { /* branch hint */
284 printf("jmp (%s)\n", regs[rb]);
291 printf("jsr (%s)\n", regs[rb]);
297 if (ra == 31 && rb == 26) {
302 printf("ret (%s)\n", regs[rb]);
311 printf("%s,(%s)\n", regs[ra], regs[rb]);
315 s4 disp = (c << 16) >> 16; /* 16 bit signed displacement */
317 if (op == 0x18 && ra == 0 && ra == 0 && disp == 0)
320 printf("%s %s,%d(%s)\n", ops[op].name, regs[ra], disp, regs[rb]);
325 printf("%s $f%d,%d(%s)\n", ops[op].name, ra, (c << 16) >> 16, regs[rb]);
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));
334 printf("%s %s,0x%016lx\n",
335 ops[op].name, regs[ra], (u8) code + 4 + ((c << 11) >> 9));
339 s4 fopfun = (c >> 5) & 0x7ff; /* 11 bit fp function code */
341 if (op == 0x17 && fopfun == 0x020 && ra == rb) {
342 if (ra == 31 && rc == 31)
345 printf("fmov $f%d,$f%d\n", ra, rc);
348 for (i = 0; op3s[i].name; i++)
349 if (op3s[i].op == op && op3s[i].fun == fopfun) {
350 printf("%s $f%d,$f%d,$f%d\n", op3s[i].name, ra, rb, rc);
353 printf("%s%x $f%d,$f%d,$f%d\n", ops[op].name, fopfun, ra, rb, rc);
358 if (op == 0x11 && opfun == 0x20 && ra == rb && ~(c&0x1000)) {
359 if (ra == 31 && rc == 31)
362 printf("clr %s\n", regs[rc]);
364 printf("mov %s,%s\n", regs[ra], regs[rc]);
367 for (i = 0; op3s[i].name; i++) {
368 if (op3s[i].op == op && op3s[i].fun == opfun) {
369 if (c & 0x1000) /* immediate instruction */
370 printf("%s %s,%d,%s\n",
371 op3s[i].name, regs[ra], lit, regs[rc]);
373 printf("%s %s,%s,%s\n",
374 op3s[i].name, regs[ra], regs[rb], regs[rc]);
380 if (c & 0x1000) /* immediate instruction */
381 printf("UNDEF %x(%x) $%d,%d,$%d\n", op, opfun, ra, lit, rc);
383 printf("UNDEF %x(%x) $%d,$%d,$%d\n", op, opfun, ra, rb, rc);
386 /* 1 instruction is 4-bytes long */
393 /* disassemble *****************************************************************
395 Outputs a disassembler listing of some machine code on 'stdout'.
397 start: pointer to first instruction
398 end: pointer to last instruction
400 *******************************************************************************/
402 void disassemble(u1 *start, u1 *end)
404 printf(" --- disassembler listing ---\n");
405 for (; start < end; )
406 start = disassinstr(start);
411 * These are local overrides for various environment variables in Emacs.
412 * Please do not remove this and leave it at the end of the file, where
413 * Emacs will automagically detect them.
414 * ---------------------------------------------------------------------
417 * indent-tabs-mode: t