Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: emitfuncs.c 4398 2006-01-31 23:43:08Z twisti $
-
*/
#include "md-abi.h"
#include "vm/jit/powerpc64/codegen.h"
-#include "vmcore/options.h"
+#include "threads/lock-common.h"
#include "vm/builtin.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
+#include "vm/exceptions.h"
#include "vm/vm.h"
+
+#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
-#include "vm/exceptions.h"
+#include "vm/jit/emit-common.h"
+#include "vm/jit/jit.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/lock.h"
-#endif
+#include "vmcore/options.h"
/* emit_load *******************************************************************
if (src->flags & INMEMORY) {
COUNT_SPILLS;
- disp = src->vv.regoff * 8;
+ disp = src->vv.regoff;
if (IS_FLT_DBL_TYPE(src->type)) {
M_DLD(tempreg, REG_SP, disp);
COUNT_SPILLS;
if (IS_FLT_DBL_TYPE(dst->type)) {
- M_DST(d, REG_SP, dst->vv.regoff * 8);
+ M_DST(d, REG_SP, dst->vv.regoff);
}
else {
- M_LST(d, REG_SP, dst->vv.regoff * 8);
+ M_LST(d, REG_SP, dst->vv.regoff);
}
}
}
*******************************************************************************/
-void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst)
+void emit_copy(jitdata *jd, instruction *iptr)
{
- codegendata *cd;
- registerdata *rd;
- s4 s1, d;
+ codegendata *cd;
+ varinfo *src;
+ varinfo *dst;
+ s4 s1, d;
/* get required compiler data */
cd = jd->cd;
- rd = jd->rd;
+
+ /* get source and destination variables */
+
+ src = VAROP(iptr->s1);
+ dst = VAROP(iptr->dst);
if ((src->vv.regoff != dst->vv.regoff) ||
((src->flags ^ dst->flags) & INMEMORY)) {
+ if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
+ /* emit nothing, as the value won't be used anyway */
+ return;
+ }
+
/* If one of the variables resides in memory, we can eliminate
the register move from/to the temporary register with the
order of getting the destination register and the load. */
if (IS_INMEMORY(src->flags)) {
- d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
+ d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
s1 = emit_load(jd, iptr, src, d);
}
else {
s1 = emit_load(jd, iptr, src, REG_IFTMP);
- d = codegen_reg_of_var(iptr->opc, dst, s1);
+ d = codegen_reg_of_var(iptr->opc, dst, s1);
}
if (s1 != d) {
*******************************************************************************/
-void emit_verbosecall_enter (jitdata *jd)
+#if !defined(NDEBUG)
+void emit_verbosecall_enter(jitdata *jd)
{
methodinfo *m;
codegendata *cd;
t = md->paramtypes[p].type;
if (IS_INT_LNG_TYPE(t)) {
if (!md->params[p].inmemory) { /* Param in Arg Reg */
- M_LST(rd->argintregs[md->params[p].regoff], REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
+ M_LST(md->params[p].regoff, REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
} else { /* Param on Stack */
- s1 = (md->params[p].regoff + cd->stackframesize) * 8 + stack_size;
+ s1 = md->params[p].regoff + cd->stackframesize * 8 + stack_size;
M_LLD(REG_ITMP2, REG_SP, s1);
M_LST(REG_ITMP2, REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
}
} else { /* IS_FLT_DBL_TYPE(t) */
if (!md->params[p].inmemory) { /* in Arg Reg */
- s1 = rd->argfltregs[md->params[p].regoff];
+ s1 = md->params[p].regoff;
M_DST(s1, REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
} else { /* on Stack */
/* this should not happen */
for (p = 0; (p < TRACE_ARGS_NUM) && (p < md->paramcount); p++) {
t = md->paramtypes[p].type;
if (IS_INT_LNG_TYPE(t)) {
- M_LLD(rd->argintregs[p], REG_SP,LA_SIZE + PA_SIZE + 8 + p * 8);
+ M_LLD(abi_registers_integer_argument[p], REG_SP,LA_SIZE + PA_SIZE + 8 + p * 8);
} else { /* Float/Dbl */
if (!md->params[p].inmemory) { /* Param in Arg Reg */
/* use reserved Place on Stack (sp + 5 * 16) to copy */
/* float/double arg reg to int reg */
- s1 = rd->argfltregs[md->params[p].regoff];
- M_MOV(s1, rd->argintregs[p]);
+ s1 = md->params[p].regoff;
+ M_MOV(s1, abi_registers_integer_argument[p]);
} else {
assert(0);
}
if (IS_INT_LNG_TYPE(t)) {
if (!md->params[p].inmemory) { /* Param in Arg Reg */
/* restore integer argument registers */
- M_LLD(rd->argintregs[p], REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
+ M_LLD(abi_registers_integer_argument[p], REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
} else {
assert(0); /* TODO: implement this */
}
} else { /* FLT/DBL */
if (!md->params[p].inmemory) { /* Param in Arg Reg */
- M_DLD(rd->argfltregs[md->params[p].regoff], REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
+ M_DLD(md->params[p].regoff, REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
} else {
assert(0); /* this shoudl never happen */
}
/* mark trace code */
M_NOP;
}
+#endif
/* emit_verbosecall_exit ******************************************************
*******************************************************************************/
+#if !defined(NDEBUG)
void emit_verbosecall_exit(jitdata *jd)
{
methodinfo *m;
M_NOP;
}
+#endif
+
/* emit_branch *****************************************************************
/* if the long-branches flag isn't set yet, do it */
if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
- log_println("setting error");
cd->flags |= (CODEGENDATA_FLAG_ERROR |
CODEGENDATA_FLAG_LONGBRANCHES);
}
/* if the long-branches flag isn't set yet, do it */
if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
- log_println("setting error");
cd->flags |= (CODEGENDATA_FLAG_ERROR |
CODEGENDATA_FLAG_LONGBRANCHES);
}
- log_println("generating long-branch");
branchdisp --; /* we jump from the second instruction */
switch (condition) {
if (checkbounds) {
#define SOFTEX 0
#if SOFTEX
- M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+ M_ILD(REG_ITMP3, s1, OFFSET(java_array_t, size));
M_CMPU(s2, REG_ITMP3);
codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
BRANCH_NOPS;
#else
- M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+ M_ILD(REG_ITMP3, s1, OFFSET(java_array_t, size));
M_CMPU(s2, REG_ITMP3);
M_BLT(1);
/* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
/* check code segment size */
- MCODECHECK(16);
+ MCODECHECK(32);
/* Get machine code which is patched back in later. The
call is 1 instruction word long. */
cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
/* create stack frame - keep stack 16-byte aligned */
-
M_AADD_IMM(REG_SP, -8 * 8, REG_SP);
/* calculate return address and move it onto the stack */
-
M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
M_AST_INTERN(REG_ITMP3, REG_SP, 5 * 8);
#endif
/* move machine code onto stack */
-
disp = dseg_add_s4(cd, mcode);
M_ILD(REG_ITMP3, REG_PV, disp);
M_IST_INTERN(REG_ITMP3, REG_SP, 3 * 8);
/* move class/method/field reference onto stack */
-
disp = dseg_add_address(cd, pref->ref);
M_ALD(REG_ITMP3, REG_PV, disp);
M_AST_INTERN(REG_ITMP3, REG_SP, 2 * 8);
/* move data segment displacement onto stack */
-
disp = dseg_add_s4(cd, pref->disp);
M_ILD(REG_ITMP3, REG_PV, disp);
M_IST_INTERN(REG_ITMP3, REG_SP, 1 * 8);
- M_NOP;
/* move patcher function pointer onto stack */
-
disp = dseg_add_functionptr(cd, pref->patcher);
M_ALD(REG_ITMP3, REG_PV, disp);
M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 8);
-#if 0
- disp = dseg_add_functionptr(cd, asm_patcher_wrapper);
- M_ALD(REG_ITMP3, REG_PV, disp);
- M_MTCTR(REG_ITMP3);
- M_RTS;
-#else
if (targetdisp == 0) {
targetdisp = ((u4 *) cd->mcodeptr) - ((u4 *) cd->mcodebase);
(((u4 *) cd->mcodeptr) + 1);
M_BR(disp);
}
-#endif
}
}
-/* emit_replacement_stubs ******************************************************
+/* emit_trap *******************************************************************
- Generates the code for the replacement stubs.
+ Emit a trap instruction and return the original machine code.
*******************************************************************************/
-#if defined(ENABLE_REPLACEMENT)
-void emit_replacement_stubs(jitdata *jd)
+uint32_t emit_trap(codegendata *cd)
{
- codegendata *cd;
- codeinfo *code;
- rplpoint *replacementpoint;
- s4 disp;
- s4 i;
-#if !defined(NDEBUG)
- u1 *savedmcodeptr;
-#endif
-
- /* get required compiler data */
-
- cd = jd->cd;
- code = jd->code;
-
- replacementpoint = jd->code->rplpoints;
-
- for (i = 0; i < code->rplpointcount; ++i, ++replacementpoint) {
- /* do not generate stubs for non-trappable points */
-
- if (replacementpoint->flags & RPLPOINT_FLAG_NOTRAP)
- continue;
-
-
- /* check code segment size */
+ uint32_t mcode;
- MCODECHECK(100);
+ /* Get machine code which is patched back in later. The
+ trap is 1 instruction word long. */
-#if !defined(NDEBUG)
- savedmcodeptr = cd->mcodeptr;
-#endif
- /* create stack frame - keep 16-byte aligned */
-
- M_AADD_IMM(REG_SP, -4 * 8, REG_SP);
-
- /* push address of `rplpoint` struct */
-
- disp = dseg_add_address(cd, replacementpoint);
- M_ALD(REG_ITMP3, REG_PV, disp);
- M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 8);
-
- /* jump to replacement function */
-
- disp = dseg_add_functionptr(cd, asm_replacement_out);
- M_ALD(REG_ITMP3, REG_PV, disp);
- M_MTCTR(REG_ITMP3);
- M_RTS;
+ mcode = *((uint32_t *) cd->mcodeptr);
- assert((cd->mcodeptr - savedmcodeptr) == 4*REPLACEMENT_STUB_SIZE);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_PATCHER);
-#if 0
- /* note start of stub code */
-
- replacementpoint->outcode = (u1 *) (cd->mcodeptr - cd->mcodebase);
-
- /* make machine code for patching */
-
- savedmcodeptr = cd->mcodeptr;
- cd->mcodeptr = (u1 *) &(replacementpoint->mcode) + 1 /* big-endian */;
-
- disp = (ptrint)((s4*)replacementpoint->outcode - (s4*)replacementpoint->pc) - 1;
- M_BR(disp);
-
- cd->mcodeptr = savedmcodeptr;
-
- /* create stack frame - keep 16-byte aligned */
-
- M_AADD_IMM(REG_SP, -4 * 4, REG_SP);
-
- /* push address of `rplpoint` struct */
-
- disp = dseg_add_unique_address(cd, replacementpoint);
- M_ALD(REG_ITMP3, REG_PV, disp);
- M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 4);
-
- /* jump to replacement function */
-
- disp = dseg_add_functionptr(cd, asm_replacement_out);
- M_ALD(REG_ITMP3, REG_PV, disp);
- M_MTCTR(REG_ITMP3);
- M_RTS;
-#endif
- }
+ return mcode;
}
-#endif /* define(ENABLE_REPLACEMENT) */
+
/*
-* These are local overrides for various environment variables in Emacs.
-* Please do not remove this and leave it at the end of the file, where
-* Emacs will automagically detect them.
-* ---------------------------------------------------------------------
-* Local variables:
-* mode: c
-* indent-tabs-mode: t
-* c-basic-offset: 4
-* tab-width: 4
-* End:
-* vim:noexpandtab:sw=4:ts=4:
-*/
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */