1 /* disass.c ********************************************************************
3 Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
5 See file COPYRIGHT for information on usage and disclaimer of warranties
7 A very primitive disassembler for Alpha machine code for easy debugging.
9 Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
10 Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
12 Last Change: 1998/11/18
14 *******************************************************************************/
16 /* The disassembler uses two tables for decoding the instructions. The first
17 table (ops) is used to classify the instructions based on the op code and
18 contains the instruction names for instructions which don't used the
19 function codes. This table is indexed by the op code (6 bit, 64 entries).
20 The second table (op3s) contains instructions which contain both an op
21 code and a function code. This table is an unsorted list of instructions
22 which is terminated by op code and function code zero. This list is
23 searched linearly for a matching pair of opcode and function code.
26 #define ITYPE_UNDEF 0 /* undefined instructions (illegal opcode) */
27 #define ITYPE_JMP 1 /* jump instructions */
28 #define ITYPE_MEM 2 /* memory instructions */
29 #define ITYPE_FMEM 3 /* floating point memory instructions */
30 #define ITYPE_BRA 4 /* branch instructions */
31 #define ITYPE_OP 5 /* integer instructions */
32 #define ITYPE_FOP 6 /* floating point instructions */
35 /* instruction decode table for 6 bit op codes */
37 static struct {char *name; int itype;} ops[] = {
39 /* 0x00 */ {"", ITYPE_UNDEF},
40 /* 0x01 */ {"", ITYPE_UNDEF},
41 /* 0x02 */ {"", ITYPE_UNDEF},
42 /* 0x03 */ {"", ITYPE_UNDEF},
43 /* 0x04 */ {"", ITYPE_UNDEF},
44 /* 0x05 */ {"", ITYPE_UNDEF},
45 /* 0x06 */ {"", ITYPE_UNDEF},
46 /* 0x07 */ {"", ITYPE_UNDEF},
47 /* 0x08 */ {"lda ", ITYPE_MEM},
48 /* 0x09 */ {"ldah ", ITYPE_MEM},
49 /* 0x0a */ {"ldb ", ITYPE_MEM},
50 /* 0x0b */ {"ldq_u ", ITYPE_MEM},
51 /* 0x0c */ {"ldw ", ITYPE_MEM},
52 /* 0x0d */ {"stw ", ITYPE_MEM},
53 /* 0x0e */ {"stb ", ITYPE_MEM},
54 /* 0x0f */ {"stq_u ", ITYPE_MEM},
55 /* 0x10 */ {"op ", ITYPE_OP},
56 /* 0x11 */ {"op ", ITYPE_OP},
57 /* 0x12 */ {"op ", ITYPE_OP},
58 /* 0x13 */ {"op ", ITYPE_OP},
59 /* 0x14 */ {"", ITYPE_UNDEF},
60 /* 0x15 */ {"", ITYPE_UNDEF},
61 /* 0x16 */ {"fop ", ITYPE_FOP},
62 /* 0x17 */ {"fop ", ITYPE_FOP},
63 /* 0x18 */ {"memfmt ", ITYPE_MEM},
64 /* 0x19 */ {"", ITYPE_UNDEF},
65 /* 0x1a */ {"jmp ", ITYPE_JMP},
66 /* 0x1b */ {"", ITYPE_UNDEF},
67 /* 0x1c */ {"op ", ITYPE_OP},
68 /* 0x1d */ {"", ITYPE_UNDEF},
69 /* 0x1e */ {"", ITYPE_UNDEF},
70 /* 0x1f */ {"", ITYPE_UNDEF},
71 /* 0x20 */ {"ldf ", ITYPE_FMEM},
72 /* 0x21 */ {"ldg ", ITYPE_FMEM},
73 /* 0x22 */ {"lds ", ITYPE_FMEM},
74 /* 0x23 */ {"ldt ", ITYPE_FMEM},
75 /* 0x24 */ {"stf ", ITYPE_FMEM},
76 /* 0x25 */ {"stg ", ITYPE_FMEM},
77 /* 0x26 */ {"sts ", ITYPE_FMEM},
78 /* 0x27 */ {"stt ", ITYPE_FMEM},
79 /* 0x28 */ {"ldl ", ITYPE_MEM},
80 /* 0x29 */ {"ldq ", ITYPE_MEM},
81 /* 0x2a */ {"ldl_l ", ITYPE_MEM},
82 /* 0x2b */ {"ldq_l ", ITYPE_MEM},
83 /* 0x2c */ {"stl ", ITYPE_MEM},
84 /* 0x2d */ {"stq ", ITYPE_MEM},
85 /* 0x2e */ {"stl_c ", ITYPE_MEM},
86 /* 0x2f */ {"stq_c ", ITYPE_MEM},
87 /* 0x30 */ {"br ", ITYPE_BRA},
88 /* 0x31 */ {"fbeq ", ITYPE_BRA},
89 /* 0x32 */ {"fblt ", ITYPE_BRA},
90 /* 0x33 */ {"fble ", ITYPE_BRA},
91 /* 0x34 */ {"bsr ", ITYPE_BRA},
92 /* 0x35 */ {"fbne ", ITYPE_BRA},
93 /* 0x36 */ {"fbge ", ITYPE_BRA},
94 /* 0x37 */ {"fbgt ", ITYPE_BRA},
95 /* 0x38 */ {"blbc ", ITYPE_BRA},
96 /* 0x39 */ {"beq ", ITYPE_BRA},
97 /* 0x3a */ {"blt ", ITYPE_BRA},
98 /* 0x3b */ {"ble ", ITYPE_BRA},
99 /* 0x3c */ {"blbs ", ITYPE_BRA},
100 /* 0x3d */ {"bne ", ITYPE_BRA},
101 /* 0x3e */ {"bge ", ITYPE_BRA},
102 /* 0x3f */ {"bgt ", ITYPE_BRA}
106 /* instruction decode list for 6 bit op codes and 9 bit function codes */
108 static struct { u2 op, fun; char *name; } op3s[] = {
110 { 0x10, 0x00, "addl " },
111 { 0x10, 0x40, "addl/v " },
112 { 0x10, 0x20, "addq " },
113 { 0x10, 0x60, "addq/v " },
114 { 0x10, 0x09, "subl " },
115 { 0x10, 0x49, "subl/v " },
116 { 0x10, 0x29, "subq " },
117 { 0x10, 0x69, "subq/v " },
118 { 0x10, 0x2D, "cmpeq " },
119 { 0x10, 0x4D, "cmplt " },
120 { 0x10, 0x6D, "cmple " },
121 { 0x10, 0x1D, "cmpult " },
122 { 0x10, 0x3D, "cmpule " },
123 { 0x10, 0x0F, "cmpbge " },
124 { 0x10, 0x02, "s4addl " },
125 { 0x10, 0x0b, "s4subl " },
126 { 0x10, 0x22, "s4addq " },
127 { 0x10, 0x2b, "s4subq " },
128 { 0x10, 0x12, "s8addl " },
129 { 0x10, 0x1b, "s8subl " },
130 { 0x10, 0x32, "s8addq " },
131 { 0x10, 0x3b, "s8subq " },
132 { 0x11, 0x00, "and " },
133 { 0x11, 0x20, "or " },
134 { 0x11, 0x40, "xor " },
135 { 0x11, 0x08, "andnot " },
136 { 0x11, 0x28, "ornot " },
137 { 0x11, 0x48, "xornot " },
138 { 0x11, 0x24, "cmoveq " },
139 { 0x11, 0x44, "cmovlt " },
140 { 0x11, 0x64, "cmovle " },
141 { 0x11, 0x26, "cmovne " },
142 { 0x11, 0x46, "cmovge " },
143 { 0x11, 0x66, "cmovgt " },
144 { 0x11, 0x14, "cmovlbs" },
145 { 0x11, 0x16, "cmovlbc" },
146 { 0x12, 0x39, "sll " },
147 { 0x12, 0x3C, "sra " },
148 { 0x12, 0x34, "srl " },
149 { 0x12, 0x30, "zap " },
150 { 0x12, 0x31, "zapnot " },
151 { 0x12, 0x06, "extbl " },
152 { 0x12, 0x16, "extwl " },
153 { 0x12, 0x26, "extll " },
154 { 0x12, 0x36, "extql " },
155 { 0x12, 0x5a, "extwh " },
156 { 0x12, 0x6a, "extlh " },
157 { 0x12, 0x7a, "extqh " },
158 { 0x12, 0x0b, "insbl " },
159 { 0x12, 0x1b, "inswl " },
160 { 0x12, 0x2b, "insll " },
161 { 0x12, 0x3b, "insql " },
162 { 0x12, 0x57, "inswh " },
163 { 0x12, 0x67, "inslh " },
164 { 0x12, 0x77, "insqh " },
165 { 0x12, 0x02, "mskbl " },
166 { 0x12, 0x12, "mskwl " },
167 { 0x12, 0x22, "mskll " },
168 { 0x12, 0x32, "mskql " },
169 { 0x12, 0x52, "mskwh " },
170 { 0x12, 0x62, "msklh " },
171 { 0x12, 0x72, "mskqh " },
172 { 0x13, 0x00, "mull " },
173 { 0x13, 0x20, "mulq " },
174 { 0x13, 0x40, "mull/v " },
175 { 0x13, 0x60, "mulq/v " },
176 { 0x13, 0x30, "umulh " },
177 { 0x16, 0x080, "fadd " },
178 { 0x16, 0x0a0, "dadd " },
179 { 0x16, 0x081, "fsub " },
180 { 0x16, 0x0a1, "dsub " },
181 { 0x16, 0x082, "fmul " },
182 { 0x16, 0x0a2, "dmul " },
183 { 0x16, 0x083, "fdiv " },
184 { 0x16, 0x0a3, "ddiv " },
185 { 0x16, 0x580, "fadds " },
186 { 0x16, 0x5a0, "dadds " },
187 { 0x16, 0x581, "fsubs " },
188 { 0x16, 0x5a1, "dsubs " },
189 { 0x16, 0x582, "fmuls " },
190 { 0x16, 0x5a2, "dmuls " },
191 { 0x16, 0x583, "fdivs " },
192 { 0x16, 0x5a3, "ddivs " },
193 { 0x16, 0x0ac, "cvtdf " },
194 { 0x16, 0x0bc, "cvtlf " },
195 { 0x16, 0x0be, "cvtld " },
196 { 0x16, 0x0af, "cvtdl " },
197 { 0x16, 0x02f, "cvtdlc " },
198 { 0x17, 0x030, "cvtli " },
199 { 0x16, 0x1af, "cvtdlv " },
200 { 0x16, 0x12f, "cvtdlcv" },
201 { 0x17, 0x130, "cvtliv " },
202 { 0x16, 0x5ac, "cvtdfs " },
203 { 0x16, 0x5af, "cvtdls " },
204 { 0x16, 0x52f, "cvtdlcs" },
205 { 0x16, 0x0a4, "fcmpun " },
206 { 0x16, 0x0a5, "fcmpeq " },
207 { 0x16, 0x0a6, "fcmplt " },
208 { 0x16, 0x0a7, "fcmple " },
209 { 0x16, 0x5a4, "fcmpuns" },
210 { 0x16, 0x5a5, "fcmpeqs" },
211 { 0x16, 0x5a6, "fcmplts" },
212 { 0x16, 0x5a7, "fcmples" },
213 { 0x17, 0x020, "fmov " },
214 { 0x17, 0x021, "fmovn " },
215 { 0x1c, 0x0, "bsext " },
216 { 0x1c, 0x1, "wsext " },
222 /* name table for 32 integer registers */
224 static char *regs[] = {
226 /* 0x00 */ "v0", /* "$0", */
227 /* 0x01 */ "t0", /* "$1", */
228 /* 0x02 */ "t1", /* "$2", */
229 /* 0x03 */ "t2", /* "$3", */
230 /* 0x04 */ "t3", /* "$4", */
231 /* 0x05 */ "t4", /* "$5", */
232 /* 0x06 */ "t5", /* "$6", */
233 /* 0x07 */ "t6", /* "$7", */
235 /* 0x08 */ "t7", /* "$8", */
236 /* 0x09 */ "s0", /* "$9", */
237 /* 0x0a */ "s1", /* "$10", */
238 /* 0x0b */ "s2", /* "$11", */
239 /* 0x0c */ "s3", /* "$12", */
240 /* 0x0d */ "s4", /* "$13", */
241 /* 0x0e */ "s5", /* "$14", */
242 /* 0x0f */ "s6", /* "$15", */
244 /* 0x10 */ "a0", /* "$16", */
245 /* 0x11 */ "a1", /* "$17", */
246 /* 0x12 */ "a2", /* "$18", */
247 /* 0x13 */ "a3", /* "$19", */
248 /* 0x14 */ "a4", /* "$20", */
249 /* 0x15 */ "a5", /* "$21", */
250 /* 0x16 */ "t8", /* "$22", */
251 /* 0x17 */ "t9", /* "$23", */
253 /* 0x18 */ "t10", /* "$24", */
254 /* 0x19 */ "t11", /* "$25", */
255 /* 0x1a */ "ra", /* "$26", */
256 /* 0x1b */ "pv", /* "$27", */
257 /* 0x1c */ "at", /* "$28", */
258 /* 0x1d */ "gp", /* "$29", */
259 /* 0x1e */ "sp", /* "$30", */
260 /* 0x1f */ "zero" /* "$31" */
264 /* function disassinstr ********************************************************
266 outputs a disassembler listing of one machine code instruction on 'stdout'
267 c: instructions machine code
268 pos: instructions address relative to method start
270 *******************************************************************************/
272 static void disassinstr(int c, int pos)
274 int op; /* 6 bit op code */
275 int opfun; /* 7 bit function code */
276 int ra, rb, rc; /* 6 bit register specifiers */
277 int lit; /* 8 bit unsigned literal */
278 int i; /* loop counter */
280 op = (c >> 26) & 0x3f; /* 6 bit op code */
281 opfun = (c >> 5) & 0x7f; /* 7 bit function code */
282 ra = (c >> 21) & 0x1f; /* 6 bit source register specifier */
283 rb = (c >> 16) & 0x1f; /* 6 bit source register specifier */
284 rc = (c >> 0) & 0x1f; /* 6 bit destination register specifiers */
285 lit = (c >> 13) & 0xff; /* 8 bit unsigned literal */
287 printf ("%6x: %8x ", pos, c);
289 switch (ops[op].itype) {
291 switch ((c >> 14) & 3) { /* branch hint */
294 printf ("jmp (%s)\n", regs[rb]);
301 printf ("jsr (%s)\n", regs[rb]);
307 if (ra == 31 && rb == 26) {
312 printf ("ret (%s)\n", regs[rb]);
321 printf ("%s,(%s)\n", regs[ra], regs[rb]);
325 int disp = (c << 16) >> 16; /* 16 bit signed displacement */
327 if (op == 0x18 && ra == 0 && ra == 0 && disp == 0)
330 printf ("%s %s,%d(%s)\n", ops[op].name, regs[ra], disp, regs[rb]);
335 printf ("%s $f%d,%d(%s)\n", ops[op].name, ra, (c << 16) >> 16, regs[rb]);
339 case ITYPE_BRA: /* 21 bit signed branch offset */
340 if (op == 0x30 && ra == 31)
341 printf("br 0x%x\n", pos + 4 + ((c << 11) >> 9));
342 else if (op == 0x34 && ra == 26)
343 printf("brs 0x%x\n", pos + 4 + ((c << 11) >> 9));
345 printf("%s %s,0x%x\n",
346 ops[op].name, regs[ra], pos + 4 + ((c << 11) >> 9));
350 int fopfun = (c >> 5) & 0x7ff; /* 11 bit fp function code */
352 if (op == 0x17 && fopfun == 0x020 && ra == rb) {
353 if (ra == 31 && rc == 31)
356 printf("fmov $f%d,$f%d\n", ra, rc);
359 for (i = 0; op3s[i].name; i++)
360 if (op3s[i].op == op && op3s[i].fun == fopfun) {
361 printf("%s $f%d,$f%d,$f%d\n", op3s[i].name, ra, rb, rc);
364 printf("%s%x $f%d,$f%d,$f%d\n", ops[op].name, fopfun, ra, rb, rc);
369 if (op == 0x11 && opfun == 0x20 && ra == rb && ~(c&0x1000)) {
370 if (ra == 31 && rc == 31)
373 printf("clr %s\n", regs[rc]);
375 printf("mov %s,%s\n", regs[ra], regs[rc]);
378 for (i = 0; op3s[i].name; i++) {
379 if (op3s[i].op == op && op3s[i].fun == opfun) {
380 if (c & 0x1000) /* immediate instruction */
381 printf("%s %s,%d,%s\n",
382 op3s[i].name, regs[ra], lit, regs[rc]);
384 printf("%s %s,%s,%s\n",
385 op3s[i].name, regs[ra], regs[rb], regs[rc]);
391 if (c & 0x1000) /* immediate instruction */
392 printf("UNDEF %x(%x) $%d,%d,$%d\n", op, opfun, ra, lit, rc);
394 printf("UNDEF %x(%x) $%d,$%d,$%d\n", op, opfun, ra, rb, rc);
399 /* function disassemble ********************************************************
401 outputs a disassembler listing of some machine code on 'stdout'
402 code: pointer to first instruction
403 len: code size (number of instructions * 4)
405 *******************************************************************************/
407 static void disassemble(int *code, int len)
411 printf (" --- disassembler listing ---\n");
412 for (p = 0; p < len; p += 4, code++)
413 disassinstr(*code, p);
418 * These are local overrides for various environment variables in Emacs.
419 * Please do not remove this and leave it at the end of the file, where
420 * Emacs will automagically detect them.
421 * ---------------------------------------------------------------------
424 * indent-tabs-mode: t