* Removed all Id tags.
[cacao.git] / src / vm / jit / mips / codegen.h
index cf055b16e7c7c4b13b2d57352aff7989ca5b4d17..12a88b412fe7e2adee0848fee2afaf62043ebe8c 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/mips/codegen.h - code generation macros and definitions for MIPS
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   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
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Andreas Krall
-
-   $Id: codegen.h 4776 2006-04-14 12:40:49Z twisti $
-
 */
 
 
 #include "vm/jit/jit.h"
 
 
-/* some defines ***************************************************************/
-
-#define PATCHER_CALL_SIZE    2 * 4      /* size in bytes of a patcher call    */
+/* additional functions and macros to generate code ***************************/
 
+/* MCODECHECK(icnt) */
 
-/* additional functions and macros to generate code ***************************/
+#define MCODECHECK(icnt) \
+    do { \
+        if ((cd->mcodeptr + (icnt) * 4) > cd->mcodeend) \
+            codegen_increase(cd); \
+    } while (0)
 
-#define gen_nullptr_check(objreg) \
-    if (checknull) { \
-        M_BEQZ(objreg, 0); \
-        codegen_add_nullpointerexception_ref(cd, cd->mcodeptr); \
-        M_NOP; \
-    }
 
-#define gen_bound_check \
-    if (checkbounds) { \
-        M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size)); \
-        M_CMPULT(s2, REG_ITMP3, REG_ITMP3); \
-        M_BEQZ(REG_ITMP3, 0); \
-        codegen_add_arrayindexoutofboundsexception_ref(cd, cd->mcodeptr, s2); \
+#define ALIGNCODENOP \
+    if ((s4) ((ptrint) cd->mcodeptr & 7)) { \
         M_NOP; \
     }
 
-#define gen_div_check(r) \
+#define M_INTMOVE(a,b) \
     do { \
-        M_BEQZ((r), 0); \
-        codegen_add_arithmeticexception_ref(cd, cd->mcodeptr); \
-        M_NOP; \
+        if ((a) != (b)) \
+            M_MOV(a, b); \
     } while (0)
 
+#if SIZEOF_VOID_P == 8
 
-/* MCODECHECK(icnt) */
+#define M_LNGMOVE(a,b)    M_INTMOVE(a,b)
 
-#define MCODECHECK(icnt) \
-       if ((cd->mcodeptr + (icnt)) > (u4 *) cd->mcodeend) \
-        cd->mcodeptr = (u4 *) codegen_increase(cd, (u1 *) cd->mcodeptr)
+#else /* SIZEOF_VOID_P == 8 */
 
+#define M_LNGMOVE(a,b) \
+    do { \
+        if (GET_LOW_REG(b) == GET_HIGH_REG(a)) { \
+            assert(GET_HIGH_REG(b) == GET_LOW_REG(a)); \
+            M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
+            M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
+        } else { \
+            M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
+            M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
+        } \
+    } while (0)
 
-#define ALIGNCODENOP \
-    if ((int) ((long) cd->mcodeptr & 7)) { \
-        M_NOP; \
-    }
+#endif /* SIZEOF_VOID_P == 8 */
 
+#define M_FLTMOVE(a,b) \
+    do { \
+        if ((a) != (b)) \
+            M_FMOV(a, b); \
+    } while (0)
 
-/* M_INTMOVE:
-     generates an integer-move from register a to b.
-     if a and b are the same int-register, no code will be generated.
-*/ 
+#define M_DBLMOVE(a,b) \
+    do { \
+        if ((a) != (b)) \
+            M_DMOV(a, b); \
+    } while (0)
 
-#define M_INTMOVE(a,b) if (a != b) { M_MOV(a, b); }
+#define ICONST(r,c)                     emit_iconst(cd, (r), (c))
+#define LCONST(r,c)                     emit_lconst(cd, (r), (c))
 
 
-/* M_FLTMOVE:
-    generates a floating-point-move from register a to b.
-    if a and b are the same float-register, no code will be generated
-*/ 
+/* branch defines *************************************************************/
 
-#define M_FLTMOVE(a,b) if (a != b) { M_DMOV(a, b); }
+#define BRANCH_NOPS \
+    do { \
+        if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) { \
+            M_NOP; \
+            M_NOP; \
+            M_NOP; \
+            M_NOP; \
+            M_NOP; \
+            M_NOP; \
+        } \
+        else { \
+            M_NOP; \
+            M_NOP; \
+        } \
+    } while (0)
+
+
+/* patcher defines ************************************************************/
 
-#define M_TFLTMOVE(t,a,b) \
+#define PATCHER_CALL_INSTRUCTIONS    1     /* number of instructions          */
+#define PATCHER_CALL_SIZE            1 * 4 /* size in bytes of a patcher call */
+
+#define PATCHER_NOPS \
     do { \
-        if ((a) != (b)) \
-            if ((t) == TYPE_DBL) { \
-                M_DMOV(a,b); \
-            } else { \
-                M_FMOV(a,b); \
-            } \
+        M_NOP; \
     } while (0)
 
-#define M_TFLD(t,a,b,disp) \
-    if ((t) == TYPE_DBL) { \
-         M_DLD(a,b,disp); \
-    } else { \
-         M_FLD(a,b,disp); \
-    }
 
-#define M_TFST(t,a,b,disp) \
-    if ((t)==TYPE_DBL) \
-         {M_DST(a,b,disp);} \
-    else \
-         {M_FST(a,b,disp);}
-
-#define M_CCFLTMOVE(t1,t2,a,b) \
-       if ((t1)==(t2)) \
-         {M_TFLTMOVE(t1,a,b);} \
-       else \
-         if ((t1)==TYPE_DBL) \
-               {M_CVTDF(a,b);} \
-         else \
-               {M_CVTFD(a,b);}
-
-#define M_CCFLD(t1,t2,a,b,disp) \
-    if ((t1)==(t2)) \
-         {M_DLD(a,b,disp);} \
-       else { \
-         M_DLD(REG_FTMP1,b,disp); \
-         if ((t1)==TYPE_DBL) \
-           {M_CVTDF(REG_FTMP1,a);} \
-         else \
-           {M_CVTFD(REG_FTMP1,a);} \
-       }
-         
-#define M_CCFST(t1,t2,a,b,disp) \
-    if ((t1)==(t2)) \
-         {M_DST(a,b,disp);} \
-       else { \
-         if ((t1)==TYPE_DBL) \
-           {M_CVTDF(a,REG_FTMP1);} \
-         else \
-           {M_CVTFD(a,REG_FTMP1);} \
-         M_DST(REG_FTMP1,b,disp); \
-       }
-         
-
-#define M_COPY(s,d)                     emit_copy(jd, iptr, (s), (d))
-#define ICONST(r,c)                     emit_iconst(cd, (r), (c))
-#define LCONST(r,c)                     emit_lconst(cd, (r), (c))
+/* stub defines ***************************************************************/
+
+#define COMPILERSTUB_CODESIZE    4 * 4
 
 
 /* macros to create code ******************************************************/
 
 
 #define M_ITYPE(op,rs,rt,imm) \
-    *(cd->mcodeptr++) = (((op) << 26) | ((rs) << 21) | ((rt) << 16) | ((imm) & 0xffff))
+    do { \
+        *((u4 *) cd->mcodeptr) = (((op) << 26) | ((rs) << 21) | ((rt) << 16) | ((imm) & 0xffff)); \
+        cd->mcodeptr += 4; \
+    } while (0)
+
+#define M_ITYPE_GET_RS(x)               (((x) >> 21) & 0x1f  )
+#define M_ITYPE_GET_RT(x)               (((x) >> 16) & 0x1f  )
+#define M_ITYPE_GET_IMM(x)              ( (x)        & 0xffff)
+
 
 #define M_JTYPE(op,imm) \
-    *(cd->mcodeptr++) = (((op) << 26) | ((off) & 0x3ffffff))
+    do { \
+        *((u4 *) cd->mcodeptr) = (((op) << 26) | ((off) & 0x3ffffff)); \
+        cd->mcodeptr += 4; \
+    } while (0)
 
 #define M_RTYPE(op,rs,rt,rd,sa,fu) \
-    *(cd->mcodeptr++) = (((op) << 26) | ((rs) << 21) | ((rt) << 16) | ((rd) << 11) | ((sa) << 6) | (fu))
+    do { \
+        *((u4 *) cd->mcodeptr) = (((op) << 26) | ((rs) << 21) | ((rt) << 16) | ((rd) << 11) | ((sa) << 6) | (fu)); \
+        cd->mcodeptr += 4; \
+    } while (0)
 
 #define M_FP2(fu, fmt, fs, fd)       M_RTYPE(0x11, fmt,  0, fs, fd, fu)
 #define M_FP3(fu, fmt, fs, ft, fd)   M_RTYPE(0x11, fmt, ft, fs, fd, fu)
         if (hi == 0) { \
             M_AADD_IMM(b,lo,a); \
         } else { \
-            M_LUI(REG_ITMP3,hi); \
-            M_AADD_IMM(REG_ITMP3,lo,REG_ITMP3); \
-            M_AADD(REG_ITMP3,b,a); \
+            M_LUI(REG_ITMP3, hi); \
+            M_AADD_IMM(REG_ITMP3, lo, REG_ITMP3); \
+            M_AADD(b, REG_ITMP3, a); \
         } \
     } while (0)
 
 #define M_SLDU(a,b,disp)        M_ITYPE(0x25,b,a,disp)          /* 16 load    */
 
 #define M_ILD_INTERN(a,b,disp)  M_ITYPE(0x23,b,a,disp)          /* 32 load    */
-#define M_LLD_INTERN(a,b,disp)  M_ITYPE(0x37,b,a,disp)          /* 64 load    */
 
 #define M_ILD(a,b,disp) \
     do { \
         } \
     } while (0)
 
+#if SIZEOF_VOID_P == 8
+
+#define M_LLD_INTERN(a,b,disp)  M_ITYPE(0x37,b,a,disp)          /* 64 load    */
+
+#else /* SIZEOF_VOID_P == 8 */
+
+# if WORDS_BIGENDIAN == 1
+
+/* ATTENTION: b may be equal to GET_LOW_REG(a) (displacement overflow case ) */
+
+#define M_LLD_INTERN(a,b,disp) \
+    do { \
+        M_ILD_INTERN(GET_HIGH_REG(a), b, disp); \
+        M_ILD_INTERN(GET_LOW_REG(a), b, disp + 4); \
+    } while (0)
+
+/* this macro is specially for ICMD_GETFIELD since the base (source)
+   register may be one of the destination registers */
+
+#define M_LLD_GETFIELD(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            if (GET_HIGH_REG(a) == (b)) { \
+                M_ILD_INTERN(GET_LOW_REG(a), b, disp + 4); \
+                M_ILD_INTERN(GET_HIGH_REG(a), b, disp); \
+            } else { \
+                M_ILD_INTERN(GET_HIGH_REG(a), b, disp); \
+                M_ILD_INTERN(GET_LOW_REG(a), b, disp + 4); \
+            } \
+        } else { \
+            M_LUI(GET_LOW_REG(a), hi); \
+            M_AADD(b, GET_LOW_REG(a), GET_LOW_REG(a)); \
+            M_LLD_INTERN(a, GET_LOW_REG(a), lo); \
+        } \
+    } while (0)
+
+# else /* if WORDS_BIGENDIAN == 1 */
+
+/* ATTENTION: b may be equal to GET_LOW_REG(a) (displacement overflow case ) */
+
+#define M_LLD_INTERN(a,b,disp) \
+    do { \
+        M_ILD_INTERN(GET_HIGH_REG(a), b, disp + 4); \
+        M_ILD_INTERN(GET_LOW_REG(a), b, disp); \
+    } while (0)
+
+/* this macro is specially for ICMD_GETFIELD since the base (source)
+   register may be one of the destination registers */
+
+#define M_LLD_GETFIELD(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            if (GET_HIGH_REG(a) == (b)) { \
+                M_ILD_INTERN(GET_LOW_REG(a), b, disp); \
+                M_ILD_INTERN(GET_HIGH_REG(a), b, disp + 4); \
+            } else { \
+                M_ILD_INTERN(GET_HIGH_REG(a), b, disp + 4); \
+                M_ILD_INTERN(GET_LOW_REG(a), b, disp); \
+            } \
+        } else { \
+            M_LUI(GET_LOW_REG(a), hi); \
+            M_AADD(b, GET_LOW_REG(a), GET_LOW_REG(a)); \
+            M_LLD_INTERN(a, GET_LOW_REG(a), lo); \
+        } \
+    } while (0)
+
+# endif /* if WORDS_BIGENDIAN == 1 */
+
+#endif /* SIZEOF_VOID_P == 8 */
+
 #define M_LLD(a,b,disp) \
     do { \
         s4 lo = (short) (disp); \
         s4 hi = (short) (((disp) - lo) >> 16); \
         if (hi == 0) { \
-            M_LLD_INTERN(a,b,lo); \
+            M_LLD_INTERN(a, b, lo); \
         } else { \
-            M_LUI(a,hi); \
-            M_AADD(b,a,a); \
-            M_LLD_INTERN(a,a,lo); \
+            M_LUI(GET_LOW_REG(a), hi); \
+            M_AADD(b, GET_LOW_REG(a), GET_LOW_REG(a)); \
+            M_LLD_INTERN(a, GET_LOW_REG(a), lo); \
         } \
     } while (0)
 
 #define M_SST(a,b,disp)         M_ITYPE(0x29,b,a,disp)          /* 16 store   */
 
 #define M_IST_INTERN(a,b,disp)  M_ITYPE(0x2b,b,a,disp)          /* 32 store   */
-#define M_LST_INTERN(a,b,disp)  M_ITYPE(0x3f,b,a,disp)          /* 64 store   */
 
 #define M_IST(a,b,disp) \
     do { \
         } else { \
             M_LUI(REG_ITMP3, hi); \
             M_AADD(b, REG_ITMP3, REG_ITMP3); \
-            M_IST_INTERN(a,REG_ITMP3,lo); \
+            M_IST_INTERN(a, REG_ITMP3, lo); \
         } \
     } while (0)
 
+#if SIZEOF_VOID_P == 8
+
+#define M_LST_INTERN(a,b,disp)  M_ITYPE(0x3f,b,a,disp)          /* 64 store   */
+
+#else /* SIZEOF_VOID_P == 8 */
+
+#if WORDS_BIGENDIAN == 1
+
+#define M_LST_INTERN(a,b,disp) \
+    do { \
+        M_IST_INTERN(GET_HIGH_REG(a), b, disp); \
+        M_IST_INTERN(GET_LOW_REG(a), b, disp + 4); \
+    } while (0)
+
+#else /* if WORDS_BIGENDIAN == 1 */
+
+#define M_LST_INTERN(a,b,disp) \
+    do { \
+        M_IST_INTERN(GET_HIGH_REG(a), b, disp + 4); \
+        M_IST_INTERN(GET_LOW_REG(a), b, disp); \
+    } while (0)
+
+#endif /* if WORDS_BIGENDIAN == 1 */
+
+#endif /* SIZEOF_VOID_P == 8 */
+
 #define M_LST(a,b,disp) \
     do { \
         s4 lo = (short) (disp); \
         } else { \
             M_LUI(REG_ITMP3, hi); \
             M_AADD(b, REG_ITMP3, REG_ITMP3); \
-            M_LST_INTERN(a,REG_ITMP3,lo); \
+            M_LST_INTERN(a, REG_ITMP3, lo); \
         } \
     } while (0)
 
         if (hi == 0) { \
             M_FLD_INTERN(a,b,lo); \
         } else { \
-            M_LUI(REG_ITMP3,hi); \
-            M_AADD(b,REG_ITMP3,REG_ITMP3); \
-            M_FLD_INTERN(a,REG_ITMP3,lo); \
+            M_LUI(REG_ITMP3, hi); \
+            M_AADD(b, REG_ITMP3, REG_ITMP3); \
+            M_FLD_INTERN(a, REG_ITMP3, lo); \
         } \
     } while (0)
 
         if (hi == 0) { \
             M_DLD_INTERN(a,b,lo); \
         } else { \
-            M_LUI(REG_ITMP3,hi); \
-            M_AADD(b,REG_ITMP3,REG_ITMP3); \
-            M_DLD_INTERN(a,REG_ITMP3,lo); \
+            M_LUI(REG_ITMP3, hi); \
+            M_AADD(b, REG_ITMP3, REG_ITMP3); \
+            M_DLD_INTERN(a, REG_ITMP3, lo); \
         } \
     } while (0)
 
         } else { \
             M_LUI(REG_ITMP3, hi); \
             M_AADD(b, REG_ITMP3, REG_ITMP3); \
-            M_FST_INTERN(a,REG_ITMP3,lo); \
+            M_FST_INTERN(a, REG_ITMP3, lo); \
         } \
     } while (0)
 
         } else { \
             M_LUI(REG_ITMP3, hi); \
             M_AADD(b, REG_ITMP3, REG_ITMP3); \
-            M_DST_INTERN(a,REG_ITMP3,lo); \
+            M_DST_INTERN(a, REG_ITMP3, lo); \
         } \
     } while (0)
 
 #define M_BGEZ(a,disp)          M_ITYPE(0x01,a,1,disp)          /* br a >= 0  */
 #define M_BGTZ(a,disp)          M_ITYPE(0x07,a,0,disp)          /* br a >  0  */
 
+#if 0
 #define M_BEQL(a,b,disp)        M_ITYPE(0x14,a,b,disp)          /* br a == b  */
 #define M_BNEL(a,b,disp)        M_ITYPE(0x15,a,b,disp)          /* br a != b  */
 #define M_BEQZL(a,disp)         M_ITYPE(0x14,a,0,disp)          /* br a == 0  */
 #define M_BNEZL(a,disp)         M_ITYPE(0x15,a,0,disp)          /* br a != 0  */
 #define M_BGEZL(a,disp)         M_ITYPE(0x01,a,3,disp)          /* br a >= 0  */
 #define M_BGTZL(a,disp)         M_ITYPE(0x17,a,0,disp)          /* br a >  0  */
+#endif
 
 #define M_BR(disp)              M_ITYPE(0x04,0,0,disp)          /* branch     */
 #define M_BRS(disp)             M_ITYPE(0x01,0,17,disp)         /* branch sbr */
 #define M_ISUB(a,b,c)           M_RTYPE(0,a,b,c,0,0x23)         /* 32 sub     */
 #define M_LSUB(a,b,c)           M_RTYPE(0,a,b,c,0,0x2f)         /* 64 sub     */
 #define M_IMUL(a,b)             M_ITYPE(0,a,b,0x18)             /* 32 mul     */
+#define M_IMULU(a,b)            M_ITYPE(0,a,b,0x19)             /* 32 mul     */
 #define M_LMUL(a,b)             M_ITYPE(0,a,b,0x1c)             /* 64 mul     */
 #define M_IDIV(a,b)             M_ITYPE(0,a,b,0x1a)             /* 32 div     */
 #define M_LDIV(a,b)             M_ITYPE(0,a,b,0x1e)             /* 64 div     */
 
 #define M_IADD_IMM(a,b,c)       M_ITYPE(0x09,a,c,b)             /* 32 add     */
 #define M_LADD_IMM(a,b,c)       M_ITYPE(0x19,a,c,b)             /* 64 add     */
-#define M_ISUB_IMM(a,b,c)       M_ITYPE(0x09,a,c,-(b))          /* 32 sub     */
-#define M_LSUB_IMM(a,b,c)       M_ITYPE(0x19,a,c,-(b))          /* 64 sub     */
+#define M_ISUB_IMM(a,b,c)       M_IADD_IMM(a,-(b),c)            /* 32 sub     */
+#define M_LSUB_IMM(a,b,c)       M_LADD_IMM(a,-(b),c)            /* 64 sub     */
 
 #define M_LUI(a,imm)            M_ITYPE(0x0f,0,a,imm)           /* a = imm<<16*/
 
 #define M_OR_IMM( a,b,c)        M_ITYPE(0x0d,a,c,b)             /* c = a |  b */
 #define M_XOR_IMM(a,b,c)        M_ITYPE(0x0e,a,c,b)             /* c = a ^  b */
 
-#define M_CZEXT(a,c)            M_AND_IMM(a,0xffff,c)           /* c = zext(a)*/
-
 #define M_ISLL(a,b,c)           M_RTYPE(0,b,a,c,0,0x04)         /* c = a << b */
 #define M_ISRL(a,b,c)           M_RTYPE(0,b,a,c,0,0x06)         /* c = a >>>b */
 #define M_ISRA(a,b,c)           M_RTYPE(0,b,a,c,0,0x07)         /* c = a >> b */
 #define M_MOVID(i,d)            M_FP3(0,4,d,i,0)                /* d = i      */
 #define M_MOVLD(l,d)            M_FP3(0,5,d,l,0)                /* d = l      */
 
+#define M_MFC1(l,f)             M_FP3(0,0,f,l,0)
+#define M_MTC1(l,f)             M_FP3(0,4,f,l,0)
+
 #define M_DMFC1(l,f)            M_FP3(0,1,f,l,0)
 #define M_DMTC1(l,f)            M_FP3(0,5,f,l,0)
 
 
 #endif /* SIZEOF_VOID_P == 8 */
 
-
-/* function gen_resolvebranch **************************************************
-
-       backpatches a branch instruction; MIPS branch instructions are very
-       regular, so it is only necessary to overwrite some fixed bits in the
-       instruction.
-
-       parameters: ip ... pointer to instruction after branch (void*)
-                   so ... offset of instruction after branch  (s4)
-                   to ... offset of branch target             (s4)
-
-*******************************************************************************/
-
-#define gen_resolvebranch(ip,so,to) \
-    do { \
-        s4 offset; \
-        \
-        offset = ((s4) (to) - (so)) >> 2; \
-        \
-        /* On the MIPS we can only branch signed 16-bit instruction words */ \
-        /* (signed 18-bit = 32KB = +/- 16KB). Check this!                 */ \
-        \
-        if ((offset < (s4) 0xffff8000) || (offset > (s4) 0x00007fff)) { \
-            throw_cacao_exception_exit(string_java_lang_InternalError, \
-                                       "Jump offset is out of range: %d > +/-%d", \
-                                       offset, 0x00007fff); \
-        } \
-        \
-        ((s4 *) (ip))[-1] |= (offset & 0x0000ffff); \
-    } while (0)
-
-
-/* function prototypes ********************************************************/
-
-void docacheflush(u1 *p, long bytelen);
-
 #endif /* _CODEGEN_H */