Authors: Christian Thalinger
- $Id: emit.c 7219 2007-01-16 22:18:57Z pm $
+ $Id: emit.c 7581 2007-03-26 07:23:16Z pm $
*/
+#include <assert.h>
+
#include "config.h"
#include "vm/types.h"
#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
#include "vm/jit/replace.h"
+#include "vm/global.h"
+#include "mm/memory.h"
#define __PORTED__
*******************************************************************************/
-inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
+__PORTED__ inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
{
- codegendata *cd;
- s4 disp;
-#if 0
- s4 s;
- u2 opcode;
-#endif
+ codegendata *cd;
/* get required compiler data */
cd = jd->cd;
-#if 0
- /* do we have to generate a conditional move? */
-
- if ((iptr != NULL) && (iptr->opc & ICMD_CONDITION_MASK)) {
- /* the passed register d is actually the source register */
-
- s = d;
-
- /* Only pass the opcode to codegen_reg_of_var to get the real
- destination register. */
-
- opcode = iptr->opc & ICMD_OPCODE_MASK;
-
- /* get the real destination register */
-
- d = codegen_reg_of_var(rd, opcode, dst, REG_ITMP1);
-
- /* and emit the conditional move */
-
- emit_cmovxx(cd, iptr, s, d);
- }
-#endif
-
if (IS_INMEMORY(dst->flags)) {
COUNT_SPILLS;
- disp = dst->vv.regoff * 8;
-
if (IS_FLT_DBL_TYPE(dst->type)) {
if (IS_2_WORD_TYPE(dst->type))
- M_DST(d, REG_SP, disp);
+ M_DST(d, REG_SP, dst->vv.regoff * 4);
else
- M_FST(d, REG_SP, disp);
+ M_FST(d, REG_SP, dst->vv.regoff * 4);
+ }
+ else {
+ if (IS_2_WORD_TYPE(dst->type))
+ M_LST(d, REG_SP, dst->vv.regoff * 4);
+ else
+ M_IST(d, REG_SP, dst->vv.regoff * 4);
}
- else
- M_LST(d, REG_SP, disp);
}
}
*******************************************************************************/
-void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst)
+__PORTED__ void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst)
{
codegendata *cd;
s4 s1, d;
*******************************************************************************/
-void emit_exception_stubs(jitdata *jd)
+__PORTED__ void emit_exception_stubs(jitdata *jd)
{
codegendata *cd;
registerdata *rd;
s4 branchmpc;
s4 targetmpc;
s4 targetdisp;
+ s4 disp;
/* get required compiler data */
MCODECHECK(512);
+ /* move index register into REG_ITMP1 */
+
/* Check if the exception is an
ArrayIndexOutOfBoundsException. If so, move index register
into a4. */
/* calcuate exception address */
- M_MOV_IMM(0, rd->argintregs[3]);
- dseg_adddata(cd);
- M_AADD_IMM32(er->branchpos - 6, rd->argintregs[3]);
+ if (N_VALID_DISP(er->branchpos - 4)) {
+ M_LDA(rd->argintregs[3], REG_PV, er->branchpos - 4);
+ } else {
+ M_INTMOVE(REG_PV, rd->argintregs[3]);
+ M_AADD_IMM(er->branchpos - 4, REG_PV);
+ }
- /* move function to call into REG_ITMP3 */
+ /* move function to call into REG_ITMP! */
- M_MOV_IMM(er->function, REG_ITMP3);
+ disp = dseg_add_functionptr(cd, er->function);
+ M_ALD(REG_ITMP1, REG_PV, disp);
if (targetdisp == 0) {
- targetdisp = cd->mcodeptr - cd->mcodebase;
+ targetdisp = (cd->mcodeptr) - (cd->mcodebase);
- emit_lea_membase_reg(cd, RIP, -((cd->mcodeptr + 7) - cd->mcodebase), rd->argintregs[0]);
+ M_MOV(REG_PV, rd->argintregs[0]);
M_MOV(REG_SP, rd->argintregs[1]);
- M_ALD(rd->argintregs[2], REG_SP, cd->stackframesize * 8);
- M_ASUB_IMM(2 * 8, REG_SP);
- M_AST(rd->argintregs[3], REG_SP, 0 * 8); /* store XPC */
+ M_ALD(rd->argintregs[2],
+ REG_SP, cd->stackframesize * 4 - SIZEOF_VOID_P);
+
+ M_ASUB_IMM((2 * 4) + 96, REG_SP);
+
+ M_AST(rd->argintregs[3], REG_SP, (0 * 4) + 96); /* store XPC */
+
+ M_MOV(REG_ITMP1, REG_PV);
+ M_JSR(REG_RA, REG_PV);
+
+ /* Recalculate PV */
- M_CALL(REG_ITMP3);
+ N_BASR(REG_ITMP1, RN);
+ disp = (s4) (cd->mcodeptr - cd->mcodebase);
+ M_LDA(REG_PV, REG_ITMP1, -disp);
- M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
- M_AADD_IMM(2 * 8, REG_SP);
+ M_MOV(REG_RESULT, REG_ITMP1_XPTR);
- M_MOV_IMM(asm_handle_exception, REG_ITMP3);
- M_JMP(REG_ITMP3);
+ M_ALD(REG_ITMP2_XPC, REG_SP, (0 * 4) + 96);
+ M_AADD_IMM((2 * 4) + 96, REG_SP);
+
+ disp = dseg_add_functionptr(cd, asm_handle_exception);
+ M_ALD(REG_ITMP3, REG_PV, disp);
+ M_JMP(RN, REG_ITMP3);
}
else {
- M_JMP_IMM((cd->mcodebase + targetdisp) -
- (cd->mcodeptr + PATCHER_CALL_SIZE));
+ disp = ((cd->mcodebase) + targetdisp) -
+ (( cd->mcodeptr) );
+
+ M_BR(disp);
}
+
}
}
*******************************************************************************/
-void emit_patcher_stubs(jitdata *jd)
+__PORTED__ void emit_patcher_stubs(jitdata *jd)
{
+
codegendata *cd;
patchref *pref;
- u8 mcode;
+ u4 mcode;
u1 *savedmcodeptr;
u1 *tmpmcodeptr;
s4 targetdisp;
targetdisp = 0;
for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
- /* check size of code segment */
+ /* check code segment size */
- MCODECHECK(512);
+ MCODECHECK(100);
+
+ /* Get machine code which is patched back in later. The
+ call is 1 instruction word long. */
+
+ tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos);
+
+ mcode = *((u4 *) tmpmcodeptr);
+
+ /* Patch in the call to call the following code (done at
+ compile time). */
- /* Get machine code which is patched back in later. A
- `call rel32' is 5 bytes long (but read 8 bytes). */
+ savedmcodeptr = cd->mcodeptr; /* save current mcodeptr */
+ cd->mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
- savedmcodeptr = cd->mcodebase + pref->branchpos;
- mcode = *((u8 *) savedmcodeptr);
+ disp = (savedmcodeptr) - (tmpmcodeptr);
+ M_BSR(REG_ITMP3, disp);
- /* patch in `call rel32' to call the following code */
+ cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
- tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
- cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
+ /* create stack frame */
- M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
+ M_ASUB_IMM(6 * 4, REG_SP);
- cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
+ /* move return address onto stack */
+
+ M_AST(REG_ITMP3, REG_SP, 5 * 4);
/* move pointer to java_objectheader onto stack */
(void) dseg_add_unique_address(cd, lock_get_initial_lock_word());
disp = dseg_add_unique_address(cd, NULL); /* vftbl */
- emit_lea_membase_reg(cd, RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, REG_ITMP3);
- M_PUSH(REG_ITMP3);
+ M_LDA(REG_ITMP3, REG_PV, disp);
+ M_AST(REG_ITMP3, REG_SP, 4 * 4);
#else
- M_PUSH_IMM(0);
+ /* nothing to do */
#endif
- /* move machine code bytes and classinfo pointer into registers */
+ /* move machine code onto stack */
- M_MOV_IMM(mcode, REG_ITMP3);
- M_PUSH(REG_ITMP3);
+ disp = dseg_add_s4(cd, mcode);
+ M_ILD(REG_ITMP3, REG_PV, disp);
+ M_IST(REG_ITMP3, REG_SP, 3 * 4);
- M_MOV_IMM(pref->ref, REG_ITMP3);
- M_PUSH(REG_ITMP3);
+ /* move class/method/field reference onto stack */
- M_MOV_IMM(pref->disp, REG_ITMP3);
- M_PUSH(REG_ITMP3);
+ disp = dseg_add_address(cd, pref->ref);
+ M_ALD(REG_ITMP3, REG_PV, disp);
+ M_AST(REG_ITMP3, REG_SP, 2 * 4);
- M_MOV_IMM(pref->patcher, REG_ITMP3);
- M_PUSH(REG_ITMP3);
+ /* move data segment displacement onto stack */
+
+ disp = dseg_add_s4(cd, pref->disp);
+ M_ILD(REG_ITMP3, REG_PV, disp);
+ M_IST(REG_ITMP3, REG_SP, 1 * 4);
+
+ /* move patcher function pointer onto stack */
+
+ disp = dseg_add_functionptr(cd, pref->patcher);
+ M_ALD(REG_ITMP3, REG_PV, disp);
+ M_AST(REG_ITMP3, REG_SP, 0 * 4);
if (targetdisp == 0) {
- targetdisp = cd->mcodeptr - cd->mcodebase;
+ targetdisp = (cd->mcodeptr) - (cd->mcodebase);
- M_MOV_IMM(asm_patcher_wrapper, REG_ITMP3);
- M_JMP(REG_ITMP3);
+ disp = dseg_add_functionptr(cd, asm_patcher_wrapper);
+ M_ALD(REG_ITMP3, REG_PV, disp);
+ M_JMP(RN, REG_ITMP3);
}
else {
- M_JMP_IMM((cd->mcodebase + targetdisp) -
- (cd->mcodeptr + PATCHER_CALL_SIZE));
+ disp = ((cd->mcodebase) + targetdisp) -
+ (( cd->mcodeptr) );
+
+ M_BR(disp);
}
}
}
void emit_replacement_stubs(jitdata *jd)
{
+#if 0
codegendata *cd;
codeinfo *code;
rplpoint *rplp;
M_MOV_IMM(asm_replacement_out, REG_ITMP3);
M_JMP(REG_ITMP3);
}
+#endif
}
#if !defined(NDEBUG)
void emit_verbosecall_enter(jitdata *jd)
{
+
methodinfo *m;
codegendata *cd;
registerdata *rd;
methoddesc *md;
s4 i, j, k;
+ s4 stackframesize, off, foff, aoff, doff, t, iargctr, fargctr, disp;
/* get required compiler data */
M_NOP;
- /* additional +1 is for 16-byte stack alignment */
+ stackframesize =
+ (6 * 8) + /* s8 on stack parameters x 6 */
+ (1 * 4) + /* methodinfo on stack parameter */
+ (ARG_CNT * 8) +
+ (TMP_CNT * 8)
+ ;
- M_LSUB_IMM((ARG_CNT + TMP_CNT + 1 + 1) * 8, REG_SP);
+ M_ASUB_IMM(stackframesize, REG_SP); /* allocate stackframe */
/* save argument registers */
- for (i = 0; i < INT_ARG_CNT; i++)
- M_LST(rd->argintregs[i], REG_SP, (1 + i) * 8);
+ off = (6 * 8) + (1 * 4);
+
+ for (i = 0; i < INT_ARG_CNT; i++, off += 8)
+ M_IST(rd->argintregs[i], REG_SP, off);
- for (i = 0; i < FLT_ARG_CNT; i++)
- M_DST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
+ for (i = 0; i < FLT_ARG_CNT; i++, off += 8)
+ M_DST(rd->argfltregs[i], REG_SP, off);
/* save temporary registers for leaf methods */
if (jd->isleafmethod) {
- for (i = 0; i < INT_TMP_CNT; i++)
- M_LST(rd->tmpintregs[i], REG_SP, (1 + ARG_CNT + i) * 8);
+ for (i = 0; i < INT_TMP_CNT; i++, off += 8)
+ M_LST(rd->tmpintregs[i], REG_SP, off);
- for (i = 0; i < FLT_TMP_CNT; i++)
- M_DST(rd->tmpfltregs[i], REG_SP, (1 + ARG_CNT + INT_TMP_CNT + i) * 8);
+ for (i = 0; i < FLT_TMP_CNT; i++, off += 8)
+ M_DST(rd->tmpfltregs[i], REG_SP, off);
}
- /* show integer hex code for float arguments */
+ /* Load arguments to new locations */
- for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
- /* If the paramtype is a float, we have to right shift all
- following integer registers. */
-
- if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
- for (k = INT_ARG_CNT - 2; k >= i; k--)
- M_MOV(rd->argintregs[k], rd->argintregs[k + 1]);
+ /* First move all arguments to stack
+ *
+ * (s8) a7
+ * (s8) a2
+ * ...
+ * (s8) a1 \ Auxilliary stack frame
+ * (s8) a0 /
+ * ------- <---- SP
+ */
- emit_movd_freg_reg(cd, rd->argfltregs[j], rd->argintregs[i]);
- j++;
+ M_ASUB_IMM(2 * 8, REG_SP);
+
+ /* offset to where first integer arg is saved on stack */
+ off = (2 * 8) + (6 * 8) + (1 * 4);
+ /* offset to where first float arg is saved on stack */
+ foff = off + (INT_ARG_CNT * 8);
+ /* offset to where first argument is passed on stack */
+ aoff = (2 * 8) + stackframesize + (cd->stackframesize * 4);
+ /* offset to destination on stack */
+ doff = 0;
+
+ iargctr = fargctr = 0;
+
+ ICONST(REG_ITMP1, 0);
+
+ for (i = 0; i < md->paramcount && i < 8; i++) {
+ t = md->paramtypes[i].type;
+
+ M_IST(REG_ITMP1, REG_SP, doff);
+ M_IST(REG_ITMP1, REG_SP, doff + 4);
+
+ if (IS_FLT_DBL_TYPE(t)) {
+ if (fargctr < 2) { /* passed in register */
+ N_STD(REG_FA0 + fargctr, doff, RN, REG_SP);
+ fargctr += 1;
+ } else { /* passed on stack */
+ if (IS_2_WORD_TYPE(t)) {
+ N_MVC(doff, 8, REG_SP, aoff, REG_SP);
+ aoff += 8;
+ } else {
+ N_MVC(doff + 4, 4, REG_SP, aoff, REG_SP);
+ aoff += 4;
+ }
+ }
+ } else {
+ if (IS_2_WORD_TYPE(t)) {
+ if (iargctr < 4) { /* passed in 2 registers */
+ N_STM(REG_A0 + iargctr, REG_A0 + iargctr + 1, doff, REG_SP);
+ iargctr += 2;
+ } else { /* passed on stack */
+ N_MVC(doff, 8, REG_SP, aoff, REG_SP);
+ aoff += 8;
+ }
+ } else {
+ if (iargctr < 5) { /* passed in register */
+ N_ST(REG_A0 + iargctr, doff + 4, RN, REG_SP);
+ iargctr += 1;
+ } else { /* passed on stack */
+ N_MVC(doff + 4, 4, REG_SP, aoff, REG_SP);
+ aoff += 4;
+ }
+ }
}
+
+ doff += 8;
}
- M_MOV_IMM(m, REG_ITMP2);
- M_AST(REG_ITMP2, REG_SP, 0 * 8);
- M_MOV_IMM(builtin_trace_args, REG_ITMP1);
- M_CALL(REG_ITMP1);
+ /* Now move a0 and a1 to registers
+ *
+ * (s8) a7
+ * ...
+ * (s8) a2
+ * ------- <- SP
+ * (s8) a0 ==> a0, a1
+ * (s8) a1 ==> a2, a3
+ */
+
+ N_LM(REG_A0, REG_A1, 0, REG_SP);
+ N_LM(REG_A2, REG_A3, 8, REG_SP);
+
+ M_AADD_IMM(2 * 8, REG_SP);
+
+ /* Finally load methodinfo argument */
+
+ disp = dseg_add_address(cd, m);
+ M_ALD(REG_ITMP2, REG_PV, disp);
+ M_AST(REG_ITMP2, REG_SP, 6 * 8);
+
+ /* Call builtin_verbosecall_enter */
+
+ disp = dseg_add_address(cd, builtin_verbosecall_enter);
+ M_ALD(REG_ITMP2, REG_PV, disp);
+ M_ASUB_IMM(96, REG_SP);
+ M_CALL(REG_ITMP2);
+ M_AADD_IMM(96, REG_SP);
/* restore argument registers */
- for (i = 0; i < INT_ARG_CNT; i++)
- M_LLD(rd->argintregs[i], REG_SP, (1 + i) * 8);
+ off = (6 * 8) + (1 * 4);
- for (i = 0; i < FLT_ARG_CNT; i++)
- M_DLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
+ for (i = 0; i < INT_ARG_CNT; i++, off += 8)
+ M_ILD(rd->argintregs[i], REG_SP, off);
+
+ for (i = 0; i < FLT_ARG_CNT; i++, off += 8)
+ M_DLD(rd->argfltregs[i], REG_SP, off);
/* restore temporary registers for leaf methods */
if (jd->isleafmethod) {
- for (i = 0; i < INT_TMP_CNT; i++)
- M_LLD(rd->tmpintregs[i], REG_SP, (1 + ARG_CNT + i) * 8);
+ for (i = 0; i < INT_TMP_CNT; i++, off += 8)
+ M_ILD(rd->tmpintregs[i], REG_SP, off);
- for (i = 0; i < FLT_TMP_CNT; i++)
- M_DLD(rd->tmpfltregs[i], REG_SP, (1 + ARG_CNT + INT_TMP_CNT + i) * 8);
+ for (i = 0; i < FLT_TMP_CNT; i++, off += 8)
+ M_DLD(rd->tmpfltregs[i], REG_SP, off);
}
- M_LADD_IMM((ARG_CNT + TMP_CNT + 1 + 1) * 8, REG_SP);
+ /* remove stackframe */
+
+ M_AADD_IMM(stackframesize, REG_SP);
/* mark trace code */
methodinfo *m;
codegendata *cd;
registerdata *rd;
+ s4 disp;
/* get required compiler data */
M_ASUB_IMM(2 * 8, REG_SP);
- M_LST(REG_RESULT, REG_SP, 0 * 8);
+ N_STM(REG_RESULT, REG_RESULT2, 0 * 8, REG_SP);
M_DST(REG_FRESULT, REG_SP, 1 * 8);
- M_MOV_IMM(m, rd->argintregs[0]);
- M_MOV(REG_RESULT, rd->argintregs[1]);
- M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
- M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
+ if (IS_2_WORD_TYPE(m->parseddesc->returntype.type)) {
+ /* (REG_A0, REG_A1) == (REG_RESULT, REG_RESULT2), se no need to move */
+ } else {
+ M_INTMOVE(REG_RESULT, REG_A1);
+ ICONST(REG_A0, 0);
+ }
+
+ disp = dseg_add_address(cd, m);
+ M_ALD(REG_A2, REG_PV, disp);
+
+ /* REG_FRESULT is REG_FA0, so no need to move */
+ M_FLTMOVE(REG_FRESULT, REG_FA1);
- M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
+ disp = dseg_add_address(cd, builtin_verbosecall_exit);
+ M_ALD(REG_ITMP1, REG_PV, disp);
+ M_ASUB_IMM(96, REG_SP);
M_CALL(REG_ITMP1);
+ M_AADD_IMM(96, REG_SP);
- M_LLD(REG_RESULT, REG_SP, 0 * 8);
+ N_LM(REG_RESULT, REG_RESULT2, 0 * 8, REG_SP);
M_DLD(REG_FRESULT, REG_SP, 1 * 8);
M_AADD_IMM(2 * 8, REG_SP);
*(cd->mcodeptr++) = 0x31;
}
+/* emit_load_high **************************************************************
+
+ Emits a possible load of the high 32-bits of an operand.
+
+*******************************************************************************/
+
+__PORTED__ s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
+{
+ codegendata *cd;
+ s4 disp;
+ s4 reg;
+
+ assert(src->type == TYPE_LNG);
+
+ /* get required compiler data */
+
+ cd = jd->cd;
+
+ if (IS_INMEMORY(src->flags)) {
+ COUNT_SPILLS;
+
+ disp = src->vv.regoff * 4;
+
+ M_ILD(tempreg, REG_SP, disp + 4);
+
+ reg = tempreg;
+ }
+ else
+ reg = GET_HIGH_REG(src->vv.regoff);
+
+ return reg;
+}
+
+/* emit_load_low ***************************************************************
+
+ Emits a possible load of the low 32-bits of an operand.
+
+*******************************************************************************/
+
+__PORTED__ s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
+{
+ codegendata *cd;
+ s4 disp;
+ s4 reg;
+
+ assert(src->type == TYPE_LNG);
+
+ /* get required compiler data */
+
+ cd = jd->cd;
+
+ if (IS_INMEMORY(src->flags)) {
+ COUNT_SPILLS;
+
+ disp = src->vv.regoff * 4;
+
+ M_ILD(tempreg, REG_SP, disp);
+
+ reg = tempreg;
+ }
+ else
+ reg = GET_LOW_REG(src->vv.regoff);
+
+ return reg;
+}
+
+/* emit_nullpointer_check ******************************************************
+
+ Emit a NullPointerException check.
+
+*******************************************************************************/
+
+__PORTED__ void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+ if (INSTRUCTION_MUST_CHECK(iptr)) {
+ M_TEST(reg);
+ M_BEQ(0);
+ codegen_add_nullpointerexception_ref(cd);
+ }
+}
+
+/* emit_arrayindexoutofbounds_check ********************************************
+
+ Emit a ArrayIndexOutOfBoundsException check.
+
+*******************************************************************************/
+
+__PORTED__ void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
+{
+ if (INSTRUCTION_MUST_CHECK(iptr)) {
+ N_C(s2, OFFSET(java_arrayheader, size), RN, s1);
+ M_BGE(0);
+ codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
+ }
+}
+
+s4 emit_load_s1_notzero(jitdata *jd, instruction *iptr, s4 tempreg) {
+ codegendata *cd = jd->cd;
+ s4 reg = emit_load_s1(jd, iptr, tempreg);
+ if (reg == 0) {
+ M_MOV(reg, tempreg);
+ return tempreg;
+ } else {
+ return reg;
+ }
+}
+
+s4 emit_load_s2_notzero(jitdata *jd, instruction *iptr, s4 tempreg) {
+ codegendata *cd = jd->cd;
+ s4 reg = emit_load_s2(jd, iptr, tempreg);
+ if (reg == 0) {
+ M_MOV(reg, tempreg);
+ return tempreg;
+ } else {
+ return reg;
+ }
+}
+
+s4 emit_load_s1_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg) {
+ codegendata *cd = jd->cd;
+ s4 reg = emit_load_s1(jd, iptr, tempreg);
+ if (reg == notreg) {
+ M_MOV(reg, tempreg);
+ return tempreg;
+ } else {
+ return reg;
+ }
+}
+
+s4 emit_load_s2_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg) {
+ codegendata *cd = jd->cd;
+ s4 reg = emit_load_s2(jd, iptr, tempreg);
+ if (reg == notreg) {
+ M_MOV(reg, tempreg);
+ return tempreg;
+ } else {
+ return reg;
+ }
+}
/*
* These are local overrides for various environment variables in Emacs.