* src/toolbox/list.hpp (DumpList): Made sort function accessible.
[cacao.git] / src / vm / jit / i386 / emit.c
index c3bf7e4eebdbd6a314776363d80a4aebcaba3de5..5751e5884d80b7e02729d34e5c6c6b4ebcab40db 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/i386/emit.c - i386 code emitter functions
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 #include <assert.h>
 
 #include "vm/types.h"
+#include "vm/os.hpp"
 
 #include "vm/jit/i386/codegen.h"
 #include "vm/jit/i386/emit.h"
 #include "vm/jit/i386/md-abi.h"
 
-#include "mm/memory.h"
+#include "mm/memory.hpp"
 
 #include "threads/lock.hpp"
 
@@ -48,7 +49,7 @@
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/replace.hpp"
 #include "vm/jit/trace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* emit_load ******************************************************************
@@ -331,6 +332,16 @@ void emit_copy(jitdata *jd, instruction *iptr)
 }
 
 
+/**
+ * Emits code updating the condition register by comparing one integer
+ * register to an immediate integer value.
+ */
+void emit_icmp_imm(codegendata* cd, int reg, int32_t value)
+{
+       M_CMP_IMM(value, reg);
+}
+
+
 /* emit_branch *****************************************************************
 
    Emits the code for conditional and unconditional branchs.
@@ -536,6 +547,19 @@ void emit_trap_countdown(codegendata *cd, s4 *counter)
        M_ALD_MEM(REG_METHODPTR, TRAP_COUNTDOWN);
 }
 
+/* emit_patcher_alignment ******************************************************
+
+   Emit NOP to ensure placement at an even address.
+
+*******************************************************************************/
+
+void emit_patcher_alignment(codegendata *cd)
+{
+       if ((uintptr_t) cd->mcodeptr & 1)
+               M_NOP;
+}
+
+
 /* emit_trap *******************************************************************
 
    Emit a trap instruction and return the original machine code.
@@ -563,6 +587,147 @@ uint32_t emit_trap(codegendata *cd)
 }
 
 
+/**
+ * Generates synchronization code to enter a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
+{
+       int align_off;
+
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+       align_off = cd->stackframesize ? 4 : 0;
+
+       if (m->flags & ACC_STATIC) {
+               M_MOV_IMM(&m->clazz->object.header, REG_ITMP1);
+       }
+       else {
+               M_ALD(REG_ITMP1, REG_SP, cd->stackframesize * 8 + 4 + align_off);
+               M_TEST(REG_ITMP1);
+               M_BNE(6);
+               M_ALD_MEM(REG_ITMP1, TRAP_NullPointerException);
+       }
+
+       M_AST(REG_ITMP1, REG_SP, syncslot_offset);
+       M_AST(REG_ITMP1, REG_SP, 0 * 4);
+       M_MOV_IMM(LOCK_monitor_enter, REG_ITMP3);
+       M_CALL(REG_ITMP3);
+}
+#endif
+
+
+/**
+ * Generates synchronization code to leave a monitor.
+ */
+#if defined(ENABLE_THREADS)
+void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
+{
+       // Get required compiler data.
+       methodinfo*  m  = jd->m;
+       codegendata* cd = jd->cd;
+
+       M_ALD(REG_ITMP2, REG_SP, syncslot_offset);
+
+       /* we need to save the proper return value */
+
+       methoddesc* md = m->parseddesc;
+
+       switch (md->returntype.type) {
+       case TYPE_INT:
+       case TYPE_ADR:
+               M_IST(REG_RESULT, REG_SP, syncslot_offset);
+               break;
+
+       case TYPE_LNG:
+               M_LST(REG_RESULT_PACKED, REG_SP, syncslot_offset);
+               break;
+
+       case TYPE_FLT:
+               emit_fstps_membase(cd, REG_SP, syncslot_offset);
+               break;
+
+       case TYPE_DBL:
+               emit_fstpl_membase(cd, REG_SP, syncslot_offset);
+               break;
+       }
+
+       M_AST(REG_ITMP2, REG_SP, 0);
+       M_MOV_IMM(LOCK_monitor_exit, REG_ITMP3);
+       M_CALL(REG_ITMP3);
+
+       /* and now restore the proper return value */
+
+       switch (md->returntype.type) {
+       case TYPE_INT:
+       case TYPE_ADR:
+               M_ILD(REG_RESULT, REG_SP, syncslot_offset);
+               break;
+
+       case TYPE_LNG:
+               M_LLD(REG_RESULT_PACKED, REG_SP, syncslot_offset);
+               break;
+
+       case TYPE_FLT:
+               emit_flds_membase(cd, REG_SP, syncslot_offset);
+               break;
+
+       case TYPE_DBL:
+               emit_fldl_membase(cd, REG_SP, syncslot_offset);
+               break;
+       }
+}
+#endif
+
+
+/**
+ * Emit profiling code for method frequency counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_method(codegendata* cd, codeinfo* code)
+{
+       M_MOV_IMM(code, REG_ITMP3);
+       M_IADD_IMM_MEMBASE(1, REG_ITMP3, OFFSET(codeinfo, frequency));
+}
+#endif
+
+
+/**
+ * Emit profiling code for basicblock frequency counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr)
+{
+       M_MOV_IMM(code->bbfrequency, REG_ITMP3);
+       M_IADD_IMM_MEMBASE(1, REG_ITMP3, bptr->nr * 4);
+}
+#endif
+
+
+/**
+ * Emit profiling code to start CPU cycle counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_cycle_start(codegendata* cd, codeinfo* code)
+{
+       // XXX Not implemented yet!
+}
+#endif
+
+
+/**
+ * Emit profiling code to stop CPU cycle counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_cycle_stop(codegendata* cd, codeinfo* code)
+{
+       // XXX Not implemented yet!
+}
+#endif
+
+
 /* emit_verbosecall_enter ******************************************************
 
    Generates the code for the call trace.
@@ -805,6 +970,15 @@ void emit_mov_imm_reg(codegendata *cd, s4 imm, s4 reg)
        emit_imm32((imm));
 }
 
+/* 2-byte opcode for use with patchers */
+void emit_mov_imm2_reg(codegendata *cd, s4 imm, s4 reg)
+{
+       *(cd->mcodeptr++) = 0xc7;
+       emit_address_byte(3, 0, reg);
+       emit_imm32((imm));
+}
+
+
 
 void emit_movb_imm_reg(codegendata *cd, s4 imm, s4 reg)
 {
@@ -1313,6 +1487,7 @@ void emit_jcc(codegendata *cd, s4 opc, s4 imm)
  */
 void emit_setcc_reg(codegendata *cd, s4 opc, s4 reg)
 {
+       assert(reg < 4);                     /* Can only operate on al, bl, cl, dl. */
        *(cd->mcodeptr++) = 0x0f;
        *(cd->mcodeptr++) = 0x90 + (u1) (opc);
        emit_reg(0,(reg));