Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: emitfuncs.c 4398 2006-01-31 23:43:08Z twisti $
+ $Id: emit-common.c 8265 2007-08-06 16:10:42Z twisti $
*/
#include "config.h"
#include <assert.h>
+#include <stdint.h>
#include "vm/types.h"
+#include "arch.h"
#include "codegen.h"
#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
+#include "vm/jit/patcher-common.h"
#include "vmcore/options.h"
#include "vmcore/statistics.h"
}
-/* emit_bxx ********************************************************************
+/* emit_patcher_traps **********************************************************
+
+ Generates the code for the patcher traps.
+
+*******************************************************************************/
+
+void emit_patcher_traps(jitdata *jd)
+{
+ codegendata *cd;
+ codeinfo *code;
+ patchref_t *pr;
+ u1 *savedmcodeptr;
+ u1 *tmpmcodeptr;
+ uint32_t mcode;
+
+ /* get required compiler data */
+
+ cd = jd->cd;
+ code = jd->code;
+
+ /* generate patcher traps code */
+
+ for (pr = list_first_unsynced(code->patchers); pr != NULL; pr = list_next_unsynced(code->patchers, pr)) {
+
+ /* Calculate the patch position where the original machine
+ code is located and the trap should be placed. */
+
+ tmpmcodeptr = (u1 *) (cd->mcodebase + pr->mpc);
+
+ /* Patch in the trap to call the signal handler (done at
+ compile time). */
- Wrappers for conditional branch instructions.
+ savedmcodeptr = cd->mcodeptr; /* save current mcodeptr */
+ cd->mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
+
+ mcode = emit_trap(cd);
+
+ cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
+
+ /* Remember the original machine code which is patched
+ back in later (done at runtime). */
+
+ pr->mcode = mcode;
+ }
+}
+
+
+/* emit_bccz *******************************************************************
+
+ Emit conditional and unconditional branch instructions on integer
+ regiseters.
*******************************************************************************/
-void emit_bc(codegendata *cd, basicblock *target, s4 condition)
+void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
{
s4 branchmpc;
s4 disp;
branchmpc = cd->mcodeptr - cd->mcodebase;
disp = target->mpc - branchmpc;
-#if 0
- emit_branch(cd, disp, condition);
+#if defined(ENABLE_STATISTICS)
+ count_emit_branch++;
+ if ((int8_t)disp == disp) count_emit_branch_8bit++;
+ else if ((int16_t)disp == disp) count_emit_branch_16bit++;
+ else if ((int32_t)disp == disp) count_emit_branch_32bit++;
+# if SIZEOF_VOID_P == 8
+ else if ((int64_t)disp == disp) count_emit_branch_64bit++;
+# endif
#endif
+
+ emit_branch(cd, disp, condition, reg, options);
}
else {
/* current mcodeptr is the correct position,
afterwards emit the NOPs */
-#if 0
- codegen_add_branch_ref(cd, target, condition);
-#endif
+ codegen_add_branch_ref(cd, target, condition, reg, options);
/* generate NOPs as placeholder for branch code */
- /* XXX if recompile-with-long-branches */
BRANCH_NOPS;
}
}
+/* emit_bcc ********************************************************************
+
+ Emit conditional and unconditional branch instructions on condition
+ codes.
+
+*******************************************************************************/
+
+void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options)
+{
+ emit_bccz(cd, target, condition, -1, options);
+}
+
+
+/* emit_br *********************************************************************
+
+ Wrapper for unconditional branches.
+
+*******************************************************************************/
+
void emit_br(codegendata *cd, basicblock *target)
{
- emit_bc(cd, target, BRANCH_UNCONDITIONAL);
+ emit_bcc(cd, target, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
}
-void emit_beq(codegendata *cd, basicblock *target)
+/* emit_bxxz *******************************************************************
+
+ Wrappers for branches on one integer register.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+
+void emit_beqz(codegendata *cd, basicblock *target, s4 reg)
{
- emit_bc(cd, target, BRANCH_EQ);
+ emit_bccz(cd, target, BRANCH_EQ, reg, BRANCH_OPT_NONE);
}
+void emit_bnez(codegendata *cd, basicblock *target, s4 reg)
+{
+ emit_bccz(cd, target, BRANCH_NE, reg, BRANCH_OPT_NONE);
+}
-void emit_bne(codegendata *cd, basicblock *target)
+void emit_bltz(codegendata *cd, basicblock *target, s4 reg)
{
- emit_bc(cd, target, BRANCH_NE);
+ emit_bccz(cd, target, BRANCH_LT, reg, BRANCH_OPT_NONE);
}
+void emit_bgez(codegendata *cd, basicblock *target, s4 reg)
+{
+ emit_bccz(cd, target, BRANCH_GE, reg, BRANCH_OPT_NONE);
+}
-void emit_blt(codegendata *cd, basicblock *target)
+void emit_bgtz(codegendata *cd, basicblock *target, s4 reg)
+{
+ emit_bccz(cd, target, BRANCH_GT, reg, BRANCH_OPT_NONE);
+}
+
+void emit_blez(codegendata *cd, basicblock *target, s4 reg)
{
- emit_bc(cd, target, BRANCH_LT);
+ emit_bccz(cd, target, BRANCH_LE, reg, BRANCH_OPT_NONE);
}
+#endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
-void emit_bge(codegendata *cd, basicblock *target)
+
+/* emit_bxx ********************************************************************
+
+ Wrappers for branches on two integer registers.
+
+ We use PACK_REGS here, so we don't have to change the branchref
+ data structure and the emit_bccz function.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
+
+void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2)
+{
+ emit_bccz(cd, target, BRANCH_EQ, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
+}
+
+void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2)
{
- emit_bc(cd, target, BRANCH_GE);
+ emit_bccz(cd, target, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
}
+#endif /* SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS */
-void emit_bgt(codegendata *cd, basicblock *target)
+
+/* emit_bxx ********************************************************************
+
+ Wrappers for branches on condition codes.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+
+void emit_beq(codegendata *cd, basicblock *target)
{
- emit_bc(cd, target, BRANCH_GT);
+ emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_NONE);
}
+void emit_bne(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_NE, BRANCH_OPT_NONE);
+}
+
+void emit_blt(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_LT, BRANCH_OPT_NONE);
+}
+
+void emit_bge(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_GE, BRANCH_OPT_NONE);
+}
+
+void emit_bgt(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_GT, BRANCH_OPT_NONE);
+}
void emit_ble(codegendata *cd, basicblock *target)
{
- emit_bc(cd, target, BRANCH_LE);
+ emit_bcc(cd, target, BRANCH_LE, BRANCH_OPT_NONE);
}
+#if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
+void emit_bult(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_ULT, BRANCH_OPT_NONE);
+}
+void emit_bule(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_ULE, BRANCH_OPT_NONE);
+}
+
+void emit_buge(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_UGE, BRANCH_OPT_NONE);
+}
+
+void emit_bugt(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_UGT, BRANCH_OPT_NONE);
+}
+#endif
+
+#if defined(__POWERPC__) || defined(__POWERPC64__)
void emit_bnan(codegendata *cd, basicblock *target)
{
- emit_bc(cd, target, BRANCH_NAN);
+ emit_bcc(cd, target, BRANCH_NAN, BRANCH_OPT_NONE);
+}
+#endif
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
+
+
+/* emit_label_bccz *************************************************************
+
+ Emit a branch to a label. Possibly emit the branch, if it is a
+ backward branch.
+
+*******************************************************************************/
+
+void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
+{
+ list_t *list;
+ branch_label_ref_t *br;
+ s4 mpc;
+ s4 disp;
+
+ /* get the label list */
+
+ list = cd->brancheslabel;
+
+ /* search if the label is already in the list */
+
+ for (br = list_first_unsynced(list); br != NULL;
+ br = list_next_unsynced(list, br)) {
+ /* is this entry the correct label? */
+
+ if (br->label == label)
+ break;
+ }
+
+ /* a branch reference was found */
+
+ if (br != NULL) {
+ /* calculate the mpc of the branch instruction */
+
+ mpc = cd->mcodeptr - cd->mcodebase;
+ disp = br->mpc - mpc;
+
+#if defined(ENABLE_STATISTICS)
+ count_emit_branch++;
+ if ((int8_t)disp == disp) count_emit_branch_8bit++;
+ else if ((int16_t)disp == disp) count_emit_branch_16bit++;
+ else if ((int32_t)disp == disp) count_emit_branch_32bit++;
+# if SIZEOF_VOID_P == 8
+ else if ((int64_t)disp == disp) count_emit_branch_64bit++;
+# endif
+#endif
+
+ emit_branch(cd, disp, condition, reg, options);
+
+ /* now remove the branch reference */
+
+ list_remove_unsynced(list, br);
+ }
+ else {
+ /* current mcodeptr is the correct position,
+ afterwards emit the NOPs */
+
+ codegen_branch_label_add(cd, label, condition, reg, options);
+
+ /* generate NOPs as placeholder for branch code */
+
+ BRANCH_NOPS;
+ }
}
-/* emit_array_checks ***********************************************************
+/* emit_label ******************************************************************
- Emit exception checks for array accesses, if they need to be
- emitted.
+ Emit a label for a branch. Possibly emit the branch, if it is a
+ forward branch.
*******************************************************************************/
-void emit_array_checks(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
+void emit_label(codegendata *cd, s4 label)
{
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- emit_nullpointer_check(cd, iptr, s1);
- emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+ list_t *list;
+ branch_label_ref_t *br;
+ s4 mpc;
+ s4 disp;
+ u1 *mcodeptr;
+
+ /* get the label list */
+
+ list = cd->brancheslabel;
+
+ /* search if the label is already in the list */
+
+ for (br = list_first_unsynced(list); br != NULL;
+ br = list_next_unsynced(list, br)) {
+ /* is this entry the correct label? */
+
+ if (br->label == label)
+ break;
+ }
+
+ /* a branch reference was found */
+
+ if (br != NULL) {
+ /* calculate the mpc of the branch instruction */
+
+ mpc = cd->mcodeptr - cd->mcodebase;
+ disp = mpc - br->mpc;
+
+ /* temporary set the mcodeptr */
+
+ mcodeptr = cd->mcodeptr;
+ cd->mcodeptr = cd->mcodebase + br->mpc;
+
+#if defined(ENABLE_STATISTICS)
+ count_emit_branch++;
+ if ((int8_t)disp == disp) count_emit_branch_8bit++;
+ else if ((int16_t)disp == disp) count_emit_branch_16bit++;
+ else if ((int32_t)disp == disp) count_emit_branch_32bit++;
+# if SIZEOF_VOID_P == 8
+ else if ((int64_t)disp == disp) count_emit_branch_64bit++;
+# endif
+#endif
+
+ emit_branch(cd, disp, br->condition, br->reg, br->options);
+
+ /* restore mcodeptr */
+
+ cd->mcodeptr = mcodeptr;
+
+ /* now remove the branch reference */
+
+ list_remove_unsynced(list, br);
+ }
+ else {
+ /* add the label to the list (use invalid values for condition
+ and register) */
+
+ codegen_branch_label_add(cd, label, -1, -1, BRANCH_OPT_NONE );
}
}
+/* emit_label_bcc **************************************************************
+
+ Emit conditional and unconditional label-branch instructions on
+ condition codes.
+
+*******************************************************************************/
+
+void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options)
+{
+ emit_label_bccz(cd, label, condition, -1, options);
+}
+
+
+/* emit_label_br ***************************************************************
+
+ Wrapper for unconditional label-branches.
+
+*******************************************************************************/
+
+void emit_label_br(codegendata *cd, s4 label)
+{
+ emit_label_bcc(cd, label, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
+}
+
+
+/* emit_label_bxxz *************************************************************
+
+ Wrappers for label-branches on one integer register.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+
+void emit_label_beqz(codegendata *cd, s4 label, s4 reg)
+{
+ emit_label_bccz(cd, label, BRANCH_EQ, reg, BRANCH_OPT_NONE);
+}
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
+
+
+/* emit_label_bxx **************************************************************
+
+ Wrappers for label-branches on condition codes.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+
+void emit_label_beq(codegendata *cd, s4 label)
+{
+ emit_label_bcc(cd, label, BRANCH_EQ, BRANCH_OPT_NONE);
+}
+
+void emit_label_bne(codegendata *cd, s4 label)
+{
+ emit_label_bcc(cd, label, BRANCH_NE, BRANCH_OPT_NONE);
+}
+
+void emit_label_blt(codegendata *cd, s4 label)
+{
+ emit_label_bcc(cd, label, BRANCH_LT, BRANCH_OPT_NONE);
+}
+
+void emit_label_bge(codegendata *cd, s4 label)
+{
+ emit_label_bcc(cd, label, BRANCH_GE, BRANCH_OPT_NONE);
+}
+
+void emit_label_bgt(codegendata *cd, s4 label)
+{
+ emit_label_bcc(cd, label, BRANCH_GT, BRANCH_OPT_NONE);
+}
+
+void emit_label_ble(codegendata *cd, s4 label)
+{
+ emit_label_bcc(cd, label, BRANCH_LE, BRANCH_OPT_NONE);
+}
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
+
+
/*
* 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