diff mbox

Valgrind: ldrexd/strexd in thumb mode

Message ID BANLkTimye=8AjAxtnvY7FUwJ+HsSJV-WMQ@mail.gmail.com
State New
Headers show

Commit Message

Dr. David Alan Gilbert July 1, 2011, 1:59 p.m. UTC
https://bugs.kde.org/attachment.cgi?id=61530 for bug
https://bugs.kde.org/show_bug.cgi?id=266035
diff mbox

Patch

--- guest_arm_toIR.c	(revision 2163)
+++ guest_arm_toIR.c	(working copy)
@@ -17706,6 +17769,76 @@ 
       }
    }
 
+   /* ----------------- (T1) LDREXD ---------------- */
+   if (INSN0(15,4) == 0xe8d) {
+     /* ldrexb, ldrexh, ldrexd (also TBB and tbh but they're done elsewhere */
+     if (INSN1(7,0) == 0x7f) {
+       /* ldrexd */
+       UInt rN  = INSN0(3,0);
+       UInt rT  = INSN1(15,12);
+       UInt rT2 = INSN1(11,8);
+
+       if (isBadRegT(rT) || isBadRegT(rT2) || rT == rT2 || rN == 15) {
+         /* undecodable; fall through */
+       } else {
+         IRTemp res;
+
+         // go uncond
+         mk_skip_over_T32_if_cond_is_false( condT );
+
+         /* Ok, now we're unconditional.  Do the load. */
+         res = newTemp(Ity_I64);
+         stmt( IRStmt_LLSC(Iend_LE, res, getIRegT(rN),
+                           NULL/*this is a load*/) );
+         putIRegT(rT, unop(Iop_64HIto32, mkexpr(res)), IRTemp_INVALID);
+         putIRegT(rT2, unop(Iop_64to32, mkexpr(res)), IRTemp_INVALID);
+
+         DIP("ldrexd r%u, r%u, [r%u]\n", rT, rT2, rN);
+         goto decode_success;
+       }
+     }
+   }
+   /* ----------------- (T1) STREXD ---------------- */
+   if (INSN0(15,4) == 0xe8c) {
+     /* strexb, strexh, strexd */
+     if (INSN1(7,4) == 0x7) {
+       /* strexd */
+       UInt rN  = INSN0(3,0);
+       UInt rT  = INSN1(15,12);
+       UInt rT2 = INSN1(11,8);
+       UInt rD  = INSN1(3,0);
+
+      if (rD == 15 || rN == 15
+          || isBadRegT(rD) || isBadRegT(rT) || isBadRegT(rT2)
+          || rD == rN || rD == rT || rD == rT2) {
+         /* undecodable; fall through */
+      } else {
+         IRTemp data;
+         IRTemp resSC1, resSC32;
+
+         // go uncond
+         mk_skip_over_T32_if_cond_is_false( condT );
+
+         data = newTemp(Ity_I64);
+         assign( data, binop(Iop_32HLto64, getIRegT(rT), getIRegT(rT2)) );
+         resSC1 = newTemp(Ity_I1);
+         stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegT(rN), mkexpr(data)) );
+
+         /* Set rD to 1 on failure, 0 on success.  Currently we have
+            resSC1 == 0 on failure, 1 on success. */
+         resSC32 = newTemp(Ity_I32);
+         assign(resSC32,
+                unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
+
+         putIRegT(rD, mkexpr(resSC32),
+                      IRTemp_INVALID);
+         DIP("strexd r%u, r%u, r%u, [r%u]\n", rD, rT, rT2, rN);
+         goto decode_success;
+      }
+      /* fall through */
+     }
+   }
+
    /* ----------------- (T1) STREX ----------------- */
    if (INSN0(15,4) == 0xE84) {
       UInt rN   = INSN0(3,0);