Merged revisions 7766-7796 via svnmerge from
[cacao.git] / src / vm / jit / sparc64 / codegen.c
index a5d4732f1f4d32fd5011b9221cbec38743f37031..5504b550c0a6759d2586fc91bd041bdfe20f0995 100644 (file)
@@ -47,6 +47,7 @@
 #include "vm/exceptions.h"
 #include "vm/global.h"
 
+#include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/codegen-common.h"
 #include "vm/jit/dseg.h"
@@ -61,6 +62,9 @@
 #include "vmcore/loader.h"
 #include "vmcore/options.h"
 
+
+#define BUILTIN_FLOAT_ARGS 1
+
 /* XXX use something like this for window control ? 
  * #define REG_PV (own_window?REG_PV_CALLEE:REG_PV_CALLER)
  */
@@ -234,7 +238,7 @@ bool codegen_emit(jitdata *jd)
                
                /* XXX could use the param slots on the stack for this! */
                for (p = 0; p < INT_ARG_CNT; p++)
-                       M_STX(REG_WINDOW_TRANSPOSE(rd->argintregs[p]), REG_SP, JITSTACK + (p * 8));
+                       M_STX(REG_WINDOW_TRANSPOSE(abi_registers_integer_argument[p]), REG_SP, JITSTACK + (p * 8));
        }
        
 
@@ -251,20 +255,24 @@ bool codegen_emit(jitdata *jd)
                        continue;
 
                var = VAR(varindex);
-
-               s1 = md->params[p].regoff;
-               if (IS_INT_LNG_TYPE(t)) {                    /* integer args          */
+               s1 = md->params[p].regoff;
+               
+               if (IS_INT_LNG_TYPE(t)) {                    /* integer args          */                        
+                       
                        if (!md->params[p].inmemory) {           /* register arguments    */
                                /*s2 = rd->argintregs[s1];*/
                                /*s2 = REG_WINDOW_TRANSPOSE(s2);*/
+                               
+                               /* need the argument index (p) here, not the register number */
+                               
                                if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
-                                       /*M_INTMOVE(s2, var->vv.regoff);*/
-                                       M_LDX(var->vv.regoff, REG_SP, JITSTACK + (s1 * 8));
+                                       /*M_INTMOVE(s2, var->vv.regoff);*/                                      
+                                       M_LDX(var->vv.regoff, REG_SP, JITSTACK + (p * 8));
 
                                } else {                             /* reg arg -> spilled    */
                                        /*M_STX(s2, REG_SP, (WINSAVE_CNT + var->vv.regoff) * 8);*/
                                        
-                                       M_LDX(REG_ITMP1, REG_SP, JITSTACK + (s1 * 8));
+                                       M_LDX(REG_ITMP1, REG_SP, JITSTACK + (p * 8));
                                        M_STX(REG_ITMP1, REG_SP, localbase + (var->vv.regoff * 8));
                                }
 
@@ -280,12 +288,11 @@ bool codegen_emit(jitdata *jd)
                
                } else {                                     /* floating args         */
                        if (!md->params[p].inmemory) {           /* register arguments    */
-                               s2 = rd->argfltregs[s1];
                                if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
-                                       M_FLTMOVE(s2, var->vv.regoff);
+                                       M_FLTMOVE(s1, var->vv.regoff);
 
                                } else {                                         /* reg arg -> spilled    */
-                                       M_DST(s2, REG_SP, localbase + (var->vv.regoff) * 8);
+                                       M_DST(s1, REG_SP, localbase + (var->vv.regoff) * 8);
                                }
 
                        } else {                                 /* stack arguments       */
@@ -466,23 +473,23 @@ bool codegen_emit(jitdata *jd)
                /* load/store/copy/move operations ************************************/
 
                case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
-               case ICMD_LLOAD:      /* ...  ==> ..., content of local variable      */
-               case ICMD_ALOAD:      /* ...  ==> ..., content of local variable      */
-               case ICMD_FLOAD:      /* ...  ==> ..., content of local variable      */
-               case ICMD_DLOAD:      /* ...  ==> ..., content of local variable      */
+               case ICMD_LLOAD:
+               case ICMD_ALOAD:
+               case ICMD_FLOAD:
+               case ICMD_DLOAD:
                case ICMD_ISTORE:     /* ..., value  ==> ...                          */
-               case ICMD_LSTORE:     /* ..., value  ==> ...                          */
-               case ICMD_FSTORE:     /* ..., value  ==> ...                          */
-               case ICMD_DSTORE:     /* ..., value  ==> ...                          */
+               case ICMD_LSTORE:
+               case ICMD_FSTORE:
+               case ICMD_DSTORE:
                case ICMD_COPY:
                case ICMD_MOVE:
 
-                       emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
+                       emit_copy(jd, iptr);
                        break;
        
                case ICMD_ASTORE:
                        if (!(iptr->flags.bits & INS_FLAG_RETADDR))
-                               emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
+                               emit_copy(jd, iptr);
                        break;
 
 
@@ -1109,7 +1116,7 @@ bool codegen_emit(jitdata *jd)
                case ICMD_I2F:
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       disp = dseg_add_float(cd, 0.0);
+                       disp = dseg_add_unique_float(cd, 0.0);
                        M_IST (s1, REG_PV_CALLEE, disp);
                        M_FLD (d, REG_PV_CALLEE, disp);
                        M_CVTIF (d, d); /* rd gets translated to double target register */
@@ -1119,7 +1126,7 @@ bool codegen_emit(jitdata *jd)
                case ICMD_I2D:
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       disp = dseg_add_float(cd, 0.0);
+                       disp = dseg_add_unique_float(cd, 0.0);
                        M_IST(s1, REG_PV_CALLEE, disp);
                        M_FLD(REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */
                        M_CVTID (REG_FTMP2, d); /* rd gets translated to double target register */
@@ -1129,7 +1136,7 @@ bool codegen_emit(jitdata *jd)
                case ICMD_L2F:
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       disp = dseg_add_double(cd, 0.0);
+                       disp = dseg_add_unique_double(cd, 0.0);
                        M_STX(s1, REG_PV_CALLEE, disp);
                        M_DLD(REG_FTMP3, REG_PV_CALLEE, disp);
                        M_CVTLF(REG_FTMP3, d);
@@ -1139,7 +1146,7 @@ bool codegen_emit(jitdata *jd)
                case ICMD_L2D:
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       disp = dseg_add_double(cd, 0.0);
+                       disp = dseg_add_unique_double(cd, 0.0);
                        M_STX(s1, REG_PV_CALLEE, disp);
                        M_DLD(d, REG_PV_CALLEE, disp);
                        M_CVTLD(d, d);
@@ -1149,7 +1156,13 @@ bool codegen_emit(jitdata *jd)
                case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       disp = dseg_add_float(cd, 0.0);
+                       disp = dseg_add_unique_float(cd, 0.0);
+                       
+                       /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5)  */
+                       M_FCMP(s1, s1);
+                       M_FBU(5);
+                       M_MOV(REG_ZERO, d); /* delay slot */
+                       
                        M_CVTFI(s1, REG_FTMP2);
                        M_FST(REG_FTMP2, REG_PV_CALLEE, disp);
                        M_ILD(d, REG_PV, disp);
@@ -1160,7 +1173,13 @@ bool codegen_emit(jitdata *jd)
                case ICMD_D2I:       /* ..., value  ==> ..., (int) value             */
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       disp = dseg_add_float(cd, 0.0);
+                       disp = dseg_add_unique_float(cd, 0.0);
+                       
+                       /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5)  */
+                       M_DCMP(s1, s1);
+                       M_FBU(5);
+                       M_MOV(REG_ZERO, d); /* delay slot */
+                       
                        M_CVTDI(s1, REG_FTMP2);
                        M_FST(REG_FTMP2, REG_PV, disp);
                        M_ILD(d, REG_PV, disp);
@@ -1170,7 +1189,13 @@ bool codegen_emit(jitdata *jd)
                case ICMD_F2L:       /* ..., value  ==> ..., (long) value             */
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       disp = dseg_add_double(cd, 0.0);
+                       disp = dseg_add_unique_double(cd, 0.0);
+                       
+                       /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5)  */
+                       M_FCMP(s1, s1);
+                       M_FBU(5);
+                       M_MOV(REG_ZERO, d); /* delay slot */
+                       
                        M_CVTFL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
                        M_DST(REG_FTMP2, REG_PV, disp);
                        M_LDX(d, REG_PV, disp);
@@ -1180,7 +1205,13 @@ bool codegen_emit(jitdata *jd)
                case ICMD_D2L:       /* ..., value  ==> ..., (long) value             */
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       disp = dseg_add_double(cd, 0.0);
+                       disp = dseg_add_unique_double(cd, 0.0);
+                       
+                       /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5)  */
+                       M_DCMP(s1, s1);
+                       M_FBU(5);
+                       M_MOV(REG_ZERO, d); /* delay slot */
+                       
                        M_CVTDL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
                        M_DST(REG_FTMP2, REG_PV, disp);
                        M_LDX(d, REG_PV, disp);
@@ -1449,8 +1480,8 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
 
-                       M_MOV(s1, rd->argintregs[0]);
-                       M_MOV(s3, rd->argintregs[1]);
+                       M_MOV(s1, REG_OUT0);
+                       M_MOV(s3, REG_OUT1);
                        disp = dseg_add_functionptr(cd, BUILTIN_canstore);
                        M_ALD(REG_ITMP3, REG_PV, disp);
                        M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
@@ -2304,6 +2335,8 @@ nowperformreturn:
 
                        MCODECHECK((s3 << 1) + 64);
 
+#ifdef BUILTIN_FLOAT_ARGS /* float args for builtins disabled */
+
                        /* copy float arguments according to ABI convention */
 
                        int num_fltregargs = 0;
@@ -2312,12 +2345,9 @@ nowperformreturn:
                        for (s3 = s3 - 1; s3 >= 0; s3--) {
                                var = VAR(iptr->sx.s23.s2.args[s3]);
 
-                               if (var->flags & PREALLOC)
-                                       continue;
-
                                if (IS_FLT_DBL_TYPE(var->type)) {
                                        if (!md->params[s3].inmemory) {
-                                               s1 = md->params[s3].regoff; /*native flt args use regoff directly*/
+                                               s1 = s3; /*native flt args use argument index directly*/
                                                d = emit_load(jd, iptr, var, REG_FTMP1);
                                                
                                                M_DMOV(d, s1 + 16);
@@ -2339,6 +2369,10 @@ nowperformreturn:
                                /*printf("builtin float arg to target reg: %d ==> %d\n", s1+16, s1);*/
                        }
                        
+#else
+                       assert(md->argfltreguse == 0);
+#endif
+                       
                        goto gen_method;
 
                case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
@@ -2367,39 +2401,40 @@ gen_method:
 
                        for (s3 = s3 - 1; s3 >= 0; s3--) {
                                var = VAR(iptr->sx.s23.s2.args[s3]);
+                               d  = md->params[s3].regoff;
 
                                if (var->flags & PREALLOC)
                                        continue;
 
                                if (IS_INT_LNG_TYPE(var->type)) {
                                        if (!md->params[s3].inmemory) {
-                                               s1 = rd->argintregs[md->params[s3].regoff];
-                                               d = emit_load(jd, iptr, var, s1);
-                                               M_INTMOVE(d, s1);
+                                               s1 = emit_load(jd, iptr, var, d);
+                                               M_INTMOVE(s1, d);
                                        } 
                                        else {
-                                               d = emit_load(jd, iptr, var, REG_ITMP1);
-                                               M_STX(d, REG_SP, JITSTACK + md->params[s3].regoff * 8);
+                                               s1 = emit_load(jd, iptr, var, REG_ITMP1);
+                                               M_STX(s1, REG_SP, JITSTACK + d * 8);
                                        }
                                }
                                else {
+#ifdef BUILTIN_FLOAT_ARGS
                                        if (iptr->opc == ICMD_BUILTIN)
                                                continue;
+#endif
                                                
                                        if (!md->params[s3].inmemory) {
-                                               s1 = rd->argfltregs[md->params[s3].regoff];
-                                               d = emit_load(jd, iptr, var, s1);
+                                               s1 = emit_load(jd, iptr, var, d);
                                                if (IS_2_WORD_TYPE(var->type))
-                                                       M_DMOV(d, s1);
+                                                       M_DMOV(s1, d);
                                                else
-                                                       M_FMOV(d, s1);
+                                                       M_FMOV(s1, d);
                                        }
                                        else {
-                                               d = emit_load(jd, iptr, var, REG_FTMP1);
+                                               s1 = emit_load(jd, iptr, var, REG_FTMP1);
                                                if (IS_2_WORD_TYPE(var->type))
-                                                       M_DST(d, REG_SP, JITSTACK + md->params[s3].regoff * 8);
+                                                       M_DST(s1, REG_SP, JITSTACK + d * 8);
                                                else
-                                                       M_FST(d, REG_SP, JITSTACK + md->params[s3].regoff * 8);
+                                                       M_FST(s1, REG_SP, JITSTACK + d * 8);
                                        }
                                }
                        }
@@ -2660,8 +2695,8 @@ gen_method:
                        else {
                                /* array type cast-check */
 
-                               s1 = emit_load_s1(jd, iptr, rd->argintregs[0]);
-                               M_INTMOVE(s1, rd->argintregs[0]);
+                               s1 = emit_load_s1(jd, iptr, REG_OUT0);
+                               M_INTMOVE(s1, REG_OUT0);
 
                                disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
 
@@ -2675,7 +2710,7 @@ gen_method:
                                else
                                        disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
 
-                               M_ALD(rd->argintregs[1], REG_PV, disp);
+                               M_ALD(REG_OUT1, REG_PV, disp);
                                disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
                                M_ALD(REG_ITMP3, REG_PV, disp);
                                /* XXX jit-c-call */
@@ -2913,82 +2948,43 @@ gen_method:
 }
 
 
-/* createcompilerstub **********************************************************
+/* codegen_emit_stub_compiler **************************************************
 
-   Creates a stub routine which calls the compiler.
+   Emits a stub routine which calls the compiler.
        
 *******************************************************************************/
 
-#define COMPILERSTUB_DATASIZE    3 * SIZEOF_VOID_P
-#define COMPILERSTUB_CODESIZE    4 * 4
-
-#define COMPILERSTUB_SIZE        COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
-
-
-u1 *createcompilerstub(methodinfo *m)
+void codegen_emit_stub_compiler(jitdata *jd)
 {
-       u1     *s;                          /* memory to hold the stub            */
-       ptrint      *d;
-       codeinfo    *code;
+       methodinfo  *m;
        codegendata *cd;
-       s4           dumpsize;
-       
-       s = CNEW(u1, COMPILERSTUB_SIZE);
-
-       /* set data pointer and code pointer */
-
-       d = (ptrint *) s;
-       s = s + COMPILERSTUB_DATASIZE;
 
-       /* mark start of dump memory area */
-
-       dumpsize = dump_size();
-
-       cd = DNEW(codegendata);
-       cd->mcodeptr = s;
-       
-       /* Store the codeinfo pointer in the same place as in the
-          methodheader for compiled methods. */
-
-       code = code_codeinfo_new(m);
+       /* get required compiler data */
 
-       d[0] = (ptrint) asm_call_jit_compiler;
-       d[1] = (ptrint) m;
-       d[2] = (ptrint) code;
+       m  = jd->m;
+       cd = jd->cd;
 
        /* code for the stub */
+
        /* no window save yet, user caller's PV */
        M_ALD_INTERN(REG_ITMP1, REG_PV_CALLER, -2 * SIZEOF_VOID_P);  /* codeinfo pointer */
        M_ALD_INTERN(REG_PV_CALLER, REG_PV_CALLER, -3 * SIZEOF_VOID_P);  /* pointer to compiler */
        M_JMP(REG_ZERO, REG_PV_CALLER, REG_ZERO);  /* jump to the compiler, RA is wasted */
        M_NOP;
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               count_cstub_len += COMPILERSTUB_SIZE;
-#endif
-
-       /* release dump area */
-
-       dump_release(dumpsize);
-
-       return s;
 }
 
 
+/* codegen_emit_stub_native ****************************************************
 
-/* createnativestub ************************************************************
-
-   Creates a stub routine which calls a native method.
+   Emits a stub routine which calls a native method.
 
 *******************************************************************************/
 
-u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
+void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
 {
        methodinfo   *m;
        codeinfo     *code;
        codegendata  *cd;
-       registerdata *rd;
        methoddesc   *md;
        s4            nativeparams;
        s4            i, j;                 /* count variables                    */
@@ -3001,7 +2997,6 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
        m    = jd->m;
        code = jd->code;
        cd   = jd->cd;
-       rd   = jd->rd;
 
        /* initialize variables */
 
@@ -3051,7 +3046,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
 
        for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
                if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
-                       M_DST(rd->argfltregs[i], REG_SP, CSTACK + (j * 8));
+                       M_DST(abi_registers_float_argument[i], REG_SP, CSTACK + (j * 8));
                        j++;
                }
        }
@@ -3071,7 +3066,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
 
        for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
                if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
-                       M_DLD(rd->argfltregs[i], REG_SP, CSTACK + (j * 8));
+                       M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + (j * 8));
                        j++;
                }
        }
@@ -3084,7 +3079,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
 
                if (IS_INT_LNG_TYPE(t)) {
                        if (!md->params[i].inmemory) {
-                               s1 = rd->argintregs[md->params[i].regoff];
+                               s1 = md->params[i].regoff;
                                /* s1 refers to the old window, transpose */
                                s1 = REG_WINDOW_TRANSPOSE(s1);
 
@@ -3097,6 +3092,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
                                }
 
                        } else {
+                               /*assert(false);*/
                                s1 = md->params[i].regoff + cd->stackframesize;
                                s2 = nmd->params[j].regoff - 6;
                                M_ALD(REG_ITMP1, REG_SP, CSTACK + s1 * 8);
@@ -3105,7 +3101,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
 
                } else {
                        if (!md->params[i].inmemory) {
-                               s1 = rd->argfltregs[md->params[i].regoff];
+                               s1 = md->params[i].regoff;
 
                                if (!nmd->params[j].inmemory) {
                                        /* no mapping to regs needed, native flt args use regoff */
@@ -3126,6 +3122,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
                                }
 
                        } else {
+                               /*assert(false);*/
                                s1 = md->params[i].regoff + cd->stackframesize;
                                s2 = nmd->params[j].regoff - 6;
                                if (IS_2_WORD_TYPE(t)) {
@@ -3221,14 +3218,9 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
        M_JMP(REG_ZERO, REG_ITMP1, REG_ZERO);/* jump to asm exception handler     */
        M_RESTORE(REG_ZERO, 0, REG_ZERO);   /* restore callers window (DELAY)     */
        
-
        /* generate patcher stubs */
 
        emit_patcher_stubs(jd);
-
-       codegen_finish(jd);
-
-       return code->entrypoint;
 }
 
 /*