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 $
*/
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:
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);
}
codegen_addreference(cd, iptr->dst.block);
break;
-#if 0
case ICMD_IF_LLT: /* ..., value ==> ... */
s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
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:
/* 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);
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++;
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 $
*/
#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)
#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 */
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: