* src/vm/jit/arm/codegen.c (codegen): Long branches are implemented
authormichi <none@none>
Tue, 13 Mar 2007 16:32:56 +0000 (16:32 +0000)
committermichi <none@none>
Tue, 13 Mar 2007 16:32:56 +0000 (16:32 +0000)
differently now.

* src/vm/jit/arm/codegen.h (M_COMPARE): Easier macros without overjumps.
(M_MOVEQ_IMM, M_MOVGT_IMM, M_ADDHI_IMM, M_SUBLO_IMM, M_CMPEQ_IMM): New macro.

src/vm/jit/arm/codegen.c
src/vm/jit/arm/codegen.h

index c314275d5f9c9438b66067d2d25f0e266e628c42..529bdeb93eea828f578917c628bc84bb5fc5cc44 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 7505 2007-03-12 13:34:37Z twisti $
+   $Id: codegen.c 7511 2007-03-13 16:32:56Z michi $
 
 */
 
@@ -1752,7 +1752,7 @@ bool codegen(jitdata *jd)
                case ICMD_IFNE:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_COMPARE(s1, iptr->sx.val.i, UNCOND, 0);
+                       M_COMPARE(s1, iptr->sx.val.i);
 
                        switch(iptr->opc) {
                        case ICMD_IFLT:
@@ -1787,8 +1787,9 @@ bool codegen(jitdata *jd)
                                M_ORR_S(s1, s2, REG_ITMP3);
                        }
                        else {
-                               ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
-                               M_CMP(s1, REG_ITMP3);
+                               M_COMPARE(s1, (iptr->sx.val.l >> 32));
+                               /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
+                               M_CMP(s1, REG_ITMP3);*/
                                ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_CMPEQ(s2, REG_ITMP3);
                        }
@@ -1796,7 +1797,6 @@ bool codegen(jitdata *jd)
                        codegen_addreference(cd, iptr->dst.block);
                        break;
 
-#if 0
                case ICMD_IF_LLT:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
@@ -1808,98 +1808,157 @@ bool codegen(jitdata *jd)
                                codegen_add_branch_ref(cd, iptr->dst.block);
                        }
                        else {
-                               ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
-                               M_CMP(s1, REG_ITMP3);
+                               /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
+                               M_COMPARE(s1, (iptr->sx.val.l >> 32));
+                               /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
+                               M_CMP(s1, REG_ITMP3);*/
+                               M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
+                               M_MOVGT_IMM(2, REG_ITMP1);
+                               M_MOVEQ_IMM(1, REG_ITMP1);
+
+                               /* low compare: x=x-1(ifLO) */
+                               M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
+                               /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
+                               M_CMP(s2, REG_ITMP3);*/
+                               M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1);
+
+                               /* branch if (x LT 1) */
+                               M_CMP_IMM(REG_ITMP1, 1);
                                M_BLT(0);
                                codegen_add_branch_ref(cd, iptr->dst.block);
+                       }
+                       break;
 
-/*                             M_BGT(3); */
-                               ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
-                               M_CMPLE(s2, REG_ITMP3);
-                               M_BLO(0);
+               case ICMD_IF_LLE:       /* ..., value ==> ...                         */
+
+                       s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
+                       if (iptr->sx.val.l == 0) {
+                               /* if high word is less than zero, the whole long is too  */
+                               M_CMP_IMM(s1, 0);
+                               M_BLT(0);
+                               codegen_add_branch_ref(cd, iptr->dst.block);
+
+                               /* ... otherwise the low word has to be zero (tricky!) */
+                               M_CMPEQ_IMM(s2, 0);
+                               M_BEQ(0);
+                               codegen_add_branch_ref(cd, iptr->dst.block);
+                       }
+                       else {
+                               /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
+                               M_COMPARE(s1, (iptr->sx.val.l >> 32));
+                               /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
+                               M_CMP(s1, REG_ITMP3);*/
+                               M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
+                               M_MOVGT_IMM(2, REG_ITMP1);
+                               M_MOVEQ_IMM(1, REG_ITMP1);
+
+                               /* low compare: x=x+1(ifHI) */
+                               M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
+                               /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
+                               M_CMP(s2, REG_ITMP3);*/
+                               M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1);
+
+                               /* branch if (x LE 1) */
+                               M_CMP_IMM(REG_ITMP1, 1);
+                               M_BLE(0);
                                codegen_add_branch_ref(cd, iptr->dst.block);
                        }
                        break;
-#endif
 
-               case ICMD_IF_LNE:       /* ..., value ==> ...                         */
+               case ICMD_IF_LGE:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
                        if (iptr->sx.val.l == 0) {
-                               M_ORR_S(s1, s2, REG_ITMP3);
+                               /* if high word is greater or equal zero, the whole long is too */
+                               M_CMP_IMM(s1, 0);
+                               M_BGE(0);
+                               codegen_add_branch_ref(cd, iptr->dst.block);
                        }
                        else {
-                               ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
-                               M_CMP(s1, REG_ITMP3);
-                               ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
-                               M_CMPEQ(s2, REG_ITMP3);
+                               /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
+                               M_COMPARE(s1, (iptr->sx.val.l >> 32));
+                               /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
+                               M_CMP(s1, REG_ITMP3);*/
+                               M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
+                               M_MOVGT_IMM(2, REG_ITMP1);
+                               M_MOVEQ_IMM(1, REG_ITMP1);
+
+                               /* low compare: x=x-1(ifLO) */
+                               M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
+                               /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
+                               M_CMP(s2, REG_ITMP3);*/
+                               M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1);
+
+                               /* branch if (x GE 1) */
+                               M_CMP_IMM(REG_ITMP1, 1);
+                               M_BGE(0);
+                               codegen_add_branch_ref(cd, iptr->dst.block);
                        }
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
                        break;
-                       
-               case ICMD_IF_LLT:
-               case ICMD_IF_LLE:
-               case ICMD_IF_LGT:
-               case ICMD_IF_LGE:
 
-                       /* ATTENTION: compare high words signed and low words unsigned */
+               case ICMD_IF_LGT:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
-                       M_COMPARE(s1, (iptr->sx.val.l >> 32), UNCOND, 0);
+                       s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
+#if 0
+                       if (iptr->sx.val.l == 0) {
+                               /* if high word is greater than zero, the whole long is too */
+                               M_CMP_IMM(s1, 0);
+                               M_BGT(0);
+                               codegen_add_branch_ref(cd, iptr->dst.block);
 
-                       switch(iptr->opc) {
-                       case ICMD_IF_LLT:
-                       case ICMD_IF_LLE:
-                               M_BLT(0);
-                               codegen_addreference(cd, iptr->dst.block);
-                               break;
-                       case ICMD_IF_LGT:
-                       case ICMD_IF_LGE:
+                               /* ... or high was zero and low is non zero (tricky!) */
+                               M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
+                               M_MOVLT_IMM(1, REG_ITMP3);
+                               M_ORR_S(REG_ITMP3, s2, REG_ITMP3);
+                               M_BNE(0);
+                               codegen_add_branch_ref(cd, iptr->dst.block);
+                       }
+                       else {
+#endif
+                               /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
+                               M_COMPARE(s1, (iptr->sx.val.l >> 32));
+                               /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
+                               M_CMP(s1, REG_ITMP3);*/
+                               M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
+                               M_MOVGT_IMM(2, REG_ITMP1);
+                               M_MOVEQ_IMM(1, REG_ITMP1);
+
+                               /* low compare: x=x+1(ifHI) */
+                               M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
+                               /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
+                               M_CMP(s2, REG_ITMP3);*/
+                               M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1);
+
+                               /* branch if (x GT 1) */
+                               M_CMP_IMM(REG_ITMP1, 1);
                                M_BGT(0);
-                               codegen_addreference(cd, iptr->dst.block);
-                               break;
-                       case ICMD_IF_LEQ: /* EQ and NE are the same for unsigned */
-                       case ICMD_IF_LNE:
-                               break;
-                       default:
-                               assert(0);
+                               codegen_add_branch_ref(cd, iptr->dst.block);
+#if 0
                        }
+#endif
+                       break;
 
-                       s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
+               case ICMD_IF_LNE:       /* ..., value ==> ...                         */
 
-                       switch(iptr->opc) {
-                       case ICMD_IF_LLT:
-                               M_COMPARE(s1, (iptr->sx.val.l & 0xffffffff), COND_EQ, 1);
-                               M_BLO(0);
-                               break;
-                       case ICMD_IF_LLE:
-                               M_COMPARE(s1, (iptr->sx.val.l & 0xffffffff), COND_EQ, 1);
-                               M_BLS(0);
-                               break;
-                       case ICMD_IF_LGT:
-                               M_COMPARE(s1, (iptr->sx.val.l & 0xffffffff), COND_EQ, 1);
-                               M_BHI(0);
-                               break;
-                       case ICMD_IF_LGE:
-                               M_COMPARE(s1, (iptr->sx.val.l & 0xffffffff), COND_EQ, 1);
-                               M_BHS(0);
-                               break;
-                       case ICMD_IF_LEQ:
-                               M_COMPARE(s1, (iptr->sx.val.l & 0xffffffff), COND_EQ, 0);
-                               M_BEQ(0);
-                               break;
-                       case ICMD_IF_LNE:
-                               M_COMPARE(s1, (iptr->sx.val.l & 0xffffffff), COND_EQ, 0);
-                               M_BNE(0);
-                               break;
-                       default:
-                               assert(0);
+                       s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
+                       if (iptr->sx.val.l == 0) {
+                               M_ORR_S(s1, s2, REG_ITMP3);
                        }
-                       codegen_addreference(cd, iptr->dst.block);
+                       else {
+                               M_COMPARE(s1, (iptr->sx.val.l >> 32));
+                               /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
+                               M_CMP(s1, REG_ITMP3);*/
+                               ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
+                               M_CMPEQ(s2, REG_ITMP3);
+                       }
+                       M_BNE(0);
+                       codegen_add_branch_ref(cd, iptr->dst.block);
                        break;
-
+                       
                case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
                case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
                case ICMD_IF_ICMPNE:
@@ -2030,7 +2089,7 @@ bool codegen(jitdata *jd)
 
                        /* range check (index <= high-low) */
                        i = i - l + 1;
-                       M_COMPARE(REG_ITMP1, i-1, UNCOND, 0);
+                       M_COMPARE(REG_ITMP1, i-1);
                        M_BHI(0); /* unsigned greater than */
                        codegen_addreference(cd, table[0].block);
 
@@ -2064,7 +2123,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
 
                        while (--i >= 0) {
-                               M_COMPARE(s1, lookup->value, UNCOND, 0);
+                               M_COMPARE(s1, lookup->value);
                                M_BEQ(0);
                                codegen_addreference(cd, lookup->target.block);
                                lookup++;
index 109105c258c27482e5665bde64478eb3460ee4dc..f0caa74ab6d8ea860c5994ce8242aa1aa2e81c9d 100644 (file)
@@ -27,7 +27,7 @@
    Authors: Michael Starzinger
             Christian Thalinger
 
-   $Id: codegen.h 7505 2007-03-12 13:34:37Z twisti $
+   $Id: codegen.h 7511 2007-03-13 16:32:56Z michi $
 
 */
 
@@ -485,12 +485,16 @@ void asm_debug_intern(int a1, int a2, int a3, int a4);
 #define M_MOVEQ(a,d)       M_DAT(COND_EQ,0x0d,d,0,0,0,a)
 
 #define M_MOVVS_IMM(i,d)   M_DAT(COND_VS,0x0d,d,0,0,1,i)
+#define M_MOVEQ_IMM(i,d)   M_DAT(COND_EQ,0x0d,d,0,0,1,i)
 #define M_MOVNE_IMM(i,d)   M_DAT(COND_NE,0x0d,d,0,0,1,i)
 #define M_MOVLT_IMM(i,d)   M_DAT(COND_LT,0x0d,d,0,0,1,i)
+#define M_MOVGT_IMM(i,d)   M_DAT(COND_GT,0x0d,d,0,0,1,i)
 #define M_MOVLS_IMM(i,d)   M_DAT(COND_LS,0x0d,d,0,0,1,i)
 
+#define M_ADDHI_IMM(d,a,i) M_DAT(COND_HI,0x04,d,a,0,1,i)
 #define M_ADDLT_IMM(d,a,i) M_DAT(COND_LT,0x04,d,a,0,1,i)
 #define M_ADDGT_IMM(d,a,i) M_DAT(COND_GT,0x04,d,a,0,1,i)
+#define M_SUBLO_IMM(d,a,i) M_DAT(COND_CC,0x02,d,a,0,1,i)
 #define M_SUBLT_IMM(d,a,i) M_DAT(COND_LT,0x02,d,a,0,1,i)
 #define M_SUBGT_IMM(d,a,i) M_DAT(COND_GT,0x02,d,a,0,1,i)
 #define M_RSBMI_IMM(d,a,i) M_DAT(COND_MI,0x03,d,a,0,1,i)
@@ -499,6 +503,8 @@ void asm_debug_intern(int a1, int a2, int a3, int a4);
 #define M_CMPEQ(a,b)       M_DAT(COND_EQ,0x0a,0,a,1,0,b)        /* TST a -  b */
 #define M_CMPLE(a,b)       M_DAT(COND_LE,0x0a,0,a,1,0,b)        /* TST a -  b */
 
+#define M_CMPEQ_IMM(a,i)   M_DAT(COND_EQ,0x0a,0,a,1,1,i)
+
 #define M_MUL(d,a,b)       M_MULT(UNCOND,d,a,b,0,0,0x0)         /* d = a *  b */
 
 
@@ -1077,18 +1083,14 @@ do { \
    uses M_CMP or M_CMP_IMM to do the compare
    ATTENTION: uses REG_ITMP3 as intermediate register
 */
-/* TODO: improve this and add some comments! */
-#define M_COMPARE(reg, val, cond, overjump) \
+#define M_COMPARE(reg, val) \
        if (IS_IMM(val)) { \
-               if (overjump) M_BNE(1); \
-               /* M_CMP_IMM */ M_DAT(cond,0x0a,0,(reg),1,1,(val)); \
+               M_CMP_IMM(reg, (val)); \
        } else if(IS_IMM(-(val))) { \
-               if (overjump) M_BNE(1); \
-               /* M_CMN_IMM */ M_DAT(cond,0x0b,0,(reg),1,1,-(val)); \
+               M_CMN_IMM(reg, -(val)); \
        } else { \
                ICONST(REG_ITMP3, (val)); \
-               if (overjump) M_BNE(1); \
-               /* M_CMP */ M_DAT(cond,0x0a,0,(reg),1,0,REG_ITMP3); \
+               M_CMP(reg, REG_ITMP3); \
        }
 
 /* M_LONGBRANCH: