Merged PR72 fix.
[cacao.git] / src / vm / jit / x86_64 / codegen.h
index ff996a32b863d1da74d6d682eca6a1abb4660aaf..8262812b0420187411b3e08da0558cae58094cb0 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/x86_64/codegen.h - code generation macros for x86_64
 
-   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
-            Christian Thalinger
-
-   Changes:
-
-   $Id: codegen.h 5507 2006-09-15 09:19:11Z christian $
-
 */
 
 
 
 #include "vm/types.h"
 
-#include "vm/jit/jit.h"
+#include "vm/jit/x86_64/emit.h"
 
-
-/* some defines ***************************************************************/
-
-#define PATCHER_CALL_SIZE    5          /* size in bytes of a patcher call    */
+#include "vm/jit/jit.h"
 
 
 /* additional functions and macros to generate code ***************************/
 
-#define CALCOFFSETBYTES(var, reg, val) \
-    if ((s4) (val) < -128 || (s4) (val) > 127) (var) += 4; \
-    else if ((s4) (val) != 0) (var) += 1; \
-    else if ((reg) == RBP || (reg) == RSP || (reg) == R12 || (reg) == R13) (var) += 1;
-
-
-#define CALCIMMEDIATEBYTES(var, val) \
-    if ((s4) (val) < -128 || (s4) (val) > 127) (var) += 4; \
-    else (var) += 1;
-
-
-/* gen_nullptr_check(objreg) */
-
-#define gen_nullptr_check(objreg) \
-       if (checknull) { \
-        M_TEST(objreg); \
-        M_BEQ(0); \
-           codegen_add_nullpointerexception_ref(cd); \
-       }
-
-
-#define gen_bound_check \
-    if (checkbounds) { \
-        M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
-        M_ICMP(REG_ITMP3, s2); \
-        M_BAE(0); \
-        codegen_add_arrayindexoutofboundsexception_ref(cd, s2); \
-    }
-
-
 /* MCODECHECK(icnt) */
 
 #define MCODECHECK(icnt) \
 
 
 #define ALIGNCODENOP \
-    if ((s4) (((ptrint) cd->mcodeptr) & 7)) { \
-        M_NOP; \
-    }
+    do { \
+        for (s1 = 0; s1 < (s4) (((ptrint) cd->mcodeptr) & 7); s1++) \
+            M_NOP; \
+    } while (0)
 
 
 /* M_INTMOVE:
     } while (0)
 
 
-#define M_COPY(s,d)    emit_copy(jd, iptr, &(jd->var[(s)]), &(jd->var[(d)]))
-
 #define ICONST(r,c) \
     do { \
         if ((c) == 0) \
     } while (0)
 
 
+/* branch defines *************************************************************/
+
+#define BRANCH_UNCONDITIONAL_SIZE    5  /* size in bytes of a branch          */
+#define BRANCH_CONDITIONAL_SIZE      6  /* size in bytes of a branch          */
+
+#define BRANCH_NOPS \
+    do { \
+        M_NOP; \
+        M_NOP; \
+        M_NOP; \
+        M_NOP; \
+        M_NOP; \
+        M_NOP; \
+    } while (0)
+
+
+/* patcher defines ************************************************************/
+
+#define PATCHER_CALL_SIZE    2          /* size in bytes of a patcher call    */
+
+#define PATCHER_NOPS \
+    do { \
+        M_NOP; \
+        M_NOP; \
+    } while (0)
+
+
+/* stub defines ***************************************************************/
+
+#define COMPILERSTUB_CODESIZE    8
+
+
 /* macros to create code ******************************************************/
 
+#define M_BYTE1(a) \
+    do { \
+        *(cd->mcodeptr) = (a); \
+        cd->mcodeptr++; \
+    } while (0)
+
+
+#define M_BYTE2(a, b) \
+    do { \
+        M_BYTE1(a); \
+        M_BYTE1(b); \
+    } while (0)
+
+
 #define M_MOV(a,b)              emit_mov_reg_reg(cd, (a), (b))
 #define M_MOV_IMM(a,b)          emit_mov_imm_reg(cd, (u8) (a), (b))
 
 #define M_LMUL_IMM(a,b,c)       emit_imul_imm_reg_reg(cd, (b), (a), (c))
 
 #define M_IINC(a)               emit_incl_reg(cd, (a))
+#define M_LINC(a)               emit_incq_reg(cd, (a))
 #define M_IDEC(a)               emit_decl_reg(cd, (a))
 
-#define M_ALD(a,b,disp)         M_LLD(a,b,disp)
+#define M_ALD(a,b,disp) \
+    do { \
+        if (b == RIP) \
+            M_LLD(a, b, disp + -((cd->mcodeptr + 7) - cd->mcodebase)); \
+        else \
+            M_LLD(a, b, disp); \
+    } while (0)
+
 #define M_ALD32(a,b,disp)       M_LLD32(a,b,disp)
 
+#define M_ALD_MEM(a,disp)       emit_mov_mem_reg(cd, (disp), (a))
+
+#define M_ALD_MEM_GET_OPC(p)     (  *(        (p) + 1))
+#define M_ALD_MEM_GET_MOD(p)     (((*(        (p) + 2)) >> 6) & 0x03)
+#define M_ALD_MEM_GET_REG(p)    ((((*(        (p) + 2)) >> 3) & 0x07) + (((*(p) >> 2) & 0x01) << 3))
+#define M_ALD_MEM_GET_RM(p)      (((*(        (p) + 2))     ) & 0x07)
+#define M_ALD_MEM_GET_DISP(p)    (  *((u4 *) ((p) + 4)))
+
 #define M_AST(a,b,c)            M_LST(a,b,c)
 #define M_AST_IMM32(a,b,c)      M_LST_IMM32(a,b,c)
 
 #define M_AADD_IMM(a,b)         M_LADD_IMM(a,b)
 #define M_ASUB_IMM(a,b)         M_LSUB_IMM(a,b)
 
+#define M_ISUB_IMM32(a,b)       emit_alul_imm32_reg(cd, ALU_SUB, (a), (b))
+
 #define M_LADD_IMM32(a,b)       emit_alu_imm32_reg(cd, ALU_ADD, (a), (b))
-#define M_AADD_IMM32(a,b)       M_LADD_IMM32(a,b)
 #define M_LSUB_IMM32(a,b)       emit_alu_imm32_reg(cd, ALU_SUB, (a), (b))
 
+#define M_AADD_IMM32(a,b)       M_LADD_IMM32(a,b)
+
 #define M_ILEA(a,b,c)           emit_leal_membase_reg(cd, (a), (b), (c))
 #define M_LLEA(a,b,c)           emit_lea_membase_reg(cd, (a), (b), (c))
 #define M_ALEA(a,b,c)           M_LLEA(a,b,c)
 #define M_SSEXT(a,b)            emit_movswq_reg_reg(cd, (a), (b))
 #define M_ISEXT(a,b)            emit_movslq_reg_reg(cd, (a), (b))
 
+#define M_BZEXT(a,b)            emit_movzbq_reg_reg(cd, (a), (b))
 #define M_CZEXT(a,b)            emit_movzwq_reg_reg(cd, (a), (b))
 
 #define M_ISLL_IMM(a,b)         emit_shiftl_imm_reg(cd, SHIFT_SHL, (a), (b))
 
 #define M_ICMP(a,b)             emit_alul_reg_reg(cd, ALU_CMP, (a), (b))
 #define M_ICMP_IMM(a,b)         emit_alul_imm_reg(cd, ALU_CMP, (a), (b))
+#define M_ICMP_IMM32(a,b)       emit_alul_imm32_reg(cd, ALU_CMP, (a), (b))
 #define M_ICMP_IMM_MEMBASE(a,b,c) emit_alul_imm_membase(cd, ALU_CMP, (a), (b), (c))
 #define M_ICMP_MEMBASE(a,b,c)   emit_alul_membase_reg(cd, ALU_CMP, (a), (b), (c))
 
 #define M_BLE(disp)             emit_jcc(cd, CC_LE, (disp))
 #define M_BGE(disp)             emit_jcc(cd, CC_GE, (disp))
 #define M_BGT(disp)             emit_jcc(cd, CC_G, (disp))
-#define M_BAE(disp)             emit_jcc(cd, CC_AE, (disp))
-#define M_BA(disp)              emit_jcc(cd, CC_A, (disp))
+
+#define M_BULT(disp)            emit_jcc(cd, CC_B, (disp))
+#define M_BULE(disp)            emit_jcc(cd, CC_BE, (disp))
+#define M_BUGE(disp)            emit_jcc(cd, CC_AE, (disp))
+#define M_BUGT(disp)            emit_jcc(cd, CC_A, (disp))
+
+#define M_SETE(a)               emit_setcc_reg(cd, CC_E, (a))
+#define M_SETNE(a)              emit_setcc_reg(cd, CC_NE, (a))
+#define M_SETULE(a)             emit_setcc_reg(cd, CC_BE, (a))
 
 #define M_CMOVEQ(a,b)           emit_cmovcc_reg_reg(cd, CC_E, (a), (b))
 #define M_CMOVNE(a,b)           emit_cmovcc_reg_reg(cd, CC_NE, (a), (b))
 #define M_CMOVGE(a,b)           emit_cmovcc_reg_reg(cd, CC_GE, (a), (b))
 #define M_CMOVGT(a,b)           emit_cmovcc_reg_reg(cd, CC_G, (a), (b))
 
-#define M_CMOVEQ_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_E, (a), (b))
-#define M_CMOVNE_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_NE, (a), (b))
-#define M_CMOVLT_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_L, (a), (b))
-#define M_CMOVLE_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_LE, (a), (b))
-#define M_CMOVGE_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_GE, (a), (b))
-#define M_CMOVGT_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_G, (a), (b))
-
-#define M_CMOVB(a,b)            emit_cmovcc_reg_reg(cd, CC_B, (a), (b))
-#define M_CMOVA(a,b)            emit_cmovcc_reg_reg(cd, CC_A, (a), (b))
+#define M_CMOVULT(a,b)          emit_cmovcc_reg_reg(cd, CC_B, (a), (b))
+#define M_CMOVUGT(a,b)          emit_cmovcc_reg_reg(cd, CC_A, (a), (b))
 #define M_CMOVP(a,b)            emit_cmovcc_reg_reg(cd, CC_P, (a), (b))
 
 #define M_PUSH(a)               emit_push_reg(cd, (a))
 
 #define M_JMP(a)                emit_jmp_reg(cd, (a))
 #define M_JMP_IMM(a)            emit_jmp_imm(cd, (a))
+#define M_JMP_IMM2(a)           emit_jmp_imm2(cd, (a))
 #define M_CALL(a)               emit_call_reg(cd, (a))
 #define M_CALL_IMM(a)           emit_call_imm(cd, (a))
-#define M_RET                   emit_ret(cd)
+#define M_RET                   M_BYTE1(0xc3)
 
-#define M_NOP                   emit_nop(cd)
+#define M_NOP                   M_BYTE1(0x90)
+#define M_UD2                   M_BYTE2(0x0f, 0x0b)
 
 #define M_CLR(a)                M_LXOR(a,a)
 
 #define M_RDTSC                 emit_rdtsc(cd)
 
 #define M_IINC_MEMBASE(a,b)     emit_incl_membase(cd, (a), (b))
+#define M_LINC_MEMBASE(a,b)     emit_incq_membase(cd, (a), (b))
 
 #define M_IADD_MEMBASE(a,b,c)   emit_alul_reg_membase(cd, ALU_ADD, (a), (b), (c))
 #define M_IADC_MEMBASE(a,b,c)   emit_alul_reg_membase(cd, ALU_ADC, (a), (b), (c))
 #define M_ISBB_MEMBASE(a,b,c)   emit_alul_reg_membase(cd, ALU_SBB, (a), (b), (c))
 
 
+#if defined(ENABLE_PROFILING)
+
 #define PROFILE_CYCLE_START \
     do { \
         if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { \
         } \
     } while (0)
 
+#else
 
-/* function gen_resolvebranch **************************************************
-
-    backpatches a branch instruction
-
-    parameters: ip ... pointer to instruction after branch (void*)
-                so ... offset of instruction after branch  (s8)
-                to ... offset of branch target             (s8)
-
-*******************************************************************************/
+#define PROFILE_CYCLE_START
+#define PROFILE_CYCLE_STOP
 
-#define gen_resolvebranch(ip,so,to) \
-    *((s4*) ((ip) - 4)) = (s4) ((to) - (so));
+#endif
 
 #endif /* _CODEGEN_H */