* Removed all Id tags.
[cacao.git] / src / vm / jit / alpha / emit.c
index 1e60a40d1fa508d69d749a03655ec9400367e204..13515ccda7166e6f20f70291cb505fce201cd478 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
-
-   $Id: emit.c 4398 2006-01-31 23:43:08Z twisti $
-
 */
 
 
 #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/options.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-common.h"
 #include "vm/jit/jit.h"
+#include "vm/jit/patcher-common.h"
 #include "vm/jit/replace.h"
 
+#include "vmcore/options.h"
+
 
 /* emit_load *******************************************************************
 
@@ -63,6 +63,7 @@
 s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
 {
        codegendata  *cd;
+       s4            disp;
        s4            reg;
 
        /* get required compiler data */
@@ -72,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;
        }
@@ -95,6 +107,7 @@ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
 {
        codegendata  *cd;
+       s4            disp;
 
        /* get required compiler data */
 
@@ -103,10 +116,21 @@ 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);
+               }
        }
 }
 
@@ -117,36 +141,57 @@ void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
 
 *******************************************************************************/
 
-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);
@@ -192,338 +237,197 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
 }
 
 
-/* emit_arrayindexoutofbounds_check ********************************************
+/* emit_branch *****************************************************************
 
-   Emit an ArrayIndexOutOfBoundsException check.
+   Emits the code for conditional and unconditional branchs.
 
 *******************************************************************************/
 
-void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
 {
-       if (INSTRUCTION_MUST_CHECK(iptr)) {
-               M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
-               M_CMPULT(s2, REG_ITMP3, REG_ITMP3);
-               M_BEQZ(REG_ITMP3, 0);
-               codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
-       }
-}
+       s4 checkdisp;
+       s4 branchdisp;
 
+       /* calculate the different displacements */
 
-/* emit_arraystore_check *******************************************************
+       checkdisp  = (disp - 4);
+       branchdisp = (disp - 4) >> 2;
 
-   Emit an ArrayStoreException check.
+       /* check which branch to generate */
 
-*******************************************************************************/
+       if (condition == BRANCH_UNCONDITIONAL) {
+               /* check displacement for overflow */
 
-void emit_arraystore_check(codegendata *cd, instruction *iptr, s4 reg)
-{
-       M_BEQZ(reg, 0);
-       codegen_add_arraystoreexception_ref(cd);
-}
+               if ((checkdisp < (s4) 0xffe00000) || (checkdisp > (s4) 0x001fffff)) {
+                       /* if the long-branches flag isn't set yet, do it */
 
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               log_println("setting error");
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
 
-/* emit_classcast_check ********************************************************
+                       vm_abort("emit_branch: emit unconditional long-branch code");
+               }
+               else {
+                       M_BR(branchdisp);
+               }
+       }
+       else {
+               /* and displacement for overflow */
 
-   Emit a ClassCastException check.
+               if ((checkdisp < (s4) 0xffe00000) || (checkdisp > (s4) 0x001fffff)) {
+                       /* if the long-branches flag isn't set yet, do it */
 
-*******************************************************************************/
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               log_println("setting error");
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
 
-void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
-{
-       if (INSTRUCTION_MUST_CHECK(iptr)) {
-               M_BNEZ(reg, 0);
-               codegen_add_classcastexception_ref(cd, s1);
+                       vm_abort("emit_branch: emit conditional long-branch code");
+               }
+               else {
+                       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_nullpointer_check ******************************************************
+/* emit_arithmetic_check *******************************************************
 
-   Emit a NullPointerException check.
+   Emit an ArithmeticException check.
 
 *******************************************************************************/
 
-void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
-               M_BEQZ(reg, 0);
-               codegen_add_nullpointerexception_ref(cd);
+               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);
        }
 }
 
 
-/* emit_exception_stubs ********************************************************
+/* emit_arrayindexoutofbounds_check ********************************************
 
-   Generates the code for the exception stubs.
+   Emit an ArrayIndexOutOfBoundsException check.
 
 *******************************************************************************/
 
-void emit_exception_stubs(jitdata *jd)
+void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
 {
-       codegendata  *cd;
-       registerdata *rd;
-       exceptionref *er;
-       s4            branchmpc;
-       s4            targetmpc;
-       s4            targetdisp;
-       s4            disp;
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-       rd = jd->rd;
-
-       /* generate exception stubs */
-
-       targetdisp = 0;
-
-       for (er = cd->exceptionrefs; er != NULL; er = er->next) {
-               /* back-patch the branch to this exception code */
-
-               branchmpc = er->branchpos;
-               targetmpc = cd->mcodeptr - cd->mcodebase;
-
-               md_codegen_patch_branch(cd, branchmpc, targetmpc);
-
-               MCODECHECK(100);
-
-               /* move index register into REG_ITMP1 */
-
-               /* Check if the exception is an
-                  ArrayIndexOutOfBoundsException.  If so, move index register
-                  into a4. */
-
-               if (er->reg != -1)
-                       M_MOV(er->reg, rd->argintregs[4]);
-
-               /* calcuate exception address */
-
-               M_LDA(rd->argintregs[3], REG_PV, er->branchpos - 4);
-
-               /* move function to call into REG_ITMP3 */
-
-               disp = dseg_add_functionptr(cd, er->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);
-
-                       M_MOV(REG_RESULT, REG_ITMP1_XPTR);
-
-                       if (jd->isleafmethod)
-                               M_ALD(REG_RA, REG_SP, 1 * 8);
-
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
-                       M_LDA(REG_SP, REG_SP, 2 * 8);
-
-                       disp = dseg_add_functionptr(cd, asm_handle_exception);
-                       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);
-               }
+       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);
        }
 }
 
 
-/* emit_patcher_stubs **********************************************************
+/* emit_classcast_check ********************************************************
 
-   Generates the code for the patcher stubs.
+   Emit a ClassCastException check.
 
 *******************************************************************************/
 
-void emit_patcher_stubs(jitdata *jd)
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
 {
-       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);
-
-               cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr       */
-
-               /* create stack frame */
-
-               M_LSUB_IMM(REG_SP, 6 * 8, REG_SP);
-
-               /* move return address onto stack */
-
-               M_AST(REG_ITMP3, REG_SP, 5 * 8);
-
-               /* move pointer to java_objectheader onto stack */
-
-#if defined(ENABLE_THREADS)
-               /* create a virtual java_objectheader */
-
-               (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   */
-
-               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 */
-
-               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 */
-
-               disp = dseg_add_address(cd, pref->ref);
-               M_ALD(REG_ITMP3, REG_PV, disp);
-               M_AST(REG_ITMP3, REG_SP, 2 * 8);
-
-               /* 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);
-
-               /* 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);
-
-               if (targetdisp == 0) {
-                       targetdisp = ((u4 *) cd->mcodeptr) - ((u4 *) cd->mcodebase);
-
-                       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);
+       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);
        }
 }
 
 
-/* emit_replacement_stubs ******************************************************
+/* emit_nullpointer_check ******************************************************
 
-   Generates the code for the replacement stubs.
+   Emit a NullPointerException check.
 
 *******************************************************************************/
 
-#if defined(ENABLE_REPLACEMENT)
-void emit_replacement_stubs(jitdata *jd)
+void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
 {
-       codegendata *cd;
-       codeinfo    *code;
-       rplpoint    *rplp;
-       s4           disp;
-       s4           i;
-#if !defined(NDEBUG)
-       u1          *savedmcodeptr;
-#endif
-
-       /* get required compiler data */
-
-       cd   = jd->cd;
-       code = jd->code;
-
-       rplp = code->rplpoints;
+       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);
+       }
+}
 
-       /* store beginning of replacement stubs */
 
-       code->replacementstubs = (u1*) (cd->mcodeptr - cd->mcodebase);
+/* emit_exception_check ********************************************************
 
-       for (i = 0; i < code->rplpointcount; ++i, ++rplp) {
-               /* do not generate stubs for non-trappable points */
+   Emit an Exception check.
 
-               if (rplp->flags & RPLPOINT_FLAG_NOTRAP)
-                       continue;
+*******************************************************************************/
 
-               /* check code segment size */
+void emit_exception_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_EXCEPTION);
+       }
+}
 
-               MCODECHECK(100);
 
-#if !defined(NDEBUG)
-               savedmcodeptr = cd->mcodeptr;
-#endif
+/* emit_trap *******************************************************************
 
-               /* create stack frame - 16-byte aligned */
+   Emit a trap instruction and return the original machine code.
 
-               M_LSUB_IMM(REG_SP, 2 * 8, REG_SP);
+*******************************************************************************/
 
-               /* push address of `rplpoint` struct */
+uint32_t emit_trap(codegendata *cd)
+{
+       uint32_t mcode;
 
-               disp = dseg_add_address(cd, rplp);
-               M_ALD(REG_ITMP3, REG_PV, disp);
-               M_AST(REG_ITMP3, REG_SP, 0 * 8);
+       /* Get machine code which is patched back in later. The
+          trap is 1 instruction word long. */
 
-               /* jump to replacement function */
+       mcode = *((u4 *) cd->mcodeptr);
 
-               disp = dseg_add_functionptr(cd, asm_replacement_out);
-               M_ALD(REG_ITMP3, REG_PV, disp);
-               M_JMP(REG_ZERO, REG_ITMP3);
+       /* Destination register must not be REG_ZERO, because then no
+          SIGSEGV is thrown. */
+       M_ALD_INTERN(REG_RESULT, REG_ZERO, EXCEPTION_HARDWARE_PATCHER);
 
-               assert((cd->mcodeptr - savedmcodeptr) == 4*REPLACEMENT_STUB_SIZE);
-       }
+       return mcode;
 }
-#endif /* defined(ENABLE_REPLACEMENT) */
 
 
 /* emit_verbosecall_enter ******************************************************
@@ -560,10 +464,10 @@ void emit_verbosecall_enter(jitdata *jd)
        /* save argument registers */
 
        for (i = 0; i < INT_ARG_CNT; i++)
-               M_LST(rd->argintregs[i], REG_SP, (2 + i) * 8);
+               M_LST(abi_registers_integer_argument[i], REG_SP, (2 + i) * 8);
 
        for (i = 0; i < FLT_ARG_CNT; i++)
-               M_DST(rd->argintregs[i], REG_SP, (2 + INT_ARG_CNT + i) * 8);
+               M_DST(abi_registers_float_argument[i], REG_SP, (2 + INT_ARG_CNT + i) * 8);
 
        /* save temporary registers for leaf methods */
 
@@ -582,12 +486,12 @@ void emit_verbosecall_enter(jitdata *jd)
 
                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);
+                               M_DST(abi_registers_float_argument[i], REG_SP, 0 * 8);
+                               M_LLD(abi_registers_integer_argument[i], REG_SP, 0 * 8);
                        }
                        else {
-                               M_FST(rd->argfltregs[i], REG_SP, 0 * 8);
-                               M_ILD(rd->argintregs[i], REG_SP, 0 * 8);
+                               M_FST(abi_registers_float_argument[i], REG_SP, 0 * 8);
+                               M_ILD(abi_registers_integer_argument[i], REG_SP, 0 * 8);
                        }
                }
        }
@@ -595,7 +499,7 @@ void emit_verbosecall_enter(jitdata *jd)
        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);
+       disp = dseg_add_functionptr(cd, builtin_verbosecall_enter);
        M_ALD(REG_PV, REG_PV, disp);
        M_JSR(REG_RA, REG_PV);
        disp = (s4) (cd->mcodeptr - cd->mcodebase);
@@ -605,10 +509,10 @@ void emit_verbosecall_enter(jitdata *jd)
        /* restore argument registers */
 
        for (i = 0; i < INT_ARG_CNT; i++)
-               M_LLD(rd->argintregs[i], REG_SP, (2 + i) * 8);
+               M_LLD(abi_registers_integer_argument[i], REG_SP, (2 + i) * 8);
 
        for (i = 0; i < FLT_ARG_CNT; i++)
-               M_DLD(rd->argintregs[i], REG_SP, (2 + INT_ARG_CNT + i) * 8);
+               M_DLD(abi_registers_float_argument[i], REG_SP, (2 + INT_ARG_CNT + i) * 8);
 
        /* restore temporary registers for leaf methods */
 
@@ -633,6 +537,8 @@ void emit_verbosecall_enter(jitdata *jd)
 
    Generates the code for the call trace.
 
+   void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m);
+
 *******************************************************************************/
 
 #if !defined(NDEBUG)
@@ -653,20 +559,20 @@ void emit_verbosecall_exit(jitdata *jd)
 
        M_NOP;
 
-       M_LDA(REG_SP, REG_SP, -4 * 8);
+       M_ASUB_IMM(REG_SP, 4 * 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);
 
-       disp = dseg_add_address(cd, m);
-       M_ALD(rd->argintregs[0], REG_PV, disp);
+       M_MOV(REG_RESULT, REG_A0);
+       M_FMOV(REG_FRESULT, REG_FA1);
+       M_FMOV(REG_FRESULT, REG_FA2);
 
-       M_MOV(REG_RESULT, rd->argintregs[1]);
-       M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
-       M_FLTMOVE(REG_FRESULT, rd->argfltregs[3]);
+       disp = dseg_add_address(cd, m);
+       M_ALD(REG_A3, REG_PV, disp);
 
-       disp = dseg_add_functionptr(cd, builtin_displaymethodstop);
+       disp = dseg_add_functionptr(cd, builtin_verbosecall_exit);
        M_ALD(REG_PV, REG_PV, disp);
        M_JSR(REG_RA, REG_PV);
        disp = (cd->mcodeptr - cd->mcodebase);
@@ -676,7 +582,7 @@ void emit_verbosecall_exit(jitdata *jd)
        M_LLD(REG_RESULT, REG_SP, 1 * 8);
 
        M_ALD(REG_RA, REG_SP, 0 * 8);
-       M_LDA(REG_SP, REG_SP, 4 * 8);
+       M_AADD_IMM(REG_SP, 4 * 8, REG_SP);
 
        /* mark trace code */