]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Change the IR representation of load linked and store conditional.
authorJulian Seward <jseward@acm.org>
Thu, 26 Nov 2009 17:17:37 +0000 (17:17 +0000)
committerJulian Seward <jseward@acm.org>
Thu, 26 Nov 2009 17:17:37 +0000 (17:17 +0000)
They are now moved out into their own new IRStmt kind (IRStmt_LLSC),
and are not treated merely as variants of standard loads (IRExpr_Load)
or store (IRStmt_Store).  This is necessary because load linked is a
load with a side effect (lodging a reservation), hence it cannot be an
IRExpr since IRExprs denote side-effect free value computations.

Fix up all front and back ends accordingly; also iropt.

Fixes #215771.

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

12 files changed:
VEX/priv/guest_amd64_toIR.c
VEX/priv/guest_arm_toIR.c
VEX/priv/guest_ppc_toIR.c
VEX/priv/guest_x86_toIR.c
VEX/priv/host_amd64_isel.c
VEX/priv/host_arm_isel.c
VEX/priv/host_ppc_isel.c
VEX/priv/host_x86_isel.c
VEX/priv/ir_defs.c
VEX/priv/ir_match.c
VEX/priv/ir_opt.c
VEX/pub/libvex_ir.h

index 1d55bc53468bada183f10718da08a84c857586e8..be656428e7c6c7fa36d943a78791783892de23e9 100644 (file)
@@ -312,12 +312,12 @@ static IRExpr* mkU ( IRType ty, ULong i )
 
 static void storeLE ( IRExpr* addr, IRExpr* data )
 {
-   stmt( IRStmt_Store(Iend_LE, IRTemp_INVALID, addr, data) );
+   stmt( IRStmt_Store(Iend_LE, addr, data) );
 }
 
-static IRExpr* loadLE ( IRType ty, IRExpr* data )
+static IRExpr* loadLE ( IRType ty, IRExpr* addr )
 {
-   return IRExpr_Load(False, Iend_LE, ty, data);
+   return IRExpr_Load(Iend_LE, ty, addr);
 }
 
 static IROp mkSizedOp ( IRType ty, IROp op8 )
index dd36a00f3693b34bb416c08fca78f744b3913d5d..fb6a6b73e4b21b81b15759578b3fda4f2a22c446 100644 (file)
@@ -495,7 +495,7 @@ static void assign ( IRTemp dst, IRExpr* e )
 
 static void storeLE ( IRExpr* addr, IRExpr* data )
 {
-   stmt( IRStmt_Store(Iend_LE, IRTemp_INVALID, addr, data) );
+   stmt( IRStmt_Store(Iend_LE, addr, data) );
 }
 
 static IRExpr* unop ( IROp op, IRExpr* a )
@@ -543,9 +543,9 @@ static IRExpr* mkU ( IRType ty, UInt i )
 }
 #endif
 
-static IRExpr* loadLE ( IRType ty, IRExpr* data )
+static IRExpr* loadLE ( IRType ty, IRExpr* addr )
 {
-   return IRExpr_Load(False, Iend_LE, ty, data);
+   return IRExpr_Load(Iend_LE, ty, addr);
 }
 
 #if 0
index 92cc7d0ddec53d142b5531dabf365687654dbb41..eda971d9d60050c443041c40d2d7a87d7822ea57 100644 (file)
@@ -467,7 +467,7 @@ static void storeBE ( IRExpr* addr, IRExpr* data )
 {
    IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
    vassert(tyA == Ity_I32 || tyA == Ity_I64);
-   stmt( IRStmt_Store(Iend_BE, IRTemp_INVALID, addr, data) );
+   stmt( IRStmt_Store(Iend_BE, addr, data) );
 }
 
 static IRExpr* unop ( IROp op, IRExpr* a )
@@ -517,20 +517,9 @@ static IRExpr* mkU64 ( ULong i )
 }
 
 /* This generates a normal (non load-linked) load. */
-static IRExpr* loadBE ( IRType ty, IRExpr* data )
+static IRExpr* loadBE ( IRType ty, IRExpr* addr )
 {
-   return IRExpr_Load(False, Iend_BE, ty, data);
-}
-
-/* And this, a linked load. */
-static IRExpr* loadlinkedBE ( IRType ty, IRExpr* data )
-{
-   if (mode64) {
-      vassert(ty == Ity_I32 || ty == Ity_I64);
-   } else {
-      vassert(ty == Ity_I32);
-   }
-   return IRExpr_Load(True, Iend_BE, ty, data);
+   return IRExpr_Load(Iend_BE, ty, addr);
 }
 
 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
@@ -4861,7 +4850,8 @@ static Bool dis_memsync ( UInt theInstr )
          stmt( IRStmt_MBE(Imbe_Fence) );
          break;
 
-      case 0x014: // lwarx (Load Word and Reserve Indexed, PPC32 p458)
+      case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
+         IRTemp res;
          /* According to the PowerPC ISA version 2.05, b0 (called EH
             in the documentation) is merely a hint bit to the
             hardware, I think as to whether or not contention is
@@ -4872,10 +4862,13 @@ static Bool dis_memsync ( UInt theInstr )
          gen_SIGBUS_if_misaligned( EA, 4 );
 
          // and actually do the load
-         putIReg( rD_addr, mkWidenFrom32(ty, loadlinkedBE(Ity_I32, mkexpr(EA)),
-                                             False) );
+         res = newTemp(Ity_I32);
+         stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
+
+         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
          break;
-         
+      }
+
       case 0x096: { 
          // stwcx. (Store Word Conditional Indexed, PPC32 p532)
          // Note this has to handle stwcx. in both 32- and 64-bit modes,
@@ -4896,7 +4889,7 @@ static Bool dis_memsync ( UInt theInstr )
 
          // Do the store, and get success/failure bit into resSC
          resSC = newTemp(Ity_I1);
-         stmt( IRStmt_Store(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
+         stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
 
          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
@@ -4948,7 +4941,8 @@ static Bool dis_memsync ( UInt theInstr )
          break;
 
       /* 64bit Memsync */
-      case 0x054: // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
+      case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
+         IRTemp res;
          /* According to the PowerPC ISA version 2.05, b0 (called EH
             in the documentation) is merely a hint bit to the
             hardware, I think as to whether or not contention is
@@ -4961,9 +4955,13 @@ static Bool dis_memsync ( UInt theInstr )
          gen_SIGBUS_if_misaligned( EA, 8 );
 
          // and actually do the load
-         putIReg( rD_addr, loadlinkedBE(Ity_I64, mkexpr(EA)) );
+         res = newTemp(Ity_I64);
+         stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
+
+         putIReg( rD_addr, mkexpr(res) );
          break;
-       
+      }
+      
       case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
          // A marginally simplified version of the stwcx. case
          IRTemp rS = newTemp(Ity_I64);
@@ -4984,7 +4982,7 @@ static Bool dis_memsync ( UInt theInstr )
 
          // Do the store, and get success/failure bit into resSC
          resSC = newTemp(Ity_I1);
-         stmt( IRStmt_Store(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
+         stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
 
          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
index 9f4fcce09dcdb5fdd46e629fce3c8e7b83cde1da..b5f462d32253fa943153a220e5de5f60f476011e 100644 (file)
@@ -648,7 +648,7 @@ static void assign ( IRTemp dst, IRExpr* e )
 
 static void storeLE ( IRExpr* addr, IRExpr* data )
 {
-   stmt( IRStmt_Store(Iend_LE, IRTemp_INVALID, addr, data) );
+   stmt( IRStmt_Store(Iend_LE, addr, data) );
 }
 
 static IRExpr* unop ( IROp op, IRExpr* a )
@@ -708,9 +708,9 @@ static IRExpr* mkV128 ( UShort mask )
    return IRExpr_Const(IRConst_V128(mask));
 }
 
-static IRExpr* loadLE ( IRType ty, IRExpr* data )
+static IRExpr* loadLE ( IRType ty, IRExpr* addr )
 {
-   return IRExpr_Load(False, Iend_LE, ty, data);
+   return IRExpr_Load(Iend_LE, ty, addr);
 }
 
 static IROp mkSizedOp ( IRType ty, IROp op8 )
index e14d3f8dd495975a5b1f79d2807c4179dbeb243a..db65dc04f70766d2485d714a1c9f030cba850585 100644 (file)
@@ -860,8 +860,6 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
       /* We can't handle big-endian loads, nor load-linked. */
       if (e->Iex.Load.end != Iend_LE)
          goto irreducible;
-      if (e->Iex.Load.isLL)
-         goto irreducible;
 
       if (ty == Ity_I64) {
          addInstr(env, AMD64Instr_Alu64R(Aalu_MOV,
@@ -1963,7 +1961,7 @@ static AMD64RMI* iselIntExpr_RMI_wrk ( ISelEnv* env, IRExpr* e )
 
    /* special case: 64-bit load from memory */
    if (e->tag == Iex_Load && ty == Ity_I64
-       && e->Iex.Load.end == Iend_LE && !e->Iex.Load.isLL) {
+       && e->Iex.Load.end == Iend_LE) {
       AMD64AMode* am = iselIntExpr_AMode(env, e->Iex.Load.addr);
       return AMD64RMI_Mem(am);
    }
@@ -2749,7 +2747,7 @@ static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
    }
 
-   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE && !e->Iex.Load.isLL) {
+   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
       AMD64AMode* am;
       HReg res = newVRegV(env);
       vassert(e->Iex.Load.ty == Ity_F32);
@@ -2873,7 +2871,7 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
       return res;
    }
 
-   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE && !e->Iex.Load.isLL) {
+   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
       AMD64AMode* am;
       HReg res = newVRegV(env);
       vassert(e->Iex.Load.ty == Ity_F64);
@@ -3178,7 +3176,7 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
       return dst;
    }
 
-   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE && !e->Iex.Load.isLL) {
+   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
       HReg        dst = newVRegV(env);
       AMD64AMode* am  = iselIntExpr_AMode(env, e->Iex.Load.addr);
       addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 16, dst, am ));
@@ -3603,9 +3601,8 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
       IRType    tya   = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr);
       IRType    tyd   = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
       IREndness end   = stmt->Ist.Store.end;
-      IRTemp    resSC = stmt->Ist.Store.resSC;
 
-      if (tya != Ity_I64 || end != Iend_LE || resSC != IRTemp_INVALID)
+      if (tya != Ity_I64 || end != Iend_LE)
          goto stmt_fail;
 
       if (tyd == Ity_I64) {
index 302d80f4e1b9dafff58caf7a91917b1db9733ffa..114e29ffc90deb7c8233caa6f4116899275c40f7 100644 (file)
@@ -757,9 +757,8 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
        IRType tya = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr);
        IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
        IREndness end = stmt->Ist.Store.end;
-       IRTemp    resSC = stmt->Ist.Store.resSC;
 
-       if (tya != Ity_I32 || end != Iend_LE || resSC != IRTemp_INVALID) 
+       if (tya != Ity_I32 || end != Iend_LE)
           goto stmt_fail;
 
        reg = iselIntExpr_R(env, stmt->Ist.Store.data);
index 131e8fe824eb8ff61a5d44fd5fabfb8a018a1e92..76ddfce07326a633a81f79d97da3e2f37b340b66 100644 (file)
@@ -1169,32 +1169,14 @@ static HReg iselWordExpr_R_wrk ( ISelEnv* env, IRExpr* e )
 
    /* --------- LOAD --------- */
    case Iex_Load: {
-      HReg r_dst; 
-
+      HReg      r_dst;
+      PPCAMode* am_addr;
       if (e->Iex.Load.end != Iend_BE)
          goto irreducible;
-
-      r_dst = newVRegI(env);
-
-      if (e->Iex.Load.isLL) {
-         /* lwarx or ldarx.  Be simple; force address into a register. */
-         HReg r_addr = iselWordExpr_R( env, e->Iex.Load.addr );
-         if (ty == Ity_I32) {
-            addInstr(env, PPCInstr_LoadL( 4, r_dst, r_addr, mode64 ));
-         }
-         else if (ty == Ity_I64 && mode64) {
-            addInstr(env, PPCInstr_LoadL( 8, r_dst, r_addr, mode64 ));
-         }
-         else
-            goto irreducible;
-      } else {
-         /* Normal load; use whatever amodes we can. */
-         PPCAMode* am_addr
-            = iselWordExpr_AMode( env, e->Iex.Load.addr, ty/*of xfer*/ );
-         addInstr(env, PPCInstr_Load( toUChar(sizeofIRType(ty)), 
-                                      r_dst, am_addr, mode64 ));
-      }
-
+      r_dst   = newVRegI(env);
+      am_addr = iselWordExpr_AMode( env, e->Iex.Load.addr, ty/*of xfer*/ );
+      addInstr(env, PPCInstr_Load( toUChar(sizeofIRType(ty)), 
+                                   r_dst, am_addr, mode64 ));
       return r_dst;
       /*NOTREACHED*/
    }
@@ -1551,7 +1533,7 @@ static HReg iselWordExpr_R_wrk ( ISelEnv* env, IRExpr* e )
          DECLARE_PATTERN(p_LDbe16_then_16Uto32);
          DEFINE_PATTERN(p_LDbe16_then_16Uto32,
                         unop(Iop_16Uto32,
-                             IRExpr_Load(False,Iend_BE,Ity_I16,bind(0))) );
+                             IRExpr_Load(Iend_BE,Ity_I16,bind(0))) );
          if (matchIRExpr(&mi,p_LDbe16_then_16Uto32,e)) {
             HReg r_dst = newVRegI(env);
             PPCAMode* amode
@@ -2609,7 +2591,7 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo,
    vassert(typeOfIRExpr(env->type_env,e) == Ity_I64);
 
    /* 64-bit load */
-   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE && !e->Iex.Load.isLL) {
+   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
       HReg tLo    = newVRegI(env);
       HReg tHi    = newVRegI(env);
       HReg r_addr = iselWordExpr_R(env, e->Iex.Load.addr);
@@ -2967,7 +2949,7 @@ static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
    }
 
-   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE && !e->Iex.Load.isLL) {
+   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
       PPCAMode* am_addr;
       HReg r_dst = newVRegF(env);
       vassert(e->Iex.Load.ty == Ity_F32);
@@ -3115,7 +3097,7 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
    }
 
    /* --------- LOAD --------- */
-   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE && !e->Iex.Load.isLL) {
+   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
       HReg r_dst = newVRegF(env);
       PPCAMode* am_addr;
       vassert(e->Iex.Load.ty == Ity_F64);
@@ -3366,7 +3348,7 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
       return dst;
    }
 
-   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE && !e->Iex.Load.isLL) {
+   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
       PPCAMode* am_addr;
       HReg v_dst = newVRegV(env);
       vassert(e->Iex.Load.ty == Ity_V128);
@@ -3770,7 +3752,6 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
       IRType    tya   = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr);
       IRType    tyd   = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
       IREndness end   = stmt->Ist.Store.end;
-      IRTemp    resSC = stmt->Ist.Store.resSC;
 
       if (end != Iend_BE)
          goto stmt_fail;
@@ -3779,34 +3760,6 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
       if (mode64 && (tya != Ity_I64))
          goto stmt_fail;
 
-      if (resSC != IRTemp_INVALID) {
-         /* deal with store-conditional */
-         HReg r_res = lookupIRTemp(env, resSC);
-         HReg r_a   = iselWordExpr_R(env, stmt->Ist.Store.addr);
-         HReg r_src = iselWordExpr_R(env, stmt->Ist.Store.data);
-         HReg r_tmp = newVRegI(env);
-         if (tyd == Ity_I32 || (tyd == Ity_I64 && mode64)) {
-            addInstr(env, PPCInstr_StoreC( tyd==Ity_I32 ? 4 : 8,
-                                           r_a, r_src, mode64 ));
-            addInstr(env, PPCInstr_MfCR( r_tmp ));
-            addInstr(env, PPCInstr_Shft(
-                             Pshft_SHR,
-                             env->mode64 ? False : True/*F:64-bit, T:32-bit shift*/,
-                             r_tmp, r_tmp, 
-                             PPCRH_Imm(False/*unsigned*/, 29)));
-            /* Probably unnecessary, since the IR dest type is Ity_I1,
-               and so we are entitled to leave whatever junk we like
-               drifting round in the upper 31 or 63 bits of r_res.
-               However, for the sake of conservativeness .. */
-            addInstr(env, PPCInstr_Alu(
-                             Palu_AND, 
-                             r_res, r_tmp, 
-                             PPCRH_Imm(False/*signed*/, 1)));
-            return;
-         }
-         goto stmt_fail;
-      }
-
       if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32 ||
           (mode64 && (tyd == Ity_I64))) {
          PPCAMode* am_addr
@@ -3979,6 +3932,67 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
       break;
    }
 
+   /* --------- Load Linked or Store Conditional --------- */
+   case Ist_LLSC: {
+      IRTemp res    = stmt->Ist.LLSC.result;
+      IRType tyRes  = typeOfIRTemp(env->type_env, res);
+      IRType tyAddr = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.addr);
+
+      if (stmt->Ist.LLSC.end != Iend_BE)
+         goto stmt_fail;
+      if (!mode64 && (tyAddr != Ity_I32))
+         goto stmt_fail;
+      if (mode64 && (tyAddr != Ity_I64))
+         goto stmt_fail;
+
+      if (stmt->Ist.LLSC.storedata == NULL) {
+         /* LL */
+         HReg r_addr = iselWordExpr_R( env, stmt->Ist.LLSC.addr );
+         HReg r_dst  = lookupIRTemp(env, res);
+         if (tyRes == Ity_I32) {
+            addInstr(env, PPCInstr_LoadL( 4, r_dst, r_addr, mode64 ));
+            return;
+         }
+         if (tyRes == Ity_I64 && mode64) {
+            addInstr(env, PPCInstr_LoadL( 8, r_dst, r_addr, mode64 ));
+            return;
+         }
+         /* fallthru */;
+      } else {
+         /* SC */
+         HReg   r_res  = lookupIRTemp(env, res); /* :: Ity_I1 */
+         HReg   r_a    = iselWordExpr_R(env, stmt->Ist.LLSC.addr);
+         HReg   r_src  = iselWordExpr_R(env, stmt->Ist.LLSC.storedata);
+         HReg   r_tmp  = newVRegI(env);
+         IRType tyData = typeOfIRExpr(env->type_env,
+                                      stmt->Ist.LLSC.storedata);
+         vassert(tyRes == Ity_I1);
+         if (tyData == Ity_I32 || (tyData == Ity_I64 && mode64)) {
+            addInstr(env, PPCInstr_StoreC( tyData==Ity_I32 ? 4 : 8,
+                                           r_a, r_src, mode64 ));
+            addInstr(env, PPCInstr_MfCR( r_tmp ));
+            addInstr(env, PPCInstr_Shft(
+                             Pshft_SHR,
+                             env->mode64 ? False : True
+                                /*F:64-bit, T:32-bit shift*/,
+                             r_tmp, r_tmp, 
+                             PPCRH_Imm(False/*unsigned*/, 29)));
+            /* Probably unnecessary, since the IR dest type is Ity_I1,
+               and so we are entitled to leave whatever junk we like
+               drifting round in the upper 31 or 63 bits of r_res.
+               However, for the sake of conservativeness .. */
+            addInstr(env, PPCInstr_Alu(
+                             Palu_AND, 
+                             r_res, r_tmp, 
+                             PPCRH_Imm(False/*signed*/, 1)));
+            return;
+         }
+         /* fallthru */
+      }
+      goto stmt_fail;
+      /*NOTREACHED*/
+   }
+
    /* --------- Call to DIRTY helper --------- */
    case Ist_Dirty: {
       IRType   retty;
index 899a5c354fd661543c8727fae19a93d7ef9bbeef..e50d9750918315e339784d04cf0fc6f8c1675c97 100644 (file)
@@ -763,8 +763,6 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
       /* We can't handle big-endian loads, nor load-linked. */
       if (e->Iex.Load.end != Iend_LE)
          goto irreducible;
-      if (e->Iex.Load.isLL)
-         goto irreducible;
 
       if (ty == Ity_I32) {
          addInstr(env, X86Instr_Alu32R(Xalu_MOV,
@@ -1069,7 +1067,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
          DECLARE_PATTERN(p_LDle8_then_8Uto32);
          DEFINE_PATTERN(p_LDle8_then_8Uto32,
                         unop(Iop_8Uto32,
-                             IRExpr_Load(False,Iend_LE,Ity_I8,bind(0))) );
+                             IRExpr_Load(Iend_LE,Ity_I8,bind(0))) );
          if (matchIRExpr(&mi,p_LDle8_then_8Uto32,e)) {
             HReg dst = newVRegI(env);
             X86AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] );
@@ -1083,7 +1081,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
          DECLARE_PATTERN(p_LDle8_then_8Sto32);
          DEFINE_PATTERN(p_LDle8_then_8Sto32,
                         unop(Iop_8Sto32,
-                             IRExpr_Load(False,Iend_LE,Ity_I8,bind(0))) );
+                             IRExpr_Load(Iend_LE,Ity_I8,bind(0))) );
          if (matchIRExpr(&mi,p_LDle8_then_8Sto32,e)) {
             HReg dst = newVRegI(env);
             X86AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] );
@@ -1097,7 +1095,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
          DECLARE_PATTERN(p_LDle16_then_16Uto32);
          DEFINE_PATTERN(p_LDle16_then_16Uto32,
                         unop(Iop_16Uto32,
-                             IRExpr_Load(False,Iend_LE,Ity_I16,bind(0))) );
+                             IRExpr_Load(Iend_LE,Ity_I16,bind(0))) );
          if (matchIRExpr(&mi,p_LDle16_then_16Uto32,e)) {
             HReg dst = newVRegI(env);
             X86AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] );
@@ -1536,7 +1534,7 @@ static X86RMI* iselIntExpr_RMI_wrk ( ISelEnv* env, IRExpr* e )
 
    /* special case: 32-bit load from memory */
    if (e->tag == Iex_Load && ty == Ity_I32 
-       && e->Iex.Load.end == Iend_LE && !e->Iex.Load.isLL) {
+       && e->Iex.Load.end == Iend_LE) {
       X86AMode* am = iselIntExpr_AMode(env, e->Iex.Load.addr);
       return X86RMI_Mem(am);
    }
@@ -1955,7 +1953,7 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e )
    }
 
    /* 64-bit load */
-   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE && !e->Iex.Load.isLL) {
+   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
       HReg     tLo, tHi;
       X86AMode *am0, *am4;
       vassert(e->Iex.Load.ty == Ity_I64);
@@ -2743,7 +2741,7 @@ static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
    }
 
-   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE && !e->Iex.Load.isLL) {
+   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
       X86AMode* am;
       HReg res = newVRegF(env);
       vassert(e->Iex.Load.ty == Ity_F32);
@@ -2867,7 +2865,7 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
       return freg;
    }
 
-   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE && !e->Iex.Load.isLL) {
+   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
       X86AMode* am;
       HReg res = newVRegF(env);
       vassert(e->Iex.Load.ty == Ity_F64);
@@ -3119,7 +3117,7 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
       return dst;
    }
 
-   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE && !e->Iex.Load.isLL) {
+   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
       HReg      dst = newVRegV(env);
       X86AMode* am  = iselIntExpr_AMode(env, e->Iex.Load.addr);
       addInstr(env, X86Instr_SseLdSt( True/*load*/, dst, am ));
@@ -3140,7 +3138,7 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
       DECLARE_PATTERN(p_zwiden_load64);
       DEFINE_PATTERN(p_zwiden_load64,
                      unop(Iop_64UtoV128, 
-                          IRExpr_Load(False,Iend_LE,Ity_I64,bind(0))));
+                          IRExpr_Load(Iend_LE,Ity_I64,bind(0))));
       if (matchIRExpr(&mi, p_zwiden_load64, e)) {
          X86AMode* am = iselIntExpr_AMode(env, mi.bindee[0]);
          HReg dst = newVRegV(env);
@@ -3608,9 +3606,8 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
       IRType    tya   = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr);
       IRType    tyd   = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
       IREndness end   = stmt->Ist.Store.end;
-      IRTemp    resSC = stmt->Ist.Store.resSC;
 
-      if (tya != Ity_I32 || end != Iend_LE || resSC != IRTemp_INVALID
+      if (tya != Ity_I32 || end != Iend_LE) 
          goto stmt_fail;
 
       if (tyd == Ity_I32) {
index 971370df82764f702cfdff8ab4da8b61dec92979..97c4f42e8232f842f497e3fdd713b0cc9815db1d 100644 (file)
@@ -648,8 +648,7 @@ void ppIRExpr ( IRExpr* e )
       vex_printf( ")" );
       break;
     case Iex_Load:
-      vex_printf( "LD%s%s:", e->Iex.Load.end==Iend_LE ? "le" : "be",
-                             e->Iex.Load.isLL ? "-LL" : "" );
+      vex_printf( "LD%s:", e->Iex.Load.end==Iend_LE ? "le" : "be" );
       ppIRType(e->Iex.Load.ty);
       vex_printf( "(" );
       ppIRExpr(e->Iex.Load.addr);
@@ -829,20 +828,31 @@ void ppIRStmt ( IRStmt* s )
          ppIRExpr(s->Ist.WrTmp.data);
          break;
       case Ist_Store:
-         if (s->Ist.Store.resSC != IRTemp_INVALID) {
-            ppIRTemp(s->Ist.Store.resSC);
-            vex_printf( " = SC( " );
-         }
          vex_printf( "ST%s(", s->Ist.Store.end==Iend_LE ? "le" : "be" );
          ppIRExpr(s->Ist.Store.addr);
          vex_printf( ") = ");
          ppIRExpr(s->Ist.Store.data);
-         if (s->Ist.Store.resSC != IRTemp_INVALID)
-            vex_printf( " )" );
          break;
       case Ist_CAS:
          ppIRCAS(s->Ist.CAS.details);
          break;
+      case Ist_LLSC:
+         if (s->Ist.LLSC.storedata == NULL) {
+            ppIRTemp(s->Ist.LLSC.result);
+            vex_printf(" = LD%s-Linked(",
+                       s->Ist.LLSC.end==Iend_LE ? "le" : "be");
+            ppIRExpr(s->Ist.LLSC.addr);
+            vex_printf(")");
+         } else {
+            ppIRTemp(s->Ist.LLSC.result);
+            vex_printf(" = ( ST%s-Cond(",
+                       s->Ist.LLSC.end==Iend_LE ? "le" : "be");
+            ppIRExpr(s->Ist.LLSC.addr);
+            vex_printf(") = ");
+            ppIRExpr(s->Ist.LLSC.storedata);
+            vex_printf(" )");
+         }
+         break;
       case Ist_Dirty:
          ppIRDirty(s->Ist.Dirty.details);
          break;
@@ -1061,10 +1071,9 @@ IRExpr* IRExpr_Unop ( IROp op, IRExpr* arg ) {
    e->Iex.Unop.arg = arg;
    return e;
 }
-IRExpr* IRExpr_Load ( Bool isLL, IREndness end, IRType ty, IRExpr* addr ) {
+IRExpr* IRExpr_Load ( IREndness end, IRType ty, IRExpr* addr ) {
    IRExpr* e        = LibVEX_Alloc(sizeof(IRExpr));
    e->tag           = Iex_Load;
-   e->Iex.Load.isLL = isLL;
    e->Iex.Load.end  = end;
    e->Iex.Load.ty   = ty;
    e->Iex.Load.addr = addr;
@@ -1257,14 +1266,12 @@ IRStmt* IRStmt_WrTmp ( IRTemp tmp, IRExpr* data ) {
    s->Ist.WrTmp.data = data;
    return s;
 }
-IRStmt* IRStmt_Store ( IREndness end,
-                       IRTemp resSC, IRExpr* addr, IRExpr* data ) {
-   IRStmt* s          = LibVEX_Alloc(sizeof(IRStmt));
-   s->tag             = Ist_Store;
-   s->Ist.Store.end   = end;
-   s->Ist.Store.resSC = resSC;
-   s->Ist.Store.addr  = addr;
-   s->Ist.Store.data  = data;
+IRStmt* IRStmt_Store ( IREndness end, IRExpr* addr, IRExpr* data ) {
+   IRStmt* s         = LibVEX_Alloc(sizeof(IRStmt));
+   s->tag            = Ist_Store;
+   s->Ist.Store.end  = end;
+   s->Ist.Store.addr = addr;
+   s->Ist.Store.data = data;
    vassert(end == Iend_LE || end == Iend_BE);
    return s;
 }
@@ -1274,6 +1281,16 @@ IRStmt* IRStmt_CAS ( IRCAS* cas ) {
    s->Ist.CAS.details = cas;
    return s;
 }
+IRStmt* IRStmt_LLSC ( IREndness end,
+                      IRTemp result, IRExpr* addr, IRExpr* storedata ) {
+   IRStmt* s = LibVEX_Alloc(sizeof(IRStmt));
+   s->tag                = Ist_LLSC;
+   s->Ist.LLSC.end       = end;
+   s->Ist.LLSC.result    = result;
+   s->Ist.LLSC.addr      = addr;
+   s->Ist.LLSC.storedata = storedata;
+   return s;
+}
 IRStmt* IRStmt_Dirty ( IRDirty* d )
 {
    IRStmt* s            = LibVEX_Alloc(sizeof(IRStmt));
@@ -1418,8 +1435,7 @@ IRExpr* deepCopyIRExpr ( IRExpr* e )
          return IRExpr_Unop(e->Iex.Unop.op,
                             deepCopyIRExpr(e->Iex.Unop.arg));
       case Iex_Load: 
-         return IRExpr_Load(e->Iex.Load.isLL,
-                            e->Iex.Load.end,
+         return IRExpr_Load(e->Iex.Load.end,
                             e->Iex.Load.ty,
                             deepCopyIRExpr(e->Iex.Load.addr));
       case Iex_Const: 
@@ -1490,11 +1506,17 @@ IRStmt* deepCopyIRStmt ( IRStmt* s )
                              deepCopyIRExpr(s->Ist.WrTmp.data));
       case Ist_Store: 
          return IRStmt_Store(s->Ist.Store.end,
-                             s->Ist.Store.resSC,
                              deepCopyIRExpr(s->Ist.Store.addr),
                              deepCopyIRExpr(s->Ist.Store.data));
       case Ist_CAS:
          return IRStmt_CAS(deepCopyIRCAS(s->Ist.CAS.details));
+      case Ist_LLSC:
+         return IRStmt_LLSC(s->Ist.LLSC.end,
+                            s->Ist.LLSC.result,
+                            deepCopyIRExpr(s->Ist.LLSC.addr),
+                            s->Ist.LLSC.storedata
+                               ? deepCopyIRExpr(s->Ist.LLSC.storedata)
+                               : NULL);
       case Ist_Dirty: 
          return IRStmt_Dirty(deepCopyIRDirty(s->Ist.Dirty.details));
       case Ist_MBE:
@@ -2138,6 +2160,10 @@ Bool isFlatIRStmt ( IRStmt* st )
                         && isIRAtom(cas->expdLo)
                         && (cas->dataHi ? isIRAtom(cas->dataHi) : True)
                         && isIRAtom(cas->dataLo) );
+      case Ist_LLSC:
+         return toBool( isIRAtom(st->Ist.LLSC.addr)
+                        && (st->Ist.LLSC.storedata
+                               ? isIRAtom(st->Ist.LLSC.storedata) : True) );
       case Ist_Dirty:
          di = st->Ist.Dirty.details;
          if (!isIRAtom(di->guard)) 
@@ -2329,6 +2355,11 @@ void useBeforeDef_Stmt ( IRSB* bb, IRStmt* stmt, Int* def_counts )
             useBeforeDef_Expr(bb,stmt,cas->dataHi,def_counts);
          useBeforeDef_Expr(bb,stmt,cas->dataLo,def_counts);
          break;
+      case Ist_LLSC:
+         useBeforeDef_Expr(bb,stmt,stmt->Ist.LLSC.addr,def_counts);
+         if (stmt->Ist.LLSC.storedata != NULL)
+            useBeforeDef_Expr(bb,stmt,stmt->Ist.LLSC.storedata,def_counts);
+         break;
       case Ist_Dirty:
          d = stmt->Ist.Dirty.details;
          for (i = 0; d->args[i] != NULL; i++)
@@ -2606,9 +2637,6 @@ void tcStmt ( IRSB* bb, IRStmt* stmt, IRType gWordTy )
             sanityCheckFail(bb,stmt,"IRStmt.Store.data: cannot Store :: Ity_I1");
          if (stmt->Ist.Store.end != Iend_LE && stmt->Ist.Store.end != Iend_BE)
             sanityCheckFail(bb,stmt,"Ist.Store.end: bogus endianness");
-         if (stmt->Ist.Store.resSC != IRTemp_INVALID
-             && typeOfIRTemp(tyenv, stmt->Ist.Store.resSC) != Ity_I1)
-            sanityCheckFail(bb,stmt,"Ist.Store.resSC: not :: Ity_I1");
          break;
       case Ist_CAS:
          cas = stmt->Ist.CAS.details;
@@ -2660,6 +2688,27 @@ void tcStmt ( IRSB* bb, IRStmt* stmt, IRType gWordTy )
          bad_cas:
          sanityCheckFail(bb,stmt,"IRStmt.CAS: ill-formed");
          break;
+      case Ist_LLSC: {
+         IRType tyRes;
+         if (typeOfIRExpr(tyenv, stmt->Ist.LLSC.addr) != gWordTy)
+            sanityCheckFail(bb,stmt,"IRStmt.LLSC.addr: not :: guest word type");
+         if (stmt->Ist.LLSC.end != Iend_LE && stmt->Ist.LLSC.end != Iend_BE)
+            sanityCheckFail(bb,stmt,"Ist.LLSC.end: bogus endianness");
+         tyRes = typeOfIRTemp(tyenv, stmt->Ist.LLSC.result);
+         if (stmt->Ist.LLSC.storedata == NULL) {
+            /* it's a LL */
+            if (tyRes != Ity_I64 && tyRes != Ity_I32)
+               sanityCheckFail(bb,stmt,"Ist.LLSC(LL).result :: bogus");
+         } else {
+            /* it's a SC */
+            if (tyRes != Ity_I1)
+               sanityCheckFail(bb,stmt,"Ist.LLSC(SC).result: not :: Ity_I1");
+            tyData = typeOfIRExpr(tyenv, stmt->Ist.LLSC.storedata);
+            if (tyData != Ity_I64 && tyData != Ity_I32)
+               sanityCheckFail(bb,stmt,"Ist.LLSC(SC).result :: storedata bogus");
+         }
+         break;
+      }
       case Ist_Dirty:
          /* Mostly check for various kinds of ill-formed dirty calls. */
          d = stmt->Ist.Dirty.details;
@@ -2790,17 +2839,6 @@ void sanityCheckIRSB ( IRSB* bb,          HChar* caller,
                "IRStmt.Tmp: destination tmp is assigned more than once");
          break;
       case Ist_Store:
-         if (stmt->Ist.Store.resSC != IRTemp_INVALID) {
-            IRTemp resSC = stmt->Ist.Store.resSC;
-            if (resSC < 0 || resSC >= n_temps)
-               sanityCheckFail(bb, stmt, 
-                  "IRStmt.Store.resSC: destination tmp is out of range");
-            def_counts[resSC]++;
-            if (def_counts[resSC] > 1)
-               sanityCheckFail(bb, stmt, 
-                  "IRStmt.Store.resSC: destination tmp "
-                   "is assigned more than once");
-         }
          break;
       case Ist_Dirty:
          if (stmt->Ist.Dirty.details->tmp != IRTemp_INVALID) {
@@ -2816,7 +2854,6 @@ void sanityCheckIRSB ( IRSB* bb,          HChar* caller,
          break;
       case Ist_CAS:
          cas = stmt->Ist.CAS.details;
-
          if (cas->oldHi != IRTemp_INVALID) {
             if (cas->oldHi < 0 || cas->oldHi >= n_temps)
                 sanityCheckFail(bb, stmt, 
@@ -2827,16 +2864,25 @@ void sanityCheckIRSB ( IRSB* bb,          HChar* caller,
                    "IRStmt.CAS: destination tmpHi is assigned more than once");
          }
          if (cas->oldLo < 0 || cas->oldLo >= n_temps)
-             sanityCheckFail(bb, stmt, 
-                "IRStmt.CAS: destination tmpLo is out of range");
-          def_counts[cas->oldLo]++;
-          if (def_counts[cas->oldLo] > 1)
-             sanityCheckFail(bb, stmt, 
-                "IRStmt.CAS: destination tmpLo is assigned more than once");
-          break;
+            sanityCheckFail(bb, stmt, 
+               "IRStmt.CAS: destination tmpLo is out of range");
+         def_counts[cas->oldLo]++;
+         if (def_counts[cas->oldLo] > 1)
+            sanityCheckFail(bb, stmt, 
+               "IRStmt.CAS: destination tmpLo is assigned more than once");
+         break;
+      case Ist_LLSC:
+         if (stmt->Ist.LLSC.result < 0 || stmt->Ist.LLSC.result >= n_temps)
+            sanityCheckFail(bb, stmt,
+               "IRStmt.LLSC: destination tmp is out of range");
+         def_counts[stmt->Ist.LLSC.result]++;
+         if (def_counts[stmt->Ist.LLSC.result] > 1)
+            sanityCheckFail(bb, stmt,
+               "IRStmt.LLSC: destination tmp is assigned more than once");
+         break;
       default:
-          /* explicitly handle the rest, so as to keep gcc quiet */
-          break;
+         /* explicitly handle the rest, so as to keep gcc quiet */
+         break;
       }
    }
 
index 20a9f3cd2481b3cf92107b4d8a0558d7ae59f7d7..f3f63f280b2376d2a3ed4d0e540ffe02c3e5d8db 100644 (file)
@@ -90,7 +90,6 @@ Bool matchWrk ( MatchInfo* mi, IRExpr* p/*attern*/, IRExpr* e/*xpr*/ )
          return True;
       case Iex_Load:
          if (e->tag != Iex_Load) return False;
-         if (p->Iex.Load.isLL != e->Iex.Load.isLL) return False;
          if (p->Iex.Load.end != e->Iex.Load.end) return False;
          if (p->Iex.Load.ty != e->Iex.Load.ty) return False;
          if (!matchWrk(mi, p->Iex.Load.addr, e->Iex.Load.addr))
index 840b12dee6a29152beba277786cc25d44939e90c..40f2466bbad9f34767281e2d63c904a70d741340 100644 (file)
@@ -334,8 +334,7 @@ static IRExpr* flatten_Expr ( IRSB* bb, IRExpr* ex )
       case Iex_Load:
          t1 = newIRTemp(bb->tyenv, ty);
          addStmtToIRSB(bb, IRStmt_WrTmp(t1,
-            IRExpr_Load(ex->Iex.Load.isLL,
-                        ex->Iex.Load.end,
+            IRExpr_Load(ex->Iex.Load.end,
                         ex->Iex.Load.ty, 
                         flatten_Expr(bb, ex->Iex.Load.addr))));
          return IRExpr_RdTmp(t1);
@@ -426,8 +425,7 @@ static void flatten_Stmt ( IRSB* bb, IRStmt* st )
       case Ist_Store:
          e1 = flatten_Expr(bb, st->Ist.Store.addr);
          e2 = flatten_Expr(bb, st->Ist.Store.data);
-         addStmtToIRSB(bb, IRStmt_Store(st->Ist.Store.end,
-                                        st->Ist.Store.resSC, e1,e2));
+         addStmtToIRSB(bb, IRStmt_Store(st->Ist.Store.end, e1,e2));
          break;
       case Ist_CAS:
          cas  = st->Ist.CAS.details;
@@ -440,6 +438,14 @@ static void flatten_Stmt ( IRSB* bb, IRStmt* st )
                          e1, e2, e3, e4, e5 );
          addStmtToIRSB(bb, IRStmt_CAS(cas2));
          break;
+      case Ist_LLSC:
+         e1 = flatten_Expr(bb, st->Ist.LLSC.addr);
+         e2 = st->Ist.LLSC.storedata
+                 ? flatten_Expr(bb, st->Ist.LLSC.storedata)
+                 : NULL;
+         addStmtToIRSB(bb, IRStmt_LLSC(st->Ist.LLSC.end,
+                                       st->Ist.LLSC.result, e1, e2));
+         break;
       case Ist_Dirty:
          d = st->Ist.Dirty.details;
          d2 = emptyIRDirty();
@@ -724,7 +730,7 @@ static void handle_gets_Stmt (
          enough do a lot better if needed. */
       /* Probably also overly-conservative, but also dump everything
          if we hit a memory bus event (fence, lock, unlock).  Ditto
-         AbiHints and CASs. */
+         AbiHints, CASs, LLs and SCs. */
       case Ist_AbiHint:
          vassert(isIRAtom(st->Ist.AbiHint.base));
          vassert(isIRAtom(st->Ist.AbiHint.nia));
@@ -732,6 +738,7 @@ static void handle_gets_Stmt (
       case Ist_MBE:
       case Ist_Dirty:
       case Ist_CAS:
+      case Ist_LLSC:
          for (j = 0; j < env->used; j++)
             env->inuse[j] = False;
          break;
@@ -1674,7 +1681,6 @@ static IRExpr* subst_Expr ( IRExpr** env, IRExpr* ex )
       case Iex_Load:
          vassert(isIRAtom(ex->Iex.Load.addr));
          return IRExpr_Load(
-                   ex->Iex.Load.isLL,
                    ex->Iex.Load.end,
                    ex->Iex.Load.ty,
                    subst_Expr(env, ex->Iex.Load.addr)
@@ -1763,7 +1769,6 @@ static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st )
          vassert(isIRAtom(st->Ist.Store.data));
          return IRStmt_Store(
                    st->Ist.Store.end,
-                   st->Ist.Store.resSC,
                    fold_Expr(subst_Expr(env, st->Ist.Store.addr)),
                    fold_Expr(subst_Expr(env, st->Ist.Store.data))
                 );
@@ -1787,6 +1792,19 @@ static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st )
          return IRStmt_CAS(cas2);
       }
 
+      case Ist_LLSC:
+         vassert(isIRAtom(st->Ist.LLSC.addr));
+         if (st->Ist.LLSC.storedata)
+            vassert(isIRAtom(st->Ist.LLSC.storedata));
+         return IRStmt_LLSC(
+                   st->Ist.LLSC.end,
+                   st->Ist.LLSC.result,
+                   fold_Expr(subst_Expr(env, st->Ist.LLSC.addr)),
+                   st->Ist.LLSC.storedata
+                      ? fold_Expr(subst_Expr(env, st->Ist.LLSC.storedata))
+                      : NULL
+                );
+
       case Ist_Dirty: {
          Int     i;
          IRDirty *d, *d2;
@@ -2022,6 +2040,11 @@ static void addUses_Stmt ( Bool* set, IRStmt* st )
             addUses_Expr(set, cas->dataHi);
          addUses_Expr(set, cas->dataLo);
          return;
+      case Ist_LLSC:
+         addUses_Expr(set, st->Ist.LLSC.addr);
+         if (st->Ist.LLSC.storedata)
+            addUses_Expr(set, st->Ist.LLSC.storedata);
+         return;
       case Ist_Dirty:
          d = st->Ist.Dirty.details;
          if (d->mFx != Ifx_None)
@@ -2608,7 +2631,8 @@ static Bool do_cse_BB ( IRSB* bb )
          to do the no-overlap assessments needed for Put/PutI.
       */
       switch (st->tag) {
-         case Ist_Dirty: case Ist_Store: case Ist_MBE: case Ist_CAS:
+         case Ist_Dirty: case Ist_Store: case Ist_MBE:
+         case Ist_CAS: case Ist_LLSC:
             paranoia = 2; break;
          case Ist_Put: case Ist_PutI: 
             paranoia = 1; break;
@@ -3299,8 +3323,6 @@ static void deltaIRStmt ( IRStmt* st, Int delta )
          deltaIRExpr(st->Ist.Exit.guard, delta);
          break;
       case Ist_Store:
-         if (st->Ist.Store.resSC != IRTemp_INVALID)
-            st->Ist.Store.resSC += delta;
          deltaIRExpr(st->Ist.Store.addr, delta);
          deltaIRExpr(st->Ist.Store.data, delta);
          break;
@@ -3316,6 +3338,12 @@ static void deltaIRStmt ( IRStmt* st, Int delta )
             deltaIRExpr(st->Ist.CAS.details->dataHi, delta);
          deltaIRExpr(st->Ist.CAS.details->dataLo, delta);
          break;
+      case Ist_LLSC:
+         st->Ist.LLSC.result += delta;
+         deltaIRExpr(st->Ist.LLSC.addr, delta);
+         if (st->Ist.LLSC.storedata)
+            deltaIRExpr(st->Ist.LLSC.storedata, delta);
+         break;
       case Ist_Dirty:
          d = st->Ist.Dirty.details;
          deltaIRExpr(d->guard, delta);
@@ -3780,6 +3808,11 @@ static void aoccCount_Stmt ( UShort* uses, IRStmt* st )
             aoccCount_Expr(uses, cas->dataHi);
          aoccCount_Expr(uses, cas->dataLo);
          return;
+      case Ist_LLSC:
+         aoccCount_Expr(uses, st->Ist.LLSC.addr);
+         if (st->Ist.LLSC.storedata)
+            aoccCount_Expr(uses, st->Ist.LLSC.storedata);
+         return;
       case Ist_Dirty:
          d = st->Ist.Dirty.details;
          if (d->mFx != Ifx_None)
@@ -3966,7 +3999,6 @@ static IRExpr* atbSubst_Expr ( ATmpInfo* env, IRExpr* e )
                 );
       case Iex_Load:
          return IRExpr_Load(
-                   e->Iex.Load.isLL,
                    e->Iex.Load.end,
                    e->Iex.Load.ty,
                    atbSubst_Expr(env, e->Iex.Load.addr)
@@ -4003,7 +4035,6 @@ static IRStmt* atbSubst_Stmt ( ATmpInfo* env, IRStmt* st )
       case Ist_Store:
          return IRStmt_Store(
                    st->Ist.Store.end,
-                   st->Ist.Store.resSC,
                    atbSubst_Expr(env, st->Ist.Store.addr),
                    atbSubst_Expr(env, st->Ist.Store.data)
                 );
@@ -4048,6 +4079,14 @@ static IRStmt* atbSubst_Stmt ( ATmpInfo* env, IRStmt* st )
                    atbSubst_Expr(env, cas->dataLo)
                 );
          return IRStmt_CAS(cas2);
+      case Ist_LLSC:
+         return IRStmt_LLSC(
+                   st->Ist.LLSC.end,
+                   st->Ist.LLSC.result,
+                   atbSubst_Expr(env, st->Ist.LLSC.addr),
+                   st->Ist.LLSC.storedata
+                      ? atbSubst_Expr(env, st->Ist.LLSC.storedata) : NULL
+                );
       case Ist_Dirty:
          d  = st->Ist.Dirty.details;
          d2 = emptyIRDirty();
@@ -4189,15 +4228,13 @@ static IRStmt* atbSubst_Stmt ( ATmpInfo* env, IRStmt* st )
 
       /* be True if this stmt writes memory or might do (==> we don't
          want to reorder other loads or stores relative to it).  Also,
-         a load-linked falls under this classification, since we
+         both LL and SC fall under this classification, since we
          really ought to be conservative and not reorder any other
-         memory transactions relative to it. */
+         memory transactions relative to them. */
       stmtStores
          = toBool( st->tag == Ist_Store
-                   || (st->tag == Ist_WrTmp
-                       && st->Ist.WrTmp.data->tag == Iex_Load
-                       && st->Ist.WrTmp.data->Iex.Load.isLL)
-                   || st->tag == Ist_Dirty );
+                   || st->tag == Ist_Dirty
+                   || st->tag == Ist_LLSC );
 
       for (k = A_NENV-1; k >= 0; k--) {
          if (env[k].bindee == NULL)
@@ -4388,6 +4425,11 @@ static void considerExpensives ( /*OUT*/Bool* hasGetIorPutI,
             vassert(cas->dataHi == NULL || isIRAtom(cas->dataHi));
             vassert(isIRAtom(cas->dataLo));
             break;
+         case Ist_LLSC:
+            vassert(isIRAtom(st->Ist.LLSC.addr));
+            if (st->Ist.LLSC.storedata)
+               vassert(isIRAtom(st->Ist.LLSC.storedata));
+            break;
          case Ist_Dirty:
             d = st->Ist.Dirty.details;
             vassert(isIRAtom(d->guard));
@@ -4406,7 +4448,7 @@ static void considerExpensives ( /*OUT*/Bool* hasGetIorPutI,
          default: 
          bad:
             ppIRStmt(st);
-            vpanic("hasGetIorPutI");
+            vpanic("considerExpensives");
       }
    }
 }
index 3310f89122c55fec90e8ea36e2fe0d6cacbeadf8..01ad488ae3fc00b76b44a7391d9caa08fd39a27a 100644 (file)
@@ -1044,20 +1044,13 @@ struct _IRExpr {
          IRExpr* arg;      /* operand */
       } Unop;
 
-      /* A load from memory.  If .isLL is True then this load also
-         lodges a reservation (ppc-style lwarx/ldarx operation).  If
-         .isLL is True, then also, the address must be naturally
-         aligned - any misaligned addresses should be caught by a
-         dominating IR check and side exit.  This alignment
-         restriction exists because on at least some LL/SC platforms
-         (ppc), lwarx etc will trap w/ SIGBUS on misaligned addresses,
-         and we have to actually generate lwarx on the host, and we
-         don't want it trapping on the host.
-
+      /* A load from memory -- a normal load, not a load-linked.
+         Load-Linkeds (and Store-Conditionals) are instead represented
+         by IRStmt.LLSC since Load-Linkeds have side effects and so
+         are not semantically valid IRExpr's.
          ppIRExpr output: LD<end>:<ty>(<addr>), eg. LDle:I32(t1)
       */
       struct {
-         Bool      isLL;   /* True iff load makes a reservation */
          IREndness end;    /* Endian-ness of the load */
          IRType    ty;     /* Type of the loaded value */
          IRExpr*   addr;   /* Address being loaded from */
@@ -1141,8 +1134,7 @@ extern IRExpr* IRExpr_Triop  ( IROp op, IRExpr* arg1,
                                         IRExpr* arg2, IRExpr* arg3 );
 extern IRExpr* IRExpr_Binop  ( IROp op, IRExpr* arg1, IRExpr* arg2 );
 extern IRExpr* IRExpr_Unop   ( IROp op, IRExpr* arg );
-extern IRExpr* IRExpr_Load   ( Bool isLL, IREndness end,
-                               IRType ty, IRExpr* addr );
+extern IRExpr* IRExpr_Load   ( IREndness end, IRType ty, IRExpr* addr );
 extern IRExpr* IRExpr_Const  ( IRConst* con );
 extern IRExpr* IRExpr_CCall  ( IRCallee* cee, IRType retty, IRExpr** args );
 extern IRExpr* IRExpr_Mux0X  ( IRExpr* cond, IRExpr* expr0, IRExpr* exprX );
@@ -1483,6 +1475,7 @@ typedef
       Ist_WrTmp,
       Ist_Store,
       Ist_CAS,
+      Ist_LLSC,
       Ist_Dirty,
       Ist_MBE,       /* META (maybe) */
       Ist_Exit
@@ -1578,28 +1571,13 @@ typedef
             IRExpr* data;  /* Expression (RHS of assignment) */
          } WrTmp;
 
-         /* Write a value to memory.  Normally scRes is
-            IRTemp_INVALID, denoting a normal store.  If scRes is not
-            IRTemp_INVALID, then this is a store-conditional, which
-            may fail or succeed depending on the outcome of a
-            previously lodged reservation on this address.  scRes is
-            written 1 if the store succeeds and 0 if it fails, and
-            must have type Ity_I1.
-
-            If scRes is not IRTemp_INVALID, then also, the address
-            must be naturally aligned - any misaligned addresses
-            should be caught by a dominating IR check and side exit.
-            This alignment restriction exists because on at least some
-            LL/SC platforms (ppc), stwcx. etc will trap w/ SIGBUS on
-            misaligned addresses, and we have to actually generate
-            stwcx. on the host, and we don't want it trapping on the
-            host.
-
+         /* Write a value to memory.  This is a normal store, not a
+            Store-Conditional.  To represent a Store-Conditional,
+            instead use IRStmt.LLSC.
             ppIRStmt output: ST<end>(<addr>) = <data>, eg. STle(t1) = t2
          */
          struct {
             IREndness end;    /* Endianness of the store */
-            IRTemp    resSC;  /* result of SC goes here (1 == success) */
             IRExpr*   addr;   /* store address */
             IRExpr*   data;   /* value to write */
          } Store;
@@ -1622,6 +1600,57 @@ typedef
             IRCAS* details;
          } CAS;
 
+         /* Either Load-Linked or Store-Conditional, depending on
+            STOREDATA.
+
+            If STOREDATA is NULL then this is a Load-Linked, meaning
+            that data is loaded from memory as normal, but a
+            'reservation' for the address is also lodged in the
+            hardware.
+
+               result = Load-Linked(addr, end)
+
+            The data transfer type is the type of RESULT (I32, I64,
+            etc).  ppIRStmt output:
+
+               result = LD<end>-Linked(<addr>), eg. LDbe-Linked(t1)
+
+            If STOREDATA is not NULL then this is a Store-Conditional,
+            hence:
+
+               result = Store-Conditional(addr, storedata, end)
+
+            The data transfer type is the type of STOREDATA and RESULT
+            has type Ity_I1. The store may fail or succeed depending
+            on the state of a previously lodged reservation on this
+            address.  RESULT is written 1 if the store succeeds and 0
+            if it fails.  eg ppIRStmt output:
+
+               result = ( ST<end>-Cond(<addr>) = <storedata> )
+               eg t3 = ( STbe-Cond(t1, t2) )
+
+            In all cases, the address must be naturally aligned for
+            the transfer type -- any misaligned addresses should be
+            caught by a dominating IR check and side exit.  This
+            alignment restriction exists because on at least some
+            LL/SC platforms (ppc), stwcx. etc will trap w/ SIGBUS on
+            misaligned addresses, and we have to actually generate
+            stwcx. on the host, and we don't want it trapping on the
+            host.
+
+            Summary of rules for transfer type:
+              STOREDATA == NULL (LL):
+                transfer type = type of RESULT
+              STOREDATA != NULL (SC):
+                transfer type = type of STOREDATA, and RESULT :: Ity_I1
+         */
+         struct {
+            IREndness end;
+            IRTemp    result;
+            IRExpr*   addr;
+            IRExpr*   storedata; /* NULL => LL, non-NULL => SC */
+         } LLSC;
+
          /* Call (possibly conditionally) a C function that has side
             effects (ie. is "dirty").  See the comments above the
             IRDirty type declaration for more information.
@@ -1668,9 +1697,10 @@ extern IRStmt* IRStmt_Put     ( Int off, IRExpr* data );
 extern IRStmt* IRStmt_PutI    ( IRRegArray* descr, IRExpr* ix, Int bias, 
                                 IRExpr* data );
 extern IRStmt* IRStmt_WrTmp   ( IRTemp tmp, IRExpr* data );
-extern IRStmt* IRStmt_Store   ( IREndness end,
-                                IRTemp resSC, IRExpr* addr, IRExpr* data );
+extern IRStmt* IRStmt_Store   ( IREndness end, IRExpr* addr, IRExpr* data );
 extern IRStmt* IRStmt_CAS     ( IRCAS* details );
+extern IRStmt* IRStmt_LLSC    ( IREndness end, IRTemp result,
+                                IRExpr* addr, IRExpr* storedata );
 extern IRStmt* IRStmt_Dirty   ( IRDirty* details );
 extern IRStmt* IRStmt_MBE     ( IRMBusEvent event );
 extern IRStmt* IRStmt_Exit    ( IRExpr* guard, IRJumpKind jk, IRConst* dst );