s390x: FLOGR is not universally available. Fixes #268715.
(Florian Krohm, britzel@acm.org)
git-svn-id: svn://svn.valgrind.org/vex/trunk@2114 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/host_s390_defs.c b/priv/host_s390_defs.c
index 9693824..b0504de 100644
--- a/priv/host_s390_defs.c
+++ b/priv/host_s390_defs.c
@@ -574,10 +574,10 @@
s390_opnd_RMI_get_reg_usage(u, insn->variant.divs.op2);
break;
- case S390_INSN_FLOGR:
- addHRegUse(u, HRmWrite, insn->variant.flogr.bitpos);
- addHRegUse(u, HRmWrite, insn->variant.flogr.modval);
- s390_opnd_RMI_get_reg_usage(u, insn->variant.flogr.src);
+ case S390_INSN_CLZ:
+ addHRegUse(u, HRmWrite, insn->variant.clz.num_bits);
+ addHRegUse(u, HRmWrite, insn->variant.clz.clobber);
+ s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src);
break;
case S390_INSN_UNOP:
@@ -781,10 +781,10 @@
s390_opnd_RMI_map_regs(m, &insn->variant.divs.op2);
break;
- case S390_INSN_FLOGR:
- insn->variant.flogr.bitpos = lookupHRegRemap(m, insn->variant.flogr.bitpos);
- insn->variant.flogr.modval = lookupHRegRemap(m, insn->variant.flogr.modval);
- s390_opnd_RMI_map_regs(m, &insn->variant.flogr.src);
+ case S390_INSN_CLZ:
+ insn->variant.clz.num_bits = lookupHRegRemap(m, insn->variant.clz.num_bits);
+ insn->variant.clz.clobber = lookupHRegRemap(m, insn->variant.clz.clobber);
+ s390_opnd_RMI_map_regs(m, &insn->variant.clz.src);
break;
case S390_INSN_UNOP:
@@ -3818,19 +3818,19 @@
s390_insn *
-s390_insn_flogr(UChar size, HReg bitpos, HReg modval, s390_opnd_RMI src)
+s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
{
s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
vassert(size == 8);
- vassert(! hregIsVirtual(bitpos));
- vassert(! hregIsVirtual(modval));
+ vassert(! hregIsVirtual(num_bits));
+ vassert(! hregIsVirtual(clobber));
- insn->tag = S390_INSN_FLOGR;
+ insn->tag = S390_INSN_CLZ;
insn->size = size;
- insn->variant.flogr.bitpos = bitpos; /* bit position */
- insn->variant.flogr.modval = modval; /* modified input value */
- insn->variant.flogr.src = src;
+ insn->variant.clz.num_bits = num_bits;
+ insn->variant.clz.clobber = clobber;
+ insn->variant.clz.src = src;
return insn;
}
@@ -4329,9 +4329,9 @@
&insn->variant.divs.op2);
break;
- case S390_INSN_FLOGR:
- s390_sprintf(buf, "%M %R,%O", "v-flogr", insn->variant.flogr.bitpos,
- &insn->variant.flogr.src);
+ case S390_INSN_CLZ:
+ s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
+ &insn->variant.clz.src);
break;
case S390_INSN_UNOP:
@@ -6003,25 +6003,25 @@
static UChar *
-s390_insn_flogr_emit(UChar *buf, const s390_insn *insn)
+s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
{
s390_opnd_RMI src;
- UChar r1, r1p1;
+ UChar r1, r1p1, r2, *p;
- r1 = hregNumber(insn->variant.flogr.bitpos);
- r1p1 = hregNumber(insn->variant.flogr.modval);
+ r1 = hregNumber(insn->variant.clz.num_bits);
+ r1p1 = hregNumber(insn->variant.clz.clobber);
vassert((r1 & 0x1) == 0);
vassert(r1p1 == r1 + 1);
- src = insn->variant.flogr.src;
+ p = buf;
+ src = insn->variant.clz.src;
+ /* Get operand and move it to r2 */
switch (src.tag) {
- case S390_OPND_REG: {
- UInt r2 = hregNumber(src.variant.reg);
-
- return s390_emit_FLOGR(buf, r1, r2);
- }
+ case S390_OPND_REG:
+ r2 = hregNumber(src.variant.reg);
+ break;
case S390_OPND_AMODE: {
const s390_amode *am = src.variant.am;
@@ -6029,23 +6029,49 @@
UChar x = hregNumber(am->x);
Int d = am->d;
- buf = s390_emit_LG(buf, R0, x, b, DISP20(d));
- return s390_emit_FLOGR(buf, r1, R0);
+ p = s390_emit_LG(p, R0, x, b, DISP20(d));
+ r2 = R0;
+ break;
}
case S390_OPND_IMMEDIATE: {
ULong value = src.variant.imm;
- buf = s390_emit_load_64imm(buf, R0, value);
- return s390_emit_FLOGR(buf, r1, R0);
+ p = s390_emit_load_64imm(p, R0, value);
+ r2 = R0;
+ break;
}
default:
goto fail;
}
+ /* Use FLOGR if you can */
+ if (s390_host_has_eimm) {
+ return s390_emit_FLOGR(p, r1, r2);
+ }
+
+ /*
+ r0 = r2;
+ r1 = 64;
+ while (r0 != 0) {
+ r1 -= 1;
+ r0 >>= 1;
+ }
+ */
+ p = s390_emit_LTGR(p, R0, r2);
+ p = s390_emit_LLILL(p, r1, 64);
+
+ p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2); /* 4 bytes */
+ p = s390_emit_AGHI(p, r1, (UShort)-1); /* r1 -= 1; 4 bytes */
+ p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1)); /* r0 >>= 1; 6 bytes */
+ p = s390_emit_LTGR(p, R0, R0); /* set cc 4 bytes */
+ p = s390_emit_BRC(p, S390_CC_NE, /* 4 bytes */
+ (UShort)(-(4 + 6 + 4) / 2));
+ return p;
+
fail:
- vpanic("s390_insn_flogr_emit");
+ vpanic("s390_insn_clz_emit");
}
@@ -6721,8 +6747,8 @@
end = s390_insn_divs_emit(buf, insn);
break;
- case S390_INSN_FLOGR:
- end = s390_insn_flogr_emit(buf, insn);
+ case S390_INSN_CLZ:
+ end = s390_insn_clz_emit(buf, insn);
break;
case S390_INSN_UNOP: