* src/vm/jit/codegen-common.h (codegen_finish_native_call): Changes signature.
[cacao.git] / src / vm / jit / powerpc / codegen.c
index 1efb03229a519ff63989f5d6db511776e4e4ae82..5269c281d125931fe54386793fdcd209d64aad5b 100644 (file)
@@ -22,8 +22,6 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 8321 2007-08-16 11:37:25Z michi $
-
 */
 
 
@@ -1589,7 +1587,7 @@ bool codegen_emit(jitdata *jd)
                        s3 = emit_load_s3(jd, iptr, REG_A1);
 
                        /* XXX what if array is NULL */
-                       disp = dseg_add_functionptr(cd, BUILTIN_canstore);
+                       disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
                        M_ALD(REG_ITMP3, REG_PV, disp);
                        M_MTCTR(REG_ITMP3);
 
@@ -1597,7 +1595,7 @@ bool codegen_emit(jitdata *jd)
                        M_INTMOVE(s3, REG_A1);
 
                        M_JSR;
-                       emit_exception_check(cd, iptr);
+                       emit_arraystore_check(cd, iptr);
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -2334,6 +2332,8 @@ nowperformreturn:
 
                case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
 
+                       REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
+
                        bte = iptr->sx.s23.s3.bte;
                        md  = bte->md;
                        goto gen_method;
@@ -2408,7 +2408,10 @@ gen_method:
 
                        switch (iptr->opc) {
                        case ICMD_BUILTIN:
-                               disp = dseg_add_functionptr(cd, bte->fp);
+                               if (bte->stub == NULL)
+                                       disp = dseg_add_functionptr(cd, bte->fp);
+                               else
+                                       disp = dseg_add_functionptr(cd, bte->stub);
 
                                M_ALD(REG_PV, REG_PV, disp);  /* pointer to built-in-function */
 
@@ -2417,6 +2420,7 @@ gen_method:
                                M_MTCTR(REG_PV);
                                M_JSR;
                                REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
                                disp = (s4) (cd->mcodeptr - cd->mcodebase);
                                M_MFLR(REG_ITMP1);
                                M_LDA(REG_PV, REG_ITMP1, -disp);
@@ -2920,6 +2924,194 @@ void codegen_emit_stub_compiler(jitdata *jd)
 }
 
 
+/* codegen_emit_stub_builtin ***************************************************
+
+   Creates a stub routine which calls a builtin function.
+
+*******************************************************************************/
+
+void codegen_emit_stub_builtin(jitdata *jd, builtintable_entry *bte)
+{
+       codeinfo    *code;
+       codegendata *cd;
+       methoddesc  *md;
+       int          i;
+       int          s1;
+       int          disp;
+
+       /* get required compiler data */
+
+       code = jd->code;
+       cd   = jd->cd;
+
+       md = bte->md;
+
+       /* calculate stackframe size */
+
+       cd->stackframesize =
+               sizeof(stackframeinfo) / SIZEOF_VOID_P +
+               2 +                             /* 4 stackframeinfo arguments (darwin)*/
+               md->paramcount;
+
+       /* Keep stack 16-byte aligned. */
+
+       ALIGN_2(cd->stackframesize);
+
+       /* create method header */
+
+       (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
+       (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize       */
+       (void) dseg_add_unique_s4(cd, 0);                      /* IsSync          */
+       (void) dseg_add_unique_s4(cd, 0);                      /* IsLeaf          */
+       (void) dseg_add_unique_s4(cd, 0);                      /* IntSave         */
+       (void) dseg_add_unique_s4(cd, 0);                      /* FltSave         */
+       (void) dseg_addlinenumbertablesize(cd);
+       (void) dseg_add_unique_s4(cd, 0);                      /* ExTableSize     */
+
+       /* generate code */
+
+       M_MFLR(REG_ZERO);
+       M_AST_INTERN(REG_ZERO, REG_SP, LA_LR_OFFSET);
+       M_STWU(REG_SP, REG_SP, -(cd->stackframesize * 8));
+
+#if defined(ENABLE_GC_CACAO)
+       /* Save callee saved integer registers in stackframeinfo (GC may
+          need to recover them during a collection). */
+
+       disp = cd->stackframesize * 8 - sizeof(stackframeinfo) +
+               OFFSET(stackframeinfo, intregs);
+
+       for (i = 0; i < INT_SAV_CNT; i++)
+               M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
+#endif
+
+       /* Save integer and float argument registers. */
+
+       for (i = 0; i < md->paramcount; i++) {
+               if (!md->params[i].inmemory) {
+                       s1 = md->params[i].regoff;
+
+                       switch (md->paramtypes[i].type) {
+                       case TYPE_INT:
+                       case TYPE_ADR:
+                               M_IST(s1, REG_SP, LA_SIZE + 4*4 + i * 8);
+                               break;
+                       case TYPE_LNG:
+                               M_LST(s1, REG_SP, LA_SIZE + 4*4 + i * 8);
+                               break;
+                       case TYPE_FLT:
+                       case TYPE_DBL:
+                               M_DST(s1, REG_SP, LA_SIZE + 4*4 + i * 8);
+                               break;
+                       }
+               }
+       }
+
+       /* create dynamic stack info */
+
+       M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A0);
+       M_MOV(REG_PV, REG_A1);
+       M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A2);
+       M_ALD(REG_A3, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
+       disp = dseg_add_functionptr(cd, codegen_stub_builtin_enter);
+       M_ALD(REG_ITMP1, REG_PV, disp);
+       M_MTCTR(REG_ITMP1);
+       M_JSR;
+
+       /* Restore integer and float argument registers. */
+
+       for (i = 0; i < md->paramcount; i++) {
+               if (!md->params[i].inmemory) {
+                       s1 = md->params[i].regoff;
+
+                       switch (md->paramtypes[i].type) {
+                       case TYPE_INT:
+                       case TYPE_ADR:
+                               M_ILD(s1, REG_SP, LA_SIZE + 4*4 + i * 8);
+                               break;
+                       case TYPE_LNG:
+                               M_LLD(s1, REG_SP, LA_SIZE + 4*4 + i * 8);
+                               break;
+                       case TYPE_FLT:
+                       case TYPE_DBL:
+                               M_DLD(s1, REG_SP, LA_SIZE + 4*4 + i * 8);
+                               break;
+                       }
+               }
+       }
+
+       /* call the builtin function */
+
+       disp = dseg_add_functionptr(cd, bte->fp);
+       M_ALD(REG_ITMP3, REG_PV, disp);
+       M_MTCTR(REG_ITMP3);
+       M_JSR;
+
+       /* save return value */
+
+       switch (md->returntype.type) {
+       case TYPE_INT:
+       case TYPE_ADR:
+               M_IST(REG_RESULT, REG_SP, LA_SIZE + 1 * 8);
+               break;
+       case TYPE_LNG:
+               M_LST(REG_RESULT_PACKED, REG_SP, LA_SIZE + 1 * 8);
+               break;
+       case TYPE_FLT:
+       case TYPE_DBL:
+               M_DST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
+               break;
+       case TYPE_VOID:
+               break;
+       }
+
+       /* remove native stackframe info */
+
+       M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A0);
+       disp = dseg_add_functionptr(cd, codegen_stub_builtin_exit);
+       M_ALD(REG_ITMP1, REG_PV, disp);
+       M_MTCTR(REG_ITMP1);
+       M_JSR;
+
+       /* restore return value */
+
+       switch (md->returntype.type) {
+       case TYPE_INT:
+       case TYPE_ADR:
+               M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 8);
+               break;
+       case TYPE_LNG:
+               M_LLD(REG_RESULT_PACKED, REG_SP, LA_SIZE + 1 * 8);
+               break;
+       case TYPE_FLT:
+       case TYPE_DBL:
+               M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
+               break;
+       case TYPE_VOID:
+               break;
+       }
+
+#if defined(ENABLE_GC_CACAO)
+       /* Restore callee saved integer registers from stackframeinfo (GC
+          might have modified them during a collection). */
+        
+       disp = cd->stackframesize * 8 - sizeof(stackframeinfo) +
+               OFFSET(stackframeinfo, intregs);
+
+       for (i = 0; i < INT_SAV_CNT; i++)
+               M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
+#endif
+
+       /* remove stackframe */
+
+       M_ALD(REG_ITMP2_XPC, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
+       M_MTLR(REG_ITMP2_XPC);
+       M_LDA(REG_SP, REG_SP, cd->stackframesize * 8);
+
+       M_RET;
+}
+
+
 /* codegen_emit_stub_native ****************************************************
 
    Emits a stub routine which calls a native method.
@@ -2955,12 +3147,12 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
                sizeof(stackframeinfo) / SIZEOF_VOID_P +
                sizeof(localref_table) / SIZEOF_VOID_P +
                4 +                             /* 4 stackframeinfo arguments (darwin)*/
-               nmd->paramcount * 2 +           /* assume all arguments are doubles   */
+               nmd->paramcount +
                nmd->memuse;
 
        /* keep stack 16-byte aligned */
 
-       cd->stackframesize = (cd->stackframesize + 3) & ~3;
+       ALIGN_2(cd->stackframesize);
 
        /* create method header */
 
@@ -2983,20 +3175,14 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
 
        funcdisp = dseg_add_functionptr(cd, f);
 
-#if !defined(WITH_STATIC_CLASSPATH)
        if (f == NULL)
                patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp);
-#endif
-
-       /* emit trace code */
-
-       emit_verbosecall_enter(jd);
 
 #if defined(ENABLE_GC_CACAO)
        /* Save callee saved integer registers in stackframeinfo (GC may
           need to recover them during a collection). */
 
-       disp = cd->stackframesize * 4 - sizeof(stackframeinfo) +
+       disp = cd->stackframesize * 8 - sizeof(stackframeinfo) +
                OFFSET(stackframeinfo, intregs);
 
        for (i = 0; i < INT_SAV_CNT; i++)
@@ -3027,15 +3213,18 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
 
        /* create native stack info */
 
-       M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A0);
+       M_MOV(REG_SP, REG_A0);
        M_MOV(REG_PV, REG_A1);
-       M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A2);
-       M_ALD(REG_A3, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
        disp = dseg_add_functionptr(cd, codegen_start_native_call);
        M_ALD(REG_ITMP1, REG_PV, disp);
        M_MTCTR(REG_ITMP1);
        M_JSR;
 
+       /* remember class argument */
+
+       if (m->flags & ACC_STATIC)
+               M_MOV(REG_RESULT, REG_ITMP3);
+
        /* restore integer and float argument registers */
 
        for (i = 0; i < md->paramcount; i++) {
@@ -3114,10 +3303,8 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
 
        /* put class into second argument register */
 
-       if (m->flags & ACC_STATIC) {
-               disp = dseg_add_address(cd, m->class);
-               M_ALD(REG_A1, REG_PV, disp);
-       }
+       if (m->flags & ACC_STATIC)
+               M_MOV(REG_ITMP3, REG_A1);
 
        /* put env into first argument register */
 
@@ -3130,23 +3317,19 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
        M_MTCTR(REG_ITMP3);
        M_JSR;
 
-       /* print call trace */
-
-       emit_verbosecall_exit(jd);
-
        /* save return value */
 
        switch (md->returntype.type) {
        case TYPE_INT:
        case TYPE_ADR:
-               M_IST(REG_RESULT, REG_SP, LA_SIZE + 1 * 8);
+               M_IST(REG_RESULT, REG_SP, LA_SIZE + 2 * 4);
                break;
        case TYPE_LNG:
-               M_LST(REG_RESULT_PACKED, REG_SP, LA_SIZE + 1 * 8);
+               M_LST(REG_RESULT_PACKED, REG_SP, LA_SIZE + 2 * 4);
                break;
        case TYPE_FLT:
        case TYPE_DBL:
-               M_DST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
+               M_DST(REG_FRESULT, REG_SP, LA_SIZE + 2 * 4);
                break;
        case TYPE_VOID:
                break;
@@ -3154,7 +3337,8 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
 
        /* remove native stackframe info */
 
-       M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A0);
+       M_MOV(REG_SP, REG_A0);
+       M_MOV(REG_PV, REG_A1);
        disp = dseg_add_functionptr(cd, codegen_finish_native_call);
        M_ALD(REG_ITMP1, REG_PV, disp);
        M_MTCTR(REG_ITMP1);
@@ -3166,14 +3350,14 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
        switch (md->returntype.type) {
        case TYPE_INT:
        case TYPE_ADR:
-               M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 8);
+               M_ILD(REG_RESULT, REG_SP, LA_SIZE + 2 * 4);
                break;
        case TYPE_LNG:
-               M_LLD(REG_RESULT_PACKED, REG_SP, LA_SIZE + 1 * 8);
+               M_LLD(REG_RESULT_PACKED, REG_SP, LA_SIZE + 2 * 4);
                break;
        case TYPE_FLT:
        case TYPE_DBL:
-               M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
+               M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 2 * 4);
                break;
        case TYPE_VOID:
                break;
@@ -3183,7 +3367,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
        /* Restore callee saved integer registers from stackframeinfo (GC
           might have modified them during a collection). */
         
-       disp = cd->stackframesize * 4 - sizeof(stackframeinfo) +
+       disp = cd->stackframesize * 8 - sizeof(stackframeinfo) +
                OFFSET(stackframeinfo, intregs);
 
        for (i = 0; i < INT_SAV_CNT; i++)