Authors: Christian Thalinger
- Changes:
-
$Id: emit.c 4398 2006-01-31 23:43:08Z twisti $
*/
#endif
#include "vm/builtin.h"
+#include "vm/options.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/dseg.h"
-#include "vm/jit/emit.h"
+#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
#include "vm/jit/replace.h"
-/* code generation functions **************************************************/
-
/* emit_load *******************************************************************
Emits a possible load of an operand.
*******************************************************************************/
-s4 emit_load(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
{
codegendata *cd;
s4 reg;
cd = jd->cd;
- if (src->flags & INMEMORY) {
+ if (IS_INMEMORY(src->flags)) {
COUNT_SPILLS;
if (IS_FLT_DBL_TYPE(src->type))
- M_DLD(tempreg, REG_SP, src->regoff * 8);
+ M_DLD(tempreg, REG_SP, src->vv.regoff * 8);
else
- M_LLD(tempreg, REG_SP, src->regoff * 8);
+ M_LLD(tempreg, REG_SP, src->vv.regoff * 8);
reg = tempreg;
- } else
- reg = src->regoff;
+ }
+ else
+ reg = src->vv.regoff;
return reg;
}
-/* emit_load_s1 ****************************************************************
+/* emit_store ******************************************************************
- Emits a possible load of the first source operand.
+ Emit a possible store for the given variable.
*******************************************************************************/
-s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg)
+void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
{
- s4 r;
-
- r = emit_load(jd, iptr, iptr->s1.var, tempreg);
+ codegendata *cd;
- return r;
+ /* get required compiler data */
+
+ cd = jd->cd;
+
+ if (IS_INMEMORY(dst->flags)) {
+ COUNT_SPILLS;
+
+ if (IS_FLT_DBL_TYPE(dst->type))
+ M_DST(d, REG_SP, dst->vv.regoff * 8);
+ else
+ M_LST(d, REG_SP, dst->vv.regoff * 8);
+ }
}
-/* emit_load_s2 ****************************************************************
+/* emit_copy *******************************************************************
- Emits a possible load of the second source operand.
+ Generates a register/memory to register/memory copy.
*******************************************************************************/
-s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg)
+void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst)
{
- s4 r;
+ codegendata *cd;
+ s4 s1, d;
+
+ /* get required compiler data */
+
+ cd = jd->cd;
+
+ 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);
+ 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);
+ }
- r = emit_load(jd, iptr, iptr->sx.s23.s2.var, tempreg);
+ if (s1 != d) {
+ if (IS_FLT_DBL_TYPE(src->type))
+ M_FMOV(s1, d);
+ else
+ M_MOV(s1, d);
+ }
- return r;
+ emit_store(jd, iptr, dst, d);
+ }
}
-/* emit_load_s3 ****************************************************************
+/* emit_iconst *****************************************************************
- Emits a possible load of the third source operand.
+ XXX
*******************************************************************************/
-s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg)
+void emit_iconst(codegendata *cd, s4 d, s4 value)
{
- s4 r;
-
- r = emit_load(jd, iptr, iptr->sx.s23.s3.var, tempreg);
+ s4 disp;
- return r;
+ if ((value >= -32768) && (value <= 32767))
+ M_LDA_INTERN(d, REG_ZERO, value);
+ else {
+ disp = dseg_add_s4(cd, value);
+ M_ILD(d, REG_PV, disp);
+ }
}
-/* emit_store ******************************************************************
+/* emit_lconst *****************************************************************
- Emit a possible store for the given variable.
+ XXX
*******************************************************************************/
-void emit_store(jitdata *jd, instruction *iptr, stackptr dst, s4 d)
+void emit_lconst(codegendata *cd, s4 d, s8 value)
{
- codegendata *cd;
-
- /* get required compiler data */
-
- cd = jd->cd;
-
- if (dst->flags & INMEMORY) {
- COUNT_SPILLS;
+ s4 disp;
- if (IS_FLT_DBL_TYPE(dst->type))
- M_DST(d, REG_SP, dst->regoff * 8);
- else
- M_LST(d, REG_SP, dst->regoff * 8);
+ if ((value >= -32768) && (value <= 32767))
+ M_LDA_INTERN(d, REG_ZERO, value);
+ else {
+ disp = dseg_add_s8(cd, value);
+ M_LLD(d, REG_PV, disp);
}
}
-/* emit_store_dst **************************************************************
+/* emit_arrayindexoutofbounds_check ********************************************
- Emit a possible store for the destination operand.
+ Emit an ArrayIndexOutOfBoundsException check.
*******************************************************************************/
-void emit_store_dst(jitdata *jd, instruction *iptr, s4 d)
+void emit_arrayindexoutofbounds_check(codegendata *cd, s4 s1, s4 s2)
{
- emit_store(jd, iptr, iptr->dst.var, d);
+ if (checkbounds) {
+ M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+ M_CMPULT(s2, REG_ITMP3, REG_ITMP3);
+ M_BEQZ(REG_ITMP3, 0);
+ codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
+ }
}
-void emit_copy(jitdata *jd, instruction *iptr, stackptr src, stackptr dst)
+/* emit_arraystore_check *******************************************************
+
+ Emit an ArrayStoreException check.
+
+*******************************************************************************/
+
+void emit_arraystore_check(codegendata *cd, s4 reg)
{
- codegendata *cd;
- registerdata *rd;
- s4 s1, d;
+ M_BEQZ(reg, 0);
+ codegen_add_arraystoreexception_ref(cd);
+}
- /* get required compiler data */
- cd = jd->cd;
- rd = jd->rd;
+/* emit_classcast_check ********************************************************
- if ((src->regoff != dst->regoff) ||
- ((src->flags ^ dst->flags) & INMEMORY)) {
- d = codegen_reg_of_var(rd, iptr->opc, dst, REG_IFTMP);
- s1 = emit_load(jd, iptr, src, d);
+ Emit a ClassCastException check.
- if (IS_FLT_DBL_TYPE(src->type))
- M_FLTMOVE(s1, d);
- else
- M_INTMOVE(s1, d);
+*******************************************************************************/
- emit_store(jd, iptr, dst, d);
- }
+void emit_classcast_check(codegendata *cd, s4 condition, s4 reg, s4 s1)
+{
+ M_BNEZ(reg, 0);
+ codegen_add_classcastexception_ref(cd, s1);
}
-void emit_iconst(codegendata *cd, s4 d, s4 value)
-{
- s4 disp;
+/* emit_nullpointer_check ******************************************************
- if ((value >= -32768) && (value <= 32767)) {
- M_LDA_INTERN(d, REG_ZERO, value);
- } else {
- disp = dseg_adds4(cd, value);
- M_ILD(d, REG_PV, disp);
- }
-}
+ Emit a NullPointerException check.
+*******************************************************************************/
-void emit_lconst(codegendata *cd, s4 d, s8 value)
+void emit_nullpointer_check(codegendata *cd, s4 reg)
{
- s4 disp;
-
- if ((value >= -32768) && (value <= 32767)) {
- M_LDA_INTERN(d, REG_ZERO, value);
- } else {
- disp = dseg_adds8(cd, value);
- M_LLD(d, REG_PV, disp);
+ if (checknull) {
+ M_BEQZ(reg, 0);
+ codegen_add_nullpointerexception_ref(cd);
}
}
{
codegendata *cd;
registerdata *rd;
- exceptionref *eref;
+ exceptionref *er;
+ s4 branchmpc;
+ s4 targetmpc;
s4 targetdisp;
s4 disp;
targetdisp = 0;
- for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
- gen_resolvebranch(cd->mcodebase + eref->branchpos,
- eref->branchpos, cd->mcodeptr - cd->mcodebase);
+ for (er = cd->exceptionrefs; er != NULL; er = er->next) {
+ /* back-patch the branch to this exception code */
+
+ branchmpc = er->branchpos;
+ targetmpc = cd->mcodeptr - cd->mcodebase;
+
+ md_codegen_patch_branch(cd, branchmpc, targetmpc);
MCODECHECK(100);
ArrayIndexOutOfBoundsException. If so, move index register
into a4. */
- if (eref->reg != -1)
- M_MOV(eref->reg, rd->argintregs[4]);
+ if (er->reg != -1)
+ M_MOV(er->reg, rd->argintregs[4]);
/* calcuate exception address */
- M_LDA(rd->argintregs[3], REG_PV, eref->branchpos - 4);
+ M_LDA(rd->argintregs[3], REG_PV, er->branchpos - 4);
/* move function to call into REG_ITMP3 */
- disp = dseg_add_functionptr(cd, eref->function);
+ disp = dseg_add_functionptr(cd, er->function);
M_ALD(REG_ITMP3, REG_PV, disp);
if (targetdisp == 0) {
codegendata *cd;
codeinfo *code;
rplpoint *rplp;
- u1 *savedmcodeptr;
s4 disp;
s4 i;
+#if !defined(NDEBUG)
+ u1 *savedmcodeptr;
+#endif
/* get required compiler data */
rplp = code->rplpoints;
- for (i = 0; i < code->rplpointcount; ++i, ++rplp) {
- /* check code segment size */
-
- MCODECHECK(100);
+ /* store beginning of replacement stubs */
- /* note start of stub code */
+ code->replacementstubs = (u1*) (cd->mcodeptr - cd->mcodebase);
- rplp->outcode = (u1 *) (ptrint) (cd->mcodeptr - cd->mcodebase);
+ for (i = 0; i < code->rplpointcount; ++i, ++rplp) {
+ /* do not generate stubs for non-trappable points */
- /* make machine code for patching */
+ if (rplp->flags & RPLPOINT_FLAG_NOTRAP)
+ continue;
- savedmcodeptr = cd->mcodeptr;
- cd->mcodeptr = (u1 *) &(rplp->mcode);
+ /* check code segment size */
- disp = (ptrint) ((s4 *) rplp->outcode - (s4 *) rplp->pc) - 1;
- M_BR(disp);
+ MCODECHECK(100);
- cd->mcodeptr = savedmcodeptr;
+#if !defined(NDEBUG)
+ savedmcodeptr = cd->mcodeptr;
+#endif
/* create stack frame - 16-byte aligned */
disp = dseg_add_functionptr(cd, asm_replacement_out);
M_ALD(REG_ITMP3, REG_PV, disp);
M_JMP(REG_ZERO, REG_ITMP3);
+
+ assert((cd->mcodeptr - savedmcodeptr) == 4*REPLACEMENT_STUB_SIZE);
}
}