* Removed all Id tags.
[cacao.git] / src / vm / jit / sparc64 / codegen.c
index f1a4a14b36b2e870ea24595994991ced877d0e73..d4f9483f382fbd84632355e2f528055c9d9545da 100644 (file)
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 4644 2006-03-16 18:44:46Z edwin $
-
 */
 
 
 #include "config.h"
 
 #include <assert.h>
+#include <stdint.h>
 #include <stdio.h>
 
 #include "vm/types.h"
@@ -42,6 +41,7 @@
 #include "mm/memory.h"
 
 #include "native/jni.h"
+#include "native/localref.h"
 #include "native/native.h"
 #include "vm/builtin.h"
 #include "vm/exceptions.h"
@@ -62,6 +62,7 @@
 #include "vmcore/loader.h"
 #include "vmcore/options.h"
 
+#include "vm/jit/sparc64/solaris/macro_rename.h"
 
 #define BUILTIN_FLOAT_ARGS 1
 
@@ -95,6 +96,22 @@ s4 get_lopart_disp(disp)
                
        return lodisp;
 }
+
+#ifndef NDEBUG
+bool check_13bit_imm(s8 imm)
+{
+       s4 sign = (imm >> 12) & 0x1;
+
+       if (sign == 0) {
+               if ((imm & ~0xfff) == 0) return true; /* pos imm. */
+       }
+       else
+               if ((imm & ~0xfff) + 0xfff == -1) return true; /* neg imm. */
+       
+       printf("immediate out-of-bounds: %ld\n", imm);
+       return false;
+}
+#endif
        
 
 /* codegen_emit ****************************************************************
@@ -141,7 +158,8 @@ bool codegen_emit(jitdata *jd)
 
        {
        s4 i, p, t, l;
-       s4 savedregs_num, localbase;
+       s4 savedregs_num;
+       s4 framesize_disp;
 
 #if 0 /* no leaf optimization yet */
        savedregs_num = (jd->isleafmethod) ? 0 : 1;       /* space to save the RA */
@@ -169,7 +187,7 @@ bool codegen_emit(jitdata *jd)
        /* create method header */
 
        (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
-       (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize       */
+       framesize_disp = dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize       */
 
 #if defined(ENABLE_THREADS)
        /* IsSync contains the offset relative to the stack pointer for the
@@ -179,7 +197,7 @@ bool codegen_emit(jitdata *jd)
        */
 
        if (checksync && (m->flags & ACC_SYNCHRONIZED))
-               (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 8); /* IsSync        */
+               (void) dseg_add_unique_s4(cd, JITSTACK + (rd->memuse + 1) * 8); /* IsSync */
        else
 #endif
                (void) dseg_add_unique_s4(cd, 0);                  /* IsSync          */
@@ -201,9 +219,15 @@ bool codegen_emit(jitdata *jd)
 
        /* save register window and create stack frame (if necessary) */
 
-       if (cd->stackframesize)
-               M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP);
-
+       if (cd->stackframesize) {
+               if (cd->stackframesize <= 4095)
+                       M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP);
+               else {
+                       M_ILD_INTERN(REG_ITMP3, REG_PV_CALLER, framesize_disp);
+                       M_SUB(REG_ZERO, REG_ITMP3, REG_ITMP3);
+                       M_SAVE_REG(REG_SP, REG_ITMP3, REG_SP);
+               }
+       }
 
        /* save callee saved float registers (none right now) */
 #if 0
@@ -272,24 +296,6 @@ bool codegen_emit(jitdata *jd)
        
        md = m->parseddesc;
 
-       /* when storing locals, use this as base */
-       localbase = JITSTACK;
-       
-       /* since the register allocator does not know about the shifting window
-        * arg regs need to be copied via the stack
-        */
-       if (md->argintreguse > 0) {
-               /* allocate scratch space for copying in to save(i&l) regs */
-               M_SUB_IMM(REG_SP, INT_ARG_CNT * 8, REG_SP);
-               
-               localbase += INT_ARG_CNT * 8;
-               
-               /* XXX could use the param slots on the stack for this! */
-               for (p = 0; p < INT_ARG_CNT; p++)
-                       M_STX(REG_WINDOW_TRANSPOSE(abi_registers_integer_argument[p]), REG_SP, JITSTACK + (p * 8));
-       }
-       
-
        for (p = 0, l = 0; p < md->paramcount; p++) {
                t = md->paramtypes[p].type;
 
@@ -306,31 +312,62 @@ bool codegen_emit(jitdata *jd)
                s1 = md->params[p].regoff;
                
                if (IS_INT_LNG_TYPE(t)) {                    /* integer args          */                        
+
+                       s2 = var->vv.regoff;
                        
                        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 */
+                               s1 = REG_WINDOW_TRANSPOSE(s1);
                                
                                if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
-                                       /*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 + (p * 8));
-                                       M_STX(REG_ITMP1, REG_SP, localbase + (var->vv.regoff * 8));
+                                       /* the register allocator does not know about the window. */
+                                       /* avoid copying the locals from save to save regs by     */
+                                       /* swapping variables.                                    */
+
+                                       {
+                                       int old_dest = var->vv.regoff;
+                                       int new_dest = p + 24;
+
+                                       /* run through all variables */
+
+                                       for (i = 0; i < jd->varcount; i++) {
+                                               varinfo* uvar = VAR(i);
+
+                                               if (IS_FLT_DBL_TYPE(uvar->type) || IS_INMEMORY(uvar->flags))
+                                                       continue;
+
+                                               s2 = uvar->vv.regoff;
+
+                                               /* free the in reg by moving all other references */
+
+                                               if (s2 == new_dest) {
+                                                       uvar->vv.regoff = old_dest;
+                                                       /*printf("p%d-var[%d]: moved %d -> %d (to free save reg)\n", p, i, s2, old_dest);*/
+                                               }
+
+                                               /* move all variables to the in reg */
+
+                                               if (s2 == old_dest) {
+                                                       uvar->vv.regoff = new_dest;
+                                                       /*printf("p%d-var[%d]: moved %d -> %d (to avoid copy)\n", p, i, s2, new_dest);*/
+                                               }
+                                       }
+                                       }
+
+
+
+                               } 
+                               else {                             /* reg arg -> spilled    */
+                                       M_STX(s1, REG_SP, JITSTACK + var->vv.regoff);
                                }
 
                        } else {                                 /* stack arguments       */
                                if (!(var->flags & INMEMORY)) {      /* stack arg -> register */
-                                       M_LDX(var->vv.regoff, REG_FP, JITSTACK + (s1 * 8));
+                                       M_LDX(var->vv.regoff, REG_FP, JITSTACK + s1);
 
                                } else {                             /* stack arg -> spilled  */
                                        /* add the callers window save registers */
-                                       var->vv.regoff = cd->stackframesize + s1;
+                                       var->vv.regoff = cd->stackframesize * 8 + s1;
                                }
                        }
                
@@ -340,27 +377,20 @@ bool codegen_emit(jitdata *jd)
                                        M_FLTMOVE(s1, var->vv.regoff);
 
                                } else {                                         /* reg arg -> spilled    */
-                                       M_DST(s1, REG_SP, localbase + (var->vv.regoff) * 8);
+                                       M_DST(s1, REG_SP, JITSTACK + var->vv.regoff);
                                }
 
                        } else {                                 /* stack arguments       */
                                if (!(var->flags & INMEMORY)) {      /* stack-arg -> register */
-                                       M_DLD(var->vv.regoff, REG_FP, JITSTACK + (s1 * 8));
+                                       M_DLD(var->vv.regoff, REG_FP, JITSTACK + s1);
 
                                } else {                             /* stack-arg -> spilled  */
-                                       var->vv.regoff = cd->stackframesize + s1;
+                                       var->vv.regoff = cd->stackframesize * 8 + s1;
                                }
                        }
                }
        } /* end for */
        
-       if (md->argintreguse > 0) {
-               /* release scratch space */
-               M_ADD_IMM(REG_SP, INT_ARG_CNT * 8, REG_SP);
-       }
-
-
-
        
        }
        
@@ -1336,7 +1366,7 @@ bool codegen_emit(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
                        emit_nullpointer_check(cd, iptr, s1);
-                       M_ILD(d, s1, OFFSET(java_arrayheader, size));
+                       M_ILD(d, s1, OFFSET(java_array_t, size));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1348,7 +1378,7 @@ bool codegen_emit(jitdata *jd)
                        /* implicit null-pointer check */
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP3);
-                       M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray, data[0]));
+                       M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray_t, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1361,7 +1391,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP3);
                        M_AADD(s2, REG_ITMP3, REG_ITMP3);
-                       M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
+                       M_SLDU(d, REG_ITMP3, OFFSET(java_chararray_t, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;                  
 
@@ -1374,7 +1404,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP3);
                        M_AADD(s2, REG_ITMP3, REG_ITMP3);
-                       M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray, data[0]));
+                       M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray_t, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1387,7 +1417,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
-                       M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
+                       M_ILD(d, REG_ITMP3, OFFSET(java_intarray_t, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1400,7 +1430,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
-                       M_LDX(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
+                       M_LDX(d, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1413,7 +1443,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
-                       M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
+                       M_FLD(d, REG_ITMP3, OFFSET(java_floatarray_t, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1426,7 +1456,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
-                       M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
+                       M_DLD(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1439,7 +1469,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
-                       M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
+                       M_ALD(d, REG_ITMP3, OFFSET(java_objectarray_t, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1452,7 +1482,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
-                       M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+                       M_BST(s3, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
                        break;
 
                case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
@@ -1465,7 +1495,7 @@ bool codegen_emit(jitdata *jd)
                        M_AADD(s2, s1, REG_ITMP1);
                        M_AADD(s2, REG_ITMP1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
-                       M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
+                       M_SST(s3, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
                        break;
 
                case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
@@ -1477,7 +1507,7 @@ bool codegen_emit(jitdata *jd)
                        M_ASLL_IMM(s2, 2, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
-                       M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
+                       M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
                        break;
 
                case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
@@ -1489,7 +1519,7 @@ bool codegen_emit(jitdata *jd)
                        M_ASLL_IMM(s2, 3, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
-                       M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
+                       M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray_t, data[0]));
                        break;
 
                case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
@@ -1501,7 +1531,7 @@ bool codegen_emit(jitdata *jd)
                        M_ASLL_IMM(s2, 2, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP1);
-                       M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
+                       M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
                        break;
 
                case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
@@ -1513,7 +1543,7 @@ bool codegen_emit(jitdata *jd)
                        M_ASLL_IMM(s2, 3, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP1);
-                       M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
+                       M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
                        break;
 
 
@@ -1539,7 +1569,7 @@ bool codegen_emit(jitdata *jd)
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        /* implicit null-pointer check */
-                       M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
+                       M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
                        break;
 
 
@@ -1550,7 +1580,7 @@ bool codegen_emit(jitdata *jd)
                        /* implicit null-pointer check */
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
-                       M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+                       M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
                        break;
 
                case ICMD_CASTORECONST:   /* ..., arrayref, index  ==> ...            */
@@ -1562,7 +1592,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
                        M_AADD(s2, REG_ITMP1, REG_ITMP1);
-                       M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
+                       M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
                        break;
 
                case ICMD_IASTORECONST:   /* ..., arrayref, index  ==> ...            */
@@ -1573,7 +1603,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
-                       M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
+                       M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
                        break;
 
                case ICMD_LASTORECONST:   /* ..., arrayref, index  ==> ...            */
@@ -1584,7 +1614,7 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
-                       M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
+                       M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray_t, data[0]));
                        break;
 
                case ICMD_AASTORECONST:   /* ..., arrayref, index  ==> ...            */
@@ -1595,23 +1625,23 @@ bool codegen_emit(jitdata *jd)
                        emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
-                       M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
+                       M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
                        break;
                
 
                case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               uf = iptr->sx.s23.s3.uf;
+                               uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
                                disp      = dseg_add_unique_address(cd, uf);
 
                                codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
                        } 
                        else {
-                               fi = iptr->sx.s23.s3.fmiref->p.field;
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
-                               disp = dseg_add_address(cd, &(fi->value));
+                               disp      = dseg_add_address(cd, fi->value);
 
                                if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
                                        codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
@@ -1647,16 +1677,16 @@ bool codegen_emit(jitdata *jd)
                case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               uf = iptr->sx.s23.s3.uf;
+                               uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
                                disp      = dseg_add_unique_address(cd, uf);
 
                                codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
                        } 
                        else {
-                               fi = iptr->sx.s23.s3.fmiref->p.field;
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
-                               disp = dseg_add_address(cd, &(fi->value));
+                               disp      = dseg_add_address(cd, fi->value);
 
                                if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
                                        codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
@@ -1695,14 +1725,14 @@ bool codegen_emit(jitdata *jd)
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
-                               disp = dseg_add_unique_address(cd, uf);
+                               disp      = dseg_add_unique_address(cd, uf);
 
                                codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
                        } 
                        else {
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
-                               disp      = dseg_add_address(cd, &(fi->value));
+                               disp      = dseg_add_address(cd, fi->value);
 
                                if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
                                        codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
@@ -2305,15 +2335,15 @@ nowperformreturn:
                        if (l == 0) {
                                M_INTMOVE(s1, REG_ITMP1);
                        }
-                       else if (l <= 4095) {
+                       else if (-l >= 4096 && -l <= 4095) {
                                M_ADD_IMM(s1, -l, REG_ITMP1);
                        }
                        else {
                                ICONST(REG_ITMP2, l);
-                               /* XXX: do I need to truncate s1 to 32-bit ? */
                                M_SUB(s1, REG_ITMP2, REG_ITMP1);
                        }
-                       i = i - l + 1;
+
+                       i = i - l + 1; /* number of targets (>0) */
 
 
                        /* range check */
@@ -2466,7 +2496,7 @@ gen_method:
                                        } 
                                        else {
                                                s1 = emit_load(jd, iptr, var, REG_ITMP1);
-                                               M_STX(s1, REG_SP, JITSTACK + d * 8);
+                                               M_STX(s1, REG_SP, JITSTACK + d);
                                        }
                                }
                                else {
@@ -2484,7 +2514,7 @@ gen_method:
                                        }
                                        else {
                                                s1 = emit_load(jd, iptr, var, REG_FTMP1);
-                                               M_DST(s1, REG_SP, JITSTACK + d * 8);
+                                               M_DST(s1, REG_SP, JITSTACK + d);
                                        }
                                }
                        }
@@ -2549,7 +2579,7 @@ gen_method:
                                                sizeof(methodptr) * lm->vftblindex;
 
                                /* implicit null-pointer check */
-                               M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_objectheader, vftbl));
+                               M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_object_t, vftbl));
                                M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
                                
                                /* generate the actual call */
@@ -2578,7 +2608,7 @@ gen_method:
                                }
 
                                /* implicit null-pointer check */
-                               M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_objectheader, vftbl));
+                               M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_object_t, vftbl));
                                M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
                                M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
 
@@ -2643,9 +2673,8 @@ gen_method:
                                        superindex = super->index;
                                }
 
-#if defined(ENABLE_THREADS)
-                               codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
-#endif
+                               if ((super == NULL) || !(super->flags & ACC_INTERFACE))
+                                       CODEGEN_CRITICAL_SECTION_NEW;
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
 
@@ -2678,7 +2707,7 @@ gen_method:
                                                emit_label_beqz(cd, BRANCH_LABEL_3, s1);
                                        }
 
-                                       M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
+                                       M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
                                        M_ILD(REG_ITMP3, REG_ITMP2,
                                                        OFFSET(vftbl_t, interfacetablelength));
                                        M_ADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
@@ -2714,19 +2743,19 @@ gen_method:
                                                emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                        }
 
-                                       M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
+                                       M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
                                        M_ALD(REG_ITMP3, REG_PV, disp);
-#if defined(ENABLE_THREADS)
-                                       codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
-#endif
+                                       
+                                       CODEGEN_CRITICAL_SECTION_START;
+
                                        M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
                                        M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
                                        M_SUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
                                        M_ALD(REG_ITMP3, REG_PV, disp);
                                        M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
-#if defined(ENABLE_THREADS)
-                                       codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
-#endif
+
+                                       CODEGEN_CRITICAL_SECTION_END;
+
                                        /*                              } */
                                        M_CMP(REG_ITMP3, REG_ITMP2);
                                        emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1);
@@ -2809,9 +2838,9 @@ gen_method:
                                supervftbl = super->vftbl;
                        }
 
-#if defined(ENABLE_THREADS)
-                       codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
-#endif
+                       if ((super == NULL) || !(super->flags & ACC_INTERFACE))
+                               CODEGEN_CRITICAL_SECTION_NEW;
+
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
                        if (s1 == d) {
@@ -2850,7 +2879,7 @@ gen_method:
                                        emit_label_beqz(cd, BRANCH_LABEL_3, s1);
                                }
 
-                               M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
+                               M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
                                M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
                                M_CMP_IMM(REG_ITMP3, superindex);
                                M_BLE(4);
@@ -2884,17 +2913,17 @@ gen_method:
                                        emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                }
 
-                               M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
+                               M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
                                M_ALD(REG_ITMP2, REG_PV, disp);
-#if defined(ENABLE_THREADS)
-                               codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
-#endif
+
+                               CODEGEN_CRITICAL_SECTION_START;
+
                                M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
                                M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
                                M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
-#if defined(ENABLE_THREADS)
-                               codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
-#endif
+
+                               CODEGEN_CRITICAL_SECTION_END;
+
                                M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
                                M_CMP(REG_ITMP1, REG_ITMP2);
                                M_XCMOVULE_IMM(1, d);
@@ -2979,8 +3008,19 @@ gen_method:
        } /* switch */
                
        } /* for instruction */
+
+       MCODECHECK(64);
        
+       /* At the end of a basic block we may have to append some nops,
+          because the patcher stub calling code might be longer than the
+          actual instruction. So codepatching does not change the
+          following block unintentionally. */
 
+       if (cd->mcodeptr < cd->lastmcodeptr) {
+               while (cd->mcodeptr < cd->lastmcodeptr) {
+                       M_NOP;
+               }
+       }
                
        } /* if (bptr -> flags >= BBREACHED) */
        } /* for basic block */
@@ -2990,7 +3030,6 @@ gen_method:
        /* generate stubs */
 
        emit_patcher_stubs(jd);
-       REPLACEMENT_EMIT_STUBS(jd);
        
        /* everything's ok */
 
@@ -3041,6 +3080,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
        s4            t;
        s4            s1, s2, disp;
        s4            funcdisp;             /* displacement of the function       */
+       s4            fltregarg_offset[FLT_ARG_CNT];
 
        /* get required compiler data */
 
@@ -3059,7 +3099,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
                sizeof(stackframeinfo) / SIZEOF_VOID_P +
                sizeof(localref_table) / SIZEOF_VOID_P +
                md->paramcount +                /* for saving arguments over calls    */
-               nmd->memuse +  /* nmd knows about the native stackframe layout */
+               nmd->memuse +              /* nmd->memuse includes the (6) abi params */
                WINSAVE_CNT;
 
 
@@ -3100,16 +3140,20 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
 
        /* save float argument registers */
 
+       assert(ABIPARAMS_CNT >= FLT_ARG_CNT);
+
        for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
                if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
-                       M_DST(abi_registers_float_argument[i], REG_SP, CSTACK + (j * 8));
+                       s1 = WINSAVE_CNT + nmd->memuse + j;
+                       M_DST(abi_registers_float_argument[i], REG_SP, BIAS + (s1*8));
+                       fltregarg_offset[i] = s1; /* remember stack offset */
                        j++;
                }
        }
 
        /* prepare data structures for native function call */
 
-       M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp == top of the stack frame (absolute == +BIAS) */
+       M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp == top of the stack frame (absolute, ie. + BIAS) */
        M_MOV(REG_PV_CALLEE, REG_OUT1);
        M_MOV(REG_FP, REG_OUT2); /* java sp */
        M_MOV(REG_RA_CALLEE, REG_OUT3);
@@ -3118,87 +3162,108 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
        M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
        M_NOP; /* XXX fill me! */
 
-       /* restore float argument registers */
-
+       /* keep float arguments on stack */
+#if 0
        for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
                if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
                        M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + (j * 8));
                        j++;
                }
        }
+#endif
 
        /* copy or spill arguments to new locations */
-       int num_fltregargs = 0;
-       int fltregarg_inswap[16];
+
        for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
                t = md->paramtypes[i].type;
 
                if (IS_INT_LNG_TYPE(t)) {
+
+                       /* integral types */
+
                        if (!md->params[i].inmemory) {
                                s1 = md->params[i].regoff;
                                /* s1 refers to the old window, transpose */
                                s1 = REG_WINDOW_TRANSPOSE(s1);
 
                                if (!nmd->params[j].inmemory) {
-                                       s2 = nat_argintregs[nmd->params[j].regoff];
+                                       s2 = nmd->params[j].regoff;
                                        M_INTMOVE(s1, s2);
                                } else {
-                                       s2 = nmd->params[j].regoff - 6;
-                                       M_AST(s1, REG_SP, CSTACK + s2 * 8);
+                                       /* nmd's regoff is relative to the start of the param array */
+                                       s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
+                                       M_AST(s1, REG_SP, s2);
                                }
 
                        } 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);
-                               M_AST(REG_ITMP1, REG_SP, CSTACK + s2 * 8);
+                               if (!nmd->params[j].inmemory) {
+                                       /* JIT stack arg -> NAT reg arg */
+
+                                       /* Due to the Env pointer that is always passed, the 6th JIT arg   */
+                                       /* is the 7th (or 8th w/ class ptr) NAT arg, and goes to the stack */
+
+                                       assert(false); /* path never taken */
+                               }
+
+                               s1 = md->params[i].regoff + cd->stackframesize * 8;
+                               s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
+                               M_ALD(REG_ITMP1, REG_SP, CSTACK + s1);
+                               M_AST(REG_ITMP1, REG_SP, s2);
                        }
 
                } else {
+
+                       /* floating point types */
+
                        if (!md->params[i].inmemory) {
                                s1 = md->params[i].regoff;
 
                                if (!nmd->params[j].inmemory) {
+
                                        /* no mapping to regs needed, native flt args use regoff */
                                        s2 = nmd->params[j].regoff;
-                                       
-                                       /* we cannot move flt regs to their native arg locations directly */
-                                       M_DMOV(s1, s2 + 16);
-                                       fltregarg_inswap[num_fltregargs] = s2;
-                                       num_fltregargs++;
-                                       /*printf("flt arg swap to %d\n", s2 + 16);*/
 
-                               } else {
+                                       /* JIT float regs are still on the stack */
+                                       M_DLD(s2, REG_SP, BIAS + (fltregarg_offset[i] * 8));
+                               } 
+                               else {
+                                       /* not supposed to happen with 16 NAT flt args */
+                                       assert(false); 
+                                       /*
                                        s2 = nmd->params[j].regoff;
                                        if (IS_2_WORD_TYPE(t))
                                                M_DST(s1, REG_SP, CSTACK + (s2 * 8));
                                        else
                                                M_FST(s1, REG_SP, CSTACK + (s2 * 8));
+                                       */
                                }
 
-                       } else {
-                               /*assert(false);*/
-                               s1 = md->params[i].regoff + cd->stackframesize;
-                               s2 = nmd->params[j].regoff - 6;
-                               if (IS_2_WORD_TYPE(t)) {
-                                       M_DLD(REG_FTMP1, REG_SP, CSTACK + s1 * 8);
-                                       M_DST(REG_FTMP1, REG_SP, CSTACK + s2 * 8);
-                               } else {
-                                       M_FLD(REG_FTMP1, REG_SP, CSTACK + s1 * 8);
-                                       M_FST(REG_FTMP1, REG_SP, CSTACK + s2 * 8);
+                       } 
+                       else {
+                               s1 = md->params[i].regoff;
+
+                               if (!nmd->params[j].inmemory) {
+
+                                       /* JIT stack -> NAT reg */
+
+                                       s2 = nmd->params[j].regoff;
+                                       M_DLD(s2, REG_FP, JITSTACK + s1);
+                               }
+                               else {
+
+                                       /* JIT stack -> NAT stack */
+
+                                       s2 = WINSAVE_CNT * 8 + nmd->params[j].regoff;
+
+                                       /* The FTMP register may already be loaded with args */
+                                       /* we know $f0 is unused because of the env pointer  */
+                                       M_DLD(REG_F0, REG_FP, JITSTACK + s1);
+                                       M_DST(REG_F0, REG_SP, BIAS + s2);
                                }
                        }
                }
        }
        
-       /* move swapped float args to target regs */
-       for (i = 0; i < num_fltregargs; i++) {
-               s1 = fltregarg_inswap[i];
-               M_DMOV(s1 + 16, s1);
-               /*printf("float arg to target reg: %d ==> %d\n", s1+16, s1);*/
-       }
-
 
        /* put class into second argument register */