]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
amd64: Handle BT/BTS/BTR/BTC Gv, Ev.
authorJulian Seward <jseward@acm.org>
Wed, 24 Aug 2005 10:46:19 +0000 (10:46 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 24 Aug 2005 10:46:19 +0000 (10:46 +0000)
x86:   Fix signedness bug in existing BT/BTS/BTR/BTC Gv, Ev code.

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

VEX/priv/guest-amd64/toIR.c
VEX/priv/guest-x86/toIR.c

index 1c31d61d530429aa35c545ae01f2a1ba9401bf41..6f0a23f7985584d66baba6314349de6bcff9c6f8 100644 (file)
@@ -6480,150 +6480,153 @@ ULong dis_MMX ( Bool* decode_ok, Prefix pfx, Int sz, Long delta )
 //..    if (amt_is_literal) delta++;
 //..    return delta;
 //.. }
-//.. 
-//.. 
-//.. /* Handle BT/BTS/BTR/BTC Gv, Ev.  Apparently b-size is not
-//..    required. */
-//.. 
-//.. typedef enum { BtOpNone, BtOpSet, BtOpReset, BtOpComp } BtOp;
-//.. 
-//.. static Char* nameBtOp ( BtOp op )
-//.. {
-//..    switch (op) {
-//..       case BtOpNone:  return "";
-//..       case BtOpSet:   return "s";
-//..       case BtOpReset: return "r";
-//..       case BtOpComp:  return "c";
-//..       default: vpanic("nameBtOp(x86)");
-//..    }
-//.. }
-//.. 
-//.. 
-//.. static
-//.. UInt dis_bt_G_E ( UChar sorb, Int sz, Long delta, BtOp op )
-//.. {
-//..    HChar  dis_buf[50];
-//..    UChar  modrm;
-//..    Int    len;
-//..    IRTemp t_fetched, t_bitno0, t_bitno1, t_bitno2, t_addr0, 
-//..           t_addr1, t_esp, t_mask;
-//.. 
-//..    vassert(sz == 2 || sz == 4);
-//.. 
-//..    t_fetched = t_bitno0 = t_bitno1 = t_bitno2 
-//..              = t_addr0 = t_addr1 = t_esp = t_mask = IRTemp_INVALID;
-//.. 
-//..    t_fetched = newTemp(Ity_I8);
-//..    t_bitno0  = newTemp(Ity_I32);
-//..    t_bitno1  = newTemp(Ity_I32);
-//..    t_bitno2  = newTemp(Ity_I8);
-//..    t_addr1   = newTemp(Ity_I32);
-//..    modrm     = getUChar(delta);
-//.. 
-//..    assign( t_bitno0, widenUto32(getIReg(sz, gregOfRM(modrm))) );
-//..    
-//..    if (epartIsReg(modrm)) {
-//..       delta++;
-//..       /* Get it onto the client's stack. */
-//..       t_esp = newTemp(Ity_I32);
-//..       t_addr0 = newTemp(Ity_I32);
-//.. 
-//..       assign( t_esp, binop(Iop_Sub32, getIReg(4, R_ESP), mkU32(sz)) );
-//..       putIReg(4, R_ESP, mkexpr(t_esp));
-//.. 
-//..       storeLE( mkexpr(t_esp), getIReg(sz, eregOfRM(modrm)) );
-//.. 
-//..       /* Make t_addr0 point at it. */
-//..       assign( t_addr0, mkexpr(t_esp) );
-//.. 
-//..       /* Mask out upper bits of the shift amount, since we're doing a
-//..          reg. */
-//..       assign( t_bitno1, binop(Iop_And32, 
-//..                               mkexpr(t_bitno0), 
-//..                               mkU32(sz == 4 ? 31 : 15)) );
-//.. 
-//..    } else {
-//..       t_addr0 = disAMode ( &len, sorb, delta, dis_buf );
-//..       delta += len;
-//..       assign( t_bitno1, mkexpr(t_bitno0) );
-//..    }
-//..   
-//..    /* At this point: t_addr0 is the address being operated on.  If it
-//..       was a reg, we will have pushed it onto the client's stack.
-//..       t_bitno1 is the bit number, suitably masked in the case of a
-//..       reg.  */
-//..   
-//..    /* Now the main sequence. */
-//..    assign( t_addr1, 
-//..            binop(Iop_Add32, 
-//..                  mkexpr(t_addr0), 
-//..                  binop(Iop_Sar32, mkexpr(t_bitno1), mkU8(3))) );
-//.. 
-//..    /* t_addr1 now holds effective address */
-//.. 
-//..    assign( t_bitno2, 
-//..            unop(Iop_32to8, 
-//..                 binop(Iop_And32, mkexpr(t_bitno1), mkU32(7))) );
-//.. 
-//..    /* t_bitno2 contains offset of bit within byte */
-//.. 
-//..    if (op != BtOpNone) {
-//..       t_mask = newTemp(Ity_I8);
-//..       assign( t_mask, binop(Iop_Shl8, mkU8(1), mkexpr(t_bitno2)) );
-//..    }
-//.. 
-//..    /* t_mask is now a suitable byte mask */
-//.. 
-//..    assign( t_fetched, loadLE(Ity_I8, mkexpr(t_addr1)) );
-//.. 
-//..    if (op != BtOpNone) {
-//..       switch (op) {
-//..          case BtOpSet: 
-//..             storeLE( mkexpr(t_addr1), 
-//..                      binop(Iop_Or8, mkexpr(t_fetched), 
-//..                                     mkexpr(t_mask)) );
-//..             break;
-//..          case BtOpComp: 
-//..             storeLE( mkexpr(t_addr1), 
-//..                      binop(Iop_Xor8, mkexpr(t_fetched), 
-//..                                      mkexpr(t_mask)) );
-//..             break;
-//..          case BtOpReset: 
-//..             storeLE( mkexpr(t_addr1), 
-//..                      binop(Iop_And8, mkexpr(t_fetched), 
-//..                                      unop(Iop_Not8, mkexpr(t_mask))) );
-//..             break;
-//..          default: 
-//..             vpanic("dis_bt_G_E(x86)");
-//..       }
-//..    }
-//..  
-//..    /* Side effect done; now get selected bit into Carry flag */
-//..    /* Flags: C=selected bit, O,S,Z,A,P undefined, so are set to zero. */
-//..    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
-//..    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
-//..    stmt( IRStmt_Put( 
-//..             OFFB_CC_DEP1,
-//..             binop(Iop_And32,
-//..                   binop(Iop_Shr32, 
-//..                         unop(Iop_8Uto32, mkexpr(t_fetched)),
-//..                         mkexpr(t_bitno2)),
-//..                   mkU32(1)))
-//..        );
-//.. 
-//..    /* Move reg operand from stack back to reg */
-//..    if (epartIsReg(modrm)) {
-//..       /* t_esp still points at it. */
-//..       putIReg(sz, eregOfRM(modrm), loadLE(szToITy(sz), mkexpr(t_esp)) );
-//..       putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t_esp), mkU32(sz)) );
-//..    }
-//.. 
-//..    DIP("bt%s%c %s, %s\n",
-//..        nameBtOp(op), nameISize(sz), nameIReg(sz, gregOfRM(modrm)), 
-//..        ( epartIsReg(modrm) ? nameIReg(sz, eregOfRM(modrm)) : dis_buf ) );
-//..  
-//..    return delta;
-//.. }
+
+
+/* Handle BT/BTS/BTR/BTC Gv, Ev.  Apparently b-size is not
+   required. */
+
+typedef enum { BtOpNone, BtOpSet, BtOpReset, BtOpComp } BtOp;
+
+static HChar* nameBtOp ( BtOp op )
+{
+   switch (op) {
+      case BtOpNone:  return "";
+      case BtOpSet:   return "s";
+      case BtOpReset: return "r";
+      case BtOpComp:  return "c";
+      default: vpanic("nameBtOp(amd64)");
+   }
+}
+
+
+static
+ULong dis_bt_G_E ( Prefix pfx, Int sz, Long delta, BtOp op )
+{
+   HChar  dis_buf[50];
+   UChar  modrm;
+   Int    len;
+   IRTemp t_fetched, t_bitno0, t_bitno1, t_bitno2, t_addr0, 
+          t_addr1, t_rsp, t_mask;
+
+   vassert(sz == 2 || sz == 4 || sz == 8);
+
+   t_fetched = t_bitno0 = t_bitno1 = t_bitno2 
+             = t_addr0 = t_addr1 = t_rsp = t_mask = IRTemp_INVALID;
+
+   t_fetched = newTemp(Ity_I8);
+   t_bitno0  = newTemp(Ity_I64);
+   t_bitno1  = newTemp(Ity_I64);
+   t_bitno2  = newTemp(Ity_I8);
+   t_addr1   = newTemp(Ity_I64);
+   modrm     = getUChar(delta);
+
+   assign( t_bitno0, widenSto64(getIRegG(sz, pfx, modrm)) );
+   
+   if (epartIsReg(modrm)) {
+      delta++;
+      /* Get it onto the client's stack. */
+      t_rsp = newTemp(Ity_I64);
+      t_addr0 = newTemp(Ity_I64);
+
+      assign( t_rsp, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(sz)) );
+      putIReg64(R_RSP, mkexpr(t_rsp));
+
+      storeLE( mkexpr(t_rsp), getIRegE(sz, pfx, modrm) );
+
+      /* Make t_addr0 point at it. */
+      assign( t_addr0, mkexpr(t_rsp) );
+
+      /* Mask out upper bits of the shift amount, since we're doing a
+         reg. */
+      assign( t_bitno1, binop(Iop_And64, 
+                              mkexpr(t_bitno0), 
+                              mkU64(sz == 8 ? 63 : sz == 4 ? 31 : 15)) );
+
+   } else {
+      t_addr0 = disAMode ( &len, pfx, delta, dis_buf, 0 );
+      delta += len;
+      assign( t_bitno1, mkexpr(t_bitno0) );
+   }
+  
+   /* At this point: t_addr0 is the address being operated on.  If it
+      was a reg, we will have pushed it onto the client's stack.
+      t_bitno1 is the bit number, suitably masked in the case of a
+      reg.  */
+  
+   /* Now the main sequence. */
+   assign( t_addr1, 
+           binop(Iop_Add64, 
+                 mkexpr(t_addr0), 
+                 binop(Iop_Sar64, mkexpr(t_bitno1), mkU8(3))) );
+
+   /* t_addr1 now holds effective address */
+
+   assign( t_bitno2, 
+           unop(Iop_64to8, 
+                binop(Iop_And64, mkexpr(t_bitno1), mkU64(7))) );
+
+   /* t_bitno2 contains offset of bit within byte */
+
+   if (op != BtOpNone) {
+      t_mask = newTemp(Ity_I8);
+      assign( t_mask, binop(Iop_Shl8, mkU8(1), mkexpr(t_bitno2)) );
+   }
+
+   /* t_mask is now a suitable byte mask */
+
+   assign( t_fetched, loadLE(Ity_I8, mkexpr(t_addr1)) );
+
+   if (op != BtOpNone) {
+      switch (op) {
+         case BtOpSet: 
+            storeLE( mkexpr(t_addr1), 
+                     binop(Iop_Or8, mkexpr(t_fetched), 
+                                    mkexpr(t_mask)) );
+            break;
+         case BtOpComp: 
+            storeLE( mkexpr(t_addr1), 
+                     binop(Iop_Xor8, mkexpr(t_fetched), 
+                                     mkexpr(t_mask)) );
+            break;
+         case BtOpReset: 
+            storeLE( mkexpr(t_addr1), 
+                     binop(Iop_And8, mkexpr(t_fetched), 
+                                     unop(Iop_Not8, mkexpr(t_mask))) );
+            break;
+         default: 
+            vpanic("dis_bt_G_E(amd64)");
+      }
+   }
+   /* Side effect done; now get selected bit into Carry flag */
+   /* Flags: C=selected bit, O,S,Z,A,P undefined, so are set to zero. */
+   stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
+   stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
+   stmt( IRStmt_Put( 
+            OFFB_CC_DEP1,
+            binop(Iop_And64,
+                  binop(Iop_Shr64, 
+                        unop(Iop_8Uto64, mkexpr(t_fetched)),
+                        mkexpr(t_bitno2)),
+                  mkU64(1)))
+       );
+   /* Set NDEP even though it isn't used.  This makes redundant-PUT
+      elimination of previous stores to this field work better. */
+   stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));
+
+   /* Move reg operand from stack back to reg */
+   if (epartIsReg(modrm)) {
+      /* t_esp still points at it. */
+      putIRegE(sz, pfx, modrm, loadLE(szToITy(sz), mkexpr(t_rsp)) );
+      putIReg64(R_RSP, binop(Iop_Add64, mkexpr(t_rsp), mkU64(sz)) );
+   }
+
+   DIP("bt%s%c %s, %s\n",
+       nameBtOp(op), nameISize(sz), nameIRegG(sz, pfx, modrm), 
+       ( epartIsReg(modrm) ? nameIRegE(sz, pfx, modrm) : dis_buf ) );
+   return delta;
+}
 
 
 
@@ -12905,20 +12908,31 @@ DisResult disInstr_AMD64_WRK (
             goto decode_failure;
          }
 
-//..       /* =-=-=-=-=-=-=-=-=- BT/BTS/BTR/BTC =-=-=-=-=-=-= */
-//.. 
-//..       case 0xA3: /* BT Gv,Ev */
-//..          delta = dis_bt_G_E ( sorb, sz, delta, BtOpNone );
-//..          break;
-//..       case 0xB3: /* BTR Gv,Ev */
-//..          delta = dis_bt_G_E ( sorb, sz, delta, BtOpReset );
-//..          break;
-//..       case 0xAB: /* BTS Gv,Ev */
-//..          delta = dis_bt_G_E ( sorb, sz, delta, BtOpSet );
-//..          break;
-//..       case 0xBB: /* BTC Gv,Ev */
-//..          delta = dis_bt_G_E ( sorb, sz, delta, BtOpComp );
-//..          break;
+      /* =-=-=-=-=-=-=-=-=- BT/BTS/BTR/BTC =-=-=-=-=-=-= */
+
+      /* All of these are possible at sizes 2, 4 and 8, but until size
+         2 and 4 test cases show up, only handle size 8. */
+
+      case 0xA3: /* BT Gv,Ev */
+         if (haveF2orF3(pfx)) goto decode_failure;
+         if (sz != 8) goto decode_failure;
+         delta = dis_bt_G_E ( pfx, sz, delta, BtOpNone );
+         break;
+      case 0xB3: /* BTR Gv,Ev */
+         if (haveF2orF3(pfx)) goto decode_failure;
+         if (sz != 8) goto decode_failure;
+         delta = dis_bt_G_E ( pfx, sz, delta, BtOpReset );
+         break;
+      case 0xAB: /* BTS Gv,Ev */
+         if (haveF2orF3(pfx)) goto decode_failure;
+         if (sz != 8) goto decode_failure;
+         delta = dis_bt_G_E ( pfx, sz, delta, BtOpSet );
+         break;
+      case 0xBB: /* BTC Gv,Ev */
+         if (haveF2orF3(pfx)) goto decode_failure;
+         if (sz != 8) goto decode_failure;
+         delta = dis_bt_G_E ( pfx, sz, delta, BtOpComp );
+         break;
 
       /* =-=-=-=-=-=-=-=-=- CMOV =-=-=-=-=-=-=-=-=-=-=-= */
  
index edef881e3e175d86ec9d11fef09cc8f22ad5a8a1..201282a0600f74cabd86f7e0f3ffed96e74d1db9 100644 (file)
@@ -5679,7 +5679,7 @@ UInt dis_bt_G_E ( UChar sorb, Int sz, Int delta, BtOp op )
    t_addr1   = newTemp(Ity_I32);
    modrm     = getIByte(delta);
 
-   assign( t_bitno0, widenUto32(getIReg(sz, gregOfRM(modrm))) );
+   assign( t_bitno0, widenSto32(getIReg(sz, gregOfRM(modrm))) );
    
    if (epartIsReg(modrm)) {
       delta++;