/* 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"
#include "vm/jit/jit.h"
#include "vm/jit/replace.h"
+#include "vmcore/options.h"
+
/* emit_load *******************************************************************
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;
}
}
+/* 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.
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
+ }
}
}
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) {
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);
{
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))
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
}
*******************************************************************************/
-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
+ }
}
*******************************************************************************/
-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);
*******************************************************************************/
-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
+ }
}
*******************************************************************************/
-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
+ }
}
*******************************************************************************/
-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);
*******************************************************************************/
-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
+ }
}
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);
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);
u1 *tmpmcodeptr;
s4 targetdisp;
s4 disp;
- s4 hi;
- s4 lo;
/* get required compiler data */
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 */
/* 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);
*******************************************************************************/
+#if defined(ENABLE_REPLACEMENT)
void emit_replacement_stubs(jitdata *jd)
{
codegendata *cd;
assert((cd->mcodeptr - savedmcodeptr) == 4*REPLACEMENT_STUB_SIZE);
}
}
+#endif /* defined(ENABLE_REPLACEMENT) */
/* emit_verbosecall_enter ******************************************************
registerdata *rd;
methoddesc *md;
s4 disp;
- s4 i, t;
+ s4 i, j, t;
/* get required compiler data */
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)) {
}
}
+#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;
/* 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 */
Generates the code for the call trace.
+ void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m);
+
*******************************************************************************/
#if !defined(NDEBUG)
methodinfo *m;
codegendata *cd;
registerdata *rd;
+ methoddesc *md;
s4 disp;
/* get required compiler data */
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 */