Merged revisions 7501-7598 via svnmerge from
[cacao.git] / src / vm / jit / emit-common.c
index 2810994f58a5973d3e900710a3f99c6defff4091..243109adc6b2754a6c65a1b6fc428d252d8094de 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "vm/types.h"
 
+#include "arch.h"
 #include "codegen.h"
 
 #include "vm/jit/emit-common.h"
@@ -246,13 +247,14 @@ void emit_store_dst(jitdata *jd, instruction *iptr, s4 d)
 }
 
 
-/* emit_bxx ********************************************************************
+/* emit_bccz *******************************************************************
 
-   Wrappers for conditional branch instructions.
+   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;
@@ -268,90 +270,379 @@ void emit_bc(codegendata *cd, basicblock *target, s4 condition)
                branchmpc = cd->mcodeptr - cd->mcodebase;
                disp      = target->mpc - branchmpc;
 
-#if 0
-               emit_branch(cd, disp, condition);
-#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_bccz(cd, target, BRANCH_EQ, reg, BRANCH_OPT_NONE);
+}
+
+void emit_bnez(codegendata *cd, basicblock *target, s4 reg)
 {
-       emit_bc(cd, target, BRANCH_EQ);
+       emit_bccz(cd, target, BRANCH_NE, reg, BRANCH_OPT_NONE);
 }
 
+void emit_bltz(codegendata *cd, basicblock *target, s4 reg)
+{
+       emit_bccz(cd, target, BRANCH_LT, reg, BRANCH_OPT_NONE);
+}
 
-void emit_bne(codegendata *cd, basicblock *target)
+void emit_bgez(codegendata *cd, basicblock *target, s4 reg)
 {
-       emit_bc(cd, target, BRANCH_NE);
+       emit_bccz(cd, target, BRANCH_GE, reg, BRANCH_OPT_NONE);
 }
 
+void emit_bgtz(codegendata *cd, basicblock *target, s4 reg)
+{
+       emit_bccz(cd, target, BRANCH_GT, reg, BRANCH_OPT_NONE);
+}
 
-void emit_blt(codegendata *cd, basicblock *target)
+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_bc(cd, target, BRANCH_GE);
+       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_bccz(cd, target, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
+}
 
-void emit_bgt(codegendata *cd, basicblock *target)
+#endif /* SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS */
+
+
+/* emit_bxx ********************************************************************
+
+   Wrappers for branches on condition codes.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+
+void emit_beq(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_NONE);
+}
+
+void emit_bne(codegendata *cd, basicblock *target)
 {
-       emit_bc(cd, target, BRANCH_GT);
+       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               *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;
+
+               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               *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;
+
+               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