1 /* src/vm/jit/alpha/disass.c - primitive disassembler for Alpha machine code
3 Copyright (C) 1996-2005, 2006, 2007 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
34 #include "vm/global.h"
36 #include "vm/jit/abi.h"
37 #include "vm/jit/disass.h"
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.
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 */
59 /* instruction decode table for 6 bit op codes */
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}
129 /* instruction decode list for 6 bit op codes and 9 bit function codes */
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 " },
244 /* disassinstr *****************************************************************
246 Outputs a disassembler listing of one machine code instruction on
249 code: pointer to instructions machine code
251 *******************************************************************************/
253 u1 *disassinstr(u1 *code)
255 s4 op; /* 6 bit op code */
256 s4 opfun; /* 7 bit function code */
257 s4 ra, rb, rc; /* 6 bit register specifiers */
258 s4 lit; /* 8 bit unsigned literal */
259 s4 i; /* loop counter */
264 op = (c >> 26) & 0x3f; /* 6 bit op code */
265 opfun = (c >> 5) & 0x7f; /* 7 bit function code */
266 ra = (c >> 21) & 0x1f; /* 6 bit source register specifier */
267 rb = (c >> 16) & 0x1f; /* 6 bit source register specifier */
268 rc = (c >> 0) & 0x1f; /* 6 bit destination register specifiers */
269 lit = (c >> 13) & 0xff; /* 8 bit unsigned literal */
271 printf("0x%016lx: %08x ", (u8) code, c);
273 switch (ops[op].itype) {
275 switch ((c >> 14) & 3) { /* branch hint */
278 printf("jmp (%s)\n", abi_registers_integer_name[rb]);
285 printf("jsr (%s)\n", abi_registers_integer_name[rb]);
291 if (ra == 31 && rb == 26) {
296 printf("ret (%s)\n", abi_registers_integer_name[rb]);
305 printf("%s,(%s)\n", abi_registers_integer_name[ra],
306 abi_registers_integer_name[rb]);
310 s4 disp = (c << 16) >> 16; /* 16 bit signed displacement */
312 if (op == 0x18 && ra == 0 && ra == 0 && disp == 0)
315 printf("%s %s,%d(%s)\n", ops[op].name,
316 abi_registers_integer_name[ra], disp,
317 abi_registers_integer_name[rb]);
322 printf("%s $f%d,%d(%s)\n", ops[op].name, ra, (c << 16) >> 16,
323 abi_registers_integer_name[rb]);
326 case ITYPE_BRA: /* 21 bit signed branch offset */
327 if (op == 0x30 && ra == 31)
328 printf("br 0x%016lx\n", (u8) code + 4 + ((c << 11) >> 9));
329 else if (op == 0x34 && ra == 26)
330 printf("brs 0x%016lx\n", (u8) code + 4 + ((c << 11) >> 9));
332 printf("%s %s,0x%016lx\n", ops[op].name,
333 abi_registers_integer_name[ra],
334 (u8) code + 4 + ((c << 11) >> 9));
338 s4 fopfun = (c >> 5) & 0x7ff; /* 11 bit fp function code */
340 if (op == 0x17 && fopfun == 0x020 && ra == rb) {
341 if (ra == 31 && rc == 31)
344 printf("fmov $f%d,$f%d\n", ra, rc);
347 for (i = 0; op3s[i].name; i++)
348 if (op3s[i].op == op && op3s[i].fun == fopfun) {
349 printf("%s $f%d,$f%d,$f%d\n", op3s[i].name, ra, rb, rc);
352 printf("%s%x $f%d,$f%d,$f%d\n", ops[op].name, fopfun, ra, rb, rc);
357 if (op == 0x11 && opfun == 0x20 && ra == rb && ~(c&0x1000)) {
358 if (ra == 31 && rc == 31)
361 printf("clr %s\n", abi_registers_integer_name[rc]);
363 printf("mov %s,%s\n", abi_registers_integer_name[ra],
364 abi_registers_integer_name[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", op3s[i].name,
371 abi_registers_integer_name[ra], lit,
372 abi_registers_integer_name[rc]);
374 printf("%s %s,%s,%s\n", op3s[i].name,
375 abi_registers_integer_name[ra],
376 abi_registers_integer_name[rb],
377 abi_registers_integer_name[rc]);
383 if (c & 0x1000) /* immediate instruction */
384 printf("UNDEF %x(%x) $%d,%d,$%d\n", op, opfun, ra, lit, rc);
386 printf("UNDEF %x(%x) $%d,$%d,$%d\n", op, opfun, ra, rb, rc);
389 /* 1 instruction is 4-bytes long */
396 /* disassemble *****************************************************************
398 Outputs a disassembler listing of some machine code on 'stdout'.
400 start: pointer to first instruction
401 end: pointer to last instruction
403 *******************************************************************************/
405 void disassemble(u1 *start, u1 *end)
407 printf(" --- disassembler listing ---\n");
408 for (; start < end; )
409 start = disassinstr(start);
414 * These are local overrides for various environment variables in Emacs.
415 * Please do not remove this and leave it at the end of the file, where
416 * Emacs will automagically detect them.
417 * ---------------------------------------------------------------------
420 * indent-tabs-mode: t