* Removed all Id tags.
[cacao.git] / src / vm / jit / mips / disass.c
index 9488a66fd57db77214cec4bcb764613011d8e507..c70318d8908d09846bc1a3136af07cd8325dd898 100644 (file)
@@ -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.
 
 
    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 <stdio.h>
 
+#include "vm/types.h"
 
-#include <stdio.h>
-#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);
 }