CACAO
disass.cpp
Go to the documentation of this file.
1 /* src/vm/jit/alpha/disass.cpp - primitive disassembler for Alpha machine code
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
25 
26 #include "config.h"
27 
28 #include <cstdio>
29 
30 #include "vm/types.hpp"
31 
32 #include "vm/global.hpp"
33 
34 #include "vm/jit/abi.hpp"
35 #include "vm/jit/disass.hpp"
36 
37 
38 /* The disassembler uses two tables for decoding the instructions. The first
39  table (ops) is used to classify the instructions based on the op code and
40  contains the instruction names for instructions which don't used the
41  function codes. This table is indexed by the op code (6 bit, 64 entries).
42  The second table (op3s) contains instructions which contain both an op
43  code and a function code. This table is an unsorted list of instructions
44  which is terminated by op code and function code zero. This list is
45  searched linearly for a matching pair of opcode and function code.
46 */
47 
48 #define ITYPE_UNDEF 0 /* undefined instructions (illegal opcode) */
49 #define ITYPE_JMP 1 /* jump instructions */
50 #define ITYPE_MEM 2 /* memory instructions */
51 #define ITYPE_FMEM 3 /* floating point memory instructions */
52 #define ITYPE_BRA 4 /* branch instructions */
53 #define ITYPE_OP 5 /* integer instructions */
54 #define ITYPE_FOP 6 /* floating point instructions */
55 
56 
57 /* instruction decode table for 6 bit op codes */
58 
59 static struct {char *name; int itype;} ops[] = {
60  /* 0x00 */ {"", ITYPE_UNDEF},
61  /* 0x01 */ {"", ITYPE_UNDEF},
62  /* 0x02 */ {"", ITYPE_UNDEF},
63  /* 0x03 */ {"", ITYPE_UNDEF},
64  /* 0x04 */ {"", ITYPE_UNDEF},
65  /* 0x05 */ {"", ITYPE_UNDEF},
66  /* 0x06 */ {"", ITYPE_UNDEF},
67  /* 0x07 */ {"", ITYPE_UNDEF},
68  /* 0x08 */ {"lda ", ITYPE_MEM},
69  /* 0x09 */ {"ldah ", ITYPE_MEM},
70  /* 0x0a */ {"ldb ", ITYPE_MEM},
71  /* 0x0b */ {"ldq_u ", ITYPE_MEM},
72  /* 0x0c */ {"ldw ", ITYPE_MEM},
73  /* 0x0d */ {"stw ", ITYPE_MEM},
74  /* 0x0e */ {"stb ", ITYPE_MEM},
75  /* 0x0f */ {"stq_u ", ITYPE_MEM},
76  /* 0x10 */ {"op ", ITYPE_OP},
77  /* 0x11 */ {"op ", ITYPE_OP},
78  /* 0x12 */ {"op ", ITYPE_OP},
79  /* 0x13 */ {"op ", ITYPE_OP},
80  /* 0x14 */ {"", ITYPE_UNDEF},
81  /* 0x15 */ {"", ITYPE_UNDEF},
82  /* 0x16 */ {"fop ", ITYPE_FOP},
83  /* 0x17 */ {"fop ", ITYPE_FOP},
84  /* 0x18 */ {"memfmt ", ITYPE_MEM},
85  /* 0x19 */ {"", ITYPE_UNDEF},
86  /* 0x1a */ {"jmp ", ITYPE_JMP},
87  /* 0x1b */ {"", ITYPE_UNDEF},
88  /* 0x1c */ {"op ", ITYPE_OP},
89  /* 0x1d */ {"", ITYPE_UNDEF},
90  /* 0x1e */ {"", ITYPE_UNDEF},
91  /* 0x1f */ {"", ITYPE_UNDEF},
92  /* 0x20 */ {"ldf ", ITYPE_FMEM},
93  /* 0x21 */ {"ldg ", ITYPE_FMEM},
94  /* 0x22 */ {"lds ", ITYPE_FMEM},
95  /* 0x23 */ {"ldt ", ITYPE_FMEM},
96  /* 0x24 */ {"stf ", ITYPE_FMEM},
97  /* 0x25 */ {"stg ", ITYPE_FMEM},
98  /* 0x26 */ {"sts ", ITYPE_FMEM},
99  /* 0x27 */ {"stt ", ITYPE_FMEM},
100  /* 0x28 */ {"ldl ", ITYPE_MEM},
101  /* 0x29 */ {"ldq ", ITYPE_MEM},
102  /* 0x2a */ {"ldl_l ", ITYPE_MEM},
103  /* 0x2b */ {"ldq_l ", ITYPE_MEM},
104  /* 0x2c */ {"stl ", ITYPE_MEM},
105  /* 0x2d */ {"stq ", ITYPE_MEM},
106  /* 0x2e */ {"stl_c ", ITYPE_MEM},
107  /* 0x2f */ {"stq_c ", ITYPE_MEM},
108  /* 0x30 */ {"br ", ITYPE_BRA},
109  /* 0x31 */ {"fbeq ", ITYPE_BRA},
110  /* 0x32 */ {"fblt ", ITYPE_BRA},
111  /* 0x33 */ {"fble ", ITYPE_BRA},
112  /* 0x34 */ {"bsr ", ITYPE_BRA},
113  /* 0x35 */ {"fbne ", ITYPE_BRA},
114  /* 0x36 */ {"fbge ", ITYPE_BRA},
115  /* 0x37 */ {"fbgt ", ITYPE_BRA},
116  /* 0x38 */ {"blbc ", ITYPE_BRA},
117  /* 0x39 */ {"beq ", ITYPE_BRA},
118  /* 0x3a */ {"blt ", ITYPE_BRA},
119  /* 0x3b */ {"ble ", ITYPE_BRA},
120  /* 0x3c */ {"blbs ", ITYPE_BRA},
121  /* 0x3d */ {"bne ", ITYPE_BRA},
122  /* 0x3e */ {"bge ", ITYPE_BRA},
123  /* 0x3f */ {"bgt ", ITYPE_BRA}
124 };
125 
126 
127 /* instruction decode list for 6 bit op codes and 9 bit function codes */
128 
129 static struct { u2 op, fun; char *name; } op3s[] = {
130  { 0x10, 0x00, "addl " },
131  { 0x10, 0x40, "addl/v " },
132  { 0x10, 0x20, "addq " },
133  { 0x10, 0x60, "addq/v " },
134  { 0x10, 0x09, "subl " },
135  { 0x10, 0x49, "subl/v " },
136  { 0x10, 0x29, "subq " },
137  { 0x10, 0x69, "subq/v " },
138  { 0x10, 0x2D, "cmpeq " },
139  { 0x10, 0x4D, "cmplt " },
140  { 0x10, 0x6D, "cmple " },
141  { 0x10, 0x1D, "cmpult " },
142  { 0x10, 0x3D, "cmpule " },
143  { 0x10, 0x0F, "cmpbge " },
144  { 0x10, 0x02, "s4addl " },
145  { 0x10, 0x0b, "s4subl " },
146  { 0x10, 0x22, "s4addq " },
147  { 0x10, 0x2b, "s4subq " },
148  { 0x10, 0x12, "s8addl " },
149  { 0x10, 0x1b, "s8subl " },
150  { 0x10, 0x32, "s8addq " },
151  { 0x10, 0x3b, "s8subq " },
152  { 0x11, 0x00, "and " },
153  { 0x11, 0x20, "or " },
154  { 0x11, 0x40, "xor " },
155  { 0x11, 0x08, "andnot " },
156  { 0x11, 0x28, "ornot " },
157  { 0x11, 0x48, "xornot " },
158  { 0x11, 0x24, "cmoveq " },
159  { 0x11, 0x44, "cmovlt " },
160  { 0x11, 0x64, "cmovle " },
161  { 0x11, 0x26, "cmovne " },
162  { 0x11, 0x46, "cmovge " },
163  { 0x11, 0x66, "cmovgt " },
164  { 0x11, 0x14, "cmovlbs" },
165  { 0x11, 0x16, "cmovlbc" },
166  { 0x12, 0x39, "sll " },
167  { 0x12, 0x3C, "sra " },
168  { 0x12, 0x34, "srl " },
169  { 0x12, 0x30, "zap " },
170  { 0x12, 0x31, "zapnot " },
171  { 0x12, 0x06, "extbl " },
172  { 0x12, 0x16, "extwl " },
173  { 0x12, 0x26, "extll " },
174  { 0x12, 0x36, "extql " },
175  { 0x12, 0x5a, "extwh " },
176  { 0x12, 0x6a, "extlh " },
177  { 0x12, 0x7a, "extqh " },
178  { 0x12, 0x0b, "insbl " },
179  { 0x12, 0x1b, "inswl " },
180  { 0x12, 0x2b, "insll " },
181  { 0x12, 0x3b, "insql " },
182  { 0x12, 0x57, "inswh " },
183  { 0x12, 0x67, "inslh " },
184  { 0x12, 0x77, "insqh " },
185  { 0x12, 0x02, "mskbl " },
186  { 0x12, 0x12, "mskwl " },
187  { 0x12, 0x22, "mskll " },
188  { 0x12, 0x32, "mskql " },
189  { 0x12, 0x52, "mskwh " },
190  { 0x12, 0x62, "msklh " },
191  { 0x12, 0x72, "mskqh " },
192  { 0x13, 0x00, "mull " },
193  { 0x13, 0x20, "mulq " },
194  { 0x13, 0x40, "mull/v " },
195  { 0x13, 0x60, "mulq/v " },
196  { 0x13, 0x30, "umulh " },
197  { 0x16, 0x080, "fadd " },
198  { 0x16, 0x0a0, "dadd " },
199  { 0x16, 0x081, "fsub " },
200  { 0x16, 0x0a1, "dsub " },
201  { 0x16, 0x082, "fmul " },
202  { 0x16, 0x0a2, "dmul " },
203  { 0x16, 0x083, "fdiv " },
204  { 0x16, 0x0a3, "ddiv " },
205  { 0x16, 0x580, "fadds " },
206  { 0x16, 0x5a0, "dadds " },
207  { 0x16, 0x581, "fsubs " },
208  { 0x16, 0x5a1, "dsubs " },
209  { 0x16, 0x582, "fmuls " },
210  { 0x16, 0x5a2, "dmuls " },
211  { 0x16, 0x583, "fdivs " },
212  { 0x16, 0x5a3, "ddivs " },
213  { 0x16, 0x0ac, "cvtdf " },
214  { 0x16, 0x0bc, "cvtlf " },
215  { 0x16, 0x0be, "cvtld " },
216  { 0x16, 0x0af, "cvtdl " },
217  { 0x16, 0x02f, "cvtdlc " },
218  { 0x17, 0x030, "cvtli " },
219  { 0x16, 0x1af, "cvtdlv " },
220  { 0x16, 0x12f, "cvtdlcv" },
221  { 0x17, 0x130, "cvtliv " },
222  { 0x16, 0x5ac, "cvtdfs " },
223  { 0x16, 0x5af, "cvtdls " },
224  { 0x16, 0x52f, "cvtdlcs" },
225  { 0x16, 0x0a4, "fcmpun " },
226  { 0x16, 0x0a5, "fcmpeq " },
227  { 0x16, 0x0a6, "fcmplt " },
228  { 0x16, 0x0a7, "fcmple " },
229  { 0x16, 0x5a4, "fcmpuns" },
230  { 0x16, 0x5a5, "fcmpeqs" },
231  { 0x16, 0x5a6, "fcmplts" },
232  { 0x16, 0x5a7, "fcmples" },
233  { 0x17, 0x020, "fmov " },
234  { 0x17, 0x021, "fmovn " },
235  { 0x1c, 0x0, "bsext " },
236  { 0x1c, 0x1, "wsext " },
237 
238  { 0x00, 0x00, NULL }
239 };
240 
241 
242 /* disassinstr *****************************************************************
243 
244  Outputs a disassembler listing of one machine code instruction on
245  'stdout'.
246 
247  code: pointer to instructions machine code
248 
249 *******************************************************************************/
250 
252 {
253  s4 op; /* 6 bit op code */
254  s4 opfun; /* 7 bit function code */
255  s4 ra, rb, rc; /* 6 bit register specifiers */
256  s4 lit; /* 8 bit unsigned literal */
257  s4 i; /* loop counter */
258  s4 c;
259 
260  c = *((s4 *) code);
261 
262  op = (c >> 26) & 0x3f; /* 6 bit op code */
263  opfun = (c >> 5) & 0x7f; /* 7 bit function code */
264  ra = (c >> 21) & 0x1f; /* 6 bit source register specifier */
265  rb = (c >> 16) & 0x1f; /* 6 bit source register specifier */
266  rc = (c >> 0) & 0x1f; /* 6 bit destination register specifiers */
267  lit = (c >> 13) & 0xff; /* 8 bit unsigned literal */
268 
269  printf("0x%016lx: %08x ", (u8) code, c);
270 
271  switch (ops[op].itype) {
272  case ITYPE_JMP:
273  switch ((c >> 14) & 3) { /* branch hint */
274  case 0:
275  if (ra == 31) {
276  printf("jmp (%s)\n", abi_registers_integer_name[rb]);
277  goto _return;
278  }
279  printf("jmp ");
280  break;
281  case 1:
282  if (ra == 26) {
283  printf("jsr (%s)\n", abi_registers_integer_name[rb]);
284  goto _return;
285  }
286  printf("jsr ");
287  break;
288  case 2:
289  if (ra == 31 && rb == 26) {
290  printf("ret\n");
291  goto _return;
292  }
293  if (ra == 31) {
294  printf("ret (%s)\n", abi_registers_integer_name[rb]);
295  goto _return;
296  }
297  printf("ret ");
298  break;
299  case 3:
300  printf("jsr_co ");
301  break;
302  }
303  printf("%s,(%s)\n", abi_registers_integer_name[ra],
305  break;
306 
307  case ITYPE_MEM: {
308  s4 disp = (c << 16) >> 16; /* 16 bit signed displacement */
309 
310  if (op == 0x18 && ra == 0 && ra == 0 && disp == 0)
311  printf("trapb\n");
312  else
313  printf("%s %s,%d(%s)\n", ops[op].name,
314  abi_registers_integer_name[ra], disp,
316  break;
317  }
318 
319  case ITYPE_FMEM:
320  printf("%s $f%d,%d(%s)\n", ops[op].name, ra, (c << 16) >> 16,
322  break;
323 
324  case ITYPE_BRA: /* 21 bit signed branch offset */
325  if (op == 0x30 && ra == 31)
326  printf("br 0x%016lx\n", (u8) code + 4 + ((c << 11) >> 9));
327  else if (op == 0x34 && ra == 26)
328  printf("brs 0x%016lx\n", (u8) code + 4 + ((c << 11) >> 9));
329  else
330  printf("%s %s,0x%016lx\n", ops[op].name,
332  (u8) code + 4 + ((c << 11) >> 9));
333  break;
334 
335  case ITYPE_FOP: {
336  s4 fopfun = (c >> 5) & 0x7ff; /* 11 bit fp function code */
337 
338  if (op == 0x17 && fopfun == 0x020 && ra == rb) {
339  if (ra == 31 && rc == 31)
340  printf("fnop\n");
341  else
342  printf("fmov $f%d,$f%d\n", ra, rc);
343  goto _return;
344  }
345  for (i = 0; op3s[i].name; i++)
346  if (op3s[i].op == op && op3s[i].fun == fopfun) {
347  printf("%s $f%d,$f%d,$f%d\n", op3s[i].name, ra, rb, rc);
348  goto _return;
349  }
350  printf("%s%x $f%d,$f%d,$f%d\n", ops[op].name, fopfun, ra, rb, rc);
351  break;
352  }
353 
354  case ITYPE_OP:
355  if (op == 0x11 && opfun == 0x20 && ra == rb && ~(c&0x1000)) {
356  if (ra == 31 && rc == 31)
357  printf("nop\n");
358  else if (ra == 31)
359  printf("clr %s\n", abi_registers_integer_name[rc]);
360  else
361  printf("mov %s,%s\n", abi_registers_integer_name[ra],
363  goto _return;
364  }
365  for (i = 0; op3s[i].name; i++) {
366  if (op3s[i].op == op && op3s[i].fun == opfun) {
367  if (c & 0x1000) /* immediate instruction */
368  printf("%s %s,%d,%s\n", op3s[i].name,
371  else
372  printf("%s %s,%s,%s\n", op3s[i].name,
376  goto _return;
377  }
378  }
379  /* fall through */
380  default:
381  if (c & 0x1000) /* immediate instruction */
382  printf("UNDEF %x(%x) $%d,%d,$%d\n", op, opfun, ra, lit, rc);
383  else
384  printf("UNDEF %x(%x) $%d,$%d,$%d\n", op, opfun, ra, rb, rc);
385  }
386 
387  /* 1 instruction is 4-bytes long */
388 
389  _return:
390  return code + 4;
391 }
392 
393 
394 /* disassemble *****************************************************************
395 
396  Outputs a disassembler listing of some machine code on 'stdout'.
397 
398  start: pointer to first instruction
399  end: pointer to last instruction
400 
401 *******************************************************************************/
402 
403 void disassemble(u1 *start, u1 *end)
404 {
405  printf(" --- disassembler listing ---\n");
406  for (; start < end; )
407  start = disassinstr(start);
408 }
409 
410 
411 /*
412  * These are local overrides for various environment variables in Emacs.
413  * Please do not remove this and leave it at the end of the file, where
414  * Emacs will automagically detect them.
415  * ---------------------------------------------------------------------
416  * Local variables:
417  * mode: c++
418  * indent-tabs-mode: t
419  * c-basic-offset: 4
420  * tab-width: 4
421  * End:
422  */
u2 fun
Definition: disass.cpp:129
#define ra
Definition: md-asm.hpp:62
u1 * disassinstr(u1 *code)
Definition: disass.cpp:48
u2 op
Definition: disass.cpp:129
#define ITYPE_JMP
Definition: disass.cpp:49
uint8_t u1
Definition: types.hpp:40
JNIEnv jclass jobject const char * name
Definition: jvmti.h:312
#define ITYPE_UNDEF
Definition: disass.cpp:48
int itype
Definition: disass.cpp:59
uint16_t u2
Definition: types.hpp:43
uint64_t u8
Definition: types.hpp:49
static struct @6 op3s[]
MIIterator i
int32_t s4
Definition: types.hpp:45
const char * abi_registers_integer_name[]
Definition: md-abi.cpp:57
#define ITYPE_BRA
Definition: disass.cpp:52
#define ITYPE_MEM
Definition: disass.cpp:50
void disassemble(u1 *start, u1 *end)
Definition: disass.cpp:403
static struct @5 ops[]
#define ITYPE_FOP
Definition: disass.cpp:54
#define printf(...)
Definition: ssa2.cpp:40
#define ITYPE_FMEM
Definition: disass.cpp:51
#define ITYPE_OP
Definition: disass.cpp:53