/* src/vm/jit/arm/codegen.c - machine code generator for Arm
- 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
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "mm/memory.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/vm.h"
+#include "vm/loader.hpp"
+#include "vm/options.h"
+#include "vm/vm.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/md.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/jitcache.hpp"
+#include "vm/jit/linenumbertable.hpp"
#include "vm/jit/methodheader.h"
-#include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/parse.hpp"
+#include "vm/jit/patcher-common.hpp"
#include "vm/jit/reg.h"
#if defined(ENABLE_LSRA)
#include "vm/jit/allocator/lsra.h"
#endif
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
/* codegen_emit ****************************************************************
varinfo *var;
basicblock *bptr;
instruction *iptr;
- exception_entry *ex;
s4 spilledregs_num;
s4 savedregs_num;
/* space to save used callee saved registers */
- savedregs_num = (jd->isleafmethod) ? 0 : 1; /* space to save the LR */
+ savedregs_num = code_is_leafmethod(code) ? 0 : 1; /* space to save the LR */
+
savedregs_num += (INT_SAV_CNT - rd->savintreguse);
/*savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);*/
assert((FLT_SAV_CNT - rd->savfltreguse) == 0);
spilledregs_num = rd->memuse;
#if defined(ENABLE_THREADS) /* space to save argument of monitor_enter */
- if (checksync && (m->flags & ACC_SYNCHRONIZED))
+ if (checksync && code_is_synchronized(code))
spilledregs_num++;
#endif
/* SECTION: Method Header */
/* create method header */
+#if defined(ENABLE_JITCACHE)
+ disp = dseg_add_unique_address(cd, code); /* CodeinfoPointer */
+ jitcache_add_cached_ref(code, CRT_CODEINFO, 0, disp);
+#else
(void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
+#endif
+
(void) dseg_add_unique_s4(cd, cd->stackframesize); /* FrameSize */
-#if defined(ENABLE_THREADS)
- /* IsSync contains the offset relative to the stack pointer for the
- argument of monitor_exit used in the exception handler. Since the
- offset could be zero and give a wrong meaning of the flag it is
- offset by one.
- */
-
- if (checksync && (m->flags & ACC_SYNCHRONIZED))
- (void) dseg_add_unique_s4(cd, rd->memuse * 8 + 4);/* IsSync */
+ code->synchronizedoffset = rd->memuse * 8;
+
+ /* REMOVEME: We still need it for exception handling in assembler. */
+
+ if (code_is_leafmethod(code))
+ (void) dseg_add_unique_s4(cd, 1);
else
-#endif
- (void) dseg_add_unique_s4(cd, 0); /* IsSync */
+ (void) dseg_add_unique_s4(cd, 0);
- (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
(void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
(void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
- (void) dseg_addlinenumbertablesize(cd);
- (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
-
- /* create exception table */
-
- for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
- dseg_add_target(cd, ex->start);
- dseg_add_target(cd, ex->end);
- dseg_add_target(cd, ex->handler);
- (void) dseg_add_unique_address(cd, ex->catchtype.any);
- }
/* save return address and used callee saved registers */
savedregs_bitmask = 0;
- if (!jd->isleafmethod)
+ if (!code_is_leafmethod(code))
savedregs_bitmask = (1<<REG_LR);
for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--)
else {
if (!md->params[i].inmemory) {
if (!(var->flags & INMEMORY)) {
- M_CAST_INT_TO_FLT_TYPED(t, s1, var->vv.regoff);
+ if (IS_2_WORD_TYPE(t))
+ M_CAST_L2D(s1, var->vv.regoff);
+ else
+ M_CAST_I2F(s1, var->vv.regoff);
}
else {
if (IS_2_WORD_TYPE(t))
#if defined(ENABLE_THREADS)
/* call monitorenter function */
- if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+ if (checksync && code_is_synchronized(code)) {
/* stack offset for monitor argument */
s1 = rd->memuse * 8;
/* get the correct lock object */
if (m->flags & ACC_STATIC) {
- disp = dseg_add_address(cd, &m->class->object.header);
+ disp = dseg_add_address(cd, &m->clazz->object.header);
+ JITCACHE_ADD_CACHED_REF(code, CRT_OBJECT_HEADER, m->clazz, disp);
M_DSEG_LOAD(REG_A0, disp);
}
else {
M_STR(REG_A0, REG_SP, s1);
disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+ JITCACHE_ADD_CACHED_REF(code,
+ CRT_BUILTIN_FP, builtintable_get_internal(LOCK_monitor_enter), disp);
M_DSEG_BRANCH(disp);
s1 = (s4) (cd->mcodeptr - cd->mcodebase);
M_RECOMPUTE_PV(s1);
/* add line number */
if (iptr->line != currentline) {
- dseg_addlinenumber(cd, iptr->line);
+ linenumbertable_list_entry_add(cd, iptr->line);
currentline = iptr->line;
}
MCODECHECK(64); /* an instruction usually needs < 64 words */
- /* the big switch */
- switch (iptr->opc) {
- case ICMD_NOP: /* ... ==> ... */
+ /* the big switch */
+ switch (iptr->opc) {
+
+ case ICMD_NOP: /* ... ==> ... */
+ case ICMD_POP: /* ..., value ==> ... */
+ case ICMD_POP2: /* ..., value, value ==> ... */
break;
- /* constant operations ************************************************/
+ /* constant operations ************************************************/
case ICMD_ICONST: /* ... ==> ..., constant */
M_DSEG_LOAD(d, disp);
}
else {
+#if defined(ENABLE_JITCACHE)
+ /* Dealing with ICONST and the JIT cache is tricky because
+ * ICONST generates different code depending on the value of the
+ * number. We therefore go the slightly less optimal way and
+ * generate an entry in the data segment.
+ * For the null constant however we use the plain integer load.
+ */
+ if (iptr->sx.val.anyptr)
+ {
+ disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
+
+ jitcache_add_cached_ref(code,
+ (iptr->flags.bits & INS_FLAG_CLASS) ? CRT_CLASSINFO
+ : CRT_STRING,
+ (iptr->flags.bits & INS_FLAG_CLASS) ? iptr->sx.val.c.cls
+ : iptr->sx.val.stringconst,
+ disp);
+
+ M_DSEG_LOAD(d, disp);
+ }
+ else {
+ ICONST(d, (u4) 0);
+ }
+
+#else
ICONST(d, (u4) iptr->sx.val.anyptr);
+#endif
}
emit_store_dst(jd, iptr, d);
break;
break;
case ICMD_ASTORE:
+
if (!(iptr->flags.bits & INS_FLAG_RETADDR))
emit_copy(jd, iptr);
break;
- /* pop operations *****************************************************/
-
- /* attention: double and longs are only one entry in CACAO ICMDs */
-
- case ICMD_POP: /* ..., value ==> ... */
- case ICMD_POP2: /* ..., value, value ==> ... */
-
- break;
-
/* integer operations *************************************************/
/* call builtin function */
bte = iptr->sx.s23.s3.bte;
disp = dseg_add_functionptr(cd, bte->fp);
+ JITCACHE_ADD_CACHED_REF(code, CRT_BUILTIN_FP, bte, disp);
M_DSEG_BRANCH(disp);
/* recompute pv */
/* call builtin function */
bte = iptr->sx.s23.s3.bte;
disp = dseg_add_functionptr(cd, bte->fp);
+ JITCACHE_ADD_CACHED_REF(code, CRT_BUILTIN_FP, bte, disp);
M_DSEG_BRANCH(disp);
/* recompute pv */
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_MNFS(d, s1);
+ M_FNEG(s1, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_ADFS(d, s1, s2);
+ M_FADD(s1, s2, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_SUFS(d, s1, s2);
+ M_FSUB(s1, s2, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_MUFS(d, s1, s2);
+ M_FMUL(s1, s2, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_DVFS(d, s1, s2);
+ M_FDIV(s1, s2, d);
emit_store_dst(jd, iptr, d);
break;
/* ATTENTION: Jave does not want IEEE behaviour in FREM, do
not use this */
+#if 0
case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
M_RMFS(d, s1, s2);
emit_store_dst(jd, iptr, d);
break;
+#endif
case ICMD_DNEG: /* ..., value ==> ..., - value */
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_MNFD(d, s1);
+ M_DNEG(s1, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_ADFD(d, s1, s2);
+ M_DADD(s1, s2, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_SUFD(d, s1, s2);
+ M_DSUB(s1, s2, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_MUFD(d, s1, s2);
+ M_DMUL(s1, s2, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_DVFD(d, s1, s2);
+ M_DDIV(s1, s2, d);
emit_store_dst(jd, iptr, d);
break;
/* ATTENTION: Jave does not want IEEE behaviour in DREM, do
not use this */
+#if 0
case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
M_RMFD(d, s1, s2);
emit_store_dst(jd, iptr, d);
break;
+#endif
case ICMD_I2F: /* ..., value ==> ..., (float) value */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_FLTS(d, s1);
+#if defined(__VFP_FP__)
+ M_FMSR(s1, d);
+ M_CVTIF(d, d);
+#else
+ M_CVTIF(s1, d);
+#endif
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_FLTD(d, s1);
+#if defined(__VFP_FP__)
+ M_FMSR(s1, d);
+ M_CVTID(d, d);
+#else
+ M_CVTID(s1, d);
+#endif
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+#if defined(__VFP_FP__)
+ M_CVTFI(s1, REG_FTMP2);
+ M_FMRS(REG_FTMP2, d);
+#else
/* this uses round towards zero, as Java likes it */
- M_FIX(d, s1);
+ M_CVTFI(s1, d);
/* this checks for NaN; to return zero as Java likes it */
- M_CMF(s1, 0x8);
+ M_FCMP(s1, 0x8);
M_MOVVS_IMM(0, d);
+#endif
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+#if defined(__VFP_FP__)
+ M_CVTDI(s1, REG_FTMP2);
+ M_FMRS(REG_FTMP2, d);
+#else
/* this uses round towards zero, as Java likes it */
- M_FIX(d, s1);
+ M_CVTDI(s1, d);
/* this checks for NaN; to return zero as Java likes it */
- M_CMF(s1, 0x8);
+ M_DCMP(s1, 0x8);
M_MOVVS_IMM(0, d);
+#endif
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
- M_MVFS(d,s1);
+ M_CVTDF(s1, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
- M_MVFD(d,s1);
+ M_CVTFD(s1, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_CMF(s2, s1);
+ M_FCMP(s2, s1);
M_MOV_IMM(d, 0);
+#if defined(__VFP_FP__)
+ M_FMSTAT; /* on VFP we need to transfer the flags */
+#endif
M_SUBGT_IMM(d, d, 1);
M_ADDLT_IMM(d, d, 1);
emit_store_dst(jd, iptr, d);
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_CMF(s2, s1);
+ M_DCMP(s2, s1);
M_MOV_IMM(d, 0);
+#if defined(__VFP_FP__)
+ M_FMSTAT; /* on VFP we need to transfer the flags */
+#endif
M_SUBGT_IMM(d, d, 1);
M_ADDLT_IMM(d, d, 1);
emit_store_dst(jd, iptr, d);
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_CMF(s1, s2);
+ M_FCMP(s1, s2);
M_MOV_IMM(d, 0);
+#if defined(__VFP_FP__)
+ M_FMSTAT; /* on VFP we need to transfer the flags */
+#endif
M_SUBLT_IMM(d, d, 1);
M_ADDGT_IMM(d, d, 1);
emit_store_dst(jd, iptr, d);
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_CMF(s1, s2);
+ M_DCMP(s1, s2);
M_MOV_IMM(d, 0);
+#if defined(__VFP_FP__)
+ M_FMSTAT; /* on VFP we need to transfer the flags */
+#endif
M_SUBLT_IMM(d, d, 1);
M_ADDGT_IMM(d, d, 1);
emit_store_dst(jd, iptr, d);
/* call builtin function */
disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
+ JITCACHE_ADD_CACHED_REF(
+ code, CRT_BUILTIN_FP,
+ builtintable_get_internal(BUILTIN_FAST_canstore), disp);
+
M_DSEG_BRANCH(disp);
/* recompute pv */
fi = iptr->sx.s23.s3.fmiref->p.field;
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
-
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+ JITCACHE_ADD_CACHED_REF(code, CRT_FIELDINFO_VALUE, fi, disp);
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
patcher_add_patch_ref(jd, PATCHER_initialize_class,
- fi->class, 0);
+ fi->clazz, 0);
}
}
fi = iptr->sx.s23.s3.fmiref->p.field;
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
-
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+ JITCACHE_ADD_CACHED_REF(code, CRT_FIELDINFO_VALUE, fi, disp);
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
patcher_add_patch_ref(jd, PATCHER_initialize_class,
- fi->class, 0);
+ fi->clazz, 0);
}
}
iptr->sx.s23.s2.uc, 0);
}
disp = dseg_add_functionptr(cd, asm_handle_exception);
+ JITCACHE_ADD_CACHED_REF(code, CRT_ASM_HANDLE_EXCEPTION, NULL, disp);
M_DSEG_LOAD(REG_ITMP3, disp);
M_MOV(REG_ITMP2_XPC, REG_PC);
M_MOV(REG_PC, REG_ITMP3);
#if !defined(ENABLE_SOFTFLOAT)
REPLACEMENT_POINT_RETURN(cd, iptr);
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- M_CAST_FLT_TO_INT_TYPED(VAROP(iptr->s1)->type, s1, REG_RESULT);
+ M_CAST_F2I(s1, REG_RESULT);
goto ICMD_RETURN_do;
#endif
#if !defined(ENABLE_SOFTFLOAT)
REPLACEMENT_POINT_RETURN(cd, iptr);
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- M_CAST_FLT_TO_INT_TYPED(VAROP(iptr->s1)->type, s1, REG_RESULT_PACKED);
+ M_CAST_D2L(s1, REG_RESULT_PACKED);
goto ICMD_RETURN_do;
#endif
#if defined(ENABLE_THREADS)
/* call monitorexit function */
- if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+ if (checksync && code_is_synchronized(code)) {
/* stack offset for monitor argument */
s1 = rd->memuse * 8;
M_LDR(REG_A0, REG_SP, s1);
disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
+ JITCACHE_ADD_CACHED_REF(code,
+ CRT_BUILTIN_FP, builtintable_get_internal(LOCK_monitor_exit),
+ disp);
+
M_DSEG_BRANCH(disp);
/* we no longer need PV here, no more loading */
/* restore callee saved registers + do return */
if (savedregs_bitmask) {
- if (!jd->isleafmethod) {
+ if (!code_is_leafmethod(code)) {
savedregs_bitmask &= ~(1<<REG_LR);
savedregs_bitmask |= (1<<REG_PC);
}
/* if LR was not on stack, we need to return manually */
- if (jd->isleafmethod)
+ if (code_is_leafmethod(code))
M_MOV(REG_PC, REG_LR);
break;
else {
if (!md->params[s3].inmemory) {
s1 = emit_load(jd, iptr, var, REG_FTMP1);
- M_CAST_FLT_TO_INT_TYPED(var->type, s1, d);
+ if (IS_2_WORD_TYPE(var->type))
+ M_CAST_D2L(s1, d);
+ else
+ M_CAST_F2I(s1, d);
}
else {
s1 = emit_load(jd, iptr, var, REG_FTMP1);
disp = dseg_add_functionptr(cd, bte->stub);
}
+ JITCACHE_ADD_CACHED_REF(code, CRT_BUILTIN, bte, disp);
+
M_DSEG_LOAD(REG_PV, disp); /* pointer to built-in-function */
/* generate the actual call */
um, disp);
}
else
+ {
disp = dseg_add_address(cd, lm->stubroutine);
+ JITCACHE_ADD_CACHED_REF(code, CRT_METHODINFO_STUBROUTINE, lm, disp);
+ }
M_DSEG_LOAD(REG_PV, disp); /* Pointer to method */
case ICMD_INVOKEVIRTUAL:
if (lm == NULL) {
+
patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
s1 = 0;
else
s1 = OFFSET(vftbl_t, table[0]) +
sizeof(methodptr) * lm->vftblindex;
+
/* implicit null-pointer check */
M_LDR_INTERN(REG_METHODPTR, REG_A0,
OFFSET(java_object_t, vftbl));
M_LDR_INTERN(REG_PV, REG_METHODPTR, s1);
-
/* generate the actual call */
M_MOV(REG_LR, REG_PC);
}
else {
s1 = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * lm->class->index;
- s2 = sizeof(methodptr) * (lm - lm->class->methods);
+ sizeof(methodptr*) * lm->clazz->index;
+ s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
}
/* implicit null-pointer check */
M_LDR_INTERN(REG_METHODPTR, REG_A0,
OFFSET(java_object_t, vftbl));
M_LDR_INTERN(REG_METHODPTR, REG_METHODPTR, s1);
+
M_LDR_INTERN(REG_PV, REG_METHODPTR, s2);
+ JITCACHE_ADD_CACHED_REF_MD_JD(jd, CRT_METHODINFO_METHODOFFSET, 1, lm);
/* generate the actual call */
our ENABLE_SOFTFLOAT define */
if (iptr->opc == ICMD_BUILTIN && d != TYPE_VOID && IS_FLT_DBL_TYPE(d)) {
#if 0 && !defined(NDEBUG)
- dolog("BUILTIN that returns float or double (%s.%s)", m->class->name->text, m->name->text);
+ dolog("BUILTIN that returns float or double (%s.%s)", m->clazz->name->text, m->name->text);
#endif
/* we cannot use this macro, since it is not defined
in ENABLE_SOFTFLOAT M_CAST_FLT_TO_INT_TYPED(d,
#if !defined(ENABLE_SOFTFLOAT)
} else {
s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_CAST_INT_TO_FLT_TYPED(VAROP(iptr->dst)->type, REG_RESULT_TYPED(VAROP(iptr->dst)->type), s1);
+ if (IS_2_WORD_TYPE(d))
+ M_CAST_L2D(REG_RESULT_PACKED, s1);
+ else
+ M_CAST_I2F(REG_RESULT, s1);
}
#endif /* !defined(ENABLE_SOFTFLOAT) */
superindex = super->index;
}
- if ((super == NULL) || !(super->flags & ACC_INTERFACE))
- CODEGEN_CRITICAL_SECTION_NEW;
-
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
/* if class is not resolved, check which code to call */
iptr->sx.s23.s3.c.ref, disp);
}
else {
+/*
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_INDEX, super, disp);
+*/
M_TST(s1, s1);
emit_label_beq(cd, BRANCH_LABEL_3);
}
}
else {
disp = dseg_add_address(cd, super->vftbl);
-
+ JITCACHE_ADD_CACHED_REF(code, CRT_CLASSINFO_VFTBL, super, disp);
M_TST(s1, s1);
emit_label_beq(cd, BRANCH_LABEL_5);
}
M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
M_DSEG_LOAD(REG_ITMP3, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
M_SUB(REG_ITMP2, REG_ITMP2, REG_ITMP3);
M_DSEG_LOAD(REG_ITMP3, disp);
M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_CMP(REG_ITMP2, REG_ITMP3);
emit_classcast_check(cd, iptr, BRANCH_UGT, 0, s1);
disp);
}
else
+ {
disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
+ JITCACHE_ADD_CACHED_REF(code, CRT_CLASSINFO, iptr->sx.s23.s3.c.cls, disp);
+ }
M_DSEG_LOAD(REG_A1, disp);
disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
+ JITCACHE_ADD_CACHED_REF(code, CRT_BUILTIN, builtintable_get_internal(BUILTIN_arraycheckcast), disp);
M_DSEG_BRANCH(disp);
/* recompute pv */
superindex = super->index;
}
- if ((super == NULL) || !(super->flags & ACC_INTERFACE))
- CODEGEN_CRITICAL_SECTION_NEW;
-
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
iptr->sx.s23.s3.c.ref, disp);
}
else {
+/* TODO: Not needed?
+ JITCACHE_ADD_CACHED_REF(code, CRT_CLASSINFO_INDEX, super, disp);
+*/
M_EOR(d, d, d);
M_TST(s1, s1);
emit_label_beq(cd, BRANCH_LABEL_3);
}
else {
disp = dseg_add_address(cd, super->vftbl);
+ JITCACHE_ADD_CACHED_REF(code, CRT_CLASSINFO_VFTBL, super, disp);
M_EOR(d, d, d);
M_TST(s1, s1);
M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
M_DSEG_LOAD(REG_ITMP2, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_LDR_INTERN(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
M_LDR_INTERN(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_SUB(REG_ITMP1, REG_ITMP1, REG_ITMP3);
M_CMP(REG_ITMP1, REG_ITMP2);
/* If d == REG_ITMP2, then it's destroyed */
iptr->sx.s23.s3.c.ref, disp);
}
else
+ {
disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
+ JITCACHE_ADD_CACHED_REF(code, CRT_CLASSINFO, iptr->sx.s23.s3.c.cls, disp);
+ }
/* a1 = arraydescriptor */
/* call builtin_multianewarray here */
disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
+ /*
+ * For some unknown reason this causes an illegal instruction.
+ * JITCACHE_ADD_CACHED_REF(code, CRT_BUILTIN, builtintable_get_internal(BUILTIN_multianewarray), disp);
+ */
+
M_DSEG_BRANCH(disp);
/* recompute pv */
} /* for all basic blocks */
- dseg_createlinenumbertable(cd);
-
-
/* generate traps */
emit_patcher_traps(jd);
}
-/* codegen_emit_stub_compiler **************************************************
-
- Emits a stub routine which calls the compiler.
-
-*******************************************************************************/
-
-void codegen_emit_stub_compiler(jitdata *jd)
-{
- methodinfo *m;
- codegendata *cd;
-
- /* get required compiler data */
-
- m = jd->m;
- cd = jd->cd;
-
- /* code for the stub */
-
- M_LDR_INTERN(REG_ITMP1, REG_PC, -(2 * 4 + 2 * SIZEOF_VOID_P));
- M_LDR_INTERN(REG_PC, REG_PC, -(3 * 4 + 3 * SIZEOF_VOID_P));
-}
-
-
/* codegen_emit_stub_native ****************************************************
Emits a stub routine which calls a native method.
methoddesc *md;
s4 i, j;
s4 t;
- s4 disp, funcdisp, s1, s2;
+ int s1, s2;
+ int disp;
/* get required compiler data */
cd->stackframesize =
4 + /* return address */
- sizeof(stackframeinfo) + /* stackframeinfo */
+ sizeof(stackframeinfo_t) + /* stackframeinfo */
sizeof(localref_table) + /* localref_table */
nmd->memuse * 4; /* stack arguments */
(void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
(void) dseg_add_unique_s4(cd, cd->stackframesize); /* FrameSize */
- (void) dseg_add_unique_s4(cd, 0); /* IsSync */
(void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
(void) dseg_add_unique_s4(cd, 0); /* IntSave */
(void) dseg_add_unique_s4(cd, 0); /* FltSave */
- (void) dseg_addlinenumbertablesize(cd);
- (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
/* generate stub code */
emit_verbosecall_enter(jd);
#endif
- /* get function address (this must happen before the stackframeinfo) */
-
- funcdisp = dseg_add_functionptr(cd, f);
-
- if (f == NULL)
- patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp);
-
#if defined(ENABLE_GC_CACAO)
/* Save callee saved integer registers in stackframeinfo (GC may
need to recover them during a collection). */
- disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo) +
- OFFSET(stackframeinfo, intregs);
+ disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo_t) +
+ OFFSET(stackframeinfo_t, intregs);
for (i = 0; i < INT_SAV_CNT; i++)
M_STR_INTERN(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
/* put env into first argument register */
- disp = dseg_add_address(cd, _Jv_env);
+ disp = dseg_add_address(cd, VM_get_jnienv());
M_DSEG_LOAD(REG_A0, disp);
}
- /* do the native function call */
+ /* Call the native function. */
- M_DSEG_BRANCH(funcdisp);
+ disp = dseg_add_functionptr(cd, f);
+ M_DSEG_BRANCH(disp);
/* recompute pv */
/* TODO: this is only needed because of the tracer ... do we
/* this depends on gcc; it is independent from our ENABLE_SOFTFLOAT define */
if (md->returntype.type != TYPE_VOID && IS_FLT_DBL_TYPE(md->returntype.type)) {
#if 0 && !defined(NDEBUG)
- dolog("NATIVESTUB that returns float or double (%s.%s)", m->class->name->text, m->name->text);
+ dolog("NATIVESTUB that returns float or double (%s.%s)", m->clazz->name->text, m->name->text);
#endif
/* we cannot use this macro, since it is not defined in ENABLE_SOFTFLOAT */
/* M_CAST_FLT_TO_INT_TYPED(md->returntype.type, REG_FRESULT, REG_RESULT_TYPED(md->returntype.type)); */
/* restore callee saved int registers from stackframeinfo (GC might have */
/* modified them during a collection). */
- disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo) +
- OFFSET(stackframeinfo, intregs);
+ disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo_t) +
+ OFFSET(stackframeinfo_t, intregs);
for (i = 0; i < INT_SAV_CNT; i++)
M_LDR_INTERN(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
M_DSEG_LOAD(REG_ITMP3, disp); /* load asm exception handler address */
M_MOV(REG_PC, REG_ITMP3); /* jump to asm exception handler */
-
- /* generate patcher stubs */
-
- emit_patcher_traps(jd);
}