* src/vm/jit/jit.h (jitdata): Removed isleafmethod.
[cacao.git] / src / vm / jit / alpha / emit.c
index a99639ce299e4341b48c8b656255b7dcc9bbb19f..63f1fbab4c6dc194525b4f96f80bedfd04456bc0 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/alpha/emit.c - Alpha code emitter functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
-   $Id: emit.c 4398 2006-01-31 23:43:08Z twisti $
-
 */
 
 
 #include "config.h"
 #include "vm/types.h"
 
+#include <assert.h>
+#include <stdint.h>
+
 #include "md-abi.h"
 
 #include "vm/jit/alpha/codegen.h"
 
-#if defined(ENABLE_THREADS)
-# include "threads/native/lock.h"
-#endif
+#include "mm/memory.h"
+
+#include "threads/lock-common.h"
 
-#include "vm/builtin.h"
+#include "vm/exceptions.h"
+
+#include "vm/jit/abi.h"
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit.h"
+#include "vm/jit/emit-common.h"
 #include "vm/jit/jit.h"
+#include "vm/jit/patcher-common.h"
 #include "vm/jit/replace.h"
+#include "vm/jit/trace.h"
 
+#include "vmcore/options.h"
 
-/* code generation functions **************************************************/
 
 /* emit_load *******************************************************************
 
@@ -64,6 +63,7 @@
 s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
 {
        codegendata  *cd;
+       s4            disp;
        s4            reg;
 
        /* get required compiler data */
@@ -73,10 +73,21 @@ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
        if (IS_INMEMORY(src->flags)) {
                COUNT_SPILLS;
 
-               if (IS_FLT_DBL_TYPE(src->type))
-                       M_DLD(tempreg, REG_SP, src->vv.regoff * 8);
-               else
-                       M_LLD(tempreg, REG_SP, src->vv.regoff * 8);
+               disp = src->vv.regoff;
+
+               switch (src->type) {
+               case TYPE_INT:
+               case TYPE_LNG:
+               case TYPE_ADR:
+                       M_LLD(tempreg, REG_SP, disp);
+                       break;
+               case TYPE_FLT:
+               case TYPE_DBL:
+                       M_DLD(tempreg, REG_SP, disp);
+                       break;
+               default:
+                       vm_abort("emit_load: unknown type %d", src->type);
+               }
 
                reg = tempreg;
        }
@@ -87,63 +98,6 @@ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
 }
 
 
-/* emit_load_s1 ****************************************************************
-
-   Emits a possible load of the first source operand.
-
-*******************************************************************************/
-
-s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg)
-{
-       varinfo       *src;
-       s4 r;
-       
-       src = jd->var + iptr->s1.varindex;
-
-       r = emit_load(jd, iptr, src, tempreg);
-
-       return r;
-}
-
-
-/* emit_load_s2 ****************************************************************
-
-   Emits a possible load of the second source operand.
-
-*******************************************************************************/
-
-s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg)
-{
-       varinfo       *src;
-       s4 r;
-
-       src = jd->var + iptr->sx.s23.s2.varindex;
-
-       r = emit_load(jd, iptr, src, tempreg);
-
-       return r;
-}
-
-
-/* emit_load_s3 ****************************************************************
-
-   Emits a possible load of the third source operand.
-
-*******************************************************************************/
-
-s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg)
-{
-       varinfo       *src;
-       s4 r;
-
-       src = jd->var + iptr->sx.s23.s3.varindex;
-
-       r = emit_load(jd, iptr, src, tempreg);
-
-       return r;
-}
-
-
 /* emit_store ******************************************************************
 
    Emit a possible store for the given variable.
@@ -153,6 +107,7 @@ s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg)
 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
 {
        codegendata  *cd;
+       s4            disp;
 
        /* get required compiler data */
 
@@ -161,66 +116,82 @@ void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
        if (IS_INMEMORY(dst->flags)) {
                COUNT_SPILLS;
 
-               if (IS_FLT_DBL_TYPE(dst->type))
-                       M_DST(d, REG_SP, dst->vv.regoff * 8);
-               else
-                       M_LST(d, REG_SP, dst->vv.regoff * 8);
+               disp = dst->vv.regoff;
+
+               switch (dst->type) {
+               case TYPE_INT:
+               case TYPE_LNG:
+               case TYPE_ADR:
+                       M_LST(d, REG_SP, disp);
+                       break;
+               case TYPE_FLT:
+               case TYPE_DBL:
+                       M_DST(d, REG_SP, disp);
+                       break;
+               default:
+                       vm_abort("emit_store: unknown type %d", dst->type);
+               }
        }
 }
 
 
-/* emit_store_dst **************************************************************
-
-   Emit a possible store for the destination operand.
-
-*******************************************************************************/
-
-void emit_store_dst(jitdata *jd, instruction *iptr, s4 d)
-{
-       varinfo *dst;
-       
-       dst = jd->var + iptr->dst.varindex;
-
-       emit_store(jd, iptr, dst, d);
-}
-
-
 /* emit_copy *******************************************************************
 
    Generates a register/memory to register/memory copy.
 
 *******************************************************************************/
 
-void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst)
+void emit_copy(jitdata *jd, instruction *iptr)
 {
-       codegendata  *cd;
-       s4            s1, d;
+       codegendata *cd;
+       varinfo     *src;
+       varinfo     *dst;
+       s4           s1, d;
 
        /* get required compiler data */
 
        cd = jd->cd;
 
+       /* get source and destination variables */
+
+       src = VAROP(iptr->s1);
+       dst = VAROP(iptr->dst);
+
        if ((src->vv.regoff != dst->vv.regoff) ||
                ((src->flags ^ dst->flags) & INMEMORY)) {
 
+               if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
+                       /* emit nothing, as the value won't be used anyway */
+                       return;
+               }
+
                /* If one of the variables resides in memory, we can eliminate
                   the register move from/to the temporary register with the
                   order of getting the destination register and the load. */
 
                if (IS_INMEMORY(src->flags)) {
-                       d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
+                       d  = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
                        s1 = emit_load(jd, iptr, src, d);
                }
                else {
                        s1 = emit_load(jd, iptr, src, REG_IFTMP);
-                       d = codegen_reg_of_var(iptr->opc, dst, s1);
+                       d  = codegen_reg_of_var(iptr->opc, dst, s1);
                }
 
                if (s1 != d) {
-                       if (IS_FLT_DBL_TYPE(src->type))
-                               M_FMOV(s1, d);
-                       else
+                       switch (src->type) {
+                       case TYPE_INT:
+                       case TYPE_LNG:
+                       case TYPE_ADR:
                                M_MOV(s1, d);
+                               break;
+                       case TYPE_FLT:
+                       case TYPE_DBL:
+                               M_FMOV(s1, d);
+                               break;
+                       default:
+                               vm_abort("emit_copy: unknown type %d", src->type);
+                       }
                }
 
                emit_store(jd, iptr, dst, d);
@@ -241,7 +212,7 @@ void emit_iconst(codegendata *cd, s4 d, s4 value)
        if ((value >= -32768) && (value <= 32767))
                M_LDA_INTERN(d, REG_ZERO, value);
        else {
-               disp = dseg_adds4(cd, value);
+               disp = dseg_add_s4(cd, value);
                M_ILD(d, REG_PV, disp);
        }
 }
@@ -260,272 +231,231 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
        if ((value >= -32768) && (value <= 32767))
                M_LDA_INTERN(d, REG_ZERO, value);
        else {
-               disp = dseg_adds8(cd, value);
+               disp = dseg_add_s8(cd, value);
                M_LLD(d, REG_PV, disp);
        }
 }
 
 
-/* emit_exception_stubs ********************************************************
+/* emit_branch *****************************************************************
 
-   Generates the code for the exception stubs.
+   Emits the code for conditional and unconditional branchs.
 
 *******************************************************************************/
 
-void emit_exception_stubs(jitdata *jd)
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
 {
-       codegendata  *cd;
-       registerdata *rd;
-       exceptionref *eref;
-       s4            targetdisp;
-       s4            disp;
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-       rd = jd->rd;
-
-       /* generate exception stubs */
-
-       targetdisp = 0;
-
-       for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
-               gen_resolvebranch(cd->mcodebase + eref->branchpos, 
-                                                 eref->branchpos, cd->mcodeptr - cd->mcodebase);
+       s4 checkdisp;
+       s4 branchdisp;
 
-               MCODECHECK(100);
+       /* calculate the different displacements */
 
-               /* move index register into REG_ITMP1 */
+       checkdisp  = (disp - 4);
+       branchdisp = (disp - 4) >> 2;
 
-               /* Check if the exception is an
-                  ArrayIndexOutOfBoundsException.  If so, move index register
-                  into a4. */
+       /* check which branch to generate */
 
-               if (eref->reg != -1)
-                       M_MOV(eref->reg, rd->argintregs[4]);
+       if (condition == BRANCH_UNCONDITIONAL) {
+               /* check displacement for overflow */
 
-               /* calcuate exception address */
+               if ((checkdisp < (s4) 0xffe00000) || (checkdisp > (s4) 0x001fffff)) {
+                       /* if the long-branches flag isn't set yet, do it */
 
-               M_LDA(rd->argintregs[3], REG_PV, eref->branchpos - 4);
-
-               /* move function to call into REG_ITMP3 */
-
-               disp = dseg_add_functionptr(cd, eref->function);
-               M_ALD(REG_ITMP3, REG_PV, disp);
-
-               if (targetdisp == 0) {
-                       targetdisp = ((u4 *) cd->mcodeptr) - ((u4 *) cd->mcodebase);
-
-                       M_MOV(REG_PV, rd->argintregs[0]);
-                       M_MOV(REG_SP, rd->argintregs[1]);
-
-                       if (jd->isleafmethod)
-                               M_MOV(REG_RA, rd->argintregs[2]);
-                       else
-                               M_ALD(rd->argintregs[2],
-                                         REG_SP, cd->stackframesize * 8 - SIZEOF_VOID_P);
-
-                       M_LDA(REG_SP, REG_SP, -2 * 8);
-                       M_AST(rd->argintregs[3], REG_SP, 0 * 8);             /* store XPC */
-
-                       if (jd->isleafmethod)
-                               M_AST(REG_RA, REG_SP, 1 * 8);
-
-                       M_MOV(REG_ITMP3, REG_PV);
-                       M_JSR(REG_RA, REG_PV);
-                       disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                       M_LDA(REG_PV, REG_RA, -disp);
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               log_println("setting error");
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
 
-                       M_MOV(REG_RESULT, REG_ITMP1_XPTR);
+                       vm_abort("emit_branch: emit unconditional long-branch code");
+               }
+               else {
+                       M_BR(branchdisp);
+               }
+       }
+       else {
+               /* and displacement for overflow */
 
-                       if (jd->isleafmethod)
-                               M_ALD(REG_RA, REG_SP, 1 * 8);
+               if ((checkdisp < (s4) 0xffe00000) || (checkdisp > (s4) 0x001fffff)) {
+                       /* if the long-branches flag isn't set yet, do it */
 
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
-                       M_LDA(REG_SP, REG_SP, 2 * 8);
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               log_println("setting error");
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
 
-                       disp = dseg_add_functionptr(cd, asm_handle_exception);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_JMP(REG_ZERO, REG_ITMP3);
+                       vm_abort("emit_branch: emit conditional long-branch code");
                }
                else {
-                       disp = (((u4 *) cd->mcodebase) + targetdisp) -
-                               (((u4 *) cd->mcodeptr) + 1);
-
-                       M_BR(disp);
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BEQZ(reg, branchdisp);
+                               break;
+                       case BRANCH_NE:
+                               M_BNEZ(reg, branchdisp);
+                               break;
+                       case BRANCH_LT:
+                               M_BLTZ(reg, branchdisp);
+                               break;
+                       case BRANCH_GE:
+                               M_BGEZ(reg, branchdisp);
+                               break;
+                       case BRANCH_GT:
+                               M_BGTZ(reg, branchdisp);
+                               break;
+                       case BRANCH_LE:
+                               M_BLEZ(reg, branchdisp);
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
                }
        }
 }
 
 
-/* emit_patcher_stubs **********************************************************
+/* emit_arithmetic_check *******************************************************
 
-   Generates the code for the patcher stubs.
+   Emit an ArithmeticException check.
 
 *******************************************************************************/
 
-void emit_patcher_stubs(jitdata *jd)
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
 {
-       codegendata *cd;
-       patchref    *pref;
-       u4           mcode;
-       u1          *savedmcodeptr;
-       u1          *tmpmcodeptr;
-       s4           targetdisp;
-       s4           disp;
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-
-       /* generate code patching stub call code */
-
-       targetdisp = 0;
-
-       for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
-               /* check code segment size */
-
-               MCODECHECK(100);
-
-               /* Get machine code which is patched back in later. The
-                  call is 1 instruction word long. */
-
-               tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos);
-
-               mcode = *((u4 *) tmpmcodeptr);
-
-               /* Patch in the call to call the following code (done at
-                  compile time). */
-
-               savedmcodeptr = cd->mcodeptr;   /* save current mcodeptr              */
-               cd->mcodeptr  = tmpmcodeptr;    /* set mcodeptr to patch position     */
-
-               disp = ((u4 *) savedmcodeptr) - (((u4 *) tmpmcodeptr) + 1);
-               M_BSR(REG_ITMP3, disp);
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_BNEZ(reg, 1);
+               /* Destination register must not be REG_ZERO, because then no
+                  SIGSEGV is thrown. */
+               M_ALD_INTERN(reg, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);
+       }
+}
 
-               cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr       */
 
-               /* create stack frame */
+/* emit_arrayindexoutofbounds_check ********************************************
 
-               M_LSUB_IMM(REG_SP, 6 * 8, REG_SP);
+   Emit an ArrayIndexOutOfBoundsException check.
 
-               /* move return address onto stack */
+*******************************************************************************/
 
-               M_AST(REG_ITMP3, REG_SP, 5 * 8);
+void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_ILD(REG_ITMP3, s1, OFFSET(java_array_t, size));
+               M_CMPULT(s2, REG_ITMP3, REG_ITMP3);
+               M_BNEZ(REG_ITMP3, 1);
+               M_ALD_INTERN(s2, REG_ZERO, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
+       }
+}
 
-               /* move pointer to java_objectheader onto stack */
 
-#if defined(ENABLE_THREADS)
-               /* create a virtual java_objectheader */
+/* emit_arraystore_check *******************************************************
 
-               (void) dseg_add_unique_address(cd, NULL);                  /* flcword */
-               (void) dseg_add_unique_address(cd, lock_get_initial_lock_word());
-               disp = dseg_add_unique_address(cd, NULL);                  /* vftbl   */
+   Emit an ArrayStoreException check.
 
-               M_LDA(REG_ITMP3, REG_PV, disp);
-               M_AST(REG_ITMP3, REG_SP, 4 * 8);
-#else
-               /* nothing to do */
-#endif
+*******************************************************************************/
 
-               /* move machine code onto stack */
+void emit_arraystore_check(codegendata *cd, instruction *iptr)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_BNEZ(REG_RESULT, 1);
+               /* Destination register must not be REG_ZERO, because then no
+                  SIGSEGV is thrown. */
+               M_ALD_INTERN(REG_RESULT, REG_ZERO, EXCEPTION_HARDWARE_ARRAYSTORE);
+       }
+}
 
-               disp = dseg_add_s4(cd, mcode);
-               M_ILD(REG_ITMP3, REG_PV, disp);
-               M_IST(REG_ITMP3, REG_SP, 3 * 8);
 
-               /* move class/method/field reference onto stack */
+/* emit_classcast_check ********************************************************
 
-               disp = dseg_add_address(cd, pref->ref);
-               M_ALD(REG_ITMP3, REG_PV, disp);
-               M_AST(REG_ITMP3, REG_SP, 2 * 8);
+   Emit a ClassCastException check.
 
-               /* move data segment displacement onto stack */
+*******************************************************************************/
 
-               disp = dseg_add_s4(cd, pref->disp);
-               M_ILD(REG_ITMP3, REG_PV, disp);
-               M_IST(REG_ITMP3, REG_SP, 1 * 8);
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               switch (condition) {
+               case BRANCH_EQ:
+                       M_BNEZ(reg, 1);
+                       break;
+               case BRANCH_LE:
+                       M_BGTZ(reg, 1);
+                       break;
+               default:
+                       vm_abort("emit_classcast_check: unknown condition %d", condition);
+               }
+               M_ALD_INTERN(s1, REG_ZERO, EXCEPTION_HARDWARE_CLASSCAST);
+       }
+}
 
-               /* move patcher function pointer onto stack */
 
-               disp = dseg_add_functionptr(cd, pref->patcher);
-               M_ALD(REG_ITMP3, REG_PV, disp);
-               M_AST(REG_ITMP3, REG_SP, 0 * 8);
+/* emit_nullpointer_check ******************************************************
 
-               if (targetdisp == 0) {
-                       targetdisp = ((u4 *) cd->mcodeptr) - ((u4 *) cd->mcodebase);
+   Emit a NullPointerException check.
 
-                       disp = dseg_add_functionptr(cd, asm_patcher_wrapper);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_JMP(REG_ZERO, REG_ITMP3);
-               }
-               else {
-                       disp = (((u4 *) cd->mcodebase) + targetdisp) -
-                               (((u4 *) cd->mcodeptr) + 1);
+*******************************************************************************/
 
-                       M_BR(disp);
-               }
+void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_BNEZ(reg, 1);
+               /* Destination register must not be REG_ZERO, because then no
+                  SIGSEGV is thrown. */
+               M_ALD_INTERN(reg, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
        }
 }
 
 
-/* emit_replacement_stubs ******************************************************
+/* emit_exception_check ********************************************************
 
-   Generates the code for the replacement stubs.
+   Emit an Exception check.
 
 *******************************************************************************/
 
-void emit_replacement_stubs(jitdata *jd)
+void emit_exception_check(codegendata *cd, instruction *iptr)
 {
-       codegendata *cd;
-       codeinfo    *code;
-       rplpoint    *rplp;
-       u1          *savedmcodeptr;
-       s4           disp;
-       s4           i;
-
-       /* get required compiler data */
-
-       cd   = jd->cd;
-       code = jd->code;
-
-       rplp = code->rplpoints;
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_BNEZ(REG_RESULT, 1);
+               /* Destination register must not be REG_ZERO, because then no
+                  SIGSEGV is thrown. */
+               M_ALD_INTERN(REG_RESULT, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);
+       }
+}
 
-       for (i = 0; i < code->rplpointcount; ++i, ++rplp) {
-               /* check code segment size */
 
-               MCODECHECK(100);
+/* emit_trap_compiler **********************************************************
 
-               /* note start of stub code */
+   Emit a trap instruction which calls the JIT compiler.
 
-               rplp->outcode = (u1 *) (ptrint) (cd->mcodeptr - cd->mcodebase);
+*******************************************************************************/
 
-               /* make machine code for patching */
+void emit_trap_compiler(codegendata *cd)
+{
+       M_ALD_INTERN(REG_METHODPTR, REG_ZERO, EXCEPTION_HARDWARE_COMPILER);
+}
 
-               savedmcodeptr = cd->mcodeptr;
-               cd->mcodeptr  = (u1 *) &(rplp->mcode);
 
-               disp = (ptrint) ((s4 *) rplp->outcode - (s4 *) rplp->pc) - 1;
-               M_BR(disp);
+/* emit_trap *******************************************************************
 
-               cd->mcodeptr = savedmcodeptr;
+   Emit a trap instruction and return the original machine code.
 
-               /* create stack frame - 16-byte aligned */
+*******************************************************************************/
 
-               M_LSUB_IMM(REG_SP, 2 * 8, REG_SP);
+uint32_t emit_trap(codegendata *cd)
+{
+       uint32_t mcode;
 
-               /* push address of `rplpoint` struct */
+       /* Get machine code which is patched back in later. The
+          trap is 1 instruction word long. */
 
-               disp = dseg_add_address(cd, rplp);
-               M_ALD(REG_ITMP3, REG_PV, disp);
-               M_AST(REG_ITMP3, REG_SP, 0 * 8);
+       mcode = *((u4 *) cd->mcodeptr);
 
-               /* jump to replacement function */
+       /* Destination register must not be REG_ZERO, because then no
+          SIGSEGV is thrown. */
+       M_ALD_INTERN(REG_RESULT, REG_ZERO, EXCEPTION_HARDWARE_PATCHER);
 
-               disp = dseg_add_functionptr(cd, asm_replacement_out);
-               M_ALD(REG_ITMP3, REG_PV, disp);
-               M_JMP(REG_ZERO, REG_ITMP3);
-       }
+       return mcode;
 }
 
 
@@ -539,17 +469,20 @@ void emit_replacement_stubs(jitdata *jd)
 void emit_verbosecall_enter(jitdata *jd)
 {
        methodinfo   *m;
+       codeinfo     *code;
        codegendata  *cd;
        registerdata *rd;
        methoddesc   *md;
+       int32_t       stackframesize;
        s4            disp;
-       s4            i, t;
+       s4            i, j, s;
 
        /* get required compiler data */
 
-       m  = jd->m;
-       cd = jd->cd;
-       rd = jd->rd;
+       m    = jd->m;
+       code = jd->code;
+       cd   = jd->cd;
+       rd   = jd->rd;
 
        md = m->parseddesc;
 
@@ -557,73 +490,100 @@ void emit_verbosecall_enter(jitdata *jd)
 
        M_NOP;
 
-       M_LDA(REG_SP, REG_SP, -((ARG_CNT + TMP_CNT + 2) * 8));
-       M_AST(REG_RA, REG_SP, 1 * 8);
+       stackframesize = ARG_CNT + TMP_CNT + md->paramcount + 1;
 
-       /* save argument registers */
+       M_LDA(REG_SP, REG_SP, -(stackframesize * 8));
+       M_AST(REG_RA, REG_SP, 0 * 8);
 
-       for (i = 0; i < INT_ARG_CNT; i++)
-               M_LST(rd->argintregs[i], REG_SP, (2 + i) * 8);
+       /* save all argument and temporary registers for leaf methods */
 
-       for (i = 0; i < FLT_ARG_CNT; i++)
-               M_DST(rd->argintregs[i], REG_SP, (2 + INT_ARG_CNT + i) * 8);
+       if (code_is_leafmethod(code)) {
+               j = 1 + md->paramcount;
 
-       /* save temporary registers for leaf methods */
+               for (i = 0; i < INT_ARG_CNT; i++, j++)
+                       M_LST(abi_registers_integer_argument[i], REG_SP, j * 8);
 
-       if (jd->isleafmethod) {
-               for (i = 0; i < INT_TMP_CNT; i++)
-                       M_LST(rd->tmpintregs[i], REG_SP, (2 + ARG_CNT + i) * 8);
+               for (i = 0; i < FLT_ARG_CNT; i++, j++)
+                       M_DST(abi_registers_float_argument[i], REG_SP, j * 8);
 
-               for (i = 0; i < FLT_TMP_CNT; i++)
-                       M_DST(rd->tmpfltregs[i], REG_SP, (2 + ARG_CNT + INT_TMP_CNT + i) * 8);
-       }
+               for (i = 0; i < INT_TMP_CNT; i++, j++)
+                       M_LST(rd->tmpintregs[i], REG_SP, j * 8);
 
-       /* load float arguments into integer registers */
+               for (i = 0; i < FLT_TMP_CNT; i++, j++)
+                       M_DST(rd->tmpfltregs[i], REG_SP, j * 8);
+       }
 
-       for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
-               t = md->paramtypes[i].type;
+       /* save argument registers */
 
-               if (IS_FLT_DBL_TYPE(t)) {
-                       if (IS_2_WORD_TYPE(t)) {
-                               M_DST(rd->argfltregs[i], REG_SP, 0 * 8);
-                               M_LLD(rd->argintregs[i], REG_SP, 0 * 8);
-                       }
-                       else {
-                               M_FST(rd->argfltregs[i], REG_SP, 0 * 8);
-                               M_ILD(rd->argintregs[i], REG_SP, 0 * 8);
+       for (i = 0; i < md->paramcount; i++) {
+               if (!md->params[i].inmemory) {
+                       s = md->params[i].regoff;
+
+                       switch (md->paramtypes[i].type) {
+                       case TYPE_ADR:
+                       case TYPE_INT:
+                       case TYPE_LNG:
+                               M_LST(s, REG_SP, (1 + i) * 8);
+                               break;
+                       case TYPE_FLT:
+                       case TYPE_DBL:
+                               M_DST(s, REG_SP, (1 + i) * 8);
+                               break;
                        }
                }
        }
 
        disp = dseg_add_address(cd, m);
-       M_ALD(REG_ITMP1, REG_PV, disp);
-       M_AST(REG_ITMP1, REG_SP, 0 * 8);
-       disp = dseg_add_functionptr(cd, builtin_trace_args);
+       M_ALD(REG_A0, REG_PV, disp);
+       M_AADD_IMM(REG_SP, 1 * 8, REG_A1);
+       M_LDA(REG_A2, REG_SP, stackframesize * 8 + cd->stackframesize * 8);
+
+       disp = dseg_add_functionptr(cd, trace_java_call_enter);
        M_ALD(REG_PV, REG_PV, disp);
        M_JSR(REG_RA, REG_PV);
        disp = (s4) (cd->mcodeptr - cd->mcodebase);
        M_LDA(REG_PV, REG_RA, -disp);
-       M_ALD(REG_RA, REG_SP, 1 * 8);
+       M_ALD(REG_RA, REG_SP, 0 * 8);
 
        /* restore argument registers */
 
-       for (i = 0; i < INT_ARG_CNT; i++)
-               M_LLD(rd->argintregs[i], REG_SP, (2 + i) * 8);
+       for (i = 0; i < md->paramcount; i++) {
+               if (!md->params[i].inmemory) {
+                       s = md->params[i].regoff;
+
+                       switch (md->paramtypes[i].type) {
+                       case TYPE_ADR:
+                       case TYPE_INT:
+                       case TYPE_LNG:
+                               M_LLD(s, REG_SP, (1 + i) * 8);
+                               break;
+                       case TYPE_FLT:
+                       case TYPE_DBL:
+                               M_DLD(s, REG_SP, (1 + i) * 8);
+                               break;
+                       }
+               }
+       }
+
+       /* restore all argument and temporary registers for leaf methods */
 
-       for (i = 0; i < FLT_ARG_CNT; i++)
-               M_DLD(rd->argintregs[i], REG_SP, (2 + INT_ARG_CNT + i) * 8);
+       if (code_is_leafmethod(code)) {
+               j = 1 + md->paramcount;
 
-       /* restore temporary registers for leaf methods */
+               for (i = 0; i < INT_ARG_CNT; i++, j++)
+                       M_LLD(abi_registers_integer_argument[i], REG_SP, j * 8);
 
-       if (jd->isleafmethod) {
-               for (i = 0; i < INT_TMP_CNT; i++)
-                       M_LLD(rd->tmpintregs[i], REG_SP, (2 + ARG_CNT + i) * 8);
+               for (i = 0; i < FLT_ARG_CNT; i++, j++)
+                       M_DLD(abi_registers_float_argument[i], REG_SP, j * 8);
 
-               for (i = 0; i < FLT_TMP_CNT; i++)
-                       M_DLD(rd->tmpfltregs[i], REG_SP, (2 + ARG_CNT + INT_TMP_CNT + i) * 8);
+               for (i = 0; i < INT_TMP_CNT; i++, j++)
+                       M_LLD(rd->tmpintregs[i], REG_SP, j * 8);
+
+               for (i = 0; i < FLT_TMP_CNT; i++, j++)
+                       M_DLD(rd->tmpfltregs[i], REG_SP, j * 8);
        }
 
-       M_LDA(REG_SP, REG_SP, (ARG_CNT + TMP_CNT + 2) * 8);
+       M_LDA(REG_SP, REG_SP, stackframesize * 8);
 
        /* mark trace code */
 
@@ -644,6 +604,7 @@ void emit_verbosecall_exit(jitdata *jd)
        methodinfo   *m;
        codegendata  *cd;
        registerdata *rd;
+       methoddesc   *md;
        s4            disp;
 
        /* get required compiler data */
@@ -652,34 +613,55 @@ void emit_verbosecall_exit(jitdata *jd)
        cd = jd->cd;
        rd = jd->rd;
 
+       md = m->parseddesc;
+
        /* mark trace code */
 
        M_NOP;
 
-       M_LDA(REG_SP, REG_SP, -4 * 8);
+       M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
        M_AST(REG_RA, REG_SP, 0 * 8);
 
-       M_LST(REG_RESULT, REG_SP, 1 * 8);
-       M_DST(REG_FRESULT, REG_SP, 2 * 8);
+       /* save return value */
+
+       switch (md->returntype.type) {
+       case TYPE_ADR:
+       case TYPE_INT:
+       case TYPE_LNG:
+               M_LST(REG_RESULT, REG_SP, 1 * 8);
+               break;
+       case TYPE_FLT:
+       case TYPE_DBL:
+               M_DST(REG_FRESULT, REG_SP, 1 * 8);
+               break;
+       }
 
        disp = dseg_add_address(cd, m);
-       M_ALD(rd->argintregs[0], REG_PV, disp);
+       M_ALD(REG_A0, REG_PV, disp);
+       M_AADD_IMM(REG_SP, 1 * 8, REG_A1);
 
-       M_MOV(REG_RESULT, rd->argintregs[1]);
-       M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
-       M_FLTMOVE(REG_FRESULT, rd->argfltregs[3]);
-
-       disp = dseg_add_functionptr(cd, builtin_displaymethodstop);
+       disp = dseg_add_functionptr(cd, trace_java_call_exit);
        M_ALD(REG_PV, REG_PV, disp);
        M_JSR(REG_RA, REG_PV);
        disp = (cd->mcodeptr - cd->mcodebase);
        M_LDA(REG_PV, REG_RA, -disp);
 
-       M_DLD(REG_FRESULT, REG_SP, 2 * 8);
-       M_LLD(REG_RESULT, REG_SP, 1 * 8);
+       /* restore return value */
+
+       switch (md->returntype.type) {
+       case TYPE_ADR:
+       case TYPE_INT:
+       case TYPE_LNG:
+               M_LLD(REG_RESULT, REG_SP, 1 * 8);
+               break;
+       case TYPE_FLT:
+       case TYPE_DBL:
+               M_DLD(REG_FRESULT, REG_SP, 1 * 8);
+               break;
+       }
 
        M_ALD(REG_RA, REG_SP, 0 * 8);
-       M_LDA(REG_SP, REG_SP, 4 * 8);
+       M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
 
        /* mark trace code */