X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fvm%2Fjit%2Fmips%2Fdisass.c;h=c70318d8908d09846bc1a3136af07cd8325dd898;hb=9f859ad50d3d5d98c185d40b86b2179bc4dc9aeb;hp=9488a66fd57db77214cec4bcb764613011d8e507;hpb=dbe4a6a9f849c2f01b7e4ad29b8c1137f4689adf;p=cacao.git diff --git a/src/vm/jit/mips/disass.c b/src/vm/jit/mips/disass.c index 9488a66fd..c70318d89 100644 --- a/src/vm/jit/mips/disass.c +++ b/src/vm/jit/mips/disass.c @@ -1,10 +1,9 @@ -/* jit/mips/disass.c - primitive disassembler for mips machine code +/* src/vm/jit/mips/disass.c - primitive disassembler for MIPS machine code - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 - Institut f. Computersprachen, TU Wien - R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst, - S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, - J. Wenninger + 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. @@ -20,21 +19,19 @@ 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 - $Id: disass.c 1109 2004-05-28 13:11:16Z twisti $ +#include "config.h" -*/ +#include +#include "vm/types.h" -#include -#include "types.h" -#include "disass.h" +#include "vm/jit/abi.h" /* The disassembler uses four tables for decoding the instructions. The first @@ -363,47 +360,6 @@ static char *fbra[] = { }; -/* instruction decode table for 32 integer registers */ - -char *regs[] = { - /* 0x00 */ "zero", /* "$0", */ - /* 0x01 */ "at", /* "$1", */ - /* 0x02 */ "v0", /* "$2", */ - /* 0x03 */ "v1", /* "$3", */ - /* 0x04 */ "a0", /* "$4", */ - /* 0x05 */ "a1", /* "$5", */ - /* 0x06 */ "a2", /* "$6", */ - /* 0x07 */ "a3", /* "$7", */ - - /* 0x08 */ "a4", /* "$8", */ - /* 0x09 */ "a5", /* "$9", */ - /* 0x0a */ "a6", /* "$10", */ - /* 0x0b */ "a7", /* "$11", */ - /* 0x0c */ "t4", /* "$12", */ - /* 0x0d */ "t5", /* "$13", */ - /* 0x0e */ "t6", /* "$14", */ - /* 0x0f */ "t7", /* "$15", */ - - /* 0x10 */ "s0", /* "$16", */ - /* 0x11 */ "s1", /* "$17", */ - /* 0x12 */ "s2", /* "$18", */ - /* 0x13 */ "s3", /* "$19", */ - /* 0x14 */ "s4", /* "$20", */ - /* 0x15 */ "s5", /* "$21", */ - /* 0x16 */ "s6", /* "$22", */ - /* 0x17 */ "s7", /* "$23", */ - - /* 0x18 */ "t8", /* "$24", */ - /* 0x19 */ "t9", /* "$25", */ - /* 0x1a */ "k0", /* "$26", */ - /* 0x1b */ "k1", /* "$27", */ - /* 0x1c */ "gp", /* "$28", */ - /* 0x1d */ "sp", /* "$29", */ - /* 0x1e */ "s8", /* "$30", */ - /* 0x1f */ "ra" /* "$31" */ -}; - - /* instruction decode table for 32 floating point registers */ #if 0 @@ -448,22 +404,25 @@ static char *fregs[] = { #endif -/* function disassinstr ******************************************************** +/* disassinstr ***************************************************************** - outputs a disassembler listing of one machine code instruction on 'stdout' - c: instructions machine code - pos: instructions address relative to method start + Outputs a disassembler listing of one machine code instruction on + 'stdout'. + + code: pointer to instructions machine code *******************************************************************************/ -void disassinstr(s4 *code, int pos) +u1 *disassinstr(u1 *code) { - int op; /* 6 bit op code */ - int opfun; /* 6 bit function code */ - int rs, rt, rd; /* 5 bit integer register specifiers */ - int fs, ft, fd; /* 5 bit floating point register specifiers */ - int shift; /* 5 bit unsigned shift amount */ - s4 c = *code; + s4 op; /* 6 bit op code */ + s4 opfun; /* 6 bit function code */ + s4 rs, rt, rd; /* 5 bit integer register specifiers */ + s4 fs, ft, fd; /* 5 bit floating point register specifiers */ + s4 shift; /* 5 bit unsigned shift amount */ + s4 c; + + c = *((s4 *) code); op = (c >> 26) & 0x3f; /* 6 bit op code */ opfun = (c >> 0) & 0x3f; /* 6 bit function code */ @@ -472,166 +431,209 @@ void disassinstr(s4 *code, int pos) rd = (c >> 11) & 0x1f; /* 5 bit destination register specifier */ shift = (c >> 6) & 0x1f; /* 5 bit unsigned shift amount */ +#if SIZEOF_VOID_P == 8 printf("0x%016lx: %08x ", (u8) code, c); - +#else + printf("0x%08x: %08x ", (u4) code, c); +#endif + switch (ops[op].itype) { - case ITYPE_JMP: /* 26 bit unsigned jump offset */ - printf ("%s %#09x\n", ops[op].name, (c & 0x3ffffff) << 2); + case ITYPE_JMP: /* 26 bit unsigned jump offset */ + printf("%s %#09x\n", ops[op].name, (c & 0x3ffffff) << 2); + break; + + case ITYPE_IMM: /* 16 bit signed immediate value */ + printf("%s %s,%s,%d\n", ops[op].name, abi_registers_integer_name[rt], + abi_registers_integer_name[rs], (c << 16) >> 16); + break; + + case ITYPE_MEM: /* 16 bit signed memory offset */ + printf("%s %s,%d(%s)\n", ops[op].name, abi_registers_integer_name[rt], + (c << 16) >> 16, abi_registers_integer_name[rs]); + break; + + case ITYPE_FMEM: /* 16 bit signed memory offset */ + printf("%s $f%d,%d(%s)\n", ops[op].name, rt, (c << 16) >> 16, + abi_registers_integer_name[rs]); + break; + + case ITYPE_BRA: /* 16 bit signed branch offset */ + if (op == 0x04 && rs == 0 && rt == 0) { +#if SIZEOF_VOID_P == 8 + printf("b 0x%016lx\n", (u8) code + 4 + ((c << 16) >> 14)); +#else + printf("b 0x%08x\n", (u4) code + 4 + ((c << 16) >> 14)); +#endif break; + } +#if SIZEOF_VOID_P == 8 + printf("%s %s,%s,0x%016lx\n", ops[op].name, + abi_registers_integer_name[rs], + abi_registers_integer_name[rt], + (u8) code + 4 + ((c << 16) >> 14)); +#else + printf("%s %s,%s,0x%08x\n", ops[op].name, + abi_registers_integer_name[rs], + abi_registers_integer_name[rt], + (u4) code + 4 + ((c << 16) >> 14)); +#endif + break; + + case ITYPE_RIMM: + if (regimms[rt].ftype == ITYPE_IMM) + printf("%s %s,%d\n", regimms[rt].name, + abi_registers_integer_name[rs], (c << 16) >> 16); + else if (regimms[rt].ftype == ITYPE_BRA) +#if SIZEOF_VOID_P == 8 + printf("%s %s,0x%016lx\n", regimms[rt].name, + abi_registers_integer_name[rs], + (u8) code + 4 + ((c << 16) >> 14)); +#else + printf("%s %s,0x%08x\n", regimms[rt].name, + abi_registers_integer_name[rs], + (u4) code + 4 + ((c << 16) >> 14)); +#endif + else + printf("regimm %#04x,$%d,%d\n", rt, rs, (c << 16) >> 16); + break; - case ITYPE_IMM: /* 16 bit signed immediate value */ - printf ("%s %s,%s,%d\n", ops[op].name, regs[rt], - regs[rs], (c << 16) >> 16); + case ITYPE_OP: + if (c == 0) { + printf("nop\n"); break; - - case ITYPE_MEM: /* 16 bit signed memory offset */ - printf ("%s %s,%d(%s)\n", ops[op].name, regs[rt], - (c << 16) >> 16, regs[rs]); + } + if (opfun == 0x25 && rt == 0) { + if (rs == 0) + printf("clr %s\n", abi_registers_integer_name[rd]); + else + printf("move %s,%s\n", abi_registers_integer_name[rd], + abi_registers_integer_name[rs]); break; - - case ITYPE_FMEM: /* 16 bit signed memory offset */ - printf ("%s $f%d,%d(%s)\n", ops[op].name, rt, - (c << 16) >> 16, regs[rs]); + } + switch (regops[opfun].ftype) { + case ITYPE_OP: + printf("%s %s,%s,%s\n", regops[opfun].name, + abi_registers_integer_name[rd], + abi_registers_integer_name[rs], + abi_registers_integer_name[rt]); break; - - case ITYPE_BRA: /* 16 bit signed branch offset */ - if (op == 0x04 && rs == 0 && rt == 0) { - printf("b 0x%016lx\n", (u8) code + 4 + ((c << 16) >> 14)); - break; - } - printf("%s %s,%s,0x%016lx\n", ops[op].name, regs[rs], regs[rt], - (u8) code + 4 + ((c << 16) >> 14)); + case ITYPE_IMM: /* immediate instruction */ + printf("%s %s,%s,%d\n", + regops[opfun].name, abi_registers_integer_name[rd], + abi_registers_integer_name[rt], shift); break; - - case ITYPE_RIMM: - if (regimms[rt].ftype == ITYPE_IMM) - printf("%s %s,%d\n", regimms[rt].name, regs[rs], - (c << 16) >> 16); - else if (regimms[rt].ftype == ITYPE_BRA) - printf("%s %s,0x%016lx\n", regimms[rt].name, regs[rs], - (u8) code + 4 + ((c << 16) >> 14)); - else - printf("regimm %#04x,$%d,%d\n", rt, rs, (c << 16) >> 16); + case ITYPE_TRAP: + printf("%s %s,%s,%d\n", regops[opfun].name, + abi_registers_integer_name[rs], + abi_registers_integer_name[rt], (c << 16) >> 22); break; - - case ITYPE_OP: - if (c == 0) { - printf("nop\n"); - return; - } - if (opfun == 0x25 && rt == 0) { - if (rs == 0) - printf("clr %s\n", regs[rd]); - else - printf("move %s,%s\n", regs[rd], regs[rs]); - return; - } - switch (regops[opfun].ftype) { - case ITYPE_OP: - printf("%s %s,%s,%s\n", regops[opfun].name, regs[rd], - regs[rs], regs[rt]); - break; - case ITYPE_IMM: /* immediate instruction */ - printf("%s %s,%s,%d\n", - regops[opfun].name, regs[rd], regs[rt], shift); - break; - case ITYPE_TRAP: - printf("%s %s,%s,%d\n", regops[opfun].name, - regs[rs], regs[rt], (c << 16) >> 22); - break; - case ITYPE_DIVMUL: /* div/mul instruction */ - printf("%s %s,%s\n", regops[opfun].name, regs[rs], regs[rt]); - break; - case ITYPE_JMP: - if (rd == 31) { - printf("%s %s\n", regops[opfun].name, regs[rs]); - break; - } - printf("%s %s,%s\n", regops[opfun].name, regs[rd], regs[rs]); - break; - case ITYPE_MTOJR: - if (opfun == 8 && rs == 31) { - printf("ret\n"); - break; - } - printf("%s %s\n", regops[opfun].name, regs[rs]); - break; - case ITYPE_MFROM: - printf("%s %s\n", regops[opfun].name, regs[rd]); - break; - case ITYPE_SYS: - printf("%s\n", regops[opfun].name); - default: - printf("special (%#04x) $%d,$%d,$%d\n", opfun, rd, rs, rt); - } + case ITYPE_DIVMUL: /* div/mul instruction */ + printf("%s %s,%s\n", regops[opfun].name, + abi_registers_integer_name[rs], + abi_registers_integer_name[rt]); break; - case ITYPE_FOP: - fs = (c >> 11) & 0x1f; /* 5 bit source register */ - ft = (c >> 16) & 0x1f; /* 5 bit source/destination register */ - fd = (c >> 6) & 0x1f; /* 5 bit destination register */ - - if (rs == 8) { /* floating point branch */ - printf("%s %x\n", fbra[ft&3], pos + 4 + ((c << 16) >> 14)); + case ITYPE_JMP: + if (rd == 31) { + printf("%s %s\n", regops[opfun].name, + abi_registers_integer_name[rs]); break; - } - - if (rs == 0) { /* move from */ - printf("mfc1 %s,$f%d\n", regs[rt], fs); - break; - } - - if (rs == 1) { /* double move from */ - printf("dmfc1 %s,$f%d\n", regs[rt], fs); + } + printf("%s %s,%s\n", regops[opfun].name, + abi_registers_integer_name[rd], + abi_registers_integer_name[rs]); + break; + case ITYPE_MTOJR: + if (opfun == 8 && rs == 31) { + printf("ret\n"); break; - } + } + printf("%s %s\n", regops[opfun].name, + abi_registers_integer_name[rs]); + break; + case ITYPE_MFROM: + printf("%s %s\n", regops[opfun].name, + abi_registers_integer_name[rd]); + break; + case ITYPE_SYS: + printf("%s\n", regops[opfun].name); + default: + printf("special (%#04x) $%d,$%d,$%d\n", opfun, rd, rs, rt); + } + break; + + case ITYPE_FOP: + fs = (c >> 11) & 0x1f; /* 5 bit source register */ + ft = (c >> 16) & 0x1f; /* 5 bit source/destination register */ + fd = (c >> 6) & 0x1f; /* 5 bit destination register */ + + if (rs == 8) { /* floating point branch */ +#if SIZEOF_VOID_P == 8 + printf("%s 0x%016lx\n", fbra[ft & 3], + (u8) code + 4 + ((c << 16) >> 14)); +#else + printf("%s 0x%08x\n", fbra[ft & 3], + (u4) code + 4 + ((c << 16) >> 14)); +#endif + break; + } - if (rs == 4) { /* move to */ - printf("mtc1 %s,$f%d\n", regs[rt], fs); - break; - } + if (rs == 0) { /* move from */ + printf("mfc1 %s,$f%d\n", abi_registers_integer_name[rt], fs); + break; + } - if (rs == 5) { /* double move to */ - printf("dmtc1 %s,$f%d\n", regs[rt], fs); - break; - } - - rs = rs & 7; /* truncate to 3 bit format specifier */ - - if (fops[opfun].ftype == ITYPE_FOP) - printf("%s%s%s $f%d,$f%d,$f%d\n", fops[opfun].name, fmt[rs], - fops[opfun].fill, fd, fs, ft); - else if (fops[opfun].ftype == ITYPE_FOP2) - printf("%s%s%s $f%d,$f%d\n", fops[opfun].name, fmt[rs], - fops[opfun].fill, fd, fs); - else if (fops[opfun].ftype == ITYPE_FCMP) - printf("%s%s%s $f%d,$f%d\n", fops[opfun].name, fmt[rs], - fops[opfun].fill, fs, ft); - else - printf("cop1 (%#04x) $f%d,$f%d,$f%d\n", opfun, fd, fs, ft); + if (rs == 1) { /* double move from */ + printf("dmfc1 %s,$f%d\n", abi_registers_integer_name[rt], fs); + break; + } + if (rs == 4) { /* move to */ + printf("mtc1 %s,$f%d\n", abi_registers_integer_name[rt], fs); break; + } - default: - printf("undef %#04x(%#04x) $%d,$%d,$%d\n", op, opfun, rd, rs, rt); + if (rs == 5) { /* double move to */ + printf("dmtc1 %s,$f%d\n", abi_registers_integer_name[rt], fs); + break; } + + rs = rs & 7; /* truncate to 3 bit format specifier */ + + if (fops[opfun].ftype == ITYPE_FOP) + printf("%s%s%s $f%d,$f%d,$f%d\n", fops[opfun].name, fmt[rs], + fops[opfun].fill, fd, fs, ft); + else if (fops[opfun].ftype == ITYPE_FOP2) + printf("%s%s%s $f%d,$f%d\n", fops[opfun].name, fmt[rs], + fops[opfun].fill, fd, fs); + else if (fops[opfun].ftype == ITYPE_FCMP) + printf("%s%s%s $f%d,$f%d\n", fops[opfun].name, fmt[rs], + fops[opfun].fill, fs, ft); + else + printf("cop1 (%#04x) $f%d,$f%d,$f%d\n", opfun, fd, fs, ft); + break; + + default: + printf("undef %#04x(%#04x) $%d,$%d,$%d\n", op, opfun, rd, rs, rt); + } + + 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 p; - printf(" --- disassembler listing ---\n"); - for (p = 0; p < len; p += 4, code++) - disassinstr(code, p); + for (; start < end; ) + start = disassinstr(start); }