* src/vm/jit/powerpc/emit.c (emit_replacement_stubs): Prepared for
[cacao.git] / src / vm / jit / alpha / emit.c
index 2c2906956a5685ca283a5ed6abea91f0fae0cf9d..019ed4f34ee3fc729b29e125968b6e7bdfbfa044 100644 (file)
@@ -26,8 +26,6 @@
 
    Authors: Christian Thalinger
 
-   Changes:
-
    $Id: emit.c 4398 2006-01-31 23:43:08Z twisti $
 
 */
 #endif
 
 #include "vm/builtin.h"
+#include "vm/options.h"
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit.h"
+#include "vm/jit/emit-common.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/replace.h"
 
 
-/* code generation functions **************************************************/
-
-/* emit_load_s1 ****************************************************************
+/* emit_load *******************************************************************
 
-   Emits a possible load of the first source operand.
+   Emits a possible load of an operand.
 
 *******************************************************************************/
 
-s4 emit_load_s1(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
 {
        codegendata  *cd;
        s4            reg;
@@ -70,157 +67,183 @@ s4 emit_load_s1(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
 
        cd = jd->cd;
 
-       if (src->flags & INMEMORY) {
+       if (IS_INMEMORY(src->flags)) {
                COUNT_SPILLS;
 
                if (IS_FLT_DBL_TYPE(src->type))
-                       M_DLD(tempreg, REG_SP, src->regoff * 8);
+                       M_DLD(tempreg, REG_SP, src->vv.regoff * 8);
                else
-                       M_LLD(tempreg, REG_SP, src->regoff * 8);
+                       M_LLD(tempreg, REG_SP, src->vv.regoff * 8);
 
                reg = tempreg;
-       } else
-               reg = src->regoff;
+       }
+       else
+               reg = src->vv.regoff;
 
        return reg;
 }
 
 
-/* emit_load_s2 ****************************************************************
+/* emit_store ******************************************************************
 
-   Emits a possible load of the second source operand.
+   Emit a possible store for the given variable.
 
 *******************************************************************************/
 
-s4 emit_load_s2(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
 {
        codegendata  *cd;
-       s4            reg;
 
        /* get required compiler data */
 
        cd = jd->cd;
 
-       if (src->flags & INMEMORY) {
+       if (IS_INMEMORY(dst->flags)) {
                COUNT_SPILLS;
 
-               if (IS_FLT_DBL_TYPE(src->type))
-                       M_DLD(tempreg, REG_SP, src->regoff * 8);
+               if (IS_FLT_DBL_TYPE(dst->type))
+                       M_DST(d, REG_SP, dst->vv.regoff * 8);
                else
-                       M_LLD(tempreg, REG_SP, src->regoff * 8);
-
-               reg = tempreg;
-       } else
-               reg = src->regoff;
-
-       return reg;
+                       M_LST(d, REG_SP, dst->vv.regoff * 8);
+       }
 }
 
 
-/* emit_load_s3 ****************************************************************
+/* emit_copy *******************************************************************
 
-   Emits a possible load of the third source operand.
+   Generates a register/memory to register/memory copy.
 
 *******************************************************************************/
 
-s4 emit_load_s3(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst)
 {
        codegendata  *cd;
-       s4            reg;
+       s4            s1, d;
 
        /* get required compiler data */
 
        cd = jd->cd;
 
-       if (src->flags & INMEMORY) {
-               COUNT_SPILLS;
+       if ((src->vv.regoff != dst->vv.regoff) ||
+               ((src->flags ^ dst->flags) & INMEMORY)) {
 
-               if (IS_FLT_DBL_TYPE(src->type))
-                       M_DLD(tempreg, REG_SP, src->regoff * 8);
-               else
-                       M_LLD(tempreg, REG_SP, src->regoff * 8);
+               /* If one of the variables resides in memory, we can eliminate
+                  the register move from/to the temporary register with the
+                  order of getting the destination register and the load. */
 
-               reg = tempreg;
-       } else
-               reg = src->regoff;
+               if (IS_INMEMORY(src->flags)) {
+                       d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
+                       s1 = emit_load(jd, iptr, src, d);
+               }
+               else {
+                       s1 = emit_load(jd, iptr, src, REG_IFTMP);
+                       d = codegen_reg_of_var(iptr->opc, dst, s1);
+               }
 
-       return reg;
+               if (s1 != d) {
+                       if (IS_FLT_DBL_TYPE(src->type))
+                               M_FMOV(s1, d);
+                       else
+                               M_MOV(s1, d);
+               }
+
+               emit_store(jd, iptr, dst, d);
+       }
 }
 
 
-/* emit_store ******************************************************************
+/* emit_iconst *****************************************************************
 
    XXX
 
 *******************************************************************************/
 
-void emit_store(jitdata *jd, instruction *iptr, stackptr dst, s4 d)
+void emit_iconst(codegendata *cd, s4 d, s4 value)
 {
-       codegendata  *cd;
+       s4 disp;
 
-       /* get required compiler data */
+       if ((value >= -32768) && (value <= 32767))
+               M_LDA_INTERN(d, REG_ZERO, value);
+       else {
+               disp = dseg_add_s4(cd, value);
+               M_ILD(d, REG_PV, disp);
+       }
+}
 
-       cd = jd->cd;
 
-       if (dst->flags & INMEMORY) {
-               COUNT_SPILLS;
+/* emit_lconst *****************************************************************
 
-               if (IS_FLT_DBL_TYPE(dst->type))
-                       M_DST(d, REG_SP, dst->regoff * 8);
-               else
-                       M_LST(d, REG_SP, dst->regoff * 8);
-       }
-}
+   XXX
 
+*******************************************************************************/
 
-void emit_copy(jitdata *jd, instruction *iptr, stackptr src, stackptr dst)
+void emit_lconst(codegendata *cd, s4 d, s8 value)
 {
-       codegendata  *cd;
-       registerdata *rd;
-       s4            s1, d;
+       s4 disp;
 
-       /* get required compiler data */
+       if ((value >= -32768) && (value <= 32767))
+               M_LDA_INTERN(d, REG_ZERO, value);
+       else {
+               disp = dseg_add_s8(cd, value);
+               M_LLD(d, REG_PV, disp);
+       }
+}
 
-       cd = jd->cd;
-       rd = jd->rd;
 
-       if ((src->regoff != dst->regoff) ||
-               ((src->flags ^ dst->flags) & INMEMORY)) {
-               d = codegen_reg_of_var(rd, iptr->opc, dst, REG_IFTMP);
-               s1 = emit_load_s1(jd, iptr, src, d);
+/* emit_arrayindexoutofbounds_check ********************************************
 
-               if (IS_FLT_DBL_TYPE(src->type))
-                       M_FLTMOVE(s1, d);
-               else
-                       M_INTMOVE(s1, d);
+   Emit an ArrayIndexOutOfBoundsException check.
 
-               emit_store(jd, iptr, dst, d);
+*******************************************************************************/
+
+void emit_arrayindexoutofbounds_check(codegendata *cd, s4 s1, s4 s2)
+{
+       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);
        }
 }
 
 
-void emit_iconst(codegendata *cd, s4 d, s4 value)
-{
-       s4 disp;
+/* emit_arraystore_check *******************************************************
 
-       if ((value >= -32768) && (value <= 32767)) {
-               M_LDA_INTERN(d, REG_ZERO, value);
-       } else {
-               disp = dseg_adds4(cd, value);
-               M_ILD(d, REG_PV, disp);
-       }
+   Emit an ArrayStoreException check.
+
+*******************************************************************************/
+
+void emit_arraystore_check(codegendata *cd, s4 reg)
+{
+       M_BEQZ(reg, 0);
+       codegen_add_arraystoreexception_ref(cd);
 }
 
 
-void emit_lconst(codegendata *cd, s4 d, s8 value)
+/* emit_classcast_check ********************************************************
+
+   Emit a ClassCastException check.
+
+*******************************************************************************/
+
+void emit_classcast_check(codegendata *cd, s4 condition, s4 reg, s4 s1)
 {
-       s4 disp;
+       M_BNEZ(reg, 0);
+       codegen_add_classcastexception_ref(cd, s1);
+}
 
-       if ((value >= -32768) && (value <= 32767)) {
-               M_LDA_INTERN(d, REG_ZERO, value);
-       } else {
-               disp = dseg_adds8(cd, value);
-               M_LLD(d, REG_PV, disp);
+
+/* emit_nullpointer_check ******************************************************
+
+   Emit a NullPointerException check.
+
+*******************************************************************************/
+
+void emit_nullpointer_check(codegendata *cd, s4 reg)
+{
+       if (checknull) {
+               M_BEQZ(reg, 0);
+               codegen_add_nullpointerexception_ref(cd);
        }
 }
 
@@ -235,7 +258,9 @@ void emit_exception_stubs(jitdata *jd)
 {
        codegendata  *cd;
        registerdata *rd;
-       exceptionref *eref;
+       exceptionref *er;
+       s4            branchmpc;
+       s4            targetmpc;
        s4            targetdisp;
        s4            disp;
 
@@ -248,9 +273,13 @@ void emit_exception_stubs(jitdata *jd)
 
        targetdisp = 0;
 
-       for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
-               gen_resolvebranch(cd->mcodebase + eref->branchpos, 
-                                                 eref->branchpos, cd->mcodeptr - cd->mcodebase);
+       for (er = cd->exceptionrefs; er != NULL; er = er->next) {
+               /* back-patch the branch to this exception code */
+
+               branchmpc = er->branchpos;
+               targetmpc = cd->mcodeptr - cd->mcodebase;
+
+               md_codegen_patch_branch(cd, branchmpc, targetmpc);
 
                MCODECHECK(100);
 
@@ -260,16 +289,16 @@ void emit_exception_stubs(jitdata *jd)
                   ArrayIndexOutOfBoundsException.  If so, move index register
                   into a4. */
 
-               if (eref->reg != -1)
-                       M_MOV(eref->reg, rd->argintregs[4]);
+               if (er->reg != -1)
+                       M_MOV(er->reg, rd->argintregs[4]);
 
                /* calcuate exception address */
 
-               M_LDA(rd->argintregs[3], REG_PV, eref->branchpos - 4);
+               M_LDA(rd->argintregs[3], REG_PV, er->branchpos - 4);
 
                /* move function to call into REG_ITMP3 */
 
-               disp = dseg_add_functionptr(cd, eref->function);
+               disp = dseg_add_functionptr(cd, er->function);
                M_ALD(REG_ITMP3, REG_PV, disp);
 
                if (targetdisp == 0) {
@@ -439,9 +468,11 @@ void emit_replacement_stubs(jitdata *jd)
        codegendata *cd;
        codeinfo    *code;
        rplpoint    *rplp;
-       u1          *savedmcodeptr;
        s4           disp;
        s4           i;
+#if !defined(NDEBUG)
+       u1          *savedmcodeptr;
+#endif
 
        /* get required compiler data */
 
@@ -450,24 +481,23 @@ void emit_replacement_stubs(jitdata *jd)
 
        rplp = code->rplpoints;
 
-       for (i = 0; i < code->rplpointcount; ++i, ++rplp) {
-               /* check code segment size */
+       /* store beginning of replacement stubs */
 
-               MCODECHECK(100);
+       code->replacementstubs = (u1*) (cd->mcodeptr - cd->mcodebase);
 
-               /* note start of stub code */
-
-               rplp->outcode = (u1 *) (ptrint) (cd->mcodeptr - cd->mcodebase);
+       for (i = 0; i < code->rplpointcount; ++i, ++rplp) {
+               /* do not generate stubs for non-trappable points */
 
-               /* make machine code for patching */
+               if (rplp->flags & RPLPOINT_FLAG_NOTRAP)
+                       continue;
 
-               savedmcodeptr = cd->mcodeptr;
-               cd->mcodeptr  = (u1 *) &(rplp->mcode);
+               /* check code segment size */
 
-               disp = (ptrint) ((s4 *) rplp->outcode - (s4 *) rplp->pc) - 1;
-               M_BR(disp);
+               MCODECHECK(100);
 
-               cd->mcodeptr = savedmcodeptr;
+#if !defined(NDEBUG)
+               savedmcodeptr = cd->mcodeptr;
+#endif
 
                /* create stack frame - 16-byte aligned */
 
@@ -484,6 +514,8 @@ void emit_replacement_stubs(jitdata *jd)
                disp = dseg_add_functionptr(cd, asm_replacement_out);
                M_ALD(REG_ITMP3, REG_PV, disp);
                M_JMP(REG_ZERO, REG_ITMP3);
+
+               assert((cd->mcodeptr - savedmcodeptr) == 4*REPLACEMENT_STUB_SIZE);
        }
 }