Authors: Christian Thalinger
- Changes:
-
- $Id: emitfuncs.c 4398 2006-01-31 23:43:08Z twisti $
+ $Id: emit.c 4398 2006-01-31 23:43:08Z twisti $
*/
#include "vm/jit/powerpc/codegen.h"
+#include "mm/memory.h"
#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/options.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_s1 ****************************************************************
-
- Emits a possible load of the first source operand.
-
-*******************************************************************************/
-
-s4 emit_load_s1(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
-{
- codegendata *cd;
- s4 disp;
- s4 reg;
-
- /* get required compiler data */
-
- cd = jd->cd;
-
- if (src->flags & INMEMORY) {
- COUNT_SPILLS;
-
- disp = src->regoff * 4;
-
- if (IS_FLT_DBL_TYPE(src->type)) {
- if (IS_2_WORD_TYPE(src->type))
- M_DLD(tempreg, REG_SP, disp);
- else
- M_FLD(tempreg, REG_SP, disp);
-
- } else {
- if (IS_2_WORD_TYPE(src->type))
- M_LLD(tempreg, REG_SP, disp);
- else
- M_ILD(tempreg, REG_SP, disp);
- }
-
- reg = tempreg;
- } else
- reg = src->regoff;
-
- return reg;
-}
-
-
-/* emit_load_s2 ****************************************************************
+/* emit_load *******************************************************************
- Emits a possible load of the second source operand.
+ Emits a possible load of an operand.
*******************************************************************************/
-s4 emit_load_s2(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
{
- codegendata *cd;
- s4 disp;
- s4 reg;
+ codegendata *cd;
+ s4 disp;
+ s4 reg;
/* get required compiler data */
cd = jd->cd;
- if (src->flags & INMEMORY) {
+ if (IS_INMEMORY(src->flags)) {
COUNT_SPILLS;
- disp = src->regoff * 4;
+ disp = src->vv.regoff * 4;
if (IS_FLT_DBL_TYPE(src->type)) {
if (IS_2_WORD_TYPE(src->type))
M_DLD(tempreg, REG_SP, disp);
else
M_FLD(tempreg, REG_SP, disp);
-
- } else {
- if (IS_2_WORD_TYPE(src->type))
- M_LLD(tempreg, REG_SP, disp);
- else
- M_ILD(tempreg, REG_SP, disp);
}
-
- reg = tempreg;
- } else
- reg = src->regoff;
-
- return reg;
-}
-
-
-/* emit_load_s3 ****************************************************************
-
- Emits a possible load of the third source operand.
-
-*******************************************************************************/
-
-s4 emit_load_s3(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
-{
- codegendata *cd;
- s4 disp;
- s4 reg;
-
- /* get required compiler data */
-
- cd = jd->cd;
-
- if (src->flags & INMEMORY) {
- COUNT_SPILLS;
-
- disp = src->regoff * 4;
-
- if (IS_FLT_DBL_TYPE(src->type)) {
- if (IS_2_WORD_TYPE(src->type))
- M_DLD(tempreg, REG_SP, disp);
- else
- M_FLD(tempreg, REG_SP, disp);
-
- } else {
+ else {
if (IS_2_WORD_TYPE(src->type))
M_LLD(tempreg, REG_SP, disp);
else
}
reg = tempreg;
- } else
- reg = src->regoff;
-
- return reg;
-}
-
-
-/* emit_load_s1_low ************************************************************
-
- Emits a possible load of the low 32-bits of the first long source
- operand.
-
-*******************************************************************************/
-
-s4 emit_load_s1_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
-{
- codegendata *cd;
- s4 disp;
- s4 reg;
-
- assert(src->type == TYPE_LNG);
-
- /* get required compiler data */
-
- cd = jd->cd;
-
- if (src->flags & INMEMORY) {
- COUNT_SPILLS;
-
- disp = src->regoff * 4;
-
- M_ILD(tempreg, REG_SP, disp + 4);
-
- reg = tempreg;
- } else
- reg = GET_LOW_REG(src->regoff);
-
- return reg;
-}
-
-
-/* emit_load_s2_low ************************************************************
-
- Emits a possible load of the low 32-bits of the second long source
- operand.
-
-*******************************************************************************/
-
-s4 emit_load_s2_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
-{
- codegendata *cd;
- s4 disp;
- s4 reg;
-
- assert(src->type == TYPE_LNG);
-
- /* get required compiler data */
-
- cd = jd->cd;
-
- if (src->flags & INMEMORY) {
- COUNT_SPILLS;
-
- disp = src->regoff * 4;
-
- M_ILD(tempreg, REG_SP, disp + 4);
-
- reg = tempreg;
- } else
- reg = GET_LOW_REG(src->regoff);
+ }
+ else
+ reg = src->vv.regoff;
return reg;
}
-/* emit_load_s3_low ************************************************************
+/* emit_load_low ***************************************************************
- Emits a possible load of the low 32-bits of the third long source
- operand.
+ Emits a possible load of the low 32-bits of an operand.
*******************************************************************************/
-s4 emit_load_s3_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
{
codegendata *cd;
s4 disp;
cd = jd->cd;
- if (src->flags & INMEMORY) {
+ if (IS_INMEMORY(src->flags)) {
COUNT_SPILLS;
- disp = src->regoff * 4;
+ disp = src->vv.regoff * 4;
M_ILD(tempreg, REG_SP, disp + 4);
reg = tempreg;
- } else
- reg = GET_LOW_REG(src->regoff);
-
- return reg;
-}
-
-
-/* emit_load_s1_high ***********************************************************
-
- Emits a possible load of the high 32-bits of the first long source
- operand.
-
-*******************************************************************************/
-
-s4 emit_load_s1_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
-{
- codegendata *cd;
- s4 disp;
- s4 reg;
-
- assert(src->type == TYPE_LNG);
-
- /* get required compiler data */
-
- cd = jd->cd;
-
- if (src->flags & INMEMORY) {
- COUNT_SPILLS;
-
- disp = src->regoff * 4;
-
- M_ILD(tempreg, REG_SP, disp);
-
- reg = tempreg;
- } else
- reg = GET_HIGH_REG(src->regoff);
-
- return reg;
-}
-
-
-/* emit_load_s2_high ***********************************************************
-
- Emits a possible load of the high 32-bits of the second long source
- operand.
-
-*******************************************************************************/
-
-s4 emit_load_s2_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
-{
- codegendata *cd;
- s4 disp;
- s4 reg;
-
- assert(src->type == TYPE_LNG);
-
- /* get required compiler data */
-
- cd = jd->cd;
-
- if (src->flags & INMEMORY) {
- COUNT_SPILLS;
-
- disp = src->regoff * 4;
-
- M_ILD(tempreg, REG_SP, disp);
-
- reg = tempreg;
- } else
- reg = GET_HIGH_REG(src->regoff);
+ }
+ else
+ reg = GET_LOW_REG(src->vv.regoff);
return reg;
}
-/* emit_load_s3_high ***********************************************************
+/* emit_load_high **************************************************************
- Emits a possible load of the high 32-bits of the third long source
- operand.
+ Emits a possible load of the high 32-bits of an operand.
*******************************************************************************/
-s4 emit_load_s3_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
{
codegendata *cd;
s4 disp;
cd = jd->cd;
- if (src->flags & INMEMORY) {
+ if (IS_INMEMORY(src->flags)) {
COUNT_SPILLS;
- disp = src->regoff * 4;
+ disp = src->vv.regoff * 4;
M_ILD(tempreg, REG_SP, disp);
reg = tempreg;
- } else
- reg = GET_HIGH_REG(src->regoff);
+ }
+ else
+ reg = GET_HIGH_REG(src->vv.regoff);
return reg;
}
*******************************************************************************/
-void emit_store(jitdata *jd, instruction *iptr, stackptr dst, s4 d)
+void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
{
- codegendata *cd;
+ codegendata *cd;
/* get required compiler data */
cd = jd->cd;
- if (dst->flags & INMEMORY) {
+ if (IS_INMEMORY(dst->flags)) {
COUNT_SPILLS;
if (IS_FLT_DBL_TYPE(dst->type)) {
if (IS_2_WORD_TYPE(dst->type))
- M_DST(d, REG_SP, dst->regoff * 4);
+ M_DST(d, REG_SP, dst->vv.regoff * 4);
else
- M_FST(d, REG_SP, dst->regoff * 4);
-
- } else {
+ M_FST(d, REG_SP, dst->vv.regoff * 4);
+ }
+ else {
if (IS_2_WORD_TYPE(dst->type))
- M_LST(d, REG_SP, dst->regoff * 4);
+ M_LST(d, REG_SP, dst->vv.regoff * 4);
else
- M_IST(d, REG_SP, dst->regoff * 4);
+ M_IST(d, REG_SP, dst->vv.regoff * 4);
}
}
}
/* emit_copy *******************************************************************
- XXX
+ Generates a register/memory to register/memory copy.
*******************************************************************************/
-void emit_copy(jitdata *jd, instruction *iptr, stackptr src, stackptr dst)
+void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst)
{
codegendata *cd;
- registerdata *rd;
s4 s1, d;
/* get required compiler data */
cd = jd->cd;
- rd = jd->rd;
- if (src->type == TYPE_LNG)
- d = codegen_reg_of_var(rd, iptr->opc, dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
- else
- d = codegen_reg_of_var(rd, iptr->opc, dst, REG_IFTMP);
+ if ((src->vv.regoff != dst->vv.regoff) ||
+ (IS_INMEMORY(src->flags ^ dst->flags))) {
- if ((src->regoff != dst->regoff) ||
- ((src->flags ^ dst->flags) & INMEMORY)) {
- s1 = emit_load_s1(jd, iptr, src, d);
+ /* 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)) {
+ if (IS_LNG_TYPE(src->type))
+ d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
+ else
+ d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
+
+ s1 = emit_load(jd, iptr, src, d);
+ }
+ else {
+ if (IS_LNG_TYPE(src->type))
+ s1 = emit_load(jd, iptr, src, REG_ITMP12_PACKED);
+ else
+ s1 = emit_load(jd, iptr, src, REG_IFTMP);
+
+ d = codegen_reg_of_var(iptr->opc, dst, s1);
+ }
if (s1 != d) {
if (IS_FLT_DBL_TYPE(src->type))
if (IS_2_WORD_TYPE(src->type)) {
M_MOV(GET_LOW_REG(s1), GET_LOW_REG(d));
M_MOV(GET_HIGH_REG(s1), GET_HIGH_REG(d));
- } else
+ }
+ else
M_MOV(s1, d);
}
}
}
+/* emit_nullpointer_check ******************************************************
+
+ Emit a NullPointerException check.
+
+*******************************************************************************/
+
+void emit_nullpointer_check(codegendata *cd, s4 reg)
+{
+ if (checknull) {
+ M_TST(reg);
+ M_BEQ(0);
+ codegen_add_nullpointerexception_ref(cd);
+ }
+}
+
+
+/* emit_arrayindexoutofbounds_check ********************************************
+
+ Emit a ArrayIndexOutOfBoundsException check.
+
+*******************************************************************************/
+
+void emit_arrayindexoutofbounds_check(codegendata *cd, s4 s1, s4 s2)
+{
+#if 0
+ if (checkbounds) {
+ M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+ M_CMPU(s2, REG_ITMP3);
+ M_BGE(0);
+ codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
+ }
+#else
+ M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+ M_CMPU(s2, REG_ITMP3);
+ M_BLT(1);
+ M_ALD_INTERN(s2, REG_ZERO, EXCEPTION_LOAD_DISP_ARRAYINDEXOUTOFBOUNDS);
+#endif
+}
+
+
/* emit_exception_stubs ********************************************************
Generates the code for the exception stubs.
{
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);
/* Move the value register to a temporary register, if
there is the need for it. */
- if (eref->reg != -1)
- M_MOV(eref->reg, REG_ITMP1);
+ if (er->reg != -1)
+ M_MOV(er->reg, REG_ITMP1);
/* calcuate exception address */
- M_LDA(REG_ITMP2_XPC, REG_PV, eref->branchpos - 4);
+ M_LDA(REG_ITMP2_XPC, 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 *) (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) + 1; /* big-endian */
+ /* 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 - keep 16-byte aligned */
M_ALD(REG_ITMP3, REG_PV, disp);
M_MTCTR(REG_ITMP3);
M_RTS;
+
+ assert((cd->mcodeptr - savedmcodeptr) == 4*REPLACEMENT_STUB_SIZE);
}
}
*******************************************************************************/
+#if !defined(NDEBUG)
void emit_verbosecall_enter(jitdata *jd)
{
methodinfo *m;
M_NOP;
}
+#endif /* !defined(NDEBUG) */
/* emit_verbosecall_exit *******************************************************
*******************************************************************************/
+#if !defined(NDEBUG)
void emit_verbosecall_exit(jitdata *jd)
{
methodinfo *m;
M_NOP;
}
+#endif /* !defined(NDEBUG) */
/*