]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add function s390_isel_amode_b12_b20 to compile an expression into an
authorFlorian Krohm <florian@eich-krohm.de>
Sat, 22 Nov 2014 20:10:21 +0000 (20:10 +0000)
committerFlorian Krohm <florian@eich-krohm.de>
Sat, 22 Nov 2014 20:10:21 +0000 (20:10 +0000)
amode that is either S390_AMODE_B12 or S390_AMODE_B20. This is needed
for compare-and-swap insns. As we're currently not generating amodes
using an index register, there was never a problem.
This change future-proofs the code.
Also add a few more asserts for amodes in the s390_insns supporting
translation chaining.
Fixes BZ #269360.

git-svn-id: svn://svn.valgrind.org/vex/trunk@3000

VEX/priv/host_s390_defs.c
VEX/priv/host_s390_isel.c

index e5f007655733d9383b5f9194a5fec0a487f41806..cce67acacf7091f44cc5c3159ba1e833d6d53653 100644 (file)
@@ -5592,6 +5592,7 @@ s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
 
    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;
@@ -5615,6 +5616,7 @@ s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, s390_amode *op2,
    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;
@@ -6345,6 +6347,8 @@ s390_insn_xdirect(s390_cc_t cond, Addr64 dst, s390_amode *guest_IA,
 {
    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
 
+   vassert(guest_IA->tag == S390_AMODE_B12);
+
    insn->tag  = S390_INSN_XDIRECT;
    insn->size = 0;   /* does not matter */
 
@@ -6362,6 +6366,8 @@ s390_insn_xindir(s390_cc_t cond, HReg dst, s390_amode *guest_IA)
 {
    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
 
+   vassert(guest_IA->tag == S390_AMODE_B12);
+
    insn->tag  = S390_INSN_XINDIR;
    insn->size = 0;   /* does not matter */
 
@@ -6379,6 +6385,8 @@ s390_insn_xassisted(s390_cc_t cond, HReg dst, s390_amode *guest_IA,
 {
    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
 
+   vassert(guest_IA->tag == S390_AMODE_B12);
+
    insn->tag  = S390_INSN_XASSISTED;
    insn->size = 0;   /* does not matter */
 
@@ -8185,9 +8193,11 @@ s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
    b  = hregNumber(am->b);
    d  = am->d;
 
+   vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
+
    switch (insn->size) {
    case 4:
-      /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
+      /* 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)
          buf = s390_emit_CS(buf, R0, r3, b, d);
@@ -8197,7 +8207,7 @@ s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
       return s390_emit_LR(buf, old, R0);
 
    case 8:
-      /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
+      /* 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 */
@@ -8233,6 +8243,7 @@ s390_insn_cdas_emit(UChar *buf, const s390_insn *insn)
    d  = am->d;
 
    vassert(scratch == 1);
+   vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
 
    switch (insn->size) {
    case 4:
index 6affc04957dc8d699b29a2aecf9bb2f4413bb43b..fc320144e1077f53b3f86ab61e31547429576d46 100644 (file)
@@ -127,6 +127,7 @@ typedef struct {
 /* Forward declarations */
 static HReg          s390_isel_int_expr(ISelEnv *, IRExpr *);
 static s390_amode   *s390_isel_amode(ISelEnv *, IRExpr *);
+static s390_amode   *s390_isel_amode_b12_b20(ISelEnv *, IRExpr *);
 static s390_cc_t     s390_isel_cc(ISelEnv *, IRExpr *);
 static s390_opnd_RMI s390_isel_int_expr_RMI(ISelEnv *, IRExpr *);
 static void          s390_isel_int128_expr(HReg *, HReg *, ISelEnv *, IRExpr *);
@@ -286,9 +287,11 @@ ulong_fits_signed_8bit(ULong val)
 }
 
 /* EXPR is an expression that is used as an address. Return an s390_amode
-   for it. */
+   for it. If select_b12_b20_only is true the returned amode must be either
+   S390_AMODE_B12 or S390_AMODE_B20. */
 static s390_amode *
-s390_isel_amode_wrk(ISelEnv *env, IRExpr *expr)
+s390_isel_amode_wrk(ISelEnv *env, IRExpr *expr,
+                    Bool select_b12_b20_only __attribute__((unused)))
 {
    if (expr->tag == Iex_Binop && expr->Iex.Binop.op == Iop_Add64) {
       IRExpr *arg1 = expr->Iex.Binop.arg1;
@@ -331,7 +334,7 @@ s390_isel_amode(ISelEnv *env, IRExpr *expr)
    /* Address computation should yield a 64-bit value */
    vassert(typeOfIRExpr(env->type_env, expr) == Ity_I64);
 
-   am = s390_isel_amode_wrk(env, expr);
+   am = s390_isel_amode_wrk(env, expr, /* B12, B20 only */ False);
 
    /* Check post-condition */
    vassert(s390_amode_is_sane(am));
@@ -340,6 +343,38 @@ s390_isel_amode(ISelEnv *env, IRExpr *expr)
 }
 
 
+/* Sometimes we must compile an expression into an amode that is either
+   S390_AMODE_B12 or S390_AMODE_B20. An example is the compare-and-swap
+   opcode. These opcodes do not have a variant hat accepts an addressing
+   mode with an index register.
+   Now, in theory we could, when emitting the compare-and-swap insn,
+   hack a, say, BX12 amode into a B12 amode like so:
+
+      r0 = b       # save away base register
+      b  = b + x   # add index register to base register
+      cas(b,d,...) # emit compare-and-swap using b12 amode
+      b  = r0      # restore base register
+
+   Unfortunately, emitting the compare-and-swap insn already utilises r0
+   under the covers, so the trick above is off limits, sadly. */
+static s390_amode *
+s390_isel_amode_b12_b20(ISelEnv *env, IRExpr *expr)
+{
+   s390_amode *am;
+
+   /* Address computation should yield a 64-bit value */
+   vassert(typeOfIRExpr(env->type_env, expr) == Ity_I64);
+
+   am = s390_isel_amode_wrk(env, expr, /* B12, B20 only */ True);
+
+   /* Check post-condition */
+   vassert(s390_amode_is_sane(am) &&
+           (am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20));
+
+   return am;
+}
+
+
 /*---------------------------------------------------------*/
 /*--- Helper functions                                  ---*/
 /*---------------------------------------------------------*/
@@ -3781,7 +3816,7 @@ no_memcpy_put:
    case Ist_CAS:
       if (stmt->Ist.CAS.details->oldHi == IRTemp_INVALID) {
          IRCAS *cas = stmt->Ist.CAS.details;
-         s390_amode *op2 = s390_isel_amode(env, cas->addr);
+         s390_amode *op2 = s390_isel_amode_b12_b20(env, cas->addr);
          HReg op3 = s390_isel_int_expr(env, cas->dataLo);  /* new value */
          HReg op1 = s390_isel_int_expr(env, cas->expdLo);  /* expected value */
          HReg old = lookupIRTemp(env, cas->oldLo);
@@ -3794,7 +3829,7 @@ no_memcpy_put:
          return;
       } else {
          IRCAS *cas = stmt->Ist.CAS.details;
-         s390_amode *op2 = s390_isel_amode(env,  cas->addr);
+         s390_amode *op2 = s390_isel_amode_b12_b20(env, cas->addr);
          HReg r8, r9, r10, r11, r1;
          HReg op3_high = s390_isel_int_expr(env, cas->dataHi);  /* new value */
          HReg op3_low  = s390_isel_int_expr(env, cas->dataLo);  /* new value */