* Removed all Id tags.
[cacao.git] / src / vm / jit / sparc64 / codegen.h
index f35f8cc198303fbe76553872cae37dc0e77b89a3..ade165128a665165191011b905ce4d3424039e77 100644 (file)
@@ -1,6 +1,7 @@
-/* vm/jit/sparc64/codegen.h - code generation macros and definitions for Sparc
+/* src/vm/jit/sparc64/codegen.h - code generation macros and definitions for
+                                  Sparc64
 
-   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
-            Reinhard Grafl
-            Alexander Jordan
-
-   Changes:
-
-   $Id: codegen.h 4722 2006-04-03 15:36:00Z twisti $
-
 */
 
 #ifndef _CODEGEN_H
 
 #include <assert.h>
 
+/* debug defines **************************************************************/
+#ifndef NDEBUG
+# define PASS13BIT(imm) ((((s4)(imm)&0x1fff)<<19)>>19)
+#else
+# define PASS13BIT(imm) imm
+#endif
+
+
 /* from md-abi.c */
 s4 nat_argintregs[INT_NATARG_CNT];
 
@@ -63,6 +62,9 @@ s4 nat_argintregs[INT_NATARG_CNT];
 #define PATCHER_CALL_INSTRUCTIONS    2     /* number of instructions          */
 #define PATCHER_CALL_SIZE            2 * 4 /* size in bytes of a patcher call */
 
+#define EXCEPTION_CHECK_INSTRUCTIONS 3     /* number of instructions          */
+#define EXCEPTION_CHECK_SIZE         3 * 4 /* byte size of an exception check */
+
 #define PATCHER_NOPS \
     do { \
         M_NOP; \
@@ -70,30 +72,13 @@ s4 nat_argintregs[INT_NATARG_CNT];
     } while (0)
 
 
-/* additional functions and macros to generate code ***************************/
+/* stub defines ***************************************************************/
 
-#define gen_nullptr_check(objreg) \
-    if (checknull) { \
-        M_BEQZ(objreg, 0); \
-        codegen_add_nullpointerexception_ref(cd); \
-        M_NOP; \
-    }
+#define COMPILERSTUB_CODESIZE    4 * 4
 
-#define gen_bound_check \
-    if (checkbounds) { \
-        M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size)); \
-        M_CMP(s2, REG_ITMP3); \
-        M_XBUGE(0); \
-        codegen_add_arrayindexoutofboundsexception_ref(cd, s2); \
-        M_NOP; \
-    }
 
-#define gen_div_check(r) \
-    do { \
-        M_BEQZ((r), 0); \
-        codegen_add_arithmeticexception_ref(cd); \
-        M_NOP; \
-    } while (0)
+/* additional functions and macros to generate code ***************************/
+
 
 /* MCODECHECK(icnt) */
 
@@ -109,6 +94,10 @@ s4 nat_argintregs[INT_NATARG_CNT];
         M_NOP; \
     }
 
+#define ALIGN_STACK_SLOTS(slots) \
+       if (slots & 1) \
+               slots++;
+
 
 /* M_INTMOVE:
      generates an integer-move from register rs to rd.
@@ -144,8 +133,8 @@ s4 nat_argintregs[INT_NATARG_CNT];
 
 /********************** instruction formats ***********************************/
 
-#define REG    0
-#define IMM    1
+#define REG     0
+#define IMM     1
 
 /* 3-address-operations: M_OP3
  *       op  ..... opcode
@@ -159,11 +148,16 @@ s4 nat_argintregs[INT_NATARG_CNT];
  */
 #define M_OP3(op,op3,rd,rs1,rs2,imm) \
        do { \
+               assert(check_13bit_imm(rs2)); \
                *((u4 *) cd->mcodeptr) =  ((((s4) (op)) << 30) | ((rd) << 25) | ((op3) << 19) | ((rs1) << 14) | ((imm)<<13) | (imm?((rs2)&0x1fff):(rs2)) ); \
                cd->mcodeptr += 4; \
        } while (0)
 
 
+#define M_OP3_GET_RD(x)               (((x) >> 25) & 0x1f)
+#define M_OP3_GET_RS(x)               (((x) >> 14) & 0x1f)
+#define M_OP3_GET_IMM(x)              ( (x)        & 0x1fff)
+
 /* 3-address-operations: M_OP3C
  *       rcond ... condition opcode
  *       rs2 ..... register number or 10bit signed immediate
@@ -180,16 +174,16 @@ s4 nat_argintregs[INT_NATARG_CNT];
 /* shift Format 3
  *    op ..... opcode
  *    op3..... op3 code
- *    rs1 .... source 1
- *    rs2 .... source 2 or constant
+ *    rs1 .... source reg 1
+ *    rs2 .... source reg 2 or immediate shift count (5 or 6 bits long depending whether 32 or 64 bit shift)
  *    rd ..... dest reg
  *    imm .... switch for constant
  *    x ...... 0 => 32, 1 => 64 bit shift 
  */
 #define M_SHFT(op,op3,rs1,rs2,rd,imm,x) \
        do { \
-               *((u4 *) cd->mcodeptr) =  ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((rs1) << 14) | ((rs2) << 0) | \
-                     ((imm) << 13) | ((x) << 12) ); \
+               *((u4 *) cd->mcodeptr) =  ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((rs1) << 14) | ((imm) << 13) | \
+                       ((x) << 12) | (((imm) && (x))?((rs2) & 0x3f):((rs2) & 0x1f)) ); \
                cd->mcodeptr += 4; \
        } while (0)
 
@@ -212,7 +206,7 @@ s4 nat_argintregs[INT_NATARG_CNT];
 
 
 #define FR_X(r) (((r)<<1) + 1) /* transpose macro for floats which reside in upper half of double word */
-#define DR_X(r) (((r)<<1)|((r)>>5)) /* double float packing, see SPARC spec. */
+#define DR_X(r) ((((r)*2)|(((r)*2)>>5)) & 0x1f) /* transpose & pack double, see SPARC spec.            */
 
 /* 3-address-floating-point-operation
  *   op .... opcode
@@ -244,6 +238,29 @@ s4 nat_argintregs[INT_NATARG_CNT];
                cd->mcodeptr += 4; \
        } while (0)
 
+/* 3-address-floating-point-compare-operation
+ *   op .... opcode
+ *   op3,opf .... function-number
+ *   fcc ... floating point condition code (fcc0 - fcc3)
+ *   rs1 ... source reg
+ *   rs2 ... source reg
+ *   
+ *
+ */ 
+#define M_FCMP_DX(op,op3,opf,fcc,rs1,rs2) \
+       do { \
+               *((u4 *) cd->mcodeptr) =  ( (((s4)(op))<<30) | ((fcc)<<25) | ((op3)<<19) | (DR_X(rs1) << 14) | \
+               ((opf)<<5) | DR_X(rs2) ); \
+               cd->mcodeptr += 4; \
+       } while (0)
+       
+#define M_FCMP_FX(op,op3,opf,fcc,rs1,rs2) \
+       do { \
+               *((u4 *) cd->mcodeptr) =  ( (((s4)(op))<<30) | ((fcc)<<25) | ((op3)<<19) | (FR_X(rs1) << 14) | \
+               ((opf)<<5) | FR_X(rs2) ); \
+               cd->mcodeptr += 4; \
+       } while (0)
+
 /**** format 2 operations ********/
 
 /* branch on integer reg instruction 
@@ -305,16 +322,18 @@ s4 nat_argintregs[INT_NATARG_CNT];
 
 #define M_SLLX(rs1,rs2,rd)             M_SHFT(0x02,0x25,rs1,rs2,rd,REG,1)      /* 64b rd = rs << rs2 */
 #define M_SLLX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x25,rs1,rs2,rd,IMM,1)
+#define M_SLL(rs1,rs2,rd)              M_SHFT(0x02,0x25,rs1,rs2,rd,REG,0)      /* 32b rd = rs << rs2 */
+#define M_SLL_IMM(rs1,rs2,rd)  M_SHFT(0x02,0x25,rs1,rs2,rd,IMM,0)
 #define M_SRLX(rs1,rs2,rd)             M_SHFT(0x02,0x26,rs1,rs2,rd,REG,1)      /* 64b rd = rs >>>rs2 */
 #define M_SRLX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x26,rs1,rs2,rd,IMM,1)
 #define M_SRL(rs1,rs2,rd)              M_SHFT(0x02,0x26,rs1,rs2,rd,REG,0)      /* 32b rd = rs >>>rs2 */
 #define M_SRL_IMM(rs1,rs2,rd)  M_SHFT(0x02,0x26,rs1,rs2,rd,IMM,0)
 #define M_SRAX(rs1,rs2,rd)             M_SHFT(0x02,0x27,rs1,rs2,rd,REG,1)      /* 64b rd = rs >> rs2 */
 #define M_SRAX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x27,rs1,rs2,rd,IMM,1)
-#define M_SRA(rs1,rs2,rd)              M_SHFT(0x02,0x27,rs1,rs2,rd,REG,0)      /* 32b rd = rs >> rs2 */
+#define M_SRA(rs1,rs2,rd)       M_SHFT(0x02,0x27,rs1,rs2,rd,REG,0)  /* 32b rd = rs >> rs2 */
 #define M_SRA_IMM(rs1,rs2,rd)  M_SHFT(0x02,0x27,rs1,rs2,rd,IMM,0)
 
-#define M_ISEXT(rs,rd)                         M_SRA_IMM(rs,0,rd)                  /* sign extend 32 bits*/
+#define M_ISEXT(rs,rd)                         M_SRA(rs,REG_ZERO,rd)                 /* sign extend 32 bits*/
 
 
 #define M_ADD(rs1,rs2,rd)      M_OP3(0x02,0x00,rd,rs1,rs2,REG)         /* 64b rd = rs1 + rs2 */
@@ -385,7 +404,10 @@ s4 nat_argintregs[INT_NATARG_CNT];
 
 /* #define FITS_13BIT_IMM(x)       ((x >= -4096) && (x <= 4095)) */
 
-bool fits13(s4 disp);
+bool fits_13(s4 disp);
+s4   get_lopart_disp(s4 disp);
+
+#define abs(x) ((x) < 0 ? (-(x)) : (x))
 
 #define sethi_part(x) ((x)>>10)
 #define setlo_part(x) ((x) & 0x3ff)
@@ -400,20 +422,24 @@ bool fits13(s4 disp);
                } \
                else { \
                        M_SETHI(sethi_part(~c), rd); \
-                       M_XOR_IMM(rd, setlo_part(c) | 0xffffffffffff1c00, rd); \
+                       M_XOR_IMM(rd, PASS13BIT(setlo_part(c) | 0xffffffffffff1c00), rd); \
                } \
        } while (0)
        
 #define DO_SETHI_PART(c,rs,rd) \
        do { \
-               M_SETHI(sethi_part(c), rd); \
                if (c > 0) { \
+                       M_SETHI(sethi_part(c), rd); \
                        M_ADD(rs,rd,rd); \
                } \
                else { \
+                       M_SETHI(sethi_part(-c), rd); \
                        M_SUB(rs,rd,rd); \
+                       assert(sethi_part(c) != 0xf); \
                } \
        } while (0)
+       
+
                
 
 #define M_LDA(rd,rs,disp) \
@@ -441,10 +467,8 @@ bool fits13(s4 disp);
             M_LDX_INTERN(rd,rs,disp); \
         } \
         else { \
-                       printf("ldx imm = %d\n", disp); \
-            DO_SETHI_PART(disp,rs,rd); \
-            M_LDX_INTERN(rd,rd,setlo_part(disp)); \
-                       assert(0); \
+               DO_SETHI_PART(disp,rs,rd); \
+               M_LDX_INTERN(rd,rd,PASS13BIT(get_lopart_disp(disp))); \
         } \
     } while (0)
 
@@ -456,8 +480,7 @@ bool fits13(s4 disp);
        } \
         else { \
             DO_SETHI_PART(disp,rs,rd); \
-            M_ILD_INTERN(rd,rd,setlo_part(disp)); \
-                       assert(0); \
+            M_ILD_INTERN(rd,rd,PASS13BIT(get_lopart_disp(disp))); \
         } \
     } while (0)
 
@@ -478,8 +501,7 @@ bool fits13(s4 disp);
         } \
         else { \
             DO_SETHI_PART(disp,rs,REG_ITMP3); \
-            M_STX_INTERN(rd,REG_ITMP3,setlo_part(disp)); \
-                       assert(0); \
+            M_STX_INTERN(rd,REG_ITMP3,PASS13BIT(get_lopart_disp(disp))); \
         } \
     } while (0)
 
@@ -492,8 +514,7 @@ bool fits13(s4 disp);
        } \
         else { \
             DO_SETHI_PART(disp,rs,REG_ITMP3); \
-            M_IST_INTERN(rd,REG_ITMP3,setlo_part(disp)); \
-                       assert(0); \
+            M_IST_INTERN(rd,REG_ITMP3,PASS13BIT(get_lopart_disp(disp))); \
         } \
     } while (0)
 
@@ -520,6 +541,7 @@ bool fits13(s4 disp);
 #define M_XBGE(disp)            M_BRACC(0x00,0x1,0xb,disp,2,1,0)      /* branch a>=b */
 #define M_XBLE(disp)            M_BRACC(0x00,0x1,0x2,disp,2,1,0)      /* branch a<=b */
 #define M_XBUGE(disp)           M_BRACC(0x00,0x1,0xd,disp,2,1,0)      /* br uns a>=b */
+#define M_XBUGT(disp)           M_BRACC(0x00,0x1,0xc,disp,2,1,0)      /* br uns a>b  */
 #define M_XBULT(disp)           M_BRACC(0x00,0x1,0x5,disp,2,1,0)      /* br uns a<b  */
 
 /* branch on (32-bit) integer condition codes */
@@ -532,11 +554,21 @@ bool fits13(s4 disp);
 #define M_BGE(disp)             M_BRACC(0x00,0x1,0xb,disp,0,1,0)      /* branch a>=b */
 #define M_BLE(disp)             M_BRACC(0x00,0x1,0x2,disp,0,1,0)      /* branch a<=b */
 #define M_BULE(disp)            M_BRACC(0x00,0x1,0x4,disp,0,1,0)      /* br uns a<=b */
+#define M_BUGT(disp)            M_BRACC(0x00,0x1,0xc,disp,0,1,0)      /* br uns a>b  */
 #define M_BULT(disp)            M_BRACC(0x00,0x1,0x5,disp,0,1,0)      /* br uns a<b  */
 
+/* branch on (fcc0) floating point condition codes */
+
+#define M_FBR(disp)             M_BRACC(0x00,0x5,0x8,disp,0,1,0)      /* branch      */
+#define M_FBU(disp)             M_BRACC(0x00,0x5,0x7,disp,0,1,0)      /* unordered   */
+#define M_FBG(disp)             M_BRACC(0x00,0x5,0x6,disp,0,1,0)      /* branch a>b  */
+#define M_FBL(disp)             M_BRACC(0x00,0x5,0x4,disp,0,1,0)      /* branch a<b  */
+#define M_FBO(disp)             M_BRACC(0x00,0x5,0xf,disp,0,1,0)      /* br ordered  */
+
 
 
 #define M_SAVE(rs1,rs2,rd)      M_OP3(0x02,0x3c,rd,rs1,rs2,IMM)
+#define M_SAVE_REG(rs1,rs2,rd)  M_OP3(0x02,0x3c,rd,rs1,rs2,REG)
 #define M_RESTORE(rs1,rs2,rd)   M_OP3(0x02,0x3d,rd,rs1,rs2,IMM)
 
 
@@ -551,7 +583,9 @@ bool fits13(s4 disp);
 
 
 #define M_DMOV(rs,rd)           M_FOP3_DX(0x02,0x34,0x02,rd,-1,rs)      /* rd = rs */
-#define M_FMOV(rs,rd)           M_FOP3_FX(0x02,0x34,0x01,rd,-1,rs)  /* rd = rs */
+#define M_FMOV(rs,rd)           M_FOP3_FX(0x02,0x34,0x01,rd,-1,rs)      /* rd = rs */
+
+#define M_FMOV_INTERN(rs,rd)    M_FOP3(0x02,0x34,0x01,rd,-1,rs)         /* rd = rs */
 
 #define M_FNEG(rs,rd)                  M_FOP3_FX(0x02,0x34,0x05,rd,-1,rs)              /* rd = -rs     */
 #define M_DNEG(rs,rd)                  M_FOP3_DX(0x02,0x34,0x06,rd,-1,rs)      /* rd = -rs     */
@@ -569,8 +603,8 @@ bool fits13(s4 disp);
 /**** compare and conditional FPU operations ***********/
 
 /* rd field 0 ==> fcc target unit is fcc0 */
-#define M_FCMP(rs1,rs2)                    M_FOP3_FX(0x02,0x35,0x051,0,rs1,rs2) /* set fcc flt  */
-#define M_DCMP(rs1,rs2)                    M_FOP3_DX(0x02,0x35,0x052,0,rs1,rs2)     /* set fcc dbl  */
+#define M_FCMP(rs1,rs2)                    M_FCMP_FX(0x02,0x35,0x051,0,rs1,rs2)     /* compare flt  */
+#define M_DCMP(rs1,rs2)                    M_FCMP_DX(0x02,0x35,0x052,0,rs1,rs2)     /* compare dbl  */
 
 /* conversion functions */
 
@@ -584,8 +618,8 @@ bool fits13(s4 disp);
 #define M_CVTFL(rs,rd)          M_FOP3(0x02,0x34,0x081,DR_X(rd),-1,FR_X(rs))     /* flt2long  */
 #define M_CVTDL(rs,rd)          M_FOP3_DX(0x02,0x34,0x082,rd,-1,rs)       /* dbl2long  */
 
-#define M_CVTFD(rs,rd)          M_FOP3(0x02,0x34,0x0c9,DR_X(rs),-1,FR_X(rs))     /* flt2dbl   */
-#define M_CVTDF(rs,rd)          M_FOP3(0x02,0x34,0x0c6,FR_X(rs),-1,DR_X(rs))     /* dbl2float */
+#define M_CVTFD(rs,rd)          M_FOP3(0x02,0x34,0x0c9,DR_X(rd),-1,FR_X(rs))     /* flt2dbl   */
+#define M_CVTDF(rs,rd)          M_FOP3(0x02,0x34,0x0c6,FR_X(rd),-1,DR_X(rs))     /* dbl2float */
 
 
 
@@ -599,7 +633,7 @@ bool fits13(s4 disp);
         } else { \
             M_SETHI(hi&0x3ffff8,rd); \
             M_AADD(rs,rd,rd); \
-            M_DLD_INTERN(rd,rd,lo); \
+            M_DLD_INTERN(rd,rd,PASS13BIT(lo)); \
         } \
     } while (0)
 /* Note for SETHI: sethi has a 22bit imm, only set upper 19 bits */ 
@@ -614,7 +648,7 @@ bool fits13(s4 disp);
         } else { \
             M_SETHI(hi&0x3ffff8,rd); \
             M_AADD(rs,rd,rd); \
-            M_FLD_INTERN(rd,rd,lo); \
+            M_FLD_INTERN(rd,rd,PASS13BIT(lo)); \
         } \
     } while (0)
 
@@ -629,7 +663,7 @@ bool fits13(s4 disp);
         } else { \
             M_SETHI(hi&0x3ffff8,REG_ITMP3); \
             M_AADD(rs,REG_ITMP3,REG_ITMP3); \
-            M_FST_INTERN(rd,REG_ITMP3,lo); \
+            M_FST_INTERN(rd,REG_ITMP3,PASS13BIT(lo)); \
         } \
     } while (0)
     
@@ -644,7 +678,7 @@ bool fits13(s4 disp);
         } else { \
             M_SETHI(hi&0x3ffff8,REG_ITMP3); \
             M_AADD(rs,REG_ITMP3,REG_ITMP3); \
-            M_DST_INTERN(rd,REG_ITMP3,lo); \
+            M_DST_INTERN(rd,REG_ITMP3,PASS13BIT(lo)); \
         } \
     } while (0)
     
@@ -665,38 +699,6 @@ bool fits13(s4 disp);
 #define M_AADD_IMM(a,b,c)       M_ADD_IMM(a,b,c)
 #define M_ASUB_IMM(a,b,c)       M_SUB_IMM(a,b,c)
 #define M_ASLL_IMM(a,b,c)       M_SLLX_IMM(a,b,c)
-
-
-
-
-/* var_to_reg_xxx **************************************************************
-
-   This function generates code to fetch data from a pseudo-register
-   into a real register. If the pseudo-register has actually been
-   assigned to a real register, no code will be emitted, since
-   following operations can use this register directly.
-    
-   v: pseudoregister to be fetched from
-   tempregnum: temporary register to be used if v is actually spilled to ram
-
-   return: the register number, where the operand can be found after 
-           fetching (this wil be either tempregnum or the register
-           number allready given to v)
-
-*******************************************************************************/
-
-#define var_to_reg_int(regnr,v,tempnr) \
-    do { \
-        if ((v)->flags & INMEMORY) { \
-            COUNT_SPILLS; \
-            M_LDX(tempnr, REG_SP, (v)->regoff * 8); \
-            regnr = tempnr; \
-        } else { \
-            regnr = (v)->regoff; \
-        } \
-    } while (0)
-                                                                                                                                 
-
-                                                                                                                                 
        
+
 #endif /* _CODEGEN_H */