* src/vm/jit/powerpc/emit.c (emit_replacement_stubs): Prepared for
[cacao.git] / src / vm / jit / powerpc / emit.c
index 09fcc3c6a87c6b732805caa089eae10832e95fea..b6e060a5ac5e341065a57d293dfebf233d6e753e 100644 (file)
@@ -26,9 +26,7 @@
 
    Authors: Christian Thalinger
 
-   Changes:
-
-   $Id: emitfuncs.c 4398 2006-01-31 23:43:08Z twisti $
+   $Id: emit.c 4398 2006-01-31 23:43:08Z twisti $
 
 */
 
 
 #include "vm/jit/powerpc/codegen.h"
 
+#include "mm/memory.h"
 #include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/options.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 ****************************************************************
-
-   Emits a possible load of the first source operand.
-
-*******************************************************************************/
-
-s4 emit_load_s1(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
-{
-       codegendata  *cd;
-       s4            disp;
-       s4            reg;
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-
-       if (src->flags & INMEMORY) {
-               COUNT_SPILLS;
-
-               disp = src->regoff * 4;
-
-               if (IS_FLT_DBL_TYPE(src->type)) {
-                       if (IS_2_WORD_TYPE(src->type))
-                               M_DLD(tempreg, REG_SP, disp);
-                       else
-                               M_FLD(tempreg, REG_SP, disp);
-
-               } else {
-                       if (IS_2_WORD_TYPE(src->type))
-                               M_LLD(tempreg, REG_SP, disp);
-                       else
-                               M_ILD(tempreg, REG_SP, disp);
-               }
-
-               reg = tempreg;
-       } else
-               reg = src->regoff;
-
-       return reg;
-}
-
-
-/* emit_load_s2 ****************************************************************
+/* emit_load *******************************************************************
 
-   Emits a possible load of the second source operand.
+   Emits a possible load of an operand.
 
 *******************************************************************************/
 
-s4 emit_load_s2(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
 {
-       codegendata  *cd;
-       s4            disp;
-       s4            reg;
+       codegendata *cd;
+       s4           disp;
+       s4           reg;
 
        /* get required compiler data */
 
        cd = jd->cd;
 
-       if (src->flags & INMEMORY) {
+       if (IS_INMEMORY(src->flags)) {
                COUNT_SPILLS;
 
-               disp = src->regoff * 4;
+               disp = src->vv.regoff * 4;
 
                if (IS_FLT_DBL_TYPE(src->type)) {
                        if (IS_2_WORD_TYPE(src->type))
                                M_DLD(tempreg, REG_SP, disp);
                        else
                                M_FLD(tempreg, REG_SP, disp);
-
-               } else {
-                       if (IS_2_WORD_TYPE(src->type))
-                               M_LLD(tempreg, REG_SP, disp);
-                       else
-                               M_ILD(tempreg, REG_SP, disp);
                }
-
-               reg = tempreg;
-       } else
-               reg = src->regoff;
-
-       return reg;
-}
-
-
-/* emit_load_s3 ****************************************************************
-
-   Emits a possible load of the third source operand.
-
-*******************************************************************************/
-
-s4 emit_load_s3(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
-{
-       codegendata  *cd;
-       s4            disp;
-       s4            reg;
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-
-       if (src->flags & INMEMORY) {
-               COUNT_SPILLS;
-
-               disp = src->regoff * 4;
-
-               if (IS_FLT_DBL_TYPE(src->type)) {
-                       if (IS_2_WORD_TYPE(src->type))
-                               M_DLD(tempreg, REG_SP, disp);
-                       else
-                               M_FLD(tempreg, REG_SP, disp);
-
-               } else {
+               else {
                        if (IS_2_WORD_TYPE(src->type))
                                M_LLD(tempreg, REG_SP, disp);
                        else
@@ -172,89 +87,21 @@ s4 emit_load_s3(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
                }
 
                reg = tempreg;
-       } else
-               reg = src->regoff;
-
-       return reg;
-}
-
-
-/* emit_load_s1_low ************************************************************
-
-   Emits a possible load of the low 32-bits of the first long source
-   operand.
-
-*******************************************************************************/
-
-s4 emit_load_s1_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
-{
-       codegendata  *cd;
-       s4            disp;
-       s4            reg;
-
-       assert(src->type == TYPE_LNG);
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-
-       if (src->flags & INMEMORY) {
-               COUNT_SPILLS;
-
-               disp = src->regoff * 4;
-
-               M_ILD(tempreg, REG_SP, disp + 4);
-
-               reg = tempreg;
-       } else
-               reg = GET_LOW_REG(src->regoff);
-
-       return reg;
-}
-
-
-/* emit_load_s2_low ************************************************************
-
-   Emits a possible load of the low 32-bits of the second long source
-   operand.
-
-*******************************************************************************/
-
-s4 emit_load_s2_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
-{
-       codegendata  *cd;
-       s4            disp;
-       s4            reg;
-
-       assert(src->type == TYPE_LNG);
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-
-       if (src->flags & INMEMORY) {
-               COUNT_SPILLS;
-
-               disp = src->regoff * 4;
-
-               M_ILD(tempreg, REG_SP, disp + 4);
-
-               reg = tempreg;
-       } else
-               reg = GET_LOW_REG(src->regoff);
+       }
+       else
+               reg = src->vv.regoff;
 
        return reg;
 }
 
 
-/* emit_load_s3_low ************************************************************
+/* emit_load_low ***************************************************************
 
-   Emits a possible load of the low 32-bits of the third long source
-   operand.
+   Emits a possible load of the low 32-bits of an operand.
 
 *******************************************************************************/
 
-s4 emit_load_s3_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
 {
        codegendata  *cd;
        s4            disp;
@@ -266,97 +113,29 @@ s4 emit_load_s3_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
 
        cd = jd->cd;
 
-       if (src->flags & INMEMORY) {
+       if (IS_INMEMORY(src->flags)) {
                COUNT_SPILLS;
 
-               disp = src->regoff * 4;
+               disp = src->vv.regoff * 4;
 
                M_ILD(tempreg, REG_SP, disp + 4);
 
                reg = tempreg;
-       } else
-               reg = GET_LOW_REG(src->regoff);
-
-       return reg;
-}
-
-
-/* emit_load_s1_high ***********************************************************
-
-   Emits a possible load of the high 32-bits of the first long source
-   operand.
-
-*******************************************************************************/
-
-s4 emit_load_s1_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
-{
-       codegendata  *cd;
-       s4            disp;
-       s4            reg;
-
-       assert(src->type == TYPE_LNG);
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-
-       if (src->flags & INMEMORY) {
-               COUNT_SPILLS;
-
-               disp = src->regoff * 4;
-
-               M_ILD(tempreg, REG_SP, disp);
-
-               reg = tempreg;
-       } else
-               reg = GET_HIGH_REG(src->regoff);
-
-       return reg;
-}
-
-
-/* emit_load_s2_high ***********************************************************
-
-   Emits a possible load of the high 32-bits of the second long source
-   operand.
-
-*******************************************************************************/
-
-s4 emit_load_s2_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
-{
-       codegendata  *cd;
-       s4            disp;
-       s4            reg;
-
-       assert(src->type == TYPE_LNG);
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-
-       if (src->flags & INMEMORY) {
-               COUNT_SPILLS;
-
-               disp = src->regoff * 4;
-
-               M_ILD(tempreg, REG_SP, disp);
-
-               reg = tempreg;
-       } else
-               reg = GET_HIGH_REG(src->regoff);
+       }
+       else
+               reg = GET_LOW_REG(src->vv.regoff);
 
        return reg;
 }
 
 
-/* emit_load_s3_high ***********************************************************
+/* emit_load_high **************************************************************
 
-   Emits a possible load of the high 32-bits of the third long source
-   operand.
+   Emits a possible load of the high 32-bits of an operand.
 
 *******************************************************************************/
 
-s4 emit_load_s3_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
 {
        codegendata  *cd;
        s4            disp;
@@ -368,16 +147,17 @@ s4 emit_load_s3_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
 
        cd = jd->cd;
 
-       if (src->flags & INMEMORY) {
+       if (IS_INMEMORY(src->flags)) {
                COUNT_SPILLS;
 
-               disp = src->regoff * 4;
+               disp = src->vv.regoff * 4;
 
                M_ILD(tempreg, REG_SP, disp);
 
                reg = tempreg;
-       } else
-               reg = GET_HIGH_REG(src->regoff);
+       }
+       else
+               reg = GET_HIGH_REG(src->vv.regoff);
 
        return reg;
 }
@@ -389,28 +169,28 @@ s4 emit_load_s3_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
 
 *******************************************************************************/
 
-void emit_store(jitdata *jd, instruction *iptr, stackptr dst, s4 d)
+void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
 {
-       codegendata  *cd;
+       codegendata *cd;
 
        /* get required compiler data */
 
        cd = jd->cd;
 
-       if (dst->flags & INMEMORY) {
+       if (IS_INMEMORY(dst->flags)) {
                COUNT_SPILLS;
 
                if (IS_FLT_DBL_TYPE(dst->type)) {
                        if (IS_2_WORD_TYPE(dst->type))
-                               M_DST(d, REG_SP, dst->regoff * 4);
+                               M_DST(d, REG_SP, dst->vv.regoff * 4);
                        else
-                               M_FST(d, REG_SP, dst->regoff * 4);
-
-               else {
+                               M_FST(d, REG_SP, dst->vv.regoff * 4);
+               }
+               else {
                        if (IS_2_WORD_TYPE(dst->type))
-                               M_LST(d, REG_SP, dst->regoff * 4);
+                               M_LST(d, REG_SP, dst->vv.regoff * 4);
                        else
-                               M_IST(d, REG_SP, dst->regoff * 4);
+                               M_IST(d, REG_SP, dst->vv.regoff * 4);
                }
        }
 }
@@ -418,29 +198,42 @@ void emit_store(jitdata *jd, instruction *iptr, stackptr dst, s4 d)
 
 /* emit_copy *******************************************************************
 
-   XXX
+   Generates a register/memory to register/memory copy.
 
 *******************************************************************************/
 
-void emit_copy(jitdata *jd, instruction *iptr, stackptr src, stackptr dst)
+void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst)
 {
        codegendata  *cd;
-       registerdata *rd;
        s4            s1, d;
 
        /* get required compiler data */
 
        cd = jd->cd;
-       rd = jd->rd;
 
-       if (src->type == TYPE_LNG)
-               d = codegen_reg_of_var(rd, iptr->opc, dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
-       else
-               d = codegen_reg_of_var(rd, iptr->opc, dst, REG_IFTMP);
+       if ((src->vv.regoff != dst->vv.regoff) ||
+               (IS_INMEMORY(src->flags ^ dst->flags))) {
 
-       if ((src->regoff != dst->regoff) ||
-               ((src->flags ^ dst->flags) & INMEMORY)) {
-               s1 = emit_load_s1(jd, iptr, src, d);
+               /* 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. */
+
+               if (IS_INMEMORY(src->flags)) {
+                       if (IS_LNG_TYPE(src->type))
+                               d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
+                       else
+                               d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
+
+                       s1 = emit_load(jd, iptr, src, d);
+               }
+               else {
+                       if (IS_LNG_TYPE(src->type))
+                               s1 = emit_load(jd, iptr, src, REG_ITMP12_PACKED);
+                       else
+                               s1 = emit_load(jd, iptr, src, REG_IFTMP);
+
+                       d = codegen_reg_of_var(iptr->opc, dst, s1);
+               }
 
                if (s1 != d) {
                        if (IS_FLT_DBL_TYPE(src->type))
@@ -449,7 +242,8 @@ void emit_copy(jitdata *jd, instruction *iptr, stackptr src, stackptr dst)
                                if (IS_2_WORD_TYPE(src->type)) {
                                        M_MOV(GET_LOW_REG(s1), GET_LOW_REG(d));
                                        M_MOV(GET_HIGH_REG(s1), GET_HIGH_REG(d));
-                } else
+                }
+                               else
                     M_MOV(s1, d);
                        }
                }
@@ -478,6 +272,46 @@ void emit_iconst(codegendata *cd, s4 d, s4 value)
 }
 
 
+/* emit_nullpointer_check ******************************************************
+
+   Emit a NullPointerException check.
+
+*******************************************************************************/
+
+void emit_nullpointer_check(codegendata *cd, s4 reg)
+{
+       if (checknull) {
+               M_TST(reg);
+               M_BEQ(0);
+               codegen_add_nullpointerexception_ref(cd);
+       }
+}
+
+
+/* emit_arrayindexoutofbounds_check ********************************************
+
+   Emit a ArrayIndexOutOfBoundsException check.
+
+*******************************************************************************/
+
+void emit_arrayindexoutofbounds_check(codegendata *cd, s4 s1, s4 s2)
+{
+#if 0
+       if (checkbounds) {
+               M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+               M_CMPU(s2, REG_ITMP3);
+               M_BGE(0);
+               codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
+       }
+#else
+       M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+       M_CMPU(s2, REG_ITMP3);
+       M_BLT(1);
+       M_ALD_INTERN(s2, REG_ZERO, EXCEPTION_LOAD_DISP_ARRAYINDEXOUTOFBOUNDS);
+#endif
+}
+
+
 /* emit_exception_stubs ********************************************************
 
    Generates the code for the exception stubs.
@@ -488,7 +322,9 @@ void emit_exception_stubs(jitdata *jd)
 {
        codegendata  *cd;
        registerdata *rd;
-       exceptionref *eref;
+       exceptionref *er;
+       s4            branchmpc;
+       s4            targetmpc;
        s4            targetdisp;
        s4            disp;
 
@@ -501,25 +337,29 @@ 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);
 
                /* Move the value register to a temporary register, if
                   there is the need for it. */
 
-               if (eref->reg != -1)
-                       M_MOV(eref->reg, REG_ITMP1);
+               if (er->reg != -1)
+                       M_MOV(er->reg, REG_ITMP1);
 
                /* calcuate exception address */
 
-               M_LDA(REG_ITMP2_XPC, REG_PV, eref->branchpos - 4);
+               M_LDA(REG_ITMP2_XPC, 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) {
@@ -697,9 +537,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 */
 
@@ -708,24 +550,23 @@ void emit_replacement_stubs(jitdata *jd)
 
        rplp = code->rplpoints;
 
-       for (i = 0; i < code->rplpointcount; ++i, ++rplp) {
-               /* check code segment size */
-
-               MCODECHECK(100);
+       /* store beginning of replacement stubs */
 
-               /* note start of stub code */
+       code->replacementstubs = (u1*) (cd->mcodeptr - cd->mcodebase);
 
-               rplp->outcode = (u1 *) (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) + 1;              /* big-endian */
+               /* 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 - keep 16-byte aligned */
 
@@ -743,6 +584,8 @@ void emit_replacement_stubs(jitdata *jd)
                M_ALD(REG_ITMP3, REG_PV, disp);
                M_MTCTR(REG_ITMP3);
                M_RTS;
+
+               assert((cd->mcodeptr - savedmcodeptr) == 4*REPLACEMENT_STUB_SIZE);
        }
 }
 
@@ -753,6 +596,7 @@ void emit_replacement_stubs(jitdata *jd)
 
 *******************************************************************************/
 
+#if !defined(NDEBUG)
 void emit_verbosecall_enter(jitdata *jd)
 {
        methodinfo   *m;
@@ -958,6 +802,7 @@ void emit_verbosecall_enter(jitdata *jd)
 
        M_NOP;
 }
+#endif /* !defined(NDEBUG) */
 
 
 /* emit_verbosecall_exit *******************************************************
@@ -966,6 +811,7 @@ void emit_verbosecall_enter(jitdata *jd)
 
 *******************************************************************************/
 
+#if !defined(NDEBUG)
 void emit_verbosecall_exit(jitdata *jd)
 {
        methodinfo   *m;
@@ -1043,6 +889,7 @@ void emit_verbosecall_exit(jitdata *jd)
 
        M_NOP;
 }
+#endif /* !defined(NDEBUG) */
 
 
 /*