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
25 $Id: disass.c 7335 2007-02-12 10:43:33Z twisti $
36 #include "vm/global.h"
38 #include "vm/jit/abi.h"
39 #include "vm/jit/disass.h"
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 /* disassinstr *****************************************************************
248 Outputs a disassembler listing of one machine code instruction on
251 code: pointer to instructions machine code
253 *******************************************************************************/
255 u1 *disassinstr(u1 *code)
257 s4 op; /* 6 bit op code */
258 s4 opfun; /* 7 bit function code */
259 s4 ra, rb, rc; /* 6 bit register specifiers */
260 s4 lit; /* 8 bit unsigned literal */
261 s4 i; /* loop counter */
266 op = (c >> 26) & 0x3f; /* 6 bit op code */
267 opfun = (c >> 5) & 0x7f; /* 7 bit function code */
268 ra = (c >> 21) & 0x1f; /* 6 bit source register specifier */
269 rb = (c >> 16) & 0x1f; /* 6 bit source register specifier */
270 rc = (c >> 0) & 0x1f; /* 6 bit destination register specifiers */
271 lit = (c >> 13) & 0xff; /* 8 bit unsigned literal */
273 printf("0x%016lx: %08x ", (u8) code, c);
275 switch (ops[op].itype) {
277 switch ((c >> 14) & 3) { /* branch hint */
280 printf("jmp (%s)\n", abi_registers_integer_name[rb]);
287 printf("jsr (%s)\n", abi_registers_integer_name[rb]);
293 if (ra == 31 && rb == 26) {
298 printf("ret (%s)\n", abi_registers_integer_name[rb]);
307 printf("%s,(%s)\n", abi_registers_integer_name[ra],
308 abi_registers_integer_name[rb]);
312 s4 disp = (c << 16) >> 16; /* 16 bit signed displacement */
314 if (op == 0x18 && ra == 0 && ra == 0 && disp == 0)
317 printf("%s %s,%d(%s)\n", ops[op].name,
318 abi_registers_integer_name[ra], disp,
319 abi_registers_integer_name[rb]);
324 printf("%s $f%d,%d(%s)\n", ops[op].name, ra, (c << 16) >> 16,
325 abi_registers_integer_name[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", ops[op].name,
335 abi_registers_integer_name[ra],
336 (u8) code + 4 + ((c << 11) >> 9));
340 s4 fopfun = (c >> 5) & 0x7ff; /* 11 bit fp function code */
342 if (op == 0x17 && fopfun == 0x020 && ra == rb) {
343 if (ra == 31 && rc == 31)
346 printf("fmov $f%d,$f%d\n", ra, rc);
349 for (i = 0; op3s[i].name; i++)
350 if (op3s[i].op == op && op3s[i].fun == fopfun) {
351 printf("%s $f%d,$f%d,$f%d\n", op3s[i].name, ra, rb, rc);
354 printf("%s%x $f%d,$f%d,$f%d\n", ops[op].name, fopfun, ra, rb, rc);
359 if (op == 0x11 && opfun == 0x20 && ra == rb && ~(c&0x1000)) {
360 if (ra == 31 && rc == 31)
363 printf("clr %s\n", abi_registers_integer_name[rc]);
365 printf("mov %s,%s\n", abi_registers_integer_name[ra],
366 abi_registers_integer_name[rc]);
369 for (i = 0; op3s[i].name; i++) {
370 if (op3s[i].op == op && op3s[i].fun == opfun) {
371 if (c & 0x1000) /* immediate instruction */
372 printf("%s %s,%d,%s\n", op3s[i].name,
373 abi_registers_integer_name[ra], lit,
374 abi_registers_integer_name[rc]);
376 printf("%s %s,%s,%s\n", op3s[i].name,
377 abi_registers_integer_name[ra],
378 abi_registers_integer_name[rb],
379 abi_registers_integer_name[rc]);
385 if (c & 0x1000) /* immediate instruction */
386 printf("UNDEF %x(%x) $%d,%d,$%d\n", op, opfun, ra, lit, rc);
388 printf("UNDEF %x(%x) $%d,$%d,$%d\n", op, opfun, ra, rb, rc);
391 /* 1 instruction is 4-bytes long */
398 /* disassemble *****************************************************************
400 Outputs a disassembler listing of some machine code on 'stdout'.
402 start: pointer to first instruction
403 end: pointer to last instruction
405 *******************************************************************************/
407 void disassemble(u1 *start, u1 *end)
409 printf(" --- disassembler listing ---\n");
410 for (; start < end; )
411 start = disassinstr(start);
416 * These are local overrides for various environment variables in Emacs.
417 * Please do not remove this and leave it at the end of the file, where
418 * Emacs will automagically detect them.
419 * ---------------------------------------------------------------------
422 * indent-tabs-mode: t