* src/vm/jit/codegen-common.c (codegen_increase): Changed signature.
[cacao.git] / src / vm / jit / alpha / codegen.h
index e286880aabd9b80ed47751f568d7433acbc3909d..3e81bff67fde688c43a4c69555da001f420626fd 100644 (file)
@@ -1,10 +1,9 @@
-/* jit/alpha/codegen.h - code generation macros and definitions for alpha
+/* vm/jit/alpha/codegen.h - code generation macros and definitions for Alpha
 
-   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 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
+   Contact: cacao@cacaojvm.org
 
    Authors: Andreas Krall
             Reinhard Grafl
 
-   $Id: codegen.h 594 2003-11-09 19:54:50Z twisti $
+   Changes: Christian Thalinger
+
+   $Id: codegen.h 4826 2006-04-24 16:06:16Z twisti $
 
 */
 
 #ifndef _CODEGEN_H
 #define _CODEGEN_H
 
-#include "jit.h"
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/jit/jit.h"
+
 
+/* additional functions and macros to generate code ***************************/
 
-/* see also file calling.doc for explanation of calling conventions           */
+/* gen_nullptr_check(objreg) */
 
-/* preallocated registers *****************************************************/
+#define gen_nullptr_check(objreg) \
+    if (checknull) { \
+        M_BEQZ((objreg), 0); \
+        codegen_add_nullpointerexception_ref(cd); \
+    }
 
-/* integer registers */
-  
-#define REG_RESULT      0    /* to deliver method results                     */ 
+#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, s2); \
+    }
 
-#define REG_RA          26   /* return address                                */
-#define REG_PV          27   /* procedure vector, must be provided by caller  */
-#define REG_METHODPTR   28   /* pointer to the place from where the procedure */
-                             /* vector has been fetched                       */
-#define REG_ITMP1       25   /* temporary register                            */
-#define REG_ITMP2       28   /* temporary register and method pointer         */
-#define REG_ITMP3       29   /* temporary register                            */
 
-#define REG_ITMP1_XPTR  25   /* exception pointer = temporary register 1      */
-#define REG_ITMP2_XPC   28   /* exception pc = temporary register 2           */
+/* MCODECHECK(icnt) */
 
-#define REG_SP          30   /* stack pointer                                 */
-#define REG_ZERO        31   /* allways zero                                  */
+#define MCODECHECK(icnt) \
+    do { \
+        if ((cd->mcodeptr + (icnt)) > (u4 *) cd->mcodeend) \
+            codegen_increase(cd); \
+    } while (0)
 
-/* floating point registers */
 
-#define REG_FRESULT     0    /* to deliver floating point method results      */ 
-#define REG_FTMP1       28   /* temporary floating point register             */
-#define REG_FTMP2       29   /* temporary floating point register             */
-#define REG_FTMP3       30   /* temporary floating point register             */
+#define ALIGNCODENOP \
+    if ((s4) ((ptrint) cd->mcodeptr & 7)) { \
+        M_NOP; \
+    }
 
-#define REG_IFTMP       28   /* temporary integer and floating point register */
 
+/* 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_INTMOVE(a,b) \
+    do { \
+        if ((a) != (b)) \
+            M_MOV(a, b); \
+    } while (0)
 
-#define INT_SAV_CNT      7   /* number of int callee saved registers          */
-#define INT_ARG_CNT      6   /* number of int argument registers              */
 
-#define FLT_SAV_CNT      8   /* number of flt callee saved registers          */
-#define FLT_ARG_CNT      6   /* number of flt argument registers              */
+/* 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
+*/ 
+
+#define M_FLTMOVE(a,b) \
+    do { \
+        if ((a) != (b)) \
+            M_FMOV(a, b); \
+    } while (0)
+
+
+#define M_COPY(s,d)                     emit_copy(jd, iptr, (s), (d))
+#define ICONST(d,c)                     emit_iconst(cd, (d), (c))
+#define LCONST(d,c)                     emit_lconst(cd, (d), (c))
 
 
 /* macros to create code ******************************************************/
                  (REG means: use b as register number)
                  (CONST means: use b as constant 8-bit-integer)
 */      
+
 #define M_OP3(op,fu,a,b,c,const) \
-       *(mcodeptr++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<(16-3*(const)))| \
-       ((const)<<12)|((fu)<<5)|((c)) )
+       *(cd->mcodeptr++) = ((((s4) (op)) << 26) | ((a) << 21) | ((b) << (16 - 3 * (const))) | ((const) << 12) | ((fu) << 5) | ((c)))
+
 
 /* 3-address-floating-point-operation: M_FOP3 
      op .... opcode
      a,b ... source floating-point registers
      c ..... destination register
 */ 
+
 #define M_FOP3(op,fu,a,b,c) \
-       *(mcodeptr++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((fu)<<5)|(c) )
+       *(cd->mcodeptr++) = ((((s4) (op)) << 26) | ((a) << 21) | ((b) << 16) | ((fu) << 5) | (c))
+
 
 /* branch instructions: M_BRA 
       op ..... opcode
       a ...... register to be tested
       disp ... relative address to be jumped to (divided by 4)
 */
+
 #define M_BRA(op,a,disp) \
-       *(mcodeptr++) = ( (((s4)(op))<<26)|((a)<<21)|((disp)&0x1fffff) )
+       *(cd->mcodeptr++) = ((((s4) (op)) << 26) | ((a) << 21) | ((disp) & 0x1fffff))
 
 
 /* memory operations: M_MEM
       b ...... base register
       disp ... displacement (16 bit signed) to be added to b
 */ 
+
 #define M_MEM(op,a,b,disp) \
-       *(mcodeptr++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((disp)&0xffff) )
+       *(cd->mcodeptr++) = ((((s4) (op)) << 26) | ((a) << 21) | ((b) << 16) | ((disp) & 0xffff))
+
+
+/* macros for all used commands (see an Alpha-manual for description) *********/
 
+#define M_LDA_INTERN(a,b,disp)  M_MEM(0x08,a,b,disp)            /* low const  */
 
-/* macros for all used commands (see an Alpha-manual for description) *********/ 
+#define M_LDA(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_LDA_INTERN(a,b,lo); \
+        } else { \
+            M_LDAH(a,b,hi); \
+            M_LDA_INTERN(a,a,lo); \
+        } \
+    } while (0)
 
-#define M_LDA(a,b,disp)         M_MEM (0x08,a,b,disp)           /* low const  */
 #define M_LDAH(a,b,disp)        M_MEM (0x09,a,b,disp)           /* high const */
+
 #define M_BLDU(a,b,disp)        M_MEM (0x0a,a,b,disp)           /*  8 load    */
 #define M_SLDU(a,b,disp)        M_MEM (0x0c,a,b,disp)           /* 16 load    */
-#define M_ILD(a,b,disp)         M_MEM (0x28,a,b,disp)           /* 32 load    */
-#define M_LLD(a,b,disp)         M_MEM (0x29,a,b,disp)           /* 64 load    */
-#define M_ALD(a,b,disp)         M_MEM (0x29,a,b,disp)           /* addr load  */
-#define M_BST(a,b,disp)         M_MEM (0x0e,a,b,disp)           /*  8 store   */
-#define M_SST(a,b,disp)         M_MEM (0x0d,a,b,disp)           /* 16 store   */
-#define M_IST(a,b,disp)         M_MEM (0x2c,a,b,disp)           /* 32 store   */
-#define M_LST(a,b,disp)         M_MEM (0x2d,a,b,disp)           /* 64 store   */
-#define M_AST(a,b,disp)         M_MEM (0x2d,a,b,disp)           /* addr store */
+
+#define M_ILD_INTERN(a,b,disp)  M_MEM(0x28,a,b,disp)            /* 32 load    */
+#define M_LLD_INTERN(a,b,disp)  M_MEM(0x29,a,b,disp)            /* 64 load    */
+
+#define M_ILD(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_ILD_INTERN(a,b,lo); \
+        } else { \
+            M_LDAH(a,b,hi); \
+            M_ILD_INTERN(a,a,lo); \
+        } \
+    } while (0)
+
+#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); \
+        } else { \
+            M_LDAH(a,b,hi); \
+            M_LLD_INTERN(a,a,lo); \
+        } \
+    } while (0)
+
+#define M_ALD(a,b,disp)         M_LLD(a,b,disp)                 /* addr load  */
+
+#define M_BST(a,b,disp)         M_MEM(0x0e,a,b,disp)            /*  8 store   */
+#define M_SST(a,b,disp)         M_MEM(0x0d,a,b,disp)            /* 16 store   */
+
+#define M_IST_INTERN(a,b,disp)  M_MEM(0x2c,a,b,disp)            /* 32 store   */
+#define M_LST_INTERN(a,b,disp)  M_MEM(0x2d,a,b,disp)            /* 64 store   */
+
+/* Stores with displacement overflow should only happen with PUTFIELD or on   */
+/* the stack. The PUTFIELD instruction does not use REG_ITMP3 and a           */
+/* reg_of_var call should not use REG_ITMP3!!!                                */
+
+#define M_IST(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_IST_INTERN(a,b,lo); \
+        } else { \
+            M_LDAH(REG_ITMP3,b,hi); \
+            M_IST_INTERN(a,REG_ITMP3,lo); \
+        } \
+    } while (0)
+
+#define M_LST(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_LST_INTERN(a,b,lo); \
+        } else { \
+            M_LDAH(REG_ITMP3,b,hi); \
+            M_LST_INTERN(a,REG_ITMP3,lo); \
+        } \
+    } while (0)
+
+#define M_AST(a,b,disp)         M_LST(a,b,disp)                 /* addr store */
 
 #define M_BSEXT(b,c)            M_OP3 (0x1c,0x0,REG_ZERO,b,c,0) /*  8 signext */
 #define M_SSEXT(b,c)            M_OP3 (0x1c,0x1,REG_ZERO,b,c,0) /* 16 signext */
 #define M_IMUL_IMM(a,b,c)       M_OP3 (0x13,0x00, a,b,c,1)      /* 32 mul     */
 #define M_LMUL_IMM(a,b,c)       M_OP3 (0x13,0x20, a,b,c,1)      /* 64 mul     */
 
+#define M_AADD_IMM(a,b,c)       M_LADD_IMM(a,b,c)
+
 #define M_CMPEQ(a,b,c)          M_OP3 (0x10,0x2d, a,b,c,0)      /* c = a == b */
 #define M_CMPLT(a,b,c)          M_OP3 (0x10,0x4d, a,b,c,0)      /* c = a <  b */
 #define M_CMPLE(a,b,c)          M_OP3 (0x10,0x6d, a,b,c,0)      /* c = a <= b */
 #define M_SRA_IMM(a,b,c)        M_OP3 (0x12,0x3c, a,b,c,1)      /* c = a >> b */
 #define M_SRL_IMM(a,b,c)        M_OP3 (0x12,0x34, a,b,c,1)      /* c = a >>>b */
 
-#define M_FLD(a,b,disp)         M_MEM (0x22,a,b,disp)           /* load flt   */
-#define M_DLD(a,b,disp)         M_MEM (0x23,a,b,disp)           /* load dbl   */
-#define M_FST(a,b,disp)         M_MEM (0x26,a,b,disp)           /* store flt  */
-#define M_DST(a,b,disp)         M_MEM (0x27,a,b,disp)           /* store dbl  */
+#define M_FLD_INTERN(a,b,disp)  M_MEM(0x22,a,b,disp)            /* load flt   */
+#define M_DLD_INTERN(a,b,disp)  M_MEM(0x23,a,b,disp)            /* load dbl   */
+
+#define M_FLD(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_FLD_INTERN(a,b,lo); \
+        } else { \
+            M_LDAH(REG_ITMP3,b,hi); \
+            M_FLD_INTERN(a,REG_ITMP3,lo); \
+        } \
+    } while (0)
+
+#define M_DLD(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_DLD_INTERN(a,b,lo); \
+        } else { \
+            M_LDAH(REG_ITMP3,b,hi); \
+            M_DLD_INTERN(a,REG_ITMP3,lo); \
+        } \
+    } while (0)
+
+#define M_FST_INTERN(a,b,disp)  M_MEM(0x26,a,b,disp)            /* store flt  */
+#define M_DST_INTERN(a,b,disp)  M_MEM(0x27,a,b,disp)            /* store dbl  */
+
+/* Stores with displacement overflow should only happen with PUTFIELD or on   */
+/* the stack. The PUTFIELD instruction does not use REG_ITMP3 and a           */
+/* reg_of_var call should not use REG_ITMP3!!!                                */
+
+#define M_FST(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_FST_INTERN(a,b,lo); \
+        } else { \
+            M_LDAH(REG_ITMP3,b,hi); \
+            M_FST_INTERN(a,REG_ITMP3,lo); \
+        } \
+    } while (0)
+
+#define M_DST(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_DST_INTERN(a,b,lo); \
+        } else { \
+            M_LDAH(REG_ITMP3,b,hi); \
+            M_DST_INTERN(a,REG_ITMP3,lo); \
+        } \
+    } while (0)
+
 
 #define M_FADD(a,b,c)           M_FOP3 (0x16, 0x080, a,b,c)     /* flt add    */
 #define M_DADD(a,b,c)           M_FOP3 (0x16, 0x0a0, a,b,c)     /* dbl add    */
 #define M_FDIVS(a,b,c)          M_FOP3 (0x16, 0x583, a,b,c)     /* flt div    */
 #define M_DDIVS(a,b,c)          M_FOP3 (0x16, 0x5a3, a,b,c)     /* dbl div    */
 
-#define M_CVTDF(b,c)            M_FOP3 (0x16, 0x0ac, 31,b,c)    /* dbl2long   */
+#define M_CVTDF(b,c)            M_FOP3 (0x16, 0x0ac, 31,b,c)    /* dbl2flt    */
 #define M_CVTLF(b,c)            M_FOP3 (0x16, 0x0bc, 31,b,c)    /* long2flt   */
 #define M_CVTLD(b,c)            M_FOP3 (0x16, 0x0be, 31,b,c)    /* long2dbl   */
 #define M_CVTDL(b,c)            M_FOP3 (0x16, 0x1af, 31,b,c)    /* dbl2long   */
 #define M_CVTDL_C(b,c)          M_FOP3 (0x16, 0x12f, 31,b,c)    /* dbl2long   */
 #define M_CVTLI(b,c)            M_FOP3 (0x17, 0x130, 31,b,c)    /* long2int   */
 
-#define M_CVTDFS(b,c)           M_FOP3 (0x16, 0x5ac, 31,b,c)    /* dbl2long   */
+#define M_CVTDFS(b,c)           M_FOP3 (0x16, 0x5ac, 31,b,c)    /* dbl2flt    */
+#define M_CVTFDS(b,c)           M_FOP3 (0x16, 0x6ac, 31,b,c)    /* flt2dbl    */
 #define M_CVTDLS(b,c)           M_FOP3 (0x16, 0x5af, 31,b,c)    /* dbl2long   */
 #define M_CVTDL_CS(b,c)         M_FOP3 (0x16, 0x52f, 31,b,c)    /* dbl2long   */
 #define M_CVTLIS(b,c)           M_FOP3 (0x17, 0x530, 31,b,c)    /* long2int   */
 #define M_JMP_CO(a,b)           M_MEM (0x1a,a,b,0xc000)        /* call cosub  */
 
 
-/* function gen_resolvebranch **************************************************
+/* gen_resolvebranch ***********************************************************
 
-       backpatches a branch instruction; Alpha branch instructions are very
-       regular, so it is only necessary to overwrite some fixed bits in the
-       instruction.
+   backpatches a branch instruction; Alpha 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)
+   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) ((s4*)(ip))[-1]|=((s4)(to)-(so))>>2&0x1fffff
-
-#define SOFTNULLPTRCHECK       /* soft null pointer check supportet as option */
+#define gen_resolvebranch(ip,so,to) \
+    ((s4 *) (ip))[-1] |= ((s4) (to) - (so)) >> 2 & 0x1fffff
 
 #endif /* _CODEGEN_H */