Patched back in the s1 == REG_ITMP1 (former d == REG_ITMP3) optimization.
[cacao.git] / src / vm / jit / x86_64 / codegen.c
index 7e79c162be2d72764b900dff24d8d8a9a4c64ac1..56c395f6765115130d391d1f9ed0f9fd43e75fe0 100644 (file)
@@ -27,7 +27,7 @@
    Authors: Andreas Krall
             Christian Thalinger
 
-   $Id: codegen.c 1988 2005-03-05 15:55:51Z twisti $
+   $Id: codegen.c 2179 2005-04-01 13:28:16Z twisti $
 
 */
 
@@ -228,11 +228,11 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
 #endif
 
-    /* keep stack 16-byte aligned for calls into native code e.g. libc or jni */
-    /* (alignment problems with movaps)                                       */
+    /* Keep stack of non-leaf functions 16-byte aligned for calls into native */
+       /* code e.g. libc or jni (alignment problems with movaps).                */
 
-       if (!(parentargs_base & 0x1)) {
-               parentargs_base++;
+       if (!m->isleafmethod || runverbose) {
+               parentargs_base |= 0x1;
        }
 
        /* create method header */
@@ -282,7 +282,7 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                x86_64_alu_imm_reg(cd, X86_64_SUB, parentargs_base * 8, REG_SP);
        }
 
-       /* save return address and used callee saved registers */
+       /* save used callee saved registers */
 
        p = parentargs_base;
        for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
@@ -462,7 +462,38 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                src = bptr->instack;
                len = bptr->indepth;
                MCODECHECK(64 + len);
-               while (src != NULL) {
+
+#ifdef LSRA
+               if (opt_lsra) {
+                       while (src != NULL) {
+                               len--;
+                               if ((len == 0) && (bptr->type != BBTYPE_STD)) {
+                                       if (bptr->type == BBTYPE_SBR) {
+                                               /*                                      d = reg_of_var(rd, src, REG_ITMP1); */
+                                               if (!(src->flags & INMEMORY))
+                                                       d= src->regoff;
+                                               else
+                                                       d=REG_ITMP1;
+                                               x86_64_pop_reg(cd, d);
+                                               store_reg_to_var_int(src, d);
+
+                                       } else if (bptr->type == BBTYPE_EXH) {
+                                               /*                                      d = reg_of_var(rd, src, REG_ITMP1); */
+                                               if (!(src->flags & INMEMORY))
+                                                       d= src->regoff;
+                                               else
+                                                       d=REG_ITMP1;
+                                               M_INTMOVE(REG_ITMP1, d);
+                                               store_reg_to_var_int(src, d);
+                                       }
+                               }
+                               src = src->prev;
+                       }
+                       
+               } else {
+#endif
+
+       while (src != NULL) {
                        len--;
                        if ((len == 0) && (bptr->type != BBTYPE_STD)) {
                                if (bptr->type == BBTYPE_SBR) {
@@ -504,7 +535,9 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                        }
                        src = src->prev;
                }
-
+#ifdef LSRA
+               }
+#endif
                /* walk through all instructions */
                
                src = bptr->instack;
@@ -1195,7 +1228,7 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                        d = reg_of_var(rd, iptr->dst, REG_NULL);
                        if (iptr->dst->flags & INMEMORY) {
                                if (src->flags & INMEMORY) {
-                                       if (x86_64_is_imm32(iptr->val.l)) {
+                                       if (IS_IMM32(iptr->val.l)) {
                                                x86_64_imul_imm_membase_reg(cd, iptr->val.l, REG_SP, src->regoff * 8, REG_ITMP1);
 
                                        } else {
@@ -1205,7 +1238,7 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                                        x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
                                        
                                } else {
-                                       if (x86_64_is_imm32(iptr->val.l)) {
+                                       if (IS_IMM32(iptr->val.l)) {
                                                x86_64_imul_imm_reg_reg(cd, iptr->val.l, src->regoff, REG_ITMP1);
 
                                        } else {
@@ -1217,7 +1250,7 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
                        } else {
                                if (src->flags & INMEMORY) {
-                                       if (x86_64_is_imm32(iptr->val.l)) {
+                                       if (IS_IMM32(iptr->val.l)) {
                                                x86_64_imul_imm_membase_reg(cd, iptr->val.l, REG_SP, src->regoff * 8, iptr->dst->regoff);
 
                                        } else {
@@ -1232,7 +1265,7 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                                                x86_64_alul_reg_reg(cd, X86_64_ADD, iptr->dst->regoff, iptr->dst->regoff);
 
                                        } else {
-                                               if (x86_64_is_imm32(iptr->val.l)) {
+                                               if (IS_IMM32(iptr->val.l)) {
                                                        x86_64_imul_imm_reg_reg(cd, iptr->val.l, src->regoff, iptr->dst->regoff);    /* 4 cycles */
 
                                                } else {
@@ -1303,13 +1336,16 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                        }
                        gen_div_check(src);
 
+                       x86_64_mov_reg_reg(cd, RDX, REG_ITMP2);    /* save %rdx, cause it's an argument register */
+
                        x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, RAX);    /* check as described in jvm spec */
                        x86_64_jcc(cd, X86_64_CC_NE, 2 + 4 + 6);
+
+
                        x86_64_alul_reg_reg(cd, X86_64_XOR, RDX, RDX);           /* 2 bytes */
                        x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP3);      /* 4 bytes */
-                       x86_64_jcc(cd, X86_64_CC_E, 3 + 1 + 3);                  /* 6 bytes */
+                       x86_64_jcc(cd, X86_64_CC_E, 1 + 3);                      /* 6 bytes */
 
-                       x86_64_mov_reg_reg(cd, RDX, REG_ITMP2);    /* save %rdx, cause it's an argument register */
                        x86_64_cltd(cd);
                        x86_64_idivl_reg(cd, REG_ITMP3);
 
@@ -1415,14 +1451,17 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                        }
                        gen_div_check(src);
 
+                       x86_64_mov_reg_reg(cd, RDX, REG_ITMP2);    /* save %rdx, cause it's an argument register */
+
                        x86_64_mov_imm_reg(cd, 0x8000000000000000LL, REG_ITMP2);    /* check as described in jvm spec */
                        x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP2, REG_ITMP1);
                        x86_64_jcc(cd, X86_64_CC_NE, 2 + 4 + 6);
+
+
                        x86_64_alul_reg_reg(cd, X86_64_XOR, RDX, RDX);              /* 2 bytes */
                        x86_64_alu_imm_reg(cd, X86_64_CMP, -1, REG_ITMP3);          /* 4 bytes */
-                       x86_64_jcc(cd, X86_64_CC_E, 3 + 2 + 3);                     /* 6 bytes */
+                       x86_64_jcc(cd, X86_64_CC_E, 2 + 3);                         /* 6 bytes */
 
-                       x86_64_mov_reg_reg(cd, RDX, REG_ITMP2);    /* save %rdx, cause it's an argument register */
                        x86_64_cqto(cd);
                        x86_64_idiv_reg(cd, REG_ITMP3);
 
@@ -2209,7 +2248,7 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                                gen_bound_check;
                        }
 
-                       if (x86_64_is_imm32(iptr->val.l)) {
+                       if (IS_IMM32(iptr->val.l)) {
                                x86_64_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
 
                        } else {
@@ -2275,11 +2314,8 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                                /* read patched code. Here we patch the following 5 nop's     */
                                /* so that the real code keeps untouched.                     */
                                if (showdisassemble) {
-                                       x86_64_nop(cd);
-                                       x86_64_nop(cd);
-                                       x86_64_nop(cd);
-                                       x86_64_nop(cd);
-                                       x86_64_nop(cd);
+                                       x86_64_nop(cd); x86_64_nop(cd); x86_64_nop(cd);
+                                       x86_64_nop(cd); x86_64_nop(cd);
                                }
                        }
 
@@ -2305,10 +2341,47 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                                var_to_reg_flt(s2, src, REG_FTMP1);
                                x86_64_movsd_reg_membase(cd, s2, REG_ITMP2, 0);
                                break;
-                       default:
-                               throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                                                  "Unknown PUTSTATIC operand type %d",
-                                                                                  iptr->op1);
+                       }
+                       break;
+
+               case ICMD_PUTSTATICCONST: /* ...  ==> ...                             */
+                                         /* val = value (in current instruction)     */
+                                         /* op1 = type, val.a = field address (in    */
+                                         /* following NOP)                           */
+
+                       /* If the static fields' class is not yet initialized, we do it   */
+                       /* now. The call code is generated later.                         */
+                       if (!((fieldinfo *) iptr[1].val.a)->class->initialized) {
+                               codegen_addclinitref(cd, cd->mcodeptr, ((fieldinfo *) iptr[1].val.a)->class);
+
+                               /* This is just for debugging purposes. Is very difficult to  */
+                               /* read patched code. Here we patch the following 5 nop's     */
+                               /* so that the real code keeps untouched.                     */
+                               if (showdisassemble) {
+                                       x86_64_nop(cd); x86_64_nop(cd); x86_64_nop(cd);
+                                       x86_64_nop(cd); x86_64_nop(cd);
+                               }
+                       }
+
+                       /* This approach is much faster than moving the field address     */
+                       /* inline into a register. */
+                       a = dseg_addaddress(cd, &(((fieldinfo *) iptr[1].val.a)->value));
+                       x86_64_mov_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + a, REG_ITMP1);
+                       switch (iptr->op1) {
+                       case TYPE_INT:
+                       case TYPE_FLT:
+                               x86_64_movl_imm_membase(cd, iptr->val.i, REG_ITMP1, 0);
+                               break;
+                       case TYPE_LNG:
+                       case TYPE_ADR:
+                       case TYPE_DBL:
+                               if (IS_IMM32(iptr->val.l)) {
+                                       x86_64_mov_imm_membase(cd, iptr->val.l, REG_ITMP1, 0);
+                               } else {
+                                       x86_64_movl_imm_membase(cd, iptr->val.l, REG_ITMP1, 0);
+                                       x86_64_movl_imm_membase(cd, iptr->val.l >> 32, REG_ITMP1, 4);
+                               }
+                               break;
                        }
                        break;
 
@@ -2324,11 +2397,8 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                                /* read patched code. Here we patch the following 5 nop's     */
                                /* so that the real code keeps untouched.                     */
                                if (showdisassemble) {
-                                       x86_64_nop(cd);
-                                       x86_64_nop(cd);
-                                       x86_64_nop(cd);
-                                       x86_64_nop(cd);
-                                       x86_64_nop(cd);
+                                       x86_64_nop(cd); x86_64_nop(cd); x86_64_nop(cd);
+                                       x86_64_nop(cd); x86_64_nop(cd);
                                }
                        }
 
@@ -2358,44 +2428,59 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
                                x86_64_movsd_membase_reg(cd, REG_ITMP2, 0, d);
                                store_reg_to_var_flt(iptr->dst, d);
                                break;
-                       default:
-                               throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                                                  "Unknown GETSTATIC operand type %d",
-                                                                                  iptr->op1);
                        }
                        break;
 
-               case ICMD_PUTFIELD:   /* ..., value  ==> ...                          */
+               case ICMD_PUTFIELD:   /* ..., objectref, value  ==> ...               */
                                      /* op1 = type, val.i = field offset             */
 
                        a = ((fieldinfo *)(iptr->val.a))->offset;
                        var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       gen_nullptr_check(s1);
                        switch (iptr->op1) {
                        case TYPE_INT:
                                var_to_reg_int(s2, src, REG_ITMP2);
-                               gen_nullptr_check(s1);
                                x86_64_movl_reg_membase(cd, s2, s1, a);
                                break;
                        case TYPE_LNG:
                        case TYPE_ADR:
                                var_to_reg_int(s2, src, REG_ITMP2);
-                               gen_nullptr_check(s1);
                                x86_64_mov_reg_membase(cd, s2, s1, a);
                                break;
                        case TYPE_FLT:
                                var_to_reg_flt(s2, src, REG_FTMP2);
-                               gen_nullptr_check(s1);
                                x86_64_movss_reg_membase(cd, s2, s1, a);
                                break;
                        case TYPE_DBL:
                                var_to_reg_flt(s2, src, REG_FTMP2);
-                               gen_nullptr_check(s1);
                                x86_64_movsd_reg_membase(cd, s2, s1, a);
                                break;
-                       default:
-                               throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                                                  "Unknown PUTFIELD operand type %d",
-                                                                                  iptr->op1);
+                       }
+                       break;
+
+               case ICMD_PUTFIELDCONST:  /* ..., objectref, value  ==> ...           */
+                                         /* val = value (in current instruction)     */
+                                         /* op1 = type, val.a = field address (in    */
+                                         /* following NOP)                           */
+
+                       a = ((fieldinfo *) iptr[1].val.a)->offset;
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       gen_nullptr_check(s1);
+                       switch (iptr->op1) {
+                       case TYPE_INT:
+                       case TYPE_FLT:
+                               x86_64_movl_imm_membase(cd, iptr->val.i, s1, a);
+                               break;
+                       case TYPE_LNG:
+                       case TYPE_ADR:
+                       case TYPE_DBL:
+                               if (IS_IMM32(iptr->val.l)) {
+                                       x86_64_mov_imm_membase(cd, iptr->val.l, s1, a);
+                               } else {
+                                       x86_64_movl_imm_membase(cd, iptr->val.l, s1, a);
+                                       x86_64_movl_imm_membase(cd, iptr->val.l >> 32, s1, a + 4);
+                               }
+                               break;
                        }
                        break;
 
@@ -2404,36 +2489,29 @@ void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
 
                        a = ((fieldinfo *)(iptr->val.a))->offset;
                        var_to_reg_int(s1, src, REG_ITMP1);
+                       gen_nullptr_check(s1);
                        switch (iptr->op1) {
                        case TYPE_INT:
                                d = reg_of_var(rd, iptr->dst, REG_ITMP1);
-                               gen_nullptr_check(s1);
                                x86_64_movl_membase_reg(cd, s1, a, d);
                                store_reg_to_var_int(iptr->dst, d);
                                break;
                        case TYPE_LNG:
                        case TYPE_ADR:
                                d = reg_of_var(rd, iptr->dst, REG_ITMP1);
-                               gen_nullptr_check(s1);
                                x86_64_mov_membase_reg(cd, s1, a, d);
                                store_reg_to_var_int(iptr->dst, d);
                                break;
                        case TYPE_FLT:
                                d = reg_of_var(rd, iptr->dst, REG_FTMP1);
-                               gen_nullptr_check(s1);
                                x86_64_movss_membase_reg(cd, s1, a, d);
                                store_reg_to_var_flt(iptr->dst, d);
                                break;
                        case TYPE_DBL:                          
                                d = reg_of_var(rd, iptr->dst, REG_FTMP1);
-                               gen_nullptr_check(s1);
                                x86_64_movsd_membase_reg(cd, s1, a, d);
                                store_reg_to_var_flt(iptr->dst, d);
                                break;
-                       default:
-                               throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                                                  "Unknown GETFIELD operand type %d",
-                                                                                  iptr->op1);
                        }
                        break;
 
@@ -2955,13 +3033,8 @@ nowperformreturn:
                                        /* op1 = arg count, val.a = method pointer    */
 
                case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
-                                       /* op1 = arg count, val.a = method pointer    */
-
-               case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
-                                       /* op1 = arg count, val.a = method pointer    */
-
-               case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
-                                       /* op1 = arg count, val.a = method pointer    */
+               case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
+               case ICMD_INVOKEINTERFACE:
 
                        s3 = iptr->op1;
 
@@ -3039,63 +3112,54 @@ gen_method: {
 
                        lm = iptr->val.a;
                        switch (iptr->opc) {
-                               case ICMD_BUILTIN3:
-                               case ICMD_BUILTIN2:
-                               case ICMD_BUILTIN1:
-
-                                       a = (s8) lm;
-                                       d = iptr->op1;
-
-                                       x86_64_mov_imm_reg(cd, a, REG_ITMP1);
-                                       x86_64_call_reg(cd, REG_ITMP1);
-                                       break;
-
-                               case ICMD_INVOKESTATIC:
+                       case ICMD_BUILTIN3:
+                       case ICMD_BUILTIN2:
+                       case ICMD_BUILTIN1:
+                               a = (s8) lm;
+                               d = iptr->op1;
 
-                                       a = (s8) lm->stubroutine;
-                                       d = lm->returntype;
-
-                                       x86_64_mov_imm_reg(cd, a, REG_ITMP2);
-                                       x86_64_call_reg(cd, REG_ITMP2);
-                                       break;
-
-                               case ICMD_INVOKESPECIAL:
-
-                                       a = (s8) lm->stubroutine;
-                                       d = lm->returntype;
+                               x86_64_mov_imm_reg(cd, a, REG_ITMP1);
+                               x86_64_call_reg(cd, REG_ITMP1);
+                               break;
 
-                                       gen_nullptr_check(rd->argintregs[0]);    /* first argument contains pointer */
-                                       x86_64_mov_membase_reg(cd, rd->argintregs[0], 0, REG_ITMP2); /* access memory for hardware nullptr */
-                                       x86_64_mov_imm_reg(cd, a, REG_ITMP2);
-                                       x86_64_call_reg(cd, REG_ITMP2);
-                                       break;
+                       case ICMD_INVOKESTATIC:
+                               a = (s8) lm->stubroutine;
+                               d = lm->returntype;
 
-                               case ICMD_INVOKEVIRTUAL:
+                               x86_64_mov_imm_reg(cd, a, REG_ITMP2);
+                               x86_64_call_reg(cd, REG_ITMP2);
+                               break;
 
-                                       d = lm->returntype;
+                       case ICMD_INVOKESPECIAL:
+                               a = (s8) lm->stubroutine;
+                               d = lm->returntype;
 
-                                       gen_nullptr_check(rd->argintregs[0]);
-                                       x86_64_mov_membase_reg(cd, rd->argintregs[0], OFFSET(java_objectheader, vftbl), REG_ITMP2);
-                                       x86_64_mov_membase32_reg(cd, REG_ITMP2, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex, REG_ITMP1);
-                                       x86_64_call_reg(cd, REG_ITMP1);
-                                       break;
+                               gen_nullptr_check(rd->argintregs[0]);    /* first argument contains pointer */
+                               x86_64_mov_membase_reg(cd, rd->argintregs[0], 0, REG_ITMP2); /* access memory for hardware nullptr */
+                               x86_64_mov_imm_reg(cd, a, REG_ITMP2);
+                               x86_64_call_reg(cd, REG_ITMP2);
+                               break;
 
-                               case ICMD_INVOKEINTERFACE:
+                       case ICMD_INVOKEVIRTUAL:
+                               d = lm->returntype;
 
-                                       ci = lm->class;
-                                       d = lm->returntype;
+                               gen_nullptr_check(rd->argintregs[0]);
+                               x86_64_mov_membase_reg(cd, rd->argintregs[0], OFFSET(java_objectheader, vftbl), REG_ITMP2);
+                               x86_64_mov_membase32_reg(cd, REG_ITMP2, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex, REG_ITMP1);
+                               x86_64_call_reg(cd, REG_ITMP1);
+                               break;
 
-                                       gen_nullptr_check(rd->argintregs[0]);
-                                       x86_64_mov_membase_reg(cd, rd->argintregs[0], OFFSET(java_objectheader, vftbl), REG_ITMP2);
-                                       x86_64_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * ci->index, REG_ITMP2);
-                                       x86_64_mov_membase32_reg(cd, REG_ITMP2, sizeof(methodptr) * (lm - ci->methods), REG_ITMP1);
-                                       x86_64_call_reg(cd, REG_ITMP1);
-                                       break;
+                       case ICMD_INVOKEINTERFACE:
+                               ci = lm->class;
+                               d = lm->returntype;
 
-                               default:
-                                       d = 0;
-                                       error("Unkown ICMD-Command: %d", iptr->opc);
-                               }
+                               gen_nullptr_check(rd->argintregs[0]);
+                               x86_64_mov_membase_reg(cd, rd->argintregs[0], OFFSET(java_objectheader, vftbl), REG_ITMP2);
+                               x86_64_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * ci->index, REG_ITMP2);
+                               x86_64_mov_membase32_reg(cd, REG_ITMP2, sizeof(methodptr) * (lm - ci->methods), REG_ITMP1);
+                               x86_64_call_reg(cd, REG_ITMP1);
+                               break;
+                       }
 
                        /* d contains return type */
 
@@ -3134,7 +3198,7 @@ gen_method: {
  */
 
                        {
-                       classinfo *super = (classinfo*) iptr->val.a;
+                       classinfo *super = (classinfo *) iptr->val.a;
                        
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
             codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
@@ -3216,7 +3280,7 @@ gen_method: {
                                        x86_64_jcc(cd, X86_64_CC_E, a);
 
                                        x86_64_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
-                                       x86_64_mov_imm_reg(cd, (s8) super->vftbl, REG_ITMP2);
+                                       x86_64_mov_imm_reg(cd, (ptrint) super->vftbl, REG_ITMP2);
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
                                        codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
 #endif
@@ -3243,27 +3307,26 @@ gen_method: {
                                      /* op1:   0 == array, 1 == class                */
                                      /* val.a: (classinfo*) superclass               */
 
-/*          superclass is an interface:
- *
*          OK if ((sub == NULL) ||
*                 (sub->vftbl->interfacetablelength > super->index) &&
*                 (sub->vftbl->interfacetable[-super->index] != NULL));
- *
*          superclass is a class:
- *
*          OK if ((sub == NULL) || (0
*                 <= (sub->vftbl->baseval - super->vftbl->baseval) <=
*                 super->vftbl->diffvall));
- */
+                       /*  superclass is an interface:
+                        *      
                       *  OK if ((sub == NULL) ||
                       *         (sub->vftbl->interfacetablelength > super->index) &&
                       *         (sub->vftbl->interfacetable[-super->index] != NULL));
+                        *      
                       *  superclass is a class:
+                        *      
                       *  OK if ((sub == NULL) || (0
                       *         <= (sub->vftbl->baseval - super->vftbl->baseval) <=
                       *         super->vftbl->diffval));
                       */
 
                        {
-                       classinfo *super = (classinfo*) iptr->val.a;
+                       classinfo *super = (classinfo *) iptr->val.a;
                        
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
             codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
 #endif
-                       d = reg_of_var(rd, iptr->dst, REG_ITMP3);
-                       var_to_reg_int(s1, src, d);
+                       var_to_reg_int(s1, src, REG_ITMP1);
                        if (iptr->op1) {                               /* class/interface */
                                if (super->flags & ACC_INTERFACE) {        /* interface       */
                                        x86_64_test_reg_reg(cd, s1, s1);
@@ -3272,8 +3335,8 @@ gen_method: {
                                        a = 3;    /* mov_membase_reg */
                                        CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
 
-                                       a += 3;    /* movl_membase_reg - only if REG_ITMP2 == R10 */
-                                       CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
+                                       a += 3;    /* movl_membase_reg - if REG_ITMP3 == R10 */
+                                       CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
 
                                        a += 3;    /* sub */
                                        CALCIMMEDIATEBYTES(a, super->index);
@@ -3282,48 +3345,48 @@ gen_method: {
                                        a += 6;    /* jcc */
 
                                        a += 3;    /* mov_membase_reg */
-                                       CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
+                                       CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
 
                                        a += 3;    /* test */
                                        a += 6;    /* jcc */
 
                                        x86_64_jcc(cd, X86_64_CC_E, a);
 
-                                       x86_64_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
-                                       x86_64_movl_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
-                                       x86_64_alu_imm_reg(cd, X86_64_SUB, super->index, REG_ITMP2);
-                                       x86_64_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
+                                       x86_64_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
+                                       x86_64_movl_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength), REG_ITMP3);
+                                       x86_64_alu_imm_reg(cd, X86_64_SUB, super->index, REG_ITMP3);
+                                       x86_64_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
                                        x86_64_jcc(cd, X86_64_CC_LE, 0);
                                        codegen_addxcastrefs(cd, cd->mcodeptr);
-                                       x86_64_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP2);
-                                       x86_64_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
+                                       x86_64_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP3);
+                                       x86_64_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
                                        x86_64_jcc(cd, X86_64_CC_E, 0);
                                        codegen_addxcastrefs(cd, cd->mcodeptr);
 
-                               } else {                                     /* class           */
+                               } else {                                   /* class           */
                                        x86_64_test_reg_reg(cd, s1, s1);
 
                                        /* TODO: clean up this calculation */
-                                       a = 3;    /* mov_membase_reg */
+                                       a = 3;     /* mov_membase_reg */
                                        CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
                                        a += 10;   /* mov_imm_reg */
-                                       a += 2;    /* movl_membase_reg - only if REG_ITMP1 == RAX */
-                                       CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
+                                       a += 3;    /* movl_membase_reg - only if REG_ITMP2 == R10 */
+                                       CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
 
-                                       if (d != REG_ITMP3) {
-                                               a += 3;    /* movl_membase_reg - only if REG_ITMP2 == R10 */
-                                               CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
-                                               a += 3;    /* movl_membase_reg - only if REG_ITMP2 == R10 */
-                                               CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
+                                       if (s1 != REG_ITMP1) {
+                                               a += 3;    /* movl_membase_reg - only if REG_ITMP3 == R11 */
+                                               CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
+                                               a += 3;    /* movl_membase_reg - only if REG_ITMP3 == R11 */
+                                               CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
                                                a += 3;    /* sub */
-                                               
+
                                        } else {
-                                               a += 3;    /* movl_membase_reg - only if REG_ITMP2 == R10 */
-                                               CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
+                                               a += 3;    /* movl_membase_reg - only if REG_ITMP3 == R11 */
+                                               CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
                                                a += 3;    /* sub */
                                                a += 10;   /* mov_imm_reg */
-                                               a += 3;    /* movl_membase_reg - only if REG_ITMP2 == R10 */
-                                               CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
+                                               a += 3;    /* movl_membase_reg - only if REG_ITMP3 == R11 */
+                                               CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
                                        }
 
                                        a += 3;    /* cmp */
@@ -3331,30 +3394,30 @@ gen_method: {
 
                                        x86_64_jcc(cd, X86_64_CC_E, a);
 
-                                       x86_64_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
-                                       x86_64_mov_imm_reg(cd, (s8) super->vftbl, REG_ITMP2);
+                                       x86_64_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
+                                       x86_64_mov_imm_reg(cd, (ptrint) super->vftbl, REG_ITMP3);
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
-                    codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
+                                       codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
 #endif
-                                       x86_64_movl_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
-                                       if (d != REG_ITMP3) {
-                                               x86_64_movl_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
-                                               x86_64_movl_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
+                                       x86_64_movl_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP2);
+                                       if (s1 != REG_ITMP1) {
+                                               x86_64_movl_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1);
+                                               x86_64_movl_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3);
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
-                        codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
+                                               codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
 #endif
-                                               x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP3, REG_ITMP1);
+                                               x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP1, REG_ITMP2);
 
                                        } else {
-                                               x86_64_movl_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP2);
-                                               x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP2, REG_ITMP1);
-                                               x86_64_mov_imm_reg(cd, (s8) super->vftbl, REG_ITMP2);
-                                               x86_64_movl_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
+                                               x86_64_movl_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP3);
+                                               x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP3, REG_ITMP2);
+                                               x86_64_mov_imm_reg(cd, (ptrint) super->vftbl, REG_ITMP3);
+                                               x86_64_movl_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3);
+                                       }
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
-                        codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
+                                       codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
 #endif
-                                       }
-                                       x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP2, REG_ITMP1);
+                                       x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP3, REG_ITMP2);
                                        x86_64_jcc(cd, X86_64_CC_A, 0);    /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
                                        codegen_addxcastrefs(cd, cd->mcodeptr);
                                }
@@ -3362,8 +3425,14 @@ gen_method: {
                        } else
                                panic("internal error: no inlined array checkcast");
                        }
+                       d = reg_of_var(rd, iptr->dst, REG_ITMP3);
                        M_INTMOVE(s1, d);
                        store_reg_to_var_int(iptr->dst, d);
+/*                     if (iptr->dst->flags & INMEMORY) { */
+/*                             x86_64_mov_reg_membase(cd, s1, REG_SP, iptr->dst->regoff * 8); */
+/*                     } else { */
+/*                             M_INTMOVE(s1, iptr->dst->regoff); */
+/*                     } */
                        break;
 
                case ICMD_CHECKASIZE:  /* ..., size ==> ..., size                     */
@@ -3434,6 +3503,9 @@ gen_method: {
        src = bptr->outstack;
        len = bptr->outdepth;
        MCODECHECK(64 + len);
+#ifdef LSRA
+       if (!opt_lsra)
+#endif
        while (src) {
                len--;
                if ((src->varkind != STACKVAR)) {
@@ -3750,18 +3822,12 @@ gen_method: {
                        tmpcd->mcodeptr = xcodeptr;     /* set dummy mcode pointer        */
                        x86_64_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
 
-                       /* Save current stack pointer into a temporary register.          */
-                       x86_64_mov_reg_reg(cd, REG_SP, REG_ITMP1);
-
                        /* Push machine code bytes to patch onto the stack.               */
                        x86_64_push_imm(cd, (u1) xmcode);
                        x86_64_push_imm(cd, (u4) mcode);
 
                        x86_64_push_imm(cd, (u8) cref->class);
 
-                       /* Push previously saved stack pointer onto stack.                */
-                       x86_64_push_reg(cd, REG_ITMP1);
-
                        x86_64_mov_imm_reg(cd, (u8) asm_check_clinit, REG_ITMP1);
                        x86_64_jmp_reg(cd, REG_ITMP1);
                }
@@ -4186,18 +4252,12 @@ u1 *createnativestub(functionptr f, methodinfo *m)
                        tmpcd->mcodeptr = xcodeptr;     /* set dummy mcode pointer        */
                        x86_64_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
 
-                       /* Save current stack pointer into a temporary register.          */
-                       x86_64_mov_reg_reg(cd, REG_SP, REG_ITMP1);
-
                        /* Push machine code bytes to patch onto the stack.               */
                        x86_64_push_imm(cd, (u1) xmcode);
                        x86_64_push_imm(cd, (u4) mcode);
 
                        x86_64_push_imm(cd, (u8) cref->class);
 
-                       /* Push previously saved stack pointer onto stack.                */
-                       x86_64_push_reg(cd, REG_ITMP1);
-
                        x86_64_mov_imm_reg(cd, (u8) asm_check_clinit, REG_ITMP1);
                        x86_64_jmp_reg(cd, REG_ITMP1);
                }