From bfea0ff978b7f19be873b80632eb863fc894876c Mon Sep 17 00:00:00 2001 From: michi Date: Tue, 13 Mar 2007 16:32:56 +0000 Subject: [PATCH] * src/vm/jit/arm/codegen.c (codegen): Long branches are implemented 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 | 207 +++++++++++++++++++++++++-------------- src/vm/jit/arm/codegen.h | 20 ++-- 2 files changed, 144 insertions(+), 83 deletions(-) diff --git a/src/vm/jit/arm/codegen.c b/src/vm/jit/arm/codegen.c index c314275d5..529bdeb93 100644 --- a/src/vm/jit/arm/codegen.c +++ b/src/vm/jit/arm/codegen.c @@ -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++; diff --git a/src/vm/jit/arm/codegen.h b/src/vm/jit/arm/codegen.h index 109105c25..f0caa74ab 100644 --- a/src/vm/jit/arm/codegen.h +++ b/src/vm/jit/arm/codegen.h @@ -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: -- 2.25.1