* Merged with 60f051a3c5ae.
[cacao.git] / src / vm / jit / alpha / codegen.h
index c33802301813d80049808ce9c3aa18224939ec7c..c43ba7b6d56574ea5e20fd3e402a99be17f594a3 100644 (file)
@@ -1,6 +1,6 @@
-/* vm/jit/alpha/codegen.h - code generation macros and definitions for Alpha
+/* src/vm/jit/alpha/codegen.h - code generation macros and definitions for Alpha
 
-   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
-
-   Changes: Christian Thalinger
-
-   $Id: codegen.h 4626 2006-03-16 12:03:47Z twisti $
-
 */
 
 
 
 /* additional functions and macros to generate code ***************************/
 
-/* gen_nullptr_check(objreg) */
-
-#define gen_nullptr_check(objreg) \
-    if (checknull) { \
-        M_BEQZ((objreg), 0); \
-        codegen_add_nullpointerexception_ref(cd, mcodeptr); \
-    }
-
 #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, mcodeptr, s2); \
+        codegen_add_arrayindexoutofboundsexception_ref(cd, s2); \
     }
 
 
 /* MCODECHECK(icnt) */
 
 #define MCODECHECK(icnt) \
-       if ((mcodeptr + (icnt)) > cd->mcodeend) \
-        mcodeptr = codegen_increase(cd, (u1 *) mcodeptr)
+    do { \
+        if ((cd->mcodeptr + (icnt) * 4) > cd->mcodeend) \
+            codegen_increase(cd); \
+    } while (0)
 
 
 #define ALIGNCODENOP \
-    if ((s4) ((ptrint) mcodeptr & 7)) { \
+    if ((s4) ((ptrint) cd->mcodeptr & 7)) { \
         M_NOP; \
     }
 
      if a and b are the same int-register, no code will be generated.
 */ 
 
-#define M_INTMOVE(a,b) if (a != b) { M_MOV(a, b); }
+#define M_INTMOVE(a,b) \
+    do { \
+        if ((a) != (b)) \
+            M_MOV(a, b); \
+    } while (0)
 
 
 /* M_FLTMOVE:
     if a and b are the same float-register, no code will be generated
 */ 
 
-#define M_FLTMOVE(a,b) if (a != b) { M_FMOV(a, b); }
-
+#define M_FLTMOVE(a,b) \
+    do { \
+        if ((a) != (b)) \
+            M_FMOV(a, b); \
+    } while (0)
 
-/* 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
+#define ICONST(d,c)        emit_iconst(cd, (d), (c))
+#define LCONST(d,c)        emit_lconst(cd, (d), (c))
 
-   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)
 
-*******************************************************************************/
+/* branch defines *************************************************************/
 
-#define var_to_reg_int(regnr,v,tempnr) \
+#define BRANCH_NOPS \
     do { \
-        if ((v)->flags & INMEMORY) { \
-            COUNT_SPILLS; \
-            M_LLD(tempnr, REG_SP, (v)->regoff * 8); \
-            regnr = tempnr; \
-        } else { \
-            regnr = (v)->regoff; \
-        } \
+        M_NOP; \
     } while (0)
 
 
-#define var_to_reg_flt(regnr,v,tempnr) \
+/* patcher defines ************************************************************/
+
+#define PATCHER_CALL_SIZE    1 * 4     /* an instruction is 4-bytes long      */
+
+#define PATCHER_NOPS \
     do { \
-        if ((v)->flags & INMEMORY) { \
-            COUNT_SPILLS; \
-            M_DLD(tempnr, REG_SP, (v)->regoff * 8); \
-            regnr = tempnr; \
-        } else { \
-            regnr = (v)->regoff; \
-        } \
+        M_NOP; \
     } while (0)
 
 
-/* store_reg_to_var_xxx ********************************************************
+/* stub defines ***************************************************************/
 
-   This function generates the code to store the result of an
-   operation back into a spilled pseudo-variable. If the
-   pseudo-variable has not been spilled in the first place, this
-   function will generate nothing.
-    
-   v ............ Pseudovariable
-   tempregnum ... Number of the temporary registers as returned by
-                  reg_of_var.
+#define COMPILERSTUB_CODESIZE    1 * 4
+
+
+/* macros to create code ******************************************************/
+
+/* M_MEM - memory instruction format *******************************************
+
+    Opcode ........ opcode
+    Ra ............ source/target register for memory access
+    Rb ............ base register
+    Memory_disp ... memory displacement (16 bit signed) to be added to Rb
 
 *******************************************************************************/
 
-#define store_reg_to_var_int(sptr, tempregnum) \
+#define M_MEM(Opcode,Ra,Rb,Memory_disp) \
     do { \
-        if ((sptr)->flags & INMEMORY) { \
-            COUNT_SPILLS; \
-            M_LST(tempregnum, REG_SP, (sptr)->regoff * 8); \
-        } \
+        *((uint32_t *) cd->mcodeptr) = ((((Opcode)) << 26) | ((Ra) << 21) | ((Rb) << 16) | ((Memory_disp) & 0xffff)); \
+        cd->mcodeptr += 4; \
     } while (0)
 
-#define store_reg_to_var_flt(sptr, tempregnum) \
-    do { \
-        if ((sptr)->flags & INMEMORY) { \
-            COUNT_SPILLS; \
-            M_DST(tempregnum, REG_SP, (sptr)->regoff * 8); \
-        } \
-    } while (0)
+#define M_MEM_GET_Opcode(x)             (          (((x) >> 26) & 0x3f  ))
+#define M_MEM_GET_Ra(x)                 (          (((x) >> 21) & 0x1f  ))
+#define M_MEM_GET_Rb(x)                 (          (((x) >> 16) & 0x1f  ))
+#define M_MEM_GET_Memory_disp(x)        ((int16_t) ( (x)        & 0xffff))
 
 
-#define M_COPY(from,to) \
-       d = reg_of_var(rd, to, REG_IFTMP); \
-       if ((from->regoff != to->regoff) || \
-           ((from->flags ^ to->flags) & INMEMORY)) { \
-               if (IS_FLT_DBL_TYPE(from->type)) { \
-                       var_to_reg_flt(s1, from, d); \
-                       M_FLTMOVE(s1,d); \
-                       store_reg_to_var_flt(to, d); \
-               } else { \
-                       var_to_reg_int(s1, from, d); \
-                       M_INTMOVE(s1,d); \
-                       store_reg_to_var_int(to, d); \
-               } \
-       }
-
-#define ICONST(r,c) \
-    if ((c) >= -32768 && (c) <= 32767) { \
-        M_LDA_INTERN((r), REG_ZERO, c); \
-    } else { \
-        disp = dseg_adds4(cd, (c)); \
-        M_ILD((r), REG_PV, disp); \
-    }
+/* M_BRA - branch instruction format *******************************************
 
-#define LCONST(r,c) \
-    if ((c) >= -32768 && (c) <= 32767) { \
-        M_LDA_INTERN((r), REG_ZERO, (c)); \
-    } else { \
-        disp = dseg_adds8(cd, (c)); \
-        M_LLD((r), REG_PV, disp); \
-    }
+    Opcode ........ opcode
+    Ra ............ register to be tested
+    Branch_disp ... relative address to be jumped to (divided by 4)
 
+*******************************************************************************/
+
+#define M_BRA(Opcode,Ra,Branch_disp) \
+    do { \
+        *((uint32_t *) cd->mcodeptr) = ((((Opcode)) << 26) | ((Ra) << 21) | ((Branch_disp) & 0x1fffff)); \
+        cd->mcodeptr += 4; \
+    } while (0)
 
-/* macros to create code ******************************************************/
 
 #define REG   0
 #define CONST 1
 */      
 
 #define M_OP3(op,fu,a,b,c,const) \
-       *(mcodeptr++) = ((((s4) (op)) << 26) | ((a) << 21) | ((b) << (16 - 3 * (const))) | ((const) << 12) | ((fu) << 5) | ((c)))
+    do { \
+        *((u4 *) cd->mcodeptr) = ((((s4) (op)) << 26) | ((a) << 21) | ((b) << (16 - 3 * (const))) | ((const) << 12) | ((fu) << 5) | ((c))); \
+        cd->mcodeptr += 4; \
+    } while (0)
 
 
 /* 3-address-floating-point-operation: M_FOP3 
 */ 
 
 #define M_FOP3(op,fu,a,b,c) \
-       *(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))
-
-
-/* memory operations: M_MEM
-      op ..... opcode
-      a ...... source/target register for memory access
-      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))
+    do { \
+        *((u4 *) cd->mcodeptr) = ((((s4) (op)) << 26) | ((a) << 21) | ((b) << 16) | ((fu) << 5) | (c)); \
+        cd->mcodeptr += 4; \
+    } while (0)
 
 
 /* macros for all used commands (see an Alpha-manual for description) *********/
         } \
     } while (0)
 
+#define M_ALD_INTERN(a,b,disp)  M_LLD_INTERN(a,b,disp)
 #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_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_ASUB_IMM(a,b,c)       M_LSUB_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_CMOVLE_IMM(a,b,c)     M_OP3 (0x11,0x64, a,b,c,1)     /* a<=0 ? c=b  */
 #define M_CMOVGT_IMM(a,b,c)     M_OP3 (0x11,0x66, a,b,c,1)     /* a> 0 ? c=b  */
 
-/* macros for unused commands (see an Alpha-manual for description) ***********/ 
+/* macros for unused commands (see an Alpha-manual for description) ***********/
 
 #define M_ANDNOT(a,b,c,const)   M_OP3 (0x11,0x08, a,b,c,const) /* c = a &~ b  */
 #define M_ORNOT(a,b,c,const)    M_OP3 (0x11,0x28, a,b,c,const) /* c = a |~ b  */
 
 #define M_JMP_CO(a,b)           M_MEM (0x1a,a,b,0xc000)        /* call cosub  */
 
-
-/* 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.
-
-   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
-
 #endif /* _CODEGEN_H */