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/06
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_BRA 3 /* branch instructions */
30 #define ITYPE_OP 4 /* integer instructions */
31 #define ITYPE_FOP 5 /* floating point instructions */
34 /* instruction decode table for 6 bit op codes */
36 static struct {char *name; int itype;} ops[] = {
38 /* 0x00 */ {"", ITYPE_UNDEF},
39 /* 0x01 */ {"", ITYPE_UNDEF},
40 /* 0x02 */ {"", ITYPE_UNDEF},
41 /* 0x03 */ {"", ITYPE_UNDEF},
42 /* 0x04 */ {"", ITYPE_UNDEF},
43 /* 0x05 */ {"", ITYPE_UNDEF},
44 /* 0x06 */ {"", ITYPE_UNDEF},
45 /* 0x07 */ {"", ITYPE_UNDEF},
46 /* 0x08 */ {"LDA ", ITYPE_MEM},
47 /* 0x09 */ {"LDAH ", ITYPE_MEM},
48 /* 0x0a */ {"LDB ", ITYPE_MEM},
49 /* 0x0b */ {"LDQ_U ", ITYPE_MEM},
50 /* 0x0c */ {"LDW ", ITYPE_MEM},
51 /* 0x0d */ {"STW ", ITYPE_MEM},
52 /* 0x0e */ {"STB ", ITYPE_MEM},
53 /* 0x0f */ {"STQ_U ", ITYPE_MEM},
54 /* 0x10 */ {"OP ", ITYPE_OP},
55 /* 0x11 */ {"OP ", ITYPE_OP},
56 /* 0x12 */ {"OP ", ITYPE_OP},
57 /* 0x13 */ {"OP ", ITYPE_OP},
58 /* 0x14 */ {"", ITYPE_UNDEF},
59 /* 0x15 */ {"", ITYPE_UNDEF},
60 /* 0x16 */ {"FOP ", ITYPE_FOP},
61 /* 0x17 */ {"FOP ", ITYPE_FOP},
62 /* 0x18 */ {"MEMFMT ", ITYPE_MEM},
63 /* 0x19 */ {"", ITYPE_UNDEF},
64 /* 0x1a */ {"JMP ", ITYPE_JMP},
65 /* 0x1b */ {"", ITYPE_UNDEF},
66 /* 0x1c */ {"OP ", ITYPE_OP},
67 /* 0x1d */ {"", ITYPE_UNDEF},
68 /* 0x1e */ {"", ITYPE_UNDEF},
69 /* 0x1f */ {"", ITYPE_UNDEF},
70 /* 0x20 */ {"LDF ", ITYPE_MEM},
71 /* 0x21 */ {"LDG ", ITYPE_MEM},
72 /* 0x22 */ {"LDS ", ITYPE_MEM},
73 /* 0x23 */ {"LDT ", ITYPE_MEM},
74 /* 0x24 */ {"STF ", ITYPE_MEM},
75 /* 0x25 */ {"STG ", ITYPE_MEM},
76 /* 0x26 */ {"STS ", ITYPE_MEM},
77 /* 0x27 */ {"STT ", ITYPE_MEM},
78 /* 0x28 */ {"LDL ", ITYPE_MEM},
79 /* 0x29 */ {"LDQ ", ITYPE_MEM},
80 /* 0x2a */ {"LDL_L ", ITYPE_MEM},
81 /* 0x2b */ {"LDQ_L ", ITYPE_MEM},
82 /* 0x2c */ {"STL ", ITYPE_MEM},
83 /* 0x2d */ {"STQ ", ITYPE_MEM},
84 /* 0x2e */ {"STL_C ", ITYPE_MEM},
85 /* 0x2f */ {"STQ_C ", ITYPE_MEM},
86 /* 0x30 */ {"BR ", ITYPE_BRA},
87 /* 0x31 */ {"FBEQ ", ITYPE_BRA},
88 /* 0x32 */ {"FBLT ", ITYPE_BRA},
89 /* 0x33 */ {"FBLE ", ITYPE_BRA},
90 /* 0x34 */ {"BSR ", ITYPE_BRA},
91 /* 0x35 */ {"FBNE ", ITYPE_BRA},
92 /* 0x36 */ {"FBGE ", ITYPE_BRA},
93 /* 0x37 */ {"FBGT ", ITYPE_BRA},
94 /* 0x38 */ {"BLBC ", ITYPE_BRA},
95 /* 0x39 */ {"BEQ ", ITYPE_BRA},
96 /* 0x3a */ {"BLT ", ITYPE_BRA},
97 /* 0x3b */ {"BLE ", ITYPE_BRA},
98 /* 0x3c */ {"BLBS ", ITYPE_BRA},
99 /* 0x3d */ {"BNE ", ITYPE_BRA},
100 /* 0x3e */ {"BGE ", ITYPE_BRA},
101 /* 0x3f */ {"BGT ", ITYPE_BRA}
105 /* instruction decode list for 6 bit op codes and 9 bit function codes */
107 static struct { u2 op, fun; char *name; } op3s[] = {
109 { 0x10, 0x00, "ADDL " },
110 { 0x10, 0x40, "ADDL/V " },
111 { 0x10, 0x20, "ADDQ " },
112 { 0x10, 0x60, "ADDQ/V " },
113 { 0x10, 0x09, "SUBL " },
114 { 0x10, 0x49, "SUBL/V " },
115 { 0x10, 0x29, "SUBQ " },
116 { 0x10, 0x69, "SUBQ/V " },
117 { 0x10, 0x2D, "CMPEQ " },
118 { 0x10, 0x4D, "CMPLT " },
119 { 0x10, 0x6D, "CMPLE " },
120 { 0x10, 0x1D, "CMPULT " },
121 { 0x10, 0x3D, "CMPULE " },
122 { 0x10, 0x0F, "CMPBGE " },
123 { 0x10, 0x02, "S4ADDL " },
124 { 0x10, 0x0b, "S4SUBL " },
125 { 0x10, 0x22, "S4ADDQ " },
126 { 0x10, 0x2b, "S4SUBQ " },
127 { 0x10, 0x12, "S8ADDL " },
128 { 0x10, 0x1b, "S8SUBL " },
129 { 0x10, 0x32, "S8ADDQ " },
130 { 0x10, 0x3b, "S8SUBQ " },
131 { 0x11, 0x00, "AND " },
132 { 0x11, 0x20, "OR " },
133 { 0x11, 0x40, "XOR " },
134 { 0x11, 0x08, "ANDNOT " },
135 { 0x11, 0x28, "ORNOT " },
136 { 0x11, 0x48, "XORNOT " },
137 { 0x11, 0x24, "CMOVEQ " },
138 { 0x11, 0x44, "CMOVLT " },
139 { 0x11, 0x64, "CMOVLE " },
140 { 0x11, 0x26, "CMOVNE " },
141 { 0x11, 0x46, "CMOVGE " },
142 { 0x11, 0x66, "CMOVGT " },
143 { 0x11, 0x14, "CMOVLBS" },
144 { 0x11, 0x16, "CMOVLBC" },
145 { 0x12, 0x39, "SLL " },
146 { 0x12, 0x3C, "SRA " },
147 { 0x12, 0x34, "SRL " },
148 { 0x12, 0x30, "ZAP " },
149 { 0x12, 0x31, "ZAPNOT " },
150 { 0x12, 0x06, "EXTBL " },
151 { 0x12, 0x16, "EXTWL " },
152 { 0x12, 0x26, "EXTLL " },
153 { 0x12, 0x36, "EXTQL " },
154 { 0x12, 0x5a, "EXTWH " },
155 { 0x12, 0x6a, "EXTLH " },
156 { 0x12, 0x7a, "EXTQH " },
157 { 0x12, 0x0b, "INSBL " },
158 { 0x12, 0x1b, "INSWL " },
159 { 0x12, 0x2b, "INSLL " },
160 { 0x12, 0x3b, "INSQL " },
161 { 0x12, 0x57, "INSWH " },
162 { 0x12, 0x67, "INSLH " },
163 { 0x12, 0x77, "INSQH " },
164 { 0x12, 0x02, "MSKBL " },
165 { 0x12, 0x12, "MSKWL " },
166 { 0x12, 0x22, "MSKLL " },
167 { 0x12, 0x32, "MSKQL " },
168 { 0x12, 0x52, "MSKWH " },
169 { 0x12, 0x62, "MSKLH " },
170 { 0x12, 0x72, "MSKQH " },
171 { 0x13, 0x00, "MULL " },
172 { 0x13, 0x20, "MULQ " },
173 { 0x13, 0x40, "MULL/V " },
174 { 0x13, 0x60, "MULQ/V " },
175 { 0x13, 0x30, "UMULH " },
176 { 0x16, 0x080, "FADD " },
177 { 0x16, 0x0a0, "DADD " },
178 { 0x16, 0x081, "FSUB " },
179 { 0x16, 0x0a1, "DSUB " },
180 { 0x16, 0x082, "FMUL " },
181 { 0x16, 0x0a2, "DMUL " },
182 { 0x16, 0x083, "FDIV " },
183 { 0x16, 0x0a3, "DDIV " },
184 { 0x16, 0x580, "FADDS " },
185 { 0x16, 0x5a0, "DADDS " },
186 { 0x16, 0x581, "FSUBS " },
187 { 0x16, 0x5a1, "DSUBS " },
188 { 0x16, 0x582, "FMULS " },
189 { 0x16, 0x5a2, "DMULS " },
190 { 0x16, 0x583, "FDIVS " },
191 { 0x16, 0x5a3, "DDIVS " },
192 { 0x16, 0x0ac, "CVTDF " },
193 { 0x16, 0x0bc, "CVTLF " },
194 { 0x16, 0x0be, "CVTLD " },
195 { 0x16, 0x0af, "CVTDL " },
196 { 0x16, 0x02f, "CVTDLC " },
197 { 0x16, 0x5ac, "CVTDFS " },
198 { 0x16, 0x5af, "CVTDLS " },
199 { 0x16, 0x52f, "CVTDLCS" },
200 { 0x16, 0x0a4, "FCMPUN " },
201 { 0x16, 0x0a5, "FCMPEQ " },
202 { 0x16, 0x0a6, "FCMPLT " },
203 { 0x16, 0x0a7, "FCMPLE " },
204 { 0x16, 0x5a4, "FCMPUNS" },
205 { 0x16, 0x5a5, "FCMPEQS" },
206 { 0x16, 0x5a6, "FCMPLTS" },
207 { 0x16, 0x5a7, "FCMPLES" },
208 { 0x17, 0x020, "FMOV " },
209 { 0x17, 0x021, "FMOVN " },
210 { 0x1c, 0x0, "BSEXT " },
211 { 0x1c, 0x1, "WSEXT " },
217 /* function disassemble ********************************************************
219 outputs a disassembler listing of one machine code instruction on 'stdout'
220 c: instructions machine code
221 pos: instructions address relative to method start
223 *******************************************************************************/
225 static void disasscmd (int c, int pos)
227 int op; /* 6 bit op code */
228 int opfun; /* 7 bit function code */
229 int ra, rb, rc; /* 6 bit register specifiers */
230 int lit; /* 8 bit unsigned literal */
231 int i; /* loop counter */
233 op = (c >> 26) & 0x3f; /* 6 bit op code */
234 opfun = (c >> 5) & 0x7f; /* 7 bit function code */
235 ra = (c >> 21) & 0x1f; /* 6 bit source register specifier */
236 rb = (c >> 16) & 0x1f; /* 6 bit source register specifier */
237 rc = (c >> 0) & 0x1f; /* 6 bit destination register specifiers */
238 lit = (c >> 13) & 0xff; /* 8 bit unsigned literal */
240 printf ("%6x: %8x ", pos, c);
242 switch (ops[op].itype) {
244 switch ((c >> 14) & 3) { /* branch hint */
258 printf ("$%d,$%d\n", ra, rb);
262 int disp = (c << 16) >> 16; /* 16 bit signed displacement */
264 if (op == 0x18 && ra == 0 && ra == 0 && disp == 0)
267 printf ("%s $%d,$%d,%d\n", ops[op].name, ra, rb, disp);
271 case ITYPE_BRA: /* 21 bit signed branch offset */
272 printf("%s $%d,%x\n", ops[op].name, ra, pos + 4 + ((c << 11) >> 9));
276 int fopfun = (c >> 5) & 0x7ff; /* 11 bit fp function code */
278 if (op == 0x17 && fopfun == 0x020 && ra == rb) {
279 if (ra == 31 && rc == 31)
282 printf("FMOV $f%d,$f%d\n", ra, rc);
285 for (i = 0; op3s[i].name; i++)
286 if (op3s[i].op == op && op3s[i].fun == fopfun) {
287 printf("%s $f%d,$f%d,$f%d\n", op3s[i].name, ra, rb, rc);
290 printf("%s%x $f%d,$f%d,$f%d\n", ops[op].name, fopfun, ra, rb, rc);
295 if (op == 0x11 && opfun == 0x20 && ra == rb && ~(c&0x1000)) {
296 if (ra == 31 && rc == 31)
299 printf("CLR $%d\n", rc);
301 printf("MOV $%d,$%d\n", ra, rc);
304 for (i = 0; op3s[i].name; i++) {
305 if (op3s[i].op == op && op3s[i].fun == opfun) {
306 if (c & 0x1000) /* immediate instruction */
307 printf("%s $%d,#%d,$%d\n", op3s[i].name, ra, lit, rc);
309 printf("%s $%d,$%d,$%d\n", op3s[i].name, ra, rb, rc);
315 if (c & 0x1000) /* immediate instruction */
316 printf("UNDEF %x(%x) $%d,#%d,$%d\n", op, opfun, ra, lit, rc);
318 printf("UNDEF %x(%x) $%d,$%d,$%d\n", op, opfun, ra, rb, rc);
323 /* function disassemble ********************************************************
325 outputs a disassembler listing of some machine code on 'stdout'
326 code: pointer to first instruction
327 len: code size (number of instructions * 4)
329 *******************************************************************************/
331 static void disassemble (int *code, int len)
335 printf (" --- disassembler listing ---\n");
336 for (p = 0; p < len; p += 4, code++)
337 disasscmd (*code, p);
342 * These are local overrides for various environment variables in Emacs.
343 * Please do not remove this and leave it at the end of the file, where
344 * Emacs will automagically detect them.
345 * ---------------------------------------------------------------------
348 * indent-tabs-mode: t