* Merged in twisti-branch.
[cacao.git] / src / vm / jit / sparc64 / codegen.h
index 7eb54dd5ceffde61456cbee775b7e1c12734e467..6edfa3b1bfffb625e44affa31b2689fe2d1d4337 100644 (file)
 
 #include "vm/jit/jit.h"
 
+#include "md-abi.h" /* for INT_NATARG_CNT */
+
+#include <assert.h>
+
 /* from md-abi.c */
 s4 nat_argintregs[INT_NATARG_CNT];
 
@@ -59,6 +63,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; \
@@ -68,28 +75,6 @@ s4 nat_argintregs[INT_NATARG_CNT];
 
 /* additional functions and macros to generate code ***************************/
 
-#define gen_nullptr_check(objreg) \
-    if (checknull) { \
-        M_BEQZ(objreg, 0); \
-        codegen_add_nullpointerexception_ref(cd); \
-        M_NOP; \
-    }
-
-#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)
 
 /* MCODECHECK(icnt) */
 
@@ -140,8 +125,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
@@ -160,6 +145,10 @@ s4 nat_argintregs[INT_NATARG_CNT];
        } 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
@@ -176,16 +165,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)
 
@@ -202,13 +191,13 @@ s4 nat_argintregs[INT_NATARG_CNT];
  #define M_FMT4(op,op3,rd,rs2,cond,cc2,cc1,cc0,imm) \
        do { \
                *((u4 *) cd->mcodeptr) =  ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((cc2) << 18) |  ((cond) << 14) | \
-                       ((imm) << 13) | ((cc1) << 12) | ((cc0) << 11) | ((rs2) << 0) ); \
+                       ((imm) << 13) | ((cc1) << 12) | ((cc0) << 11) | ((rs2) & 0x7ff) ); \
                cd->mcodeptr += 4; \
        } while (0)
 
 
-#define FR_X(r) (((r)<<1) + 1)
-#define DR_X(r) (((r)<<1)|((r)>>5))
+#define FR_X(r) (((r)<<1) + 1) /* transpose macro for floats which reside in upper half of double word */
+#define DR_X(r) ((((r)*2)|(((r)*2)>>5)) & 0x1f) /* transpose & pack double, see SPARC spec.            */
 
 /* 3-address-floating-point-operation
  *   op .... opcode
@@ -240,6 +229,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 
@@ -282,8 +294,6 @@ s4 nat_argintregs[INT_NATARG_CNT];
                cd->mcodeptr += 4; \
        } while (0)
 
-
-
 #define M_NOP M_SETHI(0,0)      /* nop */
 
 #define M_AND(rs1,rs2,rd)       M_OP3(0x02,0x01,rd,rs1,rs2,REG)     /* 64b c = a &  b */
@@ -303,16 +313,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 */
@@ -379,21 +391,61 @@ s4 nat_argintregs[INT_NATARG_CNT];
 #define M_CMOVRGE_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x7,rd,rs1,rs2,IMM)  /* rs1>=0 ? rd=rs2 */
 
 
-/**** load/store operations ********/
+/**** big constant helpers *********/
+
+/* #define FITS_13BIT_IMM(x)       ((x >= -4096) && (x <= 4095)) */
+
+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)
+
+#define DO_SETHI_REG(c,rd) \
+       do { \
+               if (c > 0) { \
+                       M_SETHI(sethi_part(c), rd); \
+                       if (setlo_part(c)) { \
+                               M_OR_IMM(rd, setlo_part(c), rd); \
+                       } \
+               } \
+               else { \
+                       M_SETHI(sethi_part(~c), rd); \
+                       M_XOR_IMM(rd, setlo_part(c) | 0xffffffffffff1c00, rd); \
+               } \
+       } while (0)
+       
+#define DO_SETHI_PART(c,rs,rd) \
+       do { \
+               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) \
     do { \
-        s4 lo = (short) (disp); \
-        s4 hi = (short) (((disp) - lo) >> 13); \
-        if (hi == 0) { \
-            M_AADD_IMM(rs,lo,rd); \
-        } else { \
-            M_SETHI(hi&0x3ffff8,rd); \
-            M_AADD_IMM(rd,lo,rd); \
+        if (fits_13(disp)) { \
+            M_AADD_IMM(rs,disp,rd); \
+        } \
+        else { \
+            DO_SETHI_REG(disp,rd); \
             M_AADD(rd,rs,rd); \
         } \
     } while (0)
 
+/**** load/store operations ********/
+
 #define M_SLDU(rd,rs,disp)      M_OP3(0x03,0x02,rd,rs,disp,IMM)        /* 16-bit load, uns*/
 #define M_SLDS(rd,rs,disp)      M_OP3(0x03,0x0a,rd,rs,disp,IMM)        /* 16-bit load, sig*/
 #define M_BLDS(rd,rs,disp)      M_OP3(0x03,0x09,rd,rs,disp,IMM)        /* 8-bit load, sig */
@@ -402,28 +454,24 @@ s4 nat_argintregs[INT_NATARG_CNT];
 #define M_LDX_INTERN(rd,rs,disp) M_OP3(0x03,0x0b,rd,rs,disp,IMM)       /* 64-bit load, sig*/
 #define M_LDX(rd,rs,disp) \
        do { \
-        s4 lo = (short) (disp); \
-        s4 hi = (short) (((disp) - lo) >> 13); \
-        if (hi == 0) { \
-            M_LDX_INTERN(rd,rs,lo); \
-        } else { \
-            M_SETHI(hi&0x3ffff8,rd); \
-            M_AADD(rs,rd,rd); \
-            M_LDX_INTERN(rd,rd,lo); \
+        if (fits_13(disp)) { \
+            M_LDX_INTERN(rd,rs,disp); \
+        } \
+        else { \
+               DO_SETHI_PART(disp,rs,rd); \
+               M_LDX_INTERN(rd,rd,get_lopart_disp(disp)); \
         } \
     } while (0)
 
 #define M_ILD_INTERN(rd,rs,disp) M_OP3(0x03,0x08,rd,rs,disp,IMM)       /* 32-bit load, sig */
 #define M_ILD(rd,rs,disp) \
        do { \
-        s4 lo = (short) (disp); \
-        s4 hi = (short) (((disp) - lo) >> 13); \
-        if (hi == 0) { \
-            M_ILD_INTERN(rd,rs,lo); \
-        } else { \
-            M_SETHI(hi&0x3ffff8,rd); \
-            M_AADD(rs,rd,rd); \
-            M_ILD_INTERN(rd,rd,lo); \
+        if (fits_13(disp)) { \
+            M_ILD_INTERN(rd,rs,disp); \
+       } \
+        else { \
+            DO_SETHI_PART(disp,rs,rd); \
+            M_ILD_INTERN(rd,rd,get_lopart_disp(disp)); \
         } \
     } while (0)
 
@@ -439,14 +487,13 @@ s4 nat_argintregs[INT_NATARG_CNT];
 #define M_STX_INTERN(rd,rs,disp) M_OP3(0x03,0x0e,rd,rs,disp,IMM)       /* 64-bit store    */
 #define M_STX(rd,rs,disp) \
        do { \
-        s4 lo = (short) (disp); \
-        s4 hi = (short) (((disp) - lo) >> 13); \
-        if (hi == 0) { \
-            M_STX_INTERN(rd,rs,lo); \
-        } else { \
-            M_SETHI(hi&0x3ffff8,REG_ITMP3); /* sethi has a 22bit imm, only set upper 19 bits */ \
-            M_AADD(rs,REG_ITMP3,REG_ITMP3); \
-            M_STX_INTERN(rd,REG_ITMP3,lo); \
+        if (fits_13(disp)) { \
+            M_STX_INTERN(rd,rs,disp); \
+        } \
+        else { \
+            DO_SETHI_PART(disp,rs,REG_ITMP3); \
+            M_STX_INTERN(rd,REG_ITMP3,setlo_part(disp)); \
+                       assert(0); \
         } \
     } while (0)
 
@@ -454,14 +501,13 @@ s4 nat_argintregs[INT_NATARG_CNT];
 #define M_IST_INTERN(rd,rs,disp) M_OP3(0x03,0x04,rd,rs,disp,IMM)       /* 32-bit store    */
 #define M_IST(rd,rs,disp) \
     do { \
-        s4 lo = (short) (disp); \
-        s4 hi = (short) (((disp) - lo) >> 13); \
-        if (hi == 0) { \
-            M_IST_INTERN(rd,rs,lo); \
-        } else { \
-            M_SETHI(hi&0x3ffff8,REG_ITMP3); /* sethi has a 22bit imm, only set upper 19 bits */ \
-            M_AADD(rs,REG_ITMP3,REG_ITMP3); \
-            M_IST_INTERN(rd,REG_ITMP3,lo); \
+        if (fits_13(disp)) { \
+            M_IST_INTERN(rd,rs,disp); \
+       } \
+        else { \
+            DO_SETHI_PART(disp,rs,REG_ITMP3); \
+            M_IST_INTERN(rd,REG_ITMP3,setlo_part(disp)); \
+                       assert(0); \
         } \
     } while (0)
 
@@ -488,6 +534,7 @@ s4 nat_argintregs[INT_NATARG_CNT];
 #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 */
@@ -500,6 +547,7 @@ s4 nat_argintregs[INT_NATARG_CNT];
 #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  */
 
 
@@ -537,8 +585,8 @@ s4 nat_argintregs[INT_NATARG_CNT];
 /**** 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 */
 
@@ -552,8 +600,8 @@ s4 nat_argintregs[INT_NATARG_CNT];
 #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 */