/* src/vm/jit/sparc64/codegen.c - machine code generator for Sparc
- 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.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: codegen.c 4644 2006-03-16 18:44:46Z edwin $
-
*/
#include "config.h"
#include <assert.h>
+#include <stdint.h>
#include <stdio.h>
#include "vm/types.h"
/* #include "vm/jit/sparc64/arch.h" */
#include "vm/jit/sparc64/codegen.h"
+#include "vm/jit/sparc64/emit.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
-#include "native/jni.h"
-#include "native/native.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/loader.hpp"
+#include "vm/options.h"
#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/sparc64/emit.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/parse.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
+#include "vm/jit/parse.hpp"
#include "vm/jit/patcher.h"
#include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
-#include "vm/jit/stacktrace.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
+#include "vm/jit/stacktrace.hpp"
#include "vm/jit/sparc64/solaris/macro_rename.h"
return lodisp;
}
+
+#ifndef NDEBUG
+bool check_13bit_imm(s8 imm)
+{
+ s4 sign = (imm >> 12) & 0x1;
+
+ if (sign == 0) {
+ if ((imm & ~0xfff) == 0) return true; /* pos imm. */
+ }
+ else
+ if ((imm & ~0xfff) + 0xfff == -1) return true; /* neg imm. */
+
+ printf("immediate out-of-bounds: %ld\n", imm);
+ return false;
+}
+#endif
/* codegen_emit ****************************************************************
bool codegen_emit(jitdata *jd)
{
- methodinfo *m;
- codeinfo *code;
- codegendata *cd;
- registerdata *rd;
- s4 len, s1, s2, s3, d, disp, slots;
- varinfo *var;
- basicblock *bptr;
- instruction *iptr;
- exception_entry *ex;
- u2 currentline;
- constant_classref *cr;
- methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
- unresolved_method *um;
- builtintable_entry *bte;
- methoddesc *md;
- fieldinfo *fi;
- unresolved_field *uf;
- s4 fieldtype;
- s4 varindex;
-
- /* get required compiler data */
-
- m = jd->m;
- code = jd->code;
- cd = jd->cd;
- rd = jd->rd;
-
- /* prevent compiler warnings */
-
- d = 0;
- currentline = 0;
- lm = NULL;
- bte = NULL;
- {
- s4 i, p, t, l;
s4 savedregs_num;
+ s4 framesize_disp;
#if 0 /* no leaf optimization yet */
- savedregs_num = (jd->isleafmethod) ? 0 : 1; /* space to save the RA */
+ savedregs_num = (code_is_leafmethod(code)) ? 0 : 1; /* space to save the RA */
#endif
savedregs_num = WINSAVE_CNT + ABIPARAMS_CNT; /* register-window save area */
- /* space to save used callee saved registers */
-
- savedregs_num += (INT_SAV_CNT - rd->savintreguse);
- savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
-
- cd->stackframesize = rd->memuse + savedregs_num;
-
#if defined(ENABLE_THREADS) /* space to save argument of monitor_enter */
- if (checksync && (m->flags & ACC_SYNCHRONIZED))
+ if (checksync && code_is_synchronized(code))
cd->stackframesize++;
#endif
if (cd->stackframesize & 1)
cd->stackframesize++;
- /* create method header */
-
- (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
- (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* 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, JITSTACK + (rd->memuse + 1) * 8); /* IsSync */
- else
-#endif
- (void) dseg_add_unique_s4(cd, 0); /* IsSync */
-
- (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 */
- 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 register window and create stack frame (if necessary) */
- if (cd->stackframesize)
- M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP);
- /* save callee saved float registers (none right now) */
-#if 0
- p = cd->stackframesize;
- for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
- p--; M_DST(rd->savfltregs[i], REG_SP, USESTACK + (p * 8));
- }
-#endif
-#if !defined(NDEBUG)
- if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
- emit_verbosecall_enter(jd);
-#endif
-
-
- /* call monitorenter function */
-#if defined(ENABLE_THREADS)
- if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
- /* stack offset for monitor argument */
- s1 = rd->memuse;
- /* save float argument registers */
- /* XXX jit-c-call */
- slots = FLT_ARG_CNT;
- ALIGN_STACK_SLOTS(slots);
- M_LDA(REG_SP, REG_SP, -(slots * 8));
- for (i = 0; i < FLT_ARG_CNT; i++)
- M_DST(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
- s1 += slots;
+/**
+ * Generates machine code for the method prolog.
+ */
+void codegen_emit_prolog(jitdata* jd)
+{
+ varinfo* var;
+ methoddesc* md;
+ int32_t s1;
+ int32_t p, t, l;
+ int32_t varindex;
+ int i;
+
+ // Get required compiler data.
+ methodinfo* m = jd->m;
+ codeinfo* code = jd->code;
+ codegendata* cd = jd->cd;
+ registerdata* rd = jd->rd;
- /* get correct lock object */
+ /* save register window and create stack frame (if necessary) */
- if (m->flags & ACC_STATIC) {
- disp = dseg_add_address(cd, &m->class->object.header);
- M_ALD(REG_OUT0, REG_PV, disp);
- disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
- M_ALD(REG_ITMP3, REG_PV, disp);
- }
+ if (cd->stackframesize) {
+ if (cd->stackframesize <= 4095)
+ M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP);
else {
- /* copy class pointer: $i0 -> $o0 */
- M_MOV(REG_RESULT_CALLEE, REG_OUT0);
- M_BNEZ(REG_OUT0, 3);
- disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
- M_ALD(REG_ITMP3, REG_PV, disp); /* branch delay */
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ILD_INTERN(REG_ITMP3, REG_PV_CALLER, framesize_disp);
+ M_SUB(REG_ZERO, REG_ITMP3, REG_ITMP3);
+ M_SAVE_REG(REG_SP, REG_ITMP3, REG_SP);
}
+ }
- M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
- M_AST(REG_OUT0, REG_SP, CSTACK + s1 * 8); /* branch delay */
-
- /* restore float argument registers */
-
- for (i = 0; i < FLT_ARG_CNT; i++)
- M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
-
- M_LDA(REG_SP, REG_SP, slots * 8);
+ /* save callee saved float registers (none right now) */
+#if 0
+ p = cd->stackframesize;
+ for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
+ p--; M_DST(rd->savfltregs[i], REG_SP, USESTACK + (p * 8));
}
#endif
-
/* take arguments out of register or stack frame */
md = m->parseddesc;
for (i = 0; i < jd->varcount; i++) {
varinfo* uvar = VAR(i);
- if (IS_FLT_DBL_TYPE(uvar->type))
+ if (IS_FLT_DBL_TYPE(uvar->type) || IS_INMEMORY(uvar->flags))
continue;
s2 = uvar->vv.regoff;
} else { /* floating args */
if (!md->params[p].inmemory) { /* register arguments */
if (!(var->flags & INMEMORY)) { /* reg arg -> register */
- M_FLTMOVE(s1, var->vv.regoff);
+ emit_fmove(cd, s1, var->vv.regoff);
} else { /* reg arg -> spilled */
M_DST(s1, REG_SP, JITSTACK + var->vv.regoff);
}
}
} /* end for */
-
-
- }
-
- /* end of header generation */
-
- /* create replacement points */
-
- REPLACEMENT_POINTS_INIT(cd, jd);
-
- /* walk through all basic blocks */
-
- for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
-
- bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
-
- if (bptr->flags >= BBREACHED) {
-
- /* branch resolving */
-
- codegen_resolve_branchrefs(cd, bptr);
-
- /* handle replacement points */
-
-#if 0
- if (bptr->bitflags & BBFLAG_REPLACEMENT) {
- replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
-
- replacementpoint++;
- }
-#endif
-
- /* copy interface registers to their destination */
-
- len = bptr->indepth;
- MCODECHECK(64+len);
-
-#if defined(ENABLE_LSRA)
-#error XXX LSRA not tested yet
- if (opt_lsra) {
- while (len) {
- len--;
- src = bptr->invars[len];
- if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
- /* d = reg_of_var(m, src, REG_ITMP1); */
- if (!(src->flags & INMEMORY))
- d = src->vv.regoff;
- else
- d = REG_ITMP1;
- M_INTMOVE(REG_ITMP1, d);
- emit_store(jd, NULL, src, d);
- }
- }
- } else {
-#endif
- while (len) {
- len--;
- var = VAR(bptr->invars[len]);
- if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
- d = codegen_reg_of_var(0, var, REG_ITMP1);
- M_INTMOVE(REG_ITMP2_XPTR, d);
- emit_store(jd, NULL, var, d);
- }
- else {
- assert((var->flags & INOUT));
- }
- }
-#if defined(ENABLE_LSRA)
- }
-#endif
- /* walk through all instructions */
-
- len = bptr->icount;
-
- for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
- if (iptr->line != currentline) {
- dseg_addlinenumber(cd, iptr->line);
- currentline = iptr->line;
- }
-
- MCODECHECK(64); /* an instruction usually needs < 64 words */
+}
- switch (iptr->opc) {
- case ICMD_INLINE_START:
- case ICMD_INLINE_END:
- break;
+/**
+ * Generates machine code for the method epilog.
+ */
+void codegen_emit_epilog(jitdata* jd)
+{
+ M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
+ M_NOP;
+}
- case ICMD_NOP: /* ... ==> ... */
- break;
- case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
+/**
+ * Generates machine code for one ICMD.
+ */
+void codegen_emit_instruction(jitdata* jd, instruction* iptr)
+{
+ varinfo* var;
+ builtintable_entry* bte;
+ methodinfo* lm; // Local methodinfo for ICMD_INVOKE*.
+ unresolved_method* um;
+ fieldinfo* fi;
+ unresolved_field* uf;
+ int32_t fieldtype;
+ int32_t s1, s2, s3, d;
+ int32_t disp;
+
+ // Get required compiler data.
+ codeinfo* code = jd->code;
+ codegendata* cd = jd->cd;
+
+ switch (iptr->opc) {
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- emit_nullpointer_check(cd, iptr, s1);
- break;
-
/* constant operations ************************************************/
- case ICMD_ICONST: /* ... ==> ..., constant */
-
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- ICONST(d, iptr->sx.val.i);
- emit_store_dst(jd, iptr, d);
- break;
-
case ICMD_LCONST: /* ... ==> ..., constant */
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- cr = iptr->sx.val.c.ref;
+ constant_classref *cr = iptr->sx.val.c.ref;
disp = dseg_add_unique_address(cd, cr);
codegen_add_patch_ref(cd, PATCHER_aconst, cr, disp);
break;
- /* load/store/copy/move operations ************************************/
-
- case ICMD_ILOAD: /* ... ==> ..., content of local variable */
- case ICMD_LLOAD:
- case ICMD_ALOAD:
- case ICMD_FLOAD:
- case ICMD_DLOAD:
- case ICMD_ISTORE: /* ..., value ==> ... */
- case ICMD_LSTORE:
- case ICMD_FSTORE:
- case ICMD_DSTORE:
- case ICMD_COPY:
- case ICMD_MOVE:
-
- emit_copy(jd, iptr);
- break;
-
- case ICMD_ASTORE:
- if (!(iptr->flags.bits & INS_FLAG_RETADDR))
- emit_copy(jd, iptr);
- break;
-
-
- /* pop/dup/swap operations ********************************************/
-
- /* attention: double and longs are only one entry in CACAO ICMDs */
-
- case ICMD_POP: /* ..., value ==> ... */
- case ICMD_POP2: /* ..., value, value ==> ... */
- break;
-
-
/* integer operations *************************************************/
case ICMD_INEG: /* ..., value ==> ..., - value */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
emit_nullpointer_check(cd, iptr, s1);
- M_ILD(d, s1, OFFSET(java_arrayheader, size));
+ M_ILD(d, s1, OFFSET(java_array_t, size));
emit_store_dst(jd, iptr, d);
break;
/* implicit null-pointer check */
emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP3);
- M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray, data[0]));
+ M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray_t, data[0]));
emit_store_dst(jd, iptr, d);
break;
emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP3);
M_AADD(s2, REG_ITMP3, REG_ITMP3);
- M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
+ M_SLDU(d, REG_ITMP3, OFFSET(java_chararray_t, data[0]));
emit_store_dst(jd, iptr, d);
break;
emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP3);
M_AADD(s2, REG_ITMP3, REG_ITMP3);
- M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray, data[0]));
+ M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray_t, data[0]));
emit_store_dst(jd, iptr, d);
break;
emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 2, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
- M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
+ M_ILD(d, REG_ITMP3, OFFSET(java_intarray_t, data[0]));
emit_store_dst(jd, iptr, d);
break;
emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 3, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
- M_LDX(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
+ M_LDX(d, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
emit_store_dst(jd, iptr, d);
break;
emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 2, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
- M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
+ M_FLD(d, REG_ITMP3, OFFSET(java_floatarray_t, data[0]));
emit_store_dst(jd, iptr, d);
break;
emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 3, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
- M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
+ M_DLD(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
emit_store_dst(jd, iptr, d);
break;
emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
- M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
+ M_ALD(d, REG_ITMP3, OFFSET(java_objectarray_t, data[0]));
emit_store_dst(jd, iptr, d);
break;
emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
- M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+ M_BST(s3, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
break;
case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
M_AADD(s2, s1, REG_ITMP1);
M_AADD(s2, REG_ITMP1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
- M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
+ M_SST(s3, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
break;
case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
M_ASLL_IMM(s2, 2, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
- M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
+ M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
break;
case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
M_ASLL_IMM(s2, 3, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
- M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
+ M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray_t, data[0]));
break;
case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
M_ASLL_IMM(s2, 2, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_FTMP1);
- M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
+ M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
break;
case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
M_ASLL_IMM(s2, 3, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_FTMP1);
- M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
+ M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
break;
M_MOV(s1, REG_OUT0);
M_MOV(s3, REG_OUT1);
- disp = dseg_add_functionptr(cd, BUILTIN_canstore);
+ disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
M_ALD(REG_ITMP3, REG_PV, disp);
M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
M_NOP;
- emit_exception_check(cd, iptr);
+ emit_arraystore_check(cd, iptr);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
/* implicit null-pointer check */
- M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
+ M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
break;
/* implicit null-pointer check */
emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP1);
- M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+ M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
break;
case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP1);
M_AADD(s2, REG_ITMP1, REG_ITMP1);
- M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
+ M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
break;
case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 2, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
- M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
+ M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
break;
case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 3, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
- M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
+ M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray_t, data[0]));
break;
case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
- M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
+ M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
break;
case ICMD_GETSTATIC: /* ... ==> ..., value */
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- uf = iptr->sx.s23.s3.uf;
+ uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
disp = dseg_add_unique_address(cd, uf);
codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
}
else {
- fi = iptr->sx.s23.s3.fmiref->p.field;
+ fi = iptr->sx.s23.s3.fmiref->p.field;
fieldtype = fi->type;
- disp = dseg_add_address(cd, &(fi->value));
+ disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+ codegen_add_patch_ref(cd, PATCHER_clinit, fi->clazz, disp);
}
M_ALD(REG_ITMP1, REG_PV, disp);
case ICMD_PUTSTATIC: /* ..., value ==> ... */
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- uf = iptr->sx.s23.s3.uf;
+ uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
disp = dseg_add_unique_address(cd, uf);
codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
}
else {
- fi = iptr->sx.s23.s3.fmiref->p.field;
+ fi = iptr->sx.s23.s3.fmiref->p.field;
fieldtype = fi->type;
- disp = dseg_add_address(cd, &(fi->value));
+ disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+ codegen_add_patch_ref(cd, PATCHER_clinit, fi->clazz, disp);
}
M_ALD(REG_ITMP1, REG_PV, disp);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
- disp = dseg_add_unique_address(cd, uf);
+ disp = dseg_add_unique_address(cd, uf);
codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
}
else {
fi = iptr->sx.s23.s3.fmiref->p.field;
fieldtype = fi->type;
- disp = dseg_add_address(cd, &(fi->value));
+ disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+ codegen_add_patch_ref(cd, PATCHER_clinit, fi->clazz, disp);
}
M_ALD(REG_ITMP1, REG_PV, disp);
case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- M_INTMOVE(s1, REG_ITMP2_XPTR);
-
-#ifdef ENABLE_VERIFIER
- if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- unresolved_class *uc = iptr->sx.s23.s2.uc;
-
- codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
- }
-#endif /* ENABLE_VERIFIER */
-
disp = dseg_add_functionptr(cd, asm_handle_exception);
M_ALD(REG_ITMP1, REG_PV, disp);
M_JMP(REG_ITMP3_XPC, REG_ITMP1, REG_ZERO);
M_NOP;
M_NOP; /* nop ensures that XPC is less than the end */
/* of basic block */
- ALIGNCODENOP;
- break;
-
- case ICMD_GOTO: /* ... ==> ... */
- case ICMD_RET: /* ... ==> ... */
-
- emit_br(cd, iptr->dst.block);
- ALIGNCODENOP;
- break;
-
- case ICMD_JSR: /* ... ==> ... */
-
- emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
- ALIGNCODENOP;
- break;
-
- case ICMD_IFNULL: /* ..., value ==> ... */
- case ICMD_IFNONNULL:
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
- break;
-
- /* Note: int compares must not branch on the register directly. */
- /* Reason is, that register content is not 32-bit clean. */
-
- case ICMD_IFEQ: /* ..., value ==> ... */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- }
- else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- emit_beq(cd, iptr->dst.block);
- break;
-
- case ICMD_IFLT: /* ..., value ==> ... */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- }
- else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- emit_blt(cd, iptr->dst.block);
- break;
-
- case ICMD_IFLE: /* ..., value ==> ... */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- }
- else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- emit_ble(cd, iptr->dst.block);
- break;
-
- case ICMD_IFNE: /* ..., value ==> ... */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- }
- else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- emit_bne(cd, iptr->dst.block);
- break;
-
- case ICMD_IFGT: /* ..., value ==> ... */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- }
- else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- emit_bgt(cd, iptr->dst.block);
break;
- case ICMD_IFGE: /* ..., value ==> ... */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- }
- else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- emit_bge(cd, iptr->dst.block);
- break;
-
case ICMD_IF_LEQ: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
emit_beq_xcc(cd, iptr->dst.block);
break;
- case ICMD_IF_ICMPEQ: /* 32-bit compare */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_CMP(s1, s2);
- emit_beq(cd, iptr->dst.block);
- break;
-
case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
M_CMP(s1, s2);
emit_bne_xcc(cd, iptr->dst.block);
break;
-
- case ICMD_IF_ICMPNE: /* 32-bit compare */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_CMP(s1, s2);
- emit_bne(cd, iptr->dst.block);
- break;
case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
M_CMP(s1, s2);
emit_blt_xcc(cd, iptr->dst.block);
break;
-
- case ICMD_IF_ICMPLT: /* 32-bit compare */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_CMP(s1, s2);
- emit_blt(cd, iptr->dst.block);
- break;
case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
M_CMP(s1, s2);
emit_bgt_xcc(cd, iptr->dst.block);
break;
-
- case ICMD_IF_ICMPGT: /* 32-bit compare */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_CMP(s1, s2);
- emit_bgt(cd, iptr->dst.block);
- break;
case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
M_CMP(s1, s2);
emit_ble_xcc(cd, iptr->dst.block);
break;
-
- case ICMD_IF_ICMPLE: /* 32-bit compare */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_CMP(s1, s2);
- emit_ble(cd, iptr->dst.block);
- break;
-
case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
M_CMP(s1, s2);
emit_bge_xcc(cd, iptr->dst.block);
break;
-
- case ICMD_IF_ICMPGE: /* 32-bit compare */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_CMP(s1, s2);
- emit_bge(cd, iptr->dst.block);
- break;
-
-
- case ICMD_IRETURN: /* ..., retvalue ==> ... */
- case ICMD_LRETURN:
-
- s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
- M_INTMOVE(s1, REG_RESULT_CALLEE);
- goto nowperformreturn;
-
- case ICMD_ARETURN: /* ..., retvalue ==> ... */
-
- s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
- M_INTMOVE(s1, REG_RESULT_CALLEE);
-
-#ifdef ENABLE_VERIFIER
- if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- unresolved_class *uc = iptr->sx.s23.s2.uc;
-
- codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
- }
-#endif /* ENABLE_VERIFIER */
- goto nowperformreturn;
-
- case ICMD_FRETURN: /* ..., retvalue ==> ... */
- case ICMD_DRETURN:
-
- s1 = emit_load_s1(jd, iptr, REG_FRESULT);
- M_DBLMOVE(s1, REG_FRESULT);
- goto nowperformreturn;
-
- case ICMD_RETURN: /* ... ==> ... */
-
-nowperformreturn:
- {
- s4 i, p;
-
- p = cd->stackframesize;
-
-#if !defined(NDEBUG)
- if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
- emit_verbosecall_exit(jd);
-#endif
-
-#if defined(ENABLE_THREADS)
- if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
- /* XXX jit-c-call */
- disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
- M_ALD(REG_ITMP3, REG_PV, disp);
-
- /* we need to save fp return value (int saved by window) */
-
- switch (iptr->opc) {
- case ICMD_FRETURN:
- case ICMD_DRETURN:
- M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8);
- M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
- M_DST(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8); /* delay */
-
- /* restore the fp return value */
-
- M_DLD(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8);
- break;
- case ICMD_IRETURN:
- case ICMD_LRETURN:
- case ICMD_ARETURN:
- case ICMD_RETURN:
- M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
- M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8); /* delay */
- break;
- default:
- assert(false);
- break;
- }
- }
-#endif
-
-
-
- M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
- M_NOP;
- ALIGNCODENOP;
- }
- break;
case ICMD_TABLESWITCH: /* ..., index ==> ... */
{
if (l == 0) {
M_INTMOVE(s1, REG_ITMP1);
}
- else if (l <= 4095) {
+ else if (-l >= 4096 && -l <= 4095) {
M_ADD_IMM(s1, -l, REG_ITMP1);
}
else {
ICONST(REG_ITMP2, l);
- /* XXX: do I need to truncate s1 to 32-bit ? */
M_SUB(s1, REG_ITMP2, REG_ITMP1);
}
- i = i - l + 1;
+
+ i = i - l + 1; /* number of targets (>0) */
/* range check */
M_NOP;
ALIGNCODENOP;
break;
-
- case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
- {
- s4 i;
- lookup_target_t *lookup;
-
- lookup = iptr->dst.lookup;
-
- i = iptr->sx.s23.s2.lookupcount;
-
- MCODECHECK((i<<2)+8);
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-
- while (--i >= 0) {
- if ((lookup->value >= -4096) && (lookup->value <= 4095)) {
- M_CMP_IMM(s1, lookup->value);
- } else {
- ICONST(REG_ITMP2, lookup->value);
- M_CMP(s1, REG_ITMP2);
- }
- emit_beq(cd, lookup->target.block);
- ++lookup;
- }
-
- emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
- ALIGNCODENOP;
- break;
- }
-
+ // XXX This is the old builtin invocation containing some
+ // special argument handling code, port me!
case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
bte = iptr->sx.s23.s3.bte;
#else
assert(md->argfltreguse == 0);
#endif
-
- goto gen_method;
-
- case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
- case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
- case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
- case ICMD_INVOKEINTERFACE:
-
- if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- lm = NULL;
- um = iptr->sx.s23.s3.um;
- md = um->methodref->parseddesc.md;
- }
- else {
- lm = iptr->sx.s23.s3.fmiref->p.method;
- um = NULL;
- md = lm->parseddesc;
- }
-gen_method:
- s3 = md->paramcount;
-
- MCODECHECK((s3 << 1) + 64);
-
- /* copy arguments to registers or stack location */
- for (s3 = s3 - 1; s3 >= 0; s3--) {
- var = VAR(iptr->sx.s23.s2.args[s3]);
- d = md->params[s3].regoff;
-
- if (var->flags & PREALLOC)
- continue;
+XXXXXX
if (IS_INT_LNG_TYPE(var->type)) {
if (!md->params[s3].inmemory) {
s1 = emit_load(jd, iptr, var, d);
M_STX(s1, REG_SP, JITSTACK + d);
}
}
- else {
-#ifdef BUILTIN_FLOAT_ARGS
- if (iptr->opc == ICMD_BUILTIN)
- continue;
-#endif
-
- if (!md->params[s3].inmemory) {
- s1 = emit_load(jd, iptr, var, d);
- if (IS_2_WORD_TYPE(var->type))
- M_DMOV(s1, d);
- else
- M_FMOV(s1, d);
- }
- else {
- s1 = emit_load(jd, iptr, var, REG_FTMP1);
- M_DST(s1, REG_SP, JITSTACK + d);
- }
- }
}
+XXXXXX
- switch (iptr->opc) {
- case ICMD_BUILTIN:
+ case ICMD_BUILTIN:
+ bte = iptr->sx.s23.s3.bte;
+ if (bte->stub == NULL) {
disp = dseg_add_functionptr(cd, bte->fp);
+ }
+ else {
+ disp = dseg_add_functionptr(cd, bte->stub);
+ }
- M_ALD(REG_PV_CALLER, REG_PV, disp); /* built-in-function pointer */
+ M_ALD(REG_PV_CALLER, REG_PV, disp); /* built-in-function pointer */
- /* XXX jit-c-call */
- /* generate the actual call */
-
- M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
- M_NOP;
- disp = (s4) (cd->mcodeptr - cd->mcodebase);
- /* REG_RA holds the value of the jmp instruction, therefore +8 */
- M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
-
- emit_exception_check(cd, iptr);
- if (md->returntype.type == TYPE_FLT) {
- /* special handling for float return value in %f0 */
- M_FMOV_INTERN(0,1);
- }
- break;
+ /* XXX jit-c-call */
+ /* generate the actual call */
+
+ M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+ M_NOP;
- case ICMD_INVOKESPECIAL:
- emit_nullpointer_check(cd, iptr, REG_OUT0);
- /* fall-through */
+ if (md->returntype.type == TYPE_FLT) {
+ /* special handling for float return value in %f0 */
+ M_FMOV_INTERN(0,1);
+ }
+ break;
- case ICMD_INVOKESTATIC:
- if (lm == NULL) {
- disp = dseg_add_unique_address(cd, NULL);
+ case ICMD_INVOKESPECIAL:
+ emit_nullpointer_check(cd, iptr, REG_OUT0);
+ /* fall-through */
- codegen_add_patch_ref(cd, PATCHER_invokestatic_special,
- um, disp);
- }
- else
- disp = dseg_add_address(cd, lm->stubroutine);
+ case ICMD_INVOKESTATIC:
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ um = iptr->sx.s23.s3.um;
+ disp = dseg_add_unique_address(cd, NULL);
- M_ALD(REG_PV_CALLER, REG_PV, disp); /* method pointer in pv */
-
- /* generate the actual call */
-
- M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
- M_NOP;
- disp = (s4) (cd->mcodeptr - cd->mcodebase);
- /* REG_RA holds the value of the jmp instruction, therefore +8 */
- M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
- break;
+ codegen_add_patch_ref(cd, PATCHER_invokestatic_special,
+ um, disp);
+ }
+ else {
+ lm = iptr->sx.s23.s3.fmiref->p.method;
+ disp = dseg_add_address(cd, lm->stubroutine);
+ }
- case ICMD_INVOKEVIRTUAL:
- emit_nullpointer_check(cd, iptr, REG_OUT0);
+ M_ALD(REG_PV_CALLER, REG_PV, disp); /* method pointer in pv */
+
+ /* generate the actual call */
+
+ M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+ M_NOP;
+ break;
- if (lm == NULL) {
- codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
+ case ICMD_INVOKEVIRTUAL:
+ emit_nullpointer_check(cd, iptr, REG_OUT0);
- s1 = 0;
- }
- else
- s1 = OFFSET(vftbl_t, table[0]) +
- sizeof(methodptr) * lm->vftblindex;
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ um = iptr->sx.s23.s3.um;
+ codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
- /* implicit null-pointer check */
- M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_objectheader, vftbl));
- M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
-
- /* generate the actual call */
-
- M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
- M_NOP;
- disp = (s4) (cd->mcodeptr - cd->mcodebase);
- /* REG_RA holds the value of the jmp instruction, therefore +8 */
- M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
- break;
+ s1 = 0;
+ }
+ else {
+ lm = iptr->sx.s23.s3.fmiref->p.method;
+ s1 = OFFSET(vftbl_t, table[0]) +
+ sizeof(methodptr) * lm->vftblindex;
+ }
- case ICMD_INVOKEINTERFACE:
- emit_nullpointer_check(cd, iptr, REG_OUT0);
+ /* implicit null-pointer check */
+ M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_object_t, vftbl));
+ M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
+
+ /* generate the actual call */
+
+ M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+ M_NOP;
+ break;
- if (lm == NULL) {
- codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
+ case ICMD_INVOKEINTERFACE:
+ emit_nullpointer_check(cd, iptr, REG_OUT0);
- s1 = 0;
- s2 = 0;
- }
- else {
- s1 = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * lm->class->index;
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ um = iptr->sx.s23.s3.um;
+ codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
- s2 = sizeof(methodptr) * (lm - lm->class->methods);
- }
+ s1 = 0;
+ s2 = 0;
+ }
+ else {
+ lm = iptr->sx.s23.s3.fmiref->p.method;
+ s1 = OFFSET(vftbl_t, interfacetable[0]) -
+ sizeof(methodptr*) * lm->clazz->index;
- /* implicit null-pointer check */
- M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_objectheader, vftbl));
- M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
- M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
-
- /* generate the actual call */
-
- M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
- M_NOP;
- disp = (s4) (cd->mcodeptr - cd->mcodebase);
- /* REG_RA holds the value of the jmp instruction, therefore +8 */
- M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
- break;
+ s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
}
- /* store return value */
+ /* implicit null-pointer check */
+ M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_object_t, vftbl));
+ M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
+ M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
- d = md->returntype.type;
+ /* generate the actual call */
+
+ M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+ M_NOP;
+ break;
- if (d != TYPE_VOID) {
- if (IS_INT_LNG_TYPE(d)) {
- s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
- M_INTMOVE(REG_RESULT_CALLER, s1);
- }
- else {
- s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
- if (IS_2_WORD_TYPE(d)) {
- M_DBLMOVE(REG_FRESULT, s1);
- } else {
- M_FLTMOVE(REG_FRESULT, s1);
- }
+XXXXXX
+ /* store return value */
+ else {
+ s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
+ if (IS_2_WORD_TYPE(d)) {
+ emit_dmove(cd, REG_FRESULT, s1);
+ } else {
+ emit_fmove(cd, REG_FRESULT, s1);
}
- emit_store_dst(jd, iptr, s1);
}
- break;
-
+XXXXX
case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
/* val.a: (classinfo*) superclass */
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 */
if (super == NULL) {
emit_label_beqz(cd, BRANCH_LABEL_1, s1);
- cr = iptr->sx.s23.s3.c.ref;
+ constant_classref *cr = iptr->sx.s23.s3.c.ref;
disp = dseg_add_unique_s4(cd, 0); /* super->flags */
codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
if (super == NULL) {
- cr = iptr->sx.s23.s3.c.ref;
+ constant_classref *cr = iptr->sx.s23.s3.c.ref;
codegen_add_patch_ref(cd, PATCHER_checkcast_interface,
cr, 0);
emit_label_beqz(cd, BRANCH_LABEL_3, s1);
}
- M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
+ M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
M_ILD(REG_ITMP3, REG_ITMP2,
OFFSET(vftbl_t, interfacetablelength));
M_ADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
if (super == NULL) {
emit_label(cd, BRANCH_LABEL_2);
- cr = iptr->sx.s23.s3.c.ref;
+ constant_classref *cr = iptr->sx.s23.s3.c.ref;
disp = dseg_add_unique_address(cd, NULL);
codegen_add_patch_ref(cd,
emit_label_beqz(cd, BRANCH_LABEL_5, s1);
}
- M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
+ M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
M_ALD(REG_ITMP3, REG_PV, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
M_SUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
M_ALD(REG_ITMP3, REG_PV, disp);
M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
/* } */
M_CMP(REG_ITMP3, REG_ITMP2);
emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1);
disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- cr = iptr->sx.s23.s3.c.ref;
+ constant_classref *cr = iptr->sx.s23.s3.c.ref;
disp = dseg_add_unique_address(cd, NULL);
codegen_add_patch_ref(cd, PATCHER_builtin_arraycheckcast,
supervftbl = super->vftbl;
}
- 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);
if (s1 == d) {
if (super == NULL) {
emit_label_beqz(cd, BRANCH_LABEL_1, s1);
- cr = iptr->sx.s23.s3.c.ref;
+ constant_classref *cr = iptr->sx.s23.s3.c.ref;
disp = dseg_add_unique_s4(cd, 0); /* super->flags */
codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
if (super == NULL) {
- cr = iptr->sx.s23.s3.c.ref;
+ constant_classref *cr = iptr->sx.s23.s3.c.ref;
codegen_add_patch_ref(cd, PATCHER_instanceof_interface,
cr, 0);
emit_label_beqz(cd, BRANCH_LABEL_3, s1);
}
- M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
+ M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
M_CMP_IMM(REG_ITMP3, superindex);
M_BLE(4);
if (super == NULL) {
emit_label(cd, BRANCH_LABEL_2);
- cr = iptr->sx.s23.s3.c.ref;
+ constant_classref *cr = iptr->sx.s23.s3.c.ref;
disp = dseg_add_unique_address(cd, NULL);
codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_class,
emit_label_beqz(cd, BRANCH_LABEL_5, s1);
}
- M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
+ M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
M_ALD(REG_ITMP2, REG_PV, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
M_CMP(REG_ITMP1, REG_ITMP2);
M_XCMOVULE_IMM(1, d);
break;
default:
- exceptions_throw_internalerror("Unknown ICMD %d during code generation",
- iptr->opc);
- return false;
-
+ vm_abort("Unknown ICMD %d during code generation", iptr->opc);
} /* switch */
-
- } /* for instruction */
-
- MCODECHECK(64);
-
- /* At the end of a basic block we may have to append some nops,
- because the patcher stub calling code might be longer than the
- actual instruction. So codepatching does not change the
- following block unintentionally. */
-
- if (cd->mcodeptr < cd->lastmcodeptr) {
- while (cd->mcodeptr < cd->lastmcodeptr) {
- M_NOP;
- }
- }
-
- } /* if (bptr -> flags >= BBREACHED) */
- } /* for basic block */
-
- dseg_createlinenumbertable(cd);
-
- /* generate stubs */
-
- emit_patcher_stubs(jd);
-
- /* everything's ok */
-
- return true;
}
}
+/* codegen_emit_stub_builtin ***************************************************
+
+ Creates a stub routine which calls a builtin function.
+
+*******************************************************************************/
+
+void codegen_emit_stub_builtin(jitdata *jd, builtintable_entry *bte)
+{
+ codeinfo *code;
+ codegendata *cd;
+ methoddesc *md;
+ s4 i;
+ s4 disp;
+ s4 s1, s2;
+
+ /* get required compiler data */
+ code = jd->code;
+ cd = jd->cd;
+
+ /* set some variables */
+ md = bte->md;
+
+ /* calculate stack frame size */
+ cd->stackframesize =
+ WINSAVE_CNT +
+ ABIPARAMS_CNT +
+ FLT_ARG_CNT +
+ sizeof(stackframeinfo_t) / SIZEOF_VOID_P +
+ 4; /* 4 arguments or return value */
+
+
+ /* keep stack 16-byte aligned (ABI requirement) */
+
+ if (cd->stackframesize & 1)
+ cd->stackframesize++;
+
+ /* create method header */
+ (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
+ (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
+ (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
+ (void) dseg_add_unique_s4(cd, 0); /* IntSave */
+ (void) dseg_add_unique_s4(cd, 0); /* FltSave */
+
+ /* generate stub code */
+ M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
+
+#if defined(ENABLE_GC_CACAO)
+ /* Save callee saved integer registers in stackframeinfo (GC may
+ need to recover them during a collection). */
+
+ disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
+ OFFSET(stackframeinfo_t, intregs) + BIAS;
+
+ for (i = 0; i < INT_SAV_CNT; i++)
+ M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
+#endif
+
+ for (i = 0; i < md->paramcount; i++) {
+ s1 = md->params[i].regoff;
+
+ switch (md->paramtypes[i].type) {
+ case TYPE_INT:
+ case TYPE_LNG:
+ case TYPE_ADR:
+ break;
+ case TYPE_FLT:
+ case TYPE_DBL:
+ M_DST(s1, REG_SP, JITSTACK + i * 8);
+ break;
+ }
+ }
+
+ /* create dynamic stack info */
+
+ M_AADD_IMM(REG_SP, BIAS + cd->stackframesize * 8, REG_OUT0); /* data sp*/
+ M_MOV(REG_PV_CALLEE, REG_OUT1); /* PV */
+ M_MOV(REG_FP, REG_OUT2); /* java sp */
+ M_MOV(REG_RA_CALLEE, REG_OUT3); /* ra */
+
+ disp = dseg_add_functionptr(cd, codegen_stub_builtin_enter);
+ M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
+ M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
+ M_NOP; /* XXX fill me! */
+
+
+ /* builtins are allowed to have 5 arguments max */
+
+ assert(md->paramcount <= 5);
+
+ /* copy arguments into position */
+
+ for (i = 0; i < md->paramcount; i++) {
+ assert(!md->params[i].inmemory);
+
+ s1 = md->params[i].regoff;
+
+ switch (md->paramtypes[i].type) {
+ case TYPE_INT:
+ case TYPE_LNG:
+ case TYPE_ADR:
+ M_MOV(REG_WINDOW_TRANSPOSE(abi_registers_integer_argument[i]), s1);
+ break;
+ case TYPE_FLT:
+ case TYPE_DBL:
+ M_DLD(s1, REG_SP, JITSTACK + i * 8);
+ break;
+ }
+
+ }
+
+ /* call the builtin function */
+
+ disp = dseg_add_functionptr(cd, bte->fp);
+ M_ALD(REG_ITMP3, REG_PV_CALLEE, disp); /* load adress of builtin */
+ M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call builtin */
+ M_NOP; /* delay slot */
+
+
+ /* save return value */
+
+ if (md->returntype.type != TYPE_VOID) {
+ if (IS_INT_LNG_TYPE(md->returntype.type))
+ M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
+ else
+ M_DST(REG_FRESULT, REG_SP, CSTACK);
+ }
+
+
+ /* remove native stackframe info */
+
+ M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
+ disp = dseg_add_functionptr(cd, codegen_stub_builtin_exit);
+ M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
+ M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
+ M_NOP;
+
+ /* restore float return value, int return value already in our return reg */
+
+ if (md->returntype.type != TYPE_VOID) {
+ if (IS_FLT_DBL_TYPE(md->returntype.type)) {
+ if (IS_2_WORD_TYPE(md->returntype.type))
+ M_DLD(REG_FRESULT, REG_SP, CSTACK);
+ else
+ M_FLD(REG_FRESULT, REG_SP, CSTACK);
+ }
+ }
+
+
+#if defined(ENABLE_GC_CACAO)
+ /* Restore callee saved integer registers from stackframeinfo (GC
+ might have modified them during a collection). */
+
+ disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
+ OFFSET(stackframeinfo_t, intregs) + BIAS;
+
+ for (i = 0; i < INT_SAV_CNT; i++)
+ M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
+#endif
+
+ /* return */
+ M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
+ M_NOP;
+
+ /* assert(0); */
+}
+
+
/* codegen_emit_stub_native ****************************************************
Emits a stub routine which calls a native method.
sizeof(stackframeinfo) / SIZEOF_VOID_P +
sizeof(localref_table) / SIZEOF_VOID_P +
md->paramcount + /* for saving arguments over calls */
- nmd->memuse + /* nmd knows about the native stackframe layout */
+ nmd->memuse + /* nmd->memuse includes the (6) abi params */
WINSAVE_CNT;
(void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
(void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* 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 */
funcdisp = dseg_add_functionptr(cd, f);
-#if !defined(WITH_STATIC_CLASSPATH)
- if (f == NULL) {
+ if (f == NULL)
codegen_add_patch_ref(cd, PATCHER_resolve_native, m, funcdisp);
- }
-#endif
- /* save float argument registers (into abi parameter slots) */
+ /* save float argument registers */
assert(ABIPARAMS_CNT >= FLT_ARG_CNT);
M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
M_NOP; /* XXX fill me! */
+ /* remember class argument */
+
+ if (m->flags & ACC_STATIC)
+ M_MOV(REG_RESULT_CALLER, REG_ITMP3);
+
/* keep float arguments on stack */
#if 0
for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
s1 = REG_WINDOW_TRANSPOSE(s1);
if (!nmd->params[j].inmemory) {
- s2 = nat_argintregs[nmd->params[j].regoff];
+ s2 = nmd->params[j].regoff;
M_INTMOVE(s1, s2);
} else {
/* nmd's regoff is relative to the start of the param array */
}
s1 = md->params[i].regoff + cd->stackframesize * 8;
- s2 = BIAS + WINSAVE_CNT + 8 + nmd->params[j].regoff;
+ s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
M_ALD(REG_ITMP1, REG_SP, CSTACK + s1);
M_AST(REG_ITMP1, REG_SP, s2);
}
}
else {
- s1 = md->params[i].regoff + cd->stackframesize * 8;
+ s1 = md->params[i].regoff;
if (!nmd->params[j].inmemory) {
/* JIT stack -> NAT reg */
- s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
- M_DLD(s2, REG_SP, s1);
+ s2 = nmd->params[j].regoff;
+ M_DLD(s2, REG_FP, JITSTACK + s1);
}
else {
/* JIT stack -> NAT stack */
- s2 = nmd->params[j].regoff - 6 * 8;
+ s2 = WINSAVE_CNT * 8 + nmd->params[j].regoff;
/* The FTMP register may already be loaded with args */
/* we know $f0 is unused because of the env pointer */
- M_DLD(REG_F0, REG_SP, CSTACK + s1);
- M_DST(REG_F0, REG_SP, CSTACK + s2);
+ M_DLD(REG_F0, REG_FP, JITSTACK + s1);
+ M_DST(REG_F0, REG_SP, BIAS + s2);
}
}
}
/* put class into second argument register */
- if (m->flags & ACC_STATIC) {
- disp = dseg_add_address(cd, m->class);
- M_ALD(REG_OUT1, REG_PV_CALLEE, disp);
- }
+ if (m->flags & ACC_STATIC)
+ M_MOV(REG_ITMP3, REG_OUT1);
/* put env into first argument register */
- disp = dseg_add_address(cd, _Jv_env);
+ disp = dseg_add_address(cd, VM_get_jnienv());
M_ALD(REG_OUT0, REG_PV_CALLEE, disp);
/* do the native function call */