-/* vm/jit/alpha/disass.c - primitive disassembler for alpha machine code
+/* src/vm/jit/alpha/disass.c - primitive disassembler for Alpha machine code
- Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
+ C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+ E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+ J. Wenninger, Institut f. Computersprachen - TU Wien
This file is part of CACAO.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
- Contact: cacao@complang.tuwien.ac.at
+*/
- Authors: Andreas Krall
- Reinhard Grafl
- $Id: disass.c 1974 2005-03-03 10:43:46Z twisti $
+#include "config.h"
-*/
+#include <stdio.h>
+#include "vm/types.h"
-#include <stdio.h>
+#include "vm/global.h"
-#include "vm/jit/alpha/disass.h"
+#include "vm/jit/abi.h"
+#include "vm/jit/disass.h"
/* The disassembler uses two tables for decoding the instructions. The first
};
-/* name table for 32 integer registers */
-
-char *regs[] = {
- /* 0x00 */ "v0", /* "$0", */
- /* 0x01 */ "t0", /* "$1", */
- /* 0x02 */ "t1", /* "$2", */
- /* 0x03 */ "t2", /* "$3", */
- /* 0x04 */ "t3", /* "$4", */
- /* 0x05 */ "t4", /* "$5", */
- /* 0x06 */ "t5", /* "$6", */
- /* 0x07 */ "t6", /* "$7", */
-
- /* 0x08 */ "t7", /* "$8", */
- /* 0x09 */ "s0", /* "$9", */
- /* 0x0a */ "s1", /* "$10", */
- /* 0x0b */ "s2", /* "$11", */
- /* 0x0c */ "s3", /* "$12", */
- /* 0x0d */ "s4", /* "$13", */
- /* 0x0e */ "s5", /* "$14", */
- /* 0x0f */ "s6", /* "$15", */
-
- /* 0x10 */ "a0", /* "$16", */
- /* 0x11 */ "a1", /* "$17", */
- /* 0x12 */ "a2", /* "$18", */
- /* 0x13 */ "a3", /* "$19", */
- /* 0x14 */ "a4", /* "$20", */
- /* 0x15 */ "a5", /* "$21", */
- /* 0x16 */ "t8", /* "$22", */
- /* 0x17 */ "t9", /* "$23", */
-
- /* 0x18 */ "t10", /* "$24", */
- /* 0x19 */ "t11", /* "$25", */
- /* 0x1a */ "ra", /* "$26", */
- /* 0x1b */ "pv", /* "$27", */
- /* 0x1c */ "at", /* "$28", */
- /* 0x1d */ "gp", /* "$29", */
- /* 0x1e */ "sp", /* "$30", */
- /* 0x1f */ "zero" /* "$31" */
-};
-
+/* disassinstr *****************************************************************
-/* function disassinstr ********************************************************
+ Outputs a disassembler listing of one machine code instruction on
+ 'stdout'.
- outputs a disassembler listing of one machine code instruction on 'stdout'
- c: instructions machine code
+ code: pointer to instructions machine code
*******************************************************************************/
-void disassinstr(s4 *code)
+u1 *disassinstr(u1 *code)
{
- int op; /* 6 bit op code */
- int opfun; /* 7 bit function code */
- int ra, rb, rc; /* 6 bit register specifiers */
- int lit; /* 8 bit unsigned literal */
- int i; /* loop counter */
- s4 c = *code;
+ s4 op; /* 6 bit op code */
+ s4 opfun; /* 7 bit function code */
+ s4 ra, rb, rc; /* 6 bit register specifiers */
+ s4 lit; /* 8 bit unsigned literal */
+ s4 i; /* loop counter */
+ s4 c;
+
+ c = *((s4 *) code);
op = (c >> 26) & 0x3f; /* 6 bit op code */
opfun = (c >> 5) & 0x7f; /* 7 bit function code */
printf("0x%016lx: %08x ", (u8) code, c);
switch (ops[op].itype) {
- case ITYPE_JMP:
- switch ((c >> 14) & 3) { /* branch hint */
- case 0:
- if (ra == 31) {
- printf ("jmp (%s)\n", regs[rb]);
- return;
- }
- printf ("jmp ");
- break;
- case 1:
- if (ra == 26) {
- printf ("jsr (%s)\n", regs[rb]);
- return;
- }
- printf ("jsr ");
- break;
- case 2:
- if (ra == 31 && rb == 26) {
- printf ("ret\n");
- return;
- }
- if (ra == 31) {
- printf ("ret (%s)\n", regs[rb]);
- return;
- }
- printf ("ret ");
- break;
- case 3:
- printf ("jsr_co ");
- break;
- }
- printf ("%s,(%s)\n", regs[ra], regs[rb]);
+ case ITYPE_JMP:
+ switch ((c >> 14) & 3) { /* branch hint */
+ case 0:
+ if (ra == 31) {
+ printf("jmp (%s)\n", abi_registers_integer_name[rb]);
+ goto _return;
+ }
+ printf("jmp ");
break;
-
- case ITYPE_MEM: {
- int disp = (c << 16) >> 16; /* 16 bit signed displacement */
-
- if (op == 0x18 && ra == 0 && ra == 0 && disp == 0)
- printf ("trapb\n");
- else
- printf ("%s %s,%d(%s)\n", ops[op].name, regs[ra], disp, regs[rb]);
+ case 1:
+ if (ra == 26) {
+ printf("jsr (%s)\n", abi_registers_integer_name[rb]);
+ goto _return;
+ }
+ printf("jsr ");
break;
+ case 2:
+ if (ra == 31 && rb == 26) {
+ printf("ret\n");
+ goto _return;
}
-
- case ITYPE_FMEM:
- printf ("%s $f%d,%d(%s)\n", ops[op].name, ra, (c << 16) >> 16, regs[rb]);
+ if (ra == 31) {
+ printf("ret (%s)\n", abi_registers_integer_name[rb]);
+ goto _return;
+ }
+ printf("ret ");
break;
-
- case ITYPE_BRA: /* 21 bit signed branch offset */
- if (op == 0x30 && ra == 31)
- printf("br 0x%016lx\n", (u8) code + 4 + ((c << 11) >> 9));
- else if (op == 0x34 && ra == 26)
- printf("brs 0x%016lx\n", (u8) code + 4 + ((c << 11) >> 9));
- else
- printf("%s %s,0x%016lx\n",
- ops[op].name, regs[ra], (u8) code + 4 + ((c << 11) >> 9));
+ case 3:
+ printf("jsr_co ");
break;
+ }
+ printf("%s,(%s)\n", abi_registers_integer_name[ra],
+ abi_registers_integer_name[rb]);
+ break;
+
+ case ITYPE_MEM: {
+ s4 disp = (c << 16) >> 16; /* 16 bit signed displacement */
+
+ if (op == 0x18 && ra == 0 && ra == 0 && disp == 0)
+ printf("trapb\n");
+ else
+ printf("%s %s,%d(%s)\n", ops[op].name,
+ abi_registers_integer_name[ra], disp,
+ abi_registers_integer_name[rb]);
+ break;
+ }
+
+ case ITYPE_FMEM:
+ printf("%s $f%d,%d(%s)\n", ops[op].name, ra, (c << 16) >> 16,
+ abi_registers_integer_name[rb]);
+ break;
+
+ case ITYPE_BRA: /* 21 bit signed branch offset */
+ if (op == 0x30 && ra == 31)
+ printf("br 0x%016lx\n", (u8) code + 4 + ((c << 11) >> 9));
+ else if (op == 0x34 && ra == 26)
+ printf("brs 0x%016lx\n", (u8) code + 4 + ((c << 11) >> 9));
+ else
+ printf("%s %s,0x%016lx\n", ops[op].name,
+ abi_registers_integer_name[ra],
+ (u8) code + 4 + ((c << 11) >> 9));
+ break;
- case ITYPE_FOP: {
- int fopfun = (c >> 5) & 0x7ff; /* 11 bit fp function code */
+ case ITYPE_FOP: {
+ s4 fopfun = (c >> 5) & 0x7ff; /* 11 bit fp function code */
- if (op == 0x17 && fopfun == 0x020 && ra == rb) {
- if (ra == 31 && rc == 31)
- printf("fnop\n");
- else
- printf("fmov $f%d,$f%d\n", ra, rc);
- return;
- }
- for (i = 0; op3s[i].name; i++)
- if (op3s[i].op == op && op3s[i].fun == fopfun) {
- printf("%s $f%d,$f%d,$f%d\n", op3s[i].name, ra, rb, rc);
- return;
- }
- printf("%s%x $f%d,$f%d,$f%d\n", ops[op].name, fopfun, ra, rb, rc);
- break;
+ if (op == 0x17 && fopfun == 0x020 && ra == rb) {
+ if (ra == 31 && rc == 31)
+ printf("fnop\n");
+ else
+ printf("fmov $f%d,$f%d\n", ra, rc);
+ goto _return;
+ }
+ for (i = 0; op3s[i].name; i++)
+ if (op3s[i].op == op && op3s[i].fun == fopfun) {
+ printf("%s $f%d,$f%d,$f%d\n", op3s[i].name, ra, rb, rc);
+ goto _return;
}
-
- case ITYPE_OP:
- if (op == 0x11 && opfun == 0x20 && ra == rb && ~(c&0x1000)) {
- if (ra == 31 && rc == 31)
- printf("nop\n");
- else if (ra == 31)
- printf("clr %s\n", regs[rc]);
- else
- printf("mov %s,%s\n", regs[ra], regs[rc]);
- return;
- }
- for (i = 0; op3s[i].name; i++) {
- if (op3s[i].op == op && op3s[i].fun == opfun) {
- if (c & 0x1000) /* immediate instruction */
- printf("%s %s,%d,%s\n",
- op3s[i].name, regs[ra], lit, regs[rc]);
- else
- printf("%s %s,%s,%s\n",
- op3s[i].name, regs[ra], regs[rb], regs[rc]);
- return;
- }
- }
- /* fall through */
- default:
- if (c & 0x1000) /* immediate instruction */
- printf("UNDEF %x(%x) $%d,%d,$%d\n", op, opfun, ra, lit, rc);
+ printf("%s%x $f%d,$f%d,$f%d\n", ops[op].name, fopfun, ra, rb, rc);
+ break;
+ }
+
+ case ITYPE_OP:
+ if (op == 0x11 && opfun == 0x20 && ra == rb && ~(c&0x1000)) {
+ if (ra == 31 && rc == 31)
+ printf("nop\n");
+ else if (ra == 31)
+ printf("clr %s\n", abi_registers_integer_name[rc]);
else
- printf("UNDEF %x(%x) $%d,$%d,$%d\n", op, opfun, ra, rb, rc);
+ printf("mov %s,%s\n", abi_registers_integer_name[ra],
+ abi_registers_integer_name[rc]);
+ goto _return;
}
+ for (i = 0; op3s[i].name; i++) {
+ if (op3s[i].op == op && op3s[i].fun == opfun) {
+ if (c & 0x1000) /* immediate instruction */
+ printf("%s %s,%d,%s\n", op3s[i].name,
+ abi_registers_integer_name[ra], lit,
+ abi_registers_integer_name[rc]);
+ else
+ printf("%s %s,%s,%s\n", op3s[i].name,
+ abi_registers_integer_name[ra],
+ abi_registers_integer_name[rb],
+ abi_registers_integer_name[rc]);
+ goto _return;
+ }
+ }
+ /* fall through */
+ default:
+ if (c & 0x1000) /* immediate instruction */
+ printf("UNDEF %x(%x) $%d,%d,$%d\n", op, opfun, ra, lit, rc);
+ else
+ printf("UNDEF %x(%x) $%d,$%d,$%d\n", op, opfun, ra, rb, rc);
+ }
+
+ /* 1 instruction is 4-bytes long */
+
+ _return:
+ return code + 4;
}
-/* function disassemble ********************************************************
+/* disassemble *****************************************************************
+
+ Outputs a disassembler listing of some machine code on 'stdout'.
- outputs a disassembler listing of some machine code on 'stdout'
- code: pointer to first instruction
- len: code size (number of instructions * 4)
+ start: pointer to first instruction
+ end: pointer to last instruction
*******************************************************************************/
-void disassemble(s4 *code, int len)
+void disassemble(u1 *start, u1 *end)
{
- int i;
-
- printf (" --- disassembler listing ---\n");
- for (i = 0; i < len; i += 4, code++)
- disassinstr(code);
+ printf(" --- disassembler listing ---\n");
+ for (; start < end; )
+ start = disassinstr(start);
}