* src/vm/jit/mips/emit.c (emit_verbosecall_exit): Fixed argument
[cacao.git] / src / vm / jit / mips / emit.c
index 273e9968456529511dd6f8242500f03dd375e29a..cc06397e9a9901ac8214a059fd19a1c4e7fa83f3 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/mips/emit.c - MIPS 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: emitfuncs.c 4398 2006-01-31 23:43:08Z twisti $
+   $Id: emit.c 4398 2006-01-31 23:43:08Z twisti $
 
 */
 
 
 #include "config.h"
 
-#include "vm/types.h"
+#include <assert.h>
 
-#include "md-abi.h"
+#include "vm/types.h"
 
 #include "vm/jit/mips/codegen.h"
+#include "vm/jit/mips/md-abi.h"
+
+#include "mm/memory.h"
 
 #if defined(ENABLE_THREADS)
 # include "threads/native/lock.h"
 #endif
 
+#include "vm/builtin.h"
 #include "vm/exceptions.h"
-#include "vm/options.h"
 #include "vm/stringlocal.h" /* XXX for gen_resolvebranch */
+
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/dseg.h"
@@ -55,6 +53,8 @@
 #include "vm/jit/jit.h"
 #include "vm/jit/replace.h"
 
+#include "vmcore/options.h"
+
 
 /* emit_load *******************************************************************
 
@@ -83,8 +83,16 @@ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
                        else
                                M_FLD(tempreg, REG_SP, disp);
                }
-               else
+               else {
+#if SIZEOF_VOID_P == 8
                        M_LLD(tempreg, REG_SP, disp);
+#else
+                       if (IS_2_WORD_TYPE(src->type))
+                               M_LLD(tempreg, REG_SP, disp);
+                       else
+                               M_ILD(tempreg, REG_SP, disp);
+#endif
+               }
 
                reg = tempreg;
        }
@@ -95,6 +103,86 @@ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
 }
 
 
+/* emit_load_low ***************************************************************
+
+   Emits a possible load of the low 32-bits of an operand.
+
+*******************************************************************************/
+
+#if SIZEOF_VOID_P == 4
+s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
+{
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
+
+       assert(src->type == TYPE_LNG);
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (src->flags & INMEMORY) {
+               COUNT_SPILLS;
+
+               disp = src->vv.regoff * 8;
+
+#if WORDS_BIGENDIAN == 1
+               M_ILD(tempreg, REG_SP, disp + 4);
+#else
+               M_ILD(tempreg, REG_SP, disp);
+#endif
+
+               reg = tempreg;
+       }
+       else
+               reg = GET_LOW_REG(src->vv.regoff);
+
+       return reg;
+}
+#endif /* SIZEOF_VOID_P == 4 */
+
+
+/* emit_load_high **************************************************************
+
+   Emits a possible load of the high 32-bits of an operand.
+
+*******************************************************************************/
+
+#if SIZEOF_VOID_P == 4
+s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
+{
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
+
+       assert(src->type == TYPE_LNG);
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (src->flags & INMEMORY) {
+               COUNT_SPILLS;
+
+               disp = src->vv.regoff * 8;
+
+#if WORDS_BIGENDIAN == 1
+               M_ILD(tempreg, REG_SP, disp);
+#else
+               M_ILD(tempreg, REG_SP, disp + 4);
+#endif
+
+               reg = tempreg;
+       }
+       else
+               reg = GET_HIGH_REG(src->vv.regoff);
+
+       return reg;
+}
+#endif /* SIZEOF_VOID_P == 4 */
+
+
 /* emit_store ******************************************************************
 
    Emits a possible store to variable.
@@ -121,8 +209,16 @@ void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
                        else
                                M_FST(d, REG_SP, disp);
                }
-               else
+               else {
+#if SIZEOF_VOID_P == 8
                        M_LST(d, REG_SP, disp);
+#else
+                       if (IS_2_WORD_TYPE(dst->type))
+                               M_LST(d, REG_SP, disp);
+                       else
+                               M_IST(d, REG_SP, disp);
+#endif
+               }
        }
 }
 
@@ -144,18 +240,27 @@ void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst)
 
        if ((src->vv.regoff != dst->vv.regoff) ||
                ((src->flags ^ dst->flags) & INMEMORY)) {
-
                /* 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);
+#if SIZEOF_VOID_P == 4
+                       if (IS_2_WORD_TYPE(src->type))
+                               d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
+                       else
+#endif
+                               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);
+#if SIZEOF_VOID_P == 4
+                       if (IS_2_WORD_TYPE(src->type))
+                               d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
+                       else
+#endif
+                               d = codegen_reg_of_var(iptr->opc, dst, s1);
                }
 
                if (s1 != d) {
@@ -165,8 +270,16 @@ void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst)
                                else
                                        M_FMOV(s1, d);
                        }
-                       else
+                       else {
+#if SIZEOF_VOID_P == 8
                                M_MOV(s1, d);
+#else
+                               if (IS_2_WORD_TYPE(src->type))
+                                       M_LNGMOVE(s1, d);
+                               else
+                                       M_MOV(s1, d);
+#endif
+                       }
                }
 
                emit_store(jd, iptr, dst, d);
@@ -205,6 +318,7 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
 {
        s4 disp;
 
+#if SIZEOF_VOID_P == 8
        if ((value >= -32768) && (value <= 32767))
                M_LADD_IMM(REG_ZERO, value, d);
        else if ((value >= 0) && (value <= 0xffff))
@@ -213,6 +327,10 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
                disp = dseg_add_s8(cd, value);
                M_LLD(d, REG_PV, disp);
        }
+#else
+       disp = dseg_add_s8(cd, value);
+       M_LLD(d, REG_PV, disp);
+#endif
 }
 
 
@@ -222,23 +340,25 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
 
 *******************************************************************************/
 
-void emit_arithmetic_check(codegendata *cd, s4 reg)
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
 {
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
 #if 0
-       M_BEQZ(reg, 0);
-       codegen_add_arithmeticexception_ref(cd);
-       M_NOP;
+               M_BEQZ(reg, 0);
+               codegen_add_arithmeticexception_ref(cd);
+               M_NOP;
 #else
-       M_BNEZ(reg, 6);
-       M_NOP;
+               M_BNEZ(reg, 6);
+               M_NOP;
 
-       M_LUI(REG_ITMP3, 0);
-       M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-       codegen_add_arithmeticexception_ref(cd);
-       M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-       M_JMP(REG_ITMP3);
-       M_NOP;
+               M_LUI(REG_ITMP3, 0);
+               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
+               codegen_add_arithmeticexception_ref(cd);
+               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
+               M_JMP(REG_ITMP3);
+               M_NOP;
 #endif
+       }
 }
 
 
@@ -248,9 +368,9 @@ void emit_arithmetic_check(codegendata *cd, s4 reg)
 
 *******************************************************************************/
 
-void emit_arrayindexoutofbounds_check(codegendata *cd, s4 s1, s4 s2)
+void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
 {
-       if (checkbounds) {
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
                M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
                M_CMPULT(s2, REG_ITMP3, REG_ITMP3);
 
@@ -279,23 +399,25 @@ void emit_arrayindexoutofbounds_check(codegendata *cd, s4 s1, s4 s2)
 
 *******************************************************************************/
 
-void emit_arraystore_check(codegendata *cd, s4 reg)
+void emit_arraystore_check(codegendata *cd, instruction *iptr, s4 reg)
 {
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
 #if 0
-       M_BEQZ(reg, 0);
-       codegen_add_arraystoreexception_ref(cd);
-       M_NOP;
+               M_BEQZ(reg, 0);
+               codegen_add_arraystoreexception_ref(cd);
+               M_NOP;
 #else
-       M_BNEZ(reg, 6);
-       M_NOP;
+               M_BNEZ(reg, 6);
+               M_NOP;
 
-       M_LUI(REG_ITMP3, 0);
-       M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-       codegen_add_arraystoreexception_ref(cd);
-       M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-       M_JMP(REG_ITMP3);
-       M_NOP;
+               M_LUI(REG_ITMP3, 0);
+               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
+               codegen_add_arraystoreexception_ref(cd);
+               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
+               M_JMP(REG_ITMP3);
+               M_NOP;
 #endif
+       }
 }
 
 
@@ -305,39 +427,41 @@ void emit_arraystore_check(codegendata *cd, s4 reg)
 
 *******************************************************************************/
 
-void emit_classcast_check(codegendata *cd, s4 condition, s4 reg, s4 s1)
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
 {
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
 #if 0
-       M_BNEZ(reg, 0);
-       codegen_add_classcastexception_ref(cd, s1);
-       M_NOP;
+               M_BNEZ(reg, 0);
+               codegen_add_classcastexception_ref(cd, s1);
+               M_NOP;
 #else
-       switch (condition) {
-       case ICMD_IFEQ:
-               M_BNEZ(reg, 6);
-               break;
+               switch (condition) {
+               case ICMD_IFEQ:
+                       M_BNEZ(reg, 6);
+                       break;
 
-       case ICMD_IFNE:
-               M_BEQZ(reg, 6);
-               break;
+               case ICMD_IFNE:
+                       M_BEQZ(reg, 6);
+                       break;
 
-       case ICMD_IFLE:
-               M_BGTZ(reg, 6);
-               break;
+               case ICMD_IFLE:
+                       M_BGTZ(reg, 6);
+                       break;
 
-       default:
-               vm_abort("emit_classcast_check: condition %d not found", condition);
-       }
+               default:
+                       vm_abort("emit_classcast_check: condition %d not found", condition);
+               }
 
-       M_NOP;
+               M_NOP;
 
-       M_LUI(REG_ITMP3, 0);
-       M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-       codegen_add_classcastexception_ref(cd, s1);
-       M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-       M_JMP(REG_ITMP3);
-       M_NOP;
+               M_LUI(REG_ITMP3, 0);
+               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
+               codegen_add_classcastexception_ref(cd, s1);
+               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
+               M_JMP(REG_ITMP3);
+               M_NOP;
 #endif
+       }
 }
 
 
@@ -347,9 +471,9 @@ void emit_classcast_check(codegendata *cd, s4 condition, s4 reg, s4 s1)
 
 *******************************************************************************/
 
-void emit_nullpointer_check(codegendata *cd, s4 reg)
+void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
 {
-       if (checknull) {
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
 #if 0
                M_BEQZ(reg, 0);
                codegen_add_nullpointerexception_ref(cd);
@@ -375,23 +499,25 @@ void emit_nullpointer_check(codegendata *cd, s4 reg)
 
 *******************************************************************************/
 
-void emit_exception_check(codegendata *cd)
+void emit_exception_check(codegendata *cd, instruction *iptr)
 {
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
 #if 0
-       M_BEQZ(REG_RESULT, 0);
-       codegen_add_fillinstacktrace_ref(cd);
-       M_NOP;
+               M_BEQZ(REG_RESULT, 0);
+               codegen_add_fillinstacktrace_ref(cd);
+               M_NOP;
 #else
-       M_BNEZ(REG_RESULT, 6);
-       M_NOP;
+               M_BNEZ(REG_RESULT, 6);
+               M_NOP;
 
-       M_LUI(REG_ITMP3, 0);
-       M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-       codegen_add_fillinstacktrace_ref(cd);
-       M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-       M_JMP(REG_ITMP3);
-       M_NOP;
+               M_LUI(REG_ITMP3, 0);
+               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
+               codegen_add_fillinstacktrace_ref(cd);
+               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
+               M_JMP(REG_ITMP3);
+               M_NOP;
 #endif
+       }
 }
 
 
@@ -458,6 +584,9 @@ void emit_exception_stubs(jitdata *jd)
                                M_ALD(REG_A2, REG_SP, (cd->stackframesize - 1) * 8);
 
                        M_MOV(REG_ITMP2_XPC, REG_A3);
+
+#if SIZEOF_VOID_P == 8
+                       /* XXX */
                        M_MOV(REG_ITMP1, REG_A4);
 
                        M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
@@ -465,16 +594,33 @@ void emit_exception_stubs(jitdata *jd)
 
                        if (jd->isleafmethod)
                                M_AST(REG_RA, REG_SP, 1 * 8);
+#else
+                       M_ASUB_IMM(REG_SP, 5*4 + 2 * 8, REG_SP);
+                       M_AST(REG_ITMP2_XPC, REG_SP, 5*4 + 0 * 8);
+
+                       if (jd->isleafmethod)
+                               M_AST(REG_RA, REG_SP, 5*4 + 1 * 8);
+
+                       M_AST(REG_ITMP1, REG_SP, 4 * 4);
+#endif
 
                        M_JSR(REG_RA, REG_ITMP3);
                        M_NOP;
                        M_MOV(REG_RESULT, REG_ITMP1_XPTR);
 
+#if SIZEOF_VOID_P == 8
                        if (jd->isleafmethod)
                                M_ALD(REG_RA, REG_SP, 1 * 8);
 
                        M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
                        M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
+#else
+                       if (jd->isleafmethod)
+                               M_ALD(REG_RA, REG_SP, 5*4 + 1 * 8);
+
+                       M_ALD(REG_ITMP2_XPC, REG_SP, 5*4 + 0 * 8);
+                       M_AADD_IMM(REG_SP, 5*4 + 2 * 8, REG_SP);
+#endif
 
                        disp = dseg_add_functionptr(cd, asm_handle_exception);
                        M_ALD(REG_ITMP3, REG_PV, disp);
@@ -507,8 +653,6 @@ void emit_patcher_stubs(jitdata *jd)
        u1          *tmpmcodeptr;
        s4           targetdisp;
        s4           disp;
-       s4           hi;
-       s4           lo;
 
        /* get required compiler data */
 
@@ -549,27 +693,24 @@ void emit_patcher_stubs(jitdata *jd)
 
                disp = ((u4 *) savedmcodeptr) - (((u4 *) tmpmcodeptr) + 1);
 
-               if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x00007fff)) {
+/*             if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x00007fff)) { */
                        /* Recalculate the displacement to be relative to PV. */
 
                        disp = savedmcodeptr - cd->mcodebase;
 
-                       lo = (short) disp;
-                       hi = (short) ((disp - lo) >> 16);
-
-                       M_LUI(REG_ITMP3, hi);
-                       M_OR_IMM(REG_ITMP3, lo, REG_ITMP3);
+                       M_LUI(REG_ITMP3, disp >> 16);
+                       M_OR_IMM(REG_ITMP3, disp, REG_ITMP3);
                        M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
                        M_JMP(REG_ITMP3);
                        M_NOP;
-               }
-               else {
-                       M_BR(disp);
-                       M_NOP;
-                       M_NOP;
-                       M_NOP;
-                       M_NOP;
-               }
+/*             } */
+/*             else { */
+/*                     M_BR(disp); */
+/*                     M_NOP; */
+/*                     M_NOP; */
+/*                     M_NOP; */
+/*                     M_NOP; */
+/*             } */
 
                cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr   */
 
@@ -633,7 +774,7 @@ void emit_patcher_stubs(jitdata *jd)
 
                /* move patcher function pointer onto stack */
 
-               disp = dseg_add_address(cd, pr->patcher);
+               disp = dseg_add_functionptr(cd, pr->patcher);
                M_ALD(REG_ITMP3, REG_PV, disp);
                M_AST(REG_ITMP3, REG_SP, 0 * 8);
 
@@ -662,6 +803,7 @@ void emit_patcher_stubs(jitdata *jd)
 
 *******************************************************************************/
 
+#if defined(ENABLE_REPLACEMENT)
 void emit_replacement_stubs(jitdata *jd)
 {
        codegendata *cd;
@@ -718,6 +860,7 @@ void emit_replacement_stubs(jitdata *jd)
                assert((cd->mcodeptr - savedmcodeptr) == 4*REPLACEMENT_STUB_SIZE);
        }
 }
+#endif /* defined(ENABLE_REPLACEMENT) */
 
 
 /* emit_verbosecall_enter ******************************************************
@@ -734,7 +877,7 @@ void emit_verbosecall_enter(jitdata *jd)
        registerdata *rd;
        methoddesc   *md;
        s4            disp;
-       s4            i, t;
+       s4            i, j, t;
 
        /* get required compiler data */
 
@@ -748,30 +891,33 @@ void emit_verbosecall_enter(jitdata *jd)
 
        M_NOP;
 
-       M_LDA(REG_SP, REG_SP, -(2 + ARG_CNT + TMP_CNT) * 8);
-       M_AST(REG_RA, REG_SP, 1 * 8);
+       M_LDA(REG_SP, REG_SP, -(PA_SIZE + (2 + ARG_CNT + TMP_CNT) * 8));
+       M_AST(REG_RA, REG_SP, PA_SIZE + 1 * 8);
 
-       /* save argument registers */
+       /* save argument registers (we store the registers as address
+          types, so it's correct for MIPS32 too) */
 
        for (i = 0; i < INT_ARG_CNT; i++)
-               M_LST(rd->argintregs[i], REG_SP, (2 + i) * 8);
+               M_AST(rd->argintregs[i], REG_SP, PA_SIZE + (2 + i) * 8);
 
        for (i = 0; i < FLT_ARG_CNT; i++)
-               M_DST(rd->argfltregs[i], REG_SP, (2 + INT_ARG_CNT + i) * 8);
+               M_DST(rd->argfltregs[i], REG_SP, PA_SIZE + (2 + INT_ARG_CNT + i) * 8);
 
        /* save temporary registers for leaf methods */
 
        if (jd->isleafmethod) {
                for (i = 0; i < INT_TMP_CNT; i++)
-                       M_LST(rd->tmpintregs[i], REG_SP, (2 + ARG_CNT + i) * 8);
+                       M_AST(rd->tmpintregs[i], REG_SP, PA_SIZE + (2 + ARG_CNT + i) * 8);
 
                for (i = 0; i < FLT_TMP_CNT; i++)
-                       M_DST(rd->tmpfltregs[i], REG_SP, (2 + ARG_CNT + INT_TMP_CNT + i) * 8);
+                       M_DST(rd->tmpfltregs[i], REG_SP, PA_SIZE + (2 + ARG_CNT + INT_TMP_CNT + i) * 8);
        }
 
-       /* load float arguments into integer registers */
+       /* Load float arguments into integer registers.  MIPS32 has less
+          float argument registers than integer ones, we need to check
+          that. */
 
-       for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
+       for (i = 0; i < md->paramcount && i < INT_ARG_CNT && i < FLT_ARG_CNT; i++) {
                t = md->paramtypes[i].type;
 
                if (IS_FLT_DBL_TYPE(t)) {
@@ -786,10 +932,33 @@ void emit_verbosecall_enter(jitdata *jd)
                }
        }
 
+#if SIZEOF_VOID_P == 4
+               for (i = 0, j = 0; i < md->paramcount && i < TRACE_ARGS_NUM; i++) {
+                       t = md->paramtypes[i].type;
+
+                       if (IS_INT_LNG_TYPE(t)) {
+                               if (IS_2_WORD_TYPE(t)) {
+                                       M_ILD(rd->argintregs[j], REG_SP, PA_SIZE + (2 + i) * 8);
+                                       M_ILD(rd->argintregs[j + 1], REG_SP, PA_SIZE + (2 + i) * 8 + 4);
+                               }
+                               else {
+# if WORDS_BIGENDIAN == 1
+                                       M_MOV(REG_ZERO, rd->argintregs[j]);
+                                       M_ILD(rd->argintregs[j + 1], REG_SP, PA_SIZE + (2 + i) * 8);
+# else
+                                       M_ILD(rd->argintregs[j], REG_SP, PA_SIZE + (2 + i) * 8);
+                                       M_MOV(REG_ZERO, rd->argintregs[j + 1]);
+# endif
+                               }
+                               j += 2;
+                       }
+               }
+#endif
+
        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_AST(REG_ITMP1, REG_SP, PA_SIZE + 0 * 8);
+       disp = dseg_add_functionptr(cd, builtin_verbosecall_enter);
        M_ALD(REG_ITMP3, REG_PV, disp);
        M_JSR(REG_RA, REG_ITMP3);
        M_NOP;
@@ -797,23 +966,23 @@ 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_ALD(rd->argintregs[i], REG_SP, PA_SIZE + (2 + i) * 8);
 
        for (i = 0; i < FLT_ARG_CNT; i++)
-               M_DLD(rd->argfltregs[i], REG_SP, (2 + INT_ARG_CNT + i) * 8);
+               M_DLD(rd->argfltregs[i], REG_SP, PA_SIZE + (2 + INT_ARG_CNT + i) * 8);
 
        /* restore temporary registers for leaf methods */
 
        if (jd->isleafmethod) {
                for (i = 0; i < INT_TMP_CNT; i++)
-                       M_LLD(rd->tmpintregs[i], REG_SP, (2 + ARG_CNT + i) * 8);
+                       M_ALD(rd->tmpintregs[i], REG_SP, PA_SIZE + (2 + ARG_CNT + i) * 8);
 
                for (i = 0; i < FLT_TMP_CNT; i++)
-                       M_DLD(rd->tmpfltregs[i], REG_SP, (2 + ARG_CNT + INT_TMP_CNT + i) * 8);
+                       M_DLD(rd->tmpfltregs[i], REG_SP, PA_SIZE + (2 + ARG_CNT + INT_TMP_CNT + i) * 8);
        }
 
-       M_ALD(REG_RA, REG_SP, 1 * 8);
-       M_LDA(REG_SP, REG_SP, (2 + ARG_CNT + TMP_CNT) * 8);
+       M_ALD(REG_RA, REG_SP, PA_SIZE + 1 * 8);
+       M_LDA(REG_SP, REG_SP, PA_SIZE + (2 + ARG_CNT + TMP_CNT) * 8);
 
        /* mark trace code */
 
@@ -826,6 +995,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)
@@ -834,6 +1005,7 @@ void emit_verbosecall_exit(jitdata *jd)
        methodinfo   *m;
        codegendata  *cd;
        registerdata *rd;
+       methoddesc   *md;
        s4            disp;
 
        /* get required compiler data */
@@ -842,33 +1014,73 @@ 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);              /* keep stack 16-byte aligned */
-       M_LST(REG_RA, REG_SP, 0 * 8);
+#if SIZEOF_VOID_P == 8
+       M_ASUB_IMM(REG_SP, 4 * 8, REG_SP);          /* keep stack 16-byte aligned */
+       M_AST(REG_RA, REG_SP, 0 * 8);
 
        M_LST(REG_RESULT, REG_SP, 1 * 8);
        M_DST(REG_FRESULT, REG_SP, 2 * 8);
 
+       M_MOV(REG_RESULT, REG_A0);
+       M_DMOV(REG_FRESULT, REG_FA1);
+       M_FMOV(REG_FRESULT, REG_FA2);
+
        disp = dseg_add_address(cd, m);
-       M_ALD(rd->argintregs[0], REG_PV, disp);
+       M_ALD(REG_A4, REG_PV, disp);
+#else
+       M_ASUB_IMM(REG_SP, (8*4 + 4 * 8), REG_SP);
+       M_AST(REG_RA, REG_SP, 8*4 + 0 * 8);
+
+       M_LST(REG_RESULT_PACKED, REG_SP, 8*4 + 1 * 8);
+       M_DST(REG_FRESULT, REG_SP, 8*4 + 2 * 8);
 
-       M_MOV(REG_RESULT, rd->argintregs[1]);
-       M_DMOV(REG_FRESULT, rd->argfltregs[2]);
-       M_FMOV(REG_FRESULT, rd->argfltregs[3]);
+       switch (md->returntype.type) {
+       case TYPE_LNG:
+               M_LNGMOVE(REG_RESULT_PACKED, REG_A0_A1_PACKED);
+               break;
+
+       default:
+# if WORDS_BIGENDIAN == 1
+               M_MOV(REG_ZERO, REG_A0);
+               M_MOV(REG_RESULT, REG_A1);
+# else
+               M_MOV(REG_RESULT, REG_A0);
+               M_MOV(REG_ZERO, REG_A1);
+# endif
+       }
+
+       M_LLD(REG_A2_A3_PACKED, REG_SP, 8*4 + 2 * 8);
+       M_FST(REG_FRESULT, REG_SP, 4*4 + 0 * 4);
+
+       disp = dseg_add_address(cd, m);
+       M_ALD(REG_ITMP1, REG_PV, disp);
+       M_AST(REG_ITMP1, REG_SP, 4*4 + 1 * 4);
+#endif
 
-       disp = dseg_add_functionptr(cd, builtin_displaymethodstop);
+       disp = dseg_add_functionptr(cd, builtin_verbosecall_exit);
        M_ALD(REG_ITMP3, REG_PV, disp);
        M_JSR(REG_RA, REG_ITMP3);
        M_NOP;
 
+#if SIZEOF_VOID_P == 8
        M_DLD(REG_FRESULT, REG_SP, 2 * 8);
        M_LLD(REG_RESULT, REG_SP, 1 * 8);
 
-       M_LLD(REG_RA, REG_SP, 0 * 8);
-       M_LDA(REG_SP, REG_SP, 4 * 8);
+       M_ALD(REG_RA, REG_SP, 0 * 8);
+       M_AADD_IMM(REG_SP, 4 * 8, REG_SP);
+#else
+       M_DLD(REG_FRESULT, REG_SP, 8*4 + 2 * 8);
+       M_LLD(REG_RESULT_PACKED, REG_SP, 8*4 + 1 * 8);
+
+       M_ALD(REG_RA, REG_SP, 8*4 + 0 * 8);
+       M_AADD_IMM(REG_SP, 8*4 + 4 * 8, REG_SP);
+#endif
 
        /* mark trace code */