s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
vassert(size == 4 || size == 8);
- vassert(hregNumber(op2->x) == 0);
- vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
insn->tag = S390_INSN_CAS;
insn->size = size;
s390_cdas *cdas = LibVEX_Alloc_inline(sizeof(s390_cdas));
vassert(size == 4 || size == 8);
- vassert(hregNumber(op2->x) == 0);
vassert(hregNumber(scratch) == 1); /* r0,r1 used as scratch reg pair */
- vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
insn->tag = S390_INSN_CDAS;
insn->size = size;
static UChar *
s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
{
- UChar r1, r3, b, old;
+ UChar r1, r3, b, x, old;
Int d;
s390_amode *am;
old= hregNumber(insn->variant.cas.old_mem);
am = insn->variant.cas.op2;
b = hregNumber(am->b);
+ x = hregNumber(am->x);
d = am->d;
- vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
+ int b_was_zero = b == 0;
+ if (x != 0) {
+ if (b != 0)
+ buf = s390_emit_AGR(buf, b, x); // b = b + x
+ else
+ b = x;
+ }
switch (insn->size) {
case 4:
/* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
buf = s390_emit_LR(buf, R0, r1);
- if (am->tag == S390_AMODE_B12)
+ if (am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_BX12)
buf = s390_emit_CS(buf, R0, r3, b, d);
else
buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
/* Now copy R0 which has the old memory value to OLD */
- return s390_emit_LR(buf, old, R0);
+ buf = s390_emit_LR(buf, old, R0);
+ break;
case 8:
/* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
buf = s390_emit_LGR(buf, R0, r1);
buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
/* Now copy R0 which has the old memory value to OLD */
- return s390_emit_LGR(buf, old, R0);
+ buf = s390_emit_LGR(buf, old, R0);
+ break;
default:
goto fail;
}
+ if (x != 0) {
+ if (! b_was_zero) {
+ buf = s390_emit_SGR(buf, b, x);
+ } else {
+ /* Nothing to do because b was 0 and that is a scratch reg. */
+ }
+ }
+ return buf;
+
fail:
vpanic("s390_insn_cas_emit");
}
static UChar *
s390_insn_cdas_emit(UChar *buf, const s390_insn *insn)
{
- UChar r1, r1p1, r3, /*r3p1,*/ b, old_high, old_low, scratch;
+ UChar r1, r1p1, r3, /*r3p1,*/ b, x, old_high, old_low, scratch;
Int d;
s390_amode *am;
s390_cdas *cdas = insn->variant.cdas.details;
scratch = hregNumber(cdas->scratch);
am = cdas->op2;
b = hregNumber(am->b);
+ x = hregNumber(am->x);
d = am->d;
+ int b_was_zero = b == 0;
+ if (x != 0) {
+ if (b != 0)
+ buf = s390_emit_AGR(buf, b, x); // b = b + x
+ else
+ b = x;
+ }
vassert(scratch == 1);
- vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
switch (insn->size) {
case 4:
buf = s390_emit_LR(buf, R0, r1);
buf = s390_emit_LR(buf, scratch, r1p1);
- if (am->tag == S390_AMODE_B12)
+ if (am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_BX12)
buf = s390_emit_CDS(buf, R0, r3, b, d);
else
buf = s390_emit_CDSY(buf, R0, r3, b, DISP20(d));
/* Now copy R0,scratch which has the old memory value to OLD */
buf = s390_emit_LR(buf, old_high, R0);
buf = s390_emit_LR(buf, old_low, scratch);
- return buf;
+ break;
case 8:
/* r1, r1+1 must not be overwritten. So copy them to R0,scratch
/* Now copy R0,scratch which has the old memory value to OLD */
buf = s390_emit_LGR(buf, old_high, R0);
buf = s390_emit_LGR(buf, old_low, scratch);
- return buf;
+ break;
default:
goto fail;
}
+ if (x != 0) {
+ if (! b_was_zero) {
+ buf = s390_emit_SGR(buf, b, x);
+ } else {
+ /* Nothing to do because b was 0 and that is a scratch reg. */
+ }
+ }
+ return buf;
+
fail:
vpanic("s390_insn_cdas_emit");
}
am = s390_isel_amode_wrk(env, expr, True, False);
- /* Check post-condition */
- vassert(s390_amode_is_sane(am) &&
- (am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20));
+ HReg x = newVRegI(env);
+ ULong d = (Long)am->d;
+
+ static UInt count = 0;
+
+ ++count;
+ if ((count % 2) == 0) {
+ /* Scenario #1: Move d to the index register and construct
+ an amode with d == 0 */
+ if (d != 0) {
+// vex_printf("!!! CASE 1\n");
+ addInstr(env, s390_insn_load_immediate(8, x, d));
+
+ if (am->tag == S390_AMODE_B12)
+ return s390_amode_bx12(0, am->b, x);
+ if (am->tag == S390_AMODE_B20)
+ return s390_amode_bx20(0, am->b, x);
+ vpanic("WHOOPSIE");
+ } else {
+// vex_printf("!!! CASE 2\n");
+ d = -11;
+ addInstr(env, s390_insn_load_immediate(8, x, d));
- return am;
+ if (am->tag == S390_AMODE_B12)
+ return s390_amode_bx12(-d, am->b, x);
+ if (am->tag == S390_AMODE_B20)
+ return s390_amode_bx20(-d, am->b, x);
+ vpanic("WHOOPSIE");
+ }
+ } else {
+ /* Scenario #2: Use b as an index register and construct an
+ amode with b == R0. */
+// vex_printf("!!! CASE 3\n");
+ if (am->tag == S390_AMODE_B12)
+ return s390_amode_bx12(d, s390_hreg_gpr(0), am->b);
+ if (am->tag == S390_AMODE_B20)
+ return s390_amode_bx20(d, s390_hreg_gpr(0), am->b);
+ vpanic("WHOOPSIE");
+ }
}