]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fill in many more cases thrown up the QEMU test program.
authorJulian Seward <jseward@acm.org>
Thu, 29 Jul 2004 20:31:09 +0000 (20:31 +0000)
committerJulian Seward <jseward@acm.org>
Thu, 29 Jul 2004 20:31:09 +0000 (20:31 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@155

VEX/priv/guest-x86/ghelpers.c
VEX/priv/guest-x86/toIR.c
VEX/priv/host-x86/isel.c
VEX/priv/ir/irdefs.c
VEX/pub/libvex_ir.h

index 6ac2557f37cad9d5b40a11e571280566dea79414..7bf38d6c5dbdfde1bc9d40d92e5b50a4681ead58 100644 (file)
@@ -230,6 +230,19 @@ static inline int lshift(int x, int n)
     return cf | pf | af | zf | sf | of;                                \
 }
 
+/* ROL: cf' = msb(result).  of' = msb(result) ^ lsb(result). */
+/* DST = result, SRC = old flags */
+#define ACTIONS_ROL(DATA_BITS,DATA_TYPE)               \
+{                                                              \
+    PREAMBLE(DATA_BITS);                                       \
+    int fl                                                     \
+       = (CC_SRC & ~(CC_O | CC_C))                             \
+         | (CC_C & (CC_DST >> (DATA_BITS-1)))                  \
+         | (CC_O & (lshift(CC_DST, 11-(DATA_BITS-1))           \
+                    ^ lshift(CC_DST, 11)));    \
+    return fl;                                                 \
+}
+
 /* ROR: cf' = msb(result).  of' = msb(result) ^ msb-1(result). */
 /* DST = result, SRC = old flags */
 #define ACTIONS_ROR(DATA_BITS,DATA_TYPE)               \
@@ -267,39 +280,49 @@ static inline int lshift(int x, int n)
          return cc_src & (CC_MASK_O | CC_MASK_S | CC_MASK_Z 
                           | CC_MASK_A | CC_MASK_C | CC_MASK_O);
 
-      case CC_OP_ADDB:   ACTIONS_ADD( 8,  UChar );
+      case CC_OP_ADDB:   ACTIONS_ADD( 8,  UChar  );
       case CC_OP_ADDW:   ACTIONS_ADD( 16, UShort );
-      case CC_OP_ADDL:   ACTIONS_ADD( 32, UInt );
+      case CC_OP_ADDL:   ACTIONS_ADD( 32, UInt   );
 
-      case CC_OP_ADCB:   ACTIONS_ADC( 8,  UChar );
+      case CC_OP_ADCB:   ACTIONS_ADC( 8,  UChar  );
       case CC_OP_ADCW:   ACTIONS_ADC( 16, UShort );
-      case CC_OP_ADCL:   ACTIONS_ADC( 32, UInt );
+      case CC_OP_ADCL:   ACTIONS_ADC( 32, UInt   );
 
-      case CC_OP_SUBB:   ACTIONS_SUB(  8, UChar );
+      case CC_OP_SUBB:   ACTIONS_SUB(  8, UChar  );
       case CC_OP_SUBW:   ACTIONS_SUB( 16, UShort );
-      case CC_OP_SUBL:   ACTIONS_SUB( 32, UInt );
+      case CC_OP_SUBL:   ACTIONS_SUB( 32, UInt   );
 
-      case CC_OP_SBBB:   ACTIONS_SBB(  8, UChar );
+      case CC_OP_SBBB:   ACTIONS_SBB(  8, UChar  );
       case CC_OP_SBBW:   ACTIONS_SBB( 16, UShort );
-      case CC_OP_SBBL:   ACTIONS_SBB( 32, UInt );
+      case CC_OP_SBBL:   ACTIONS_SBB( 32, UInt   );
 
-      case CC_OP_LOGICB: ACTIONS_LOGIC(  8, UChar );
+      case CC_OP_LOGICB: ACTIONS_LOGIC(  8, UChar  );
       case CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort );
-      case CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt );
+      case CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt   );
 
-      case CC_OP_INCB:   ACTIONS_INC(  8, UChar );
+      case CC_OP_INCB:   ACTIONS_INC(  8, UChar  );
       case CC_OP_INCW:   ACTIONS_INC( 16, UShort );
-      case CC_OP_INCL:   ACTIONS_INC( 32, UInt );
+      case CC_OP_INCL:   ACTIONS_INC( 32, UInt   );
 
-      case CC_OP_DECB:   ACTIONS_DEC(  8, UChar );
+      case CC_OP_DECB:   ACTIONS_DEC(  8, UChar  );
       case CC_OP_DECW:   ACTIONS_DEC( 16, UShort );
-      case CC_OP_DECL:   ACTIONS_DEC( 32, UInt );
+      case CC_OP_DECL:   ACTIONS_DEC( 32, UInt   );
+
+      case CC_OP_SHLB:   ACTIONS_SHL(  8, UChar  );
+      case CC_OP_SHLW:   ACTIONS_SHL( 16, UShort );
+      case CC_OP_SHLL:   ACTIONS_SHL( 32, UInt   );
+
+      case CC_OP_SARB:   ACTIONS_SAR(  8, UChar  );
+      case CC_OP_SARW:   ACTIONS_SAR( 16, UShort );
+      case CC_OP_SARL:   ACTIONS_SAR( 32, UInt   );
 
-      case CC_OP_SHLL:   ACTIONS_SHL( 32, UInt );
-      case CC_OP_SARL:   ACTIONS_SAR( 32, UInt );
+      case CC_OP_ROLB:   ACTIONS_ROL(  8, UChar  );
+      case CC_OP_ROLW:   ACTIONS_ROL( 16, UShort );
+      case CC_OP_ROLL:   ACTIONS_ROL( 32, UInt   );
 
+      case CC_OP_RORB:   ACTIONS_ROR(  8, UChar  );
       case CC_OP_RORW:   ACTIONS_ROR( 16, UShort );
-      case CC_OP_RORL:   ACTIONS_ROR( 32, UInt );
+      case CC_OP_RORL:   ACTIONS_ROR( 32, UInt   );
 
       case CC_OP_MULL:   ACTIONS_MUL( 32, UInt, Long );
 
index ee6b56978418e4c790ff8ef4673415c17ce893b6..97b29ee6bd7e5175fbbb30cf32b20401bcb4ed87 100644 (file)
@@ -1974,7 +1974,7 @@ void codegen_div ( Int sz, IRTemp t, Bool signed_divide )
          assign( src64, binop(Iop_32HLto64, 
                  getIReg(4,R_EDX), getIReg(4,R_EAX)) );
          assign( dst64, binop(op, mkexpr(src64), mkexpr(t)) );
-         putIReg( 4, R_EAX, unop(Iop_64LOto32,mkexpr(dst64)) );
+         putIReg( 4, R_EAX, unop(Iop_64to32,mkexpr(dst64)) );
          putIReg( 4, R_EDX, unop(Iop_64HIto32,mkexpr(dst64)) );
          break;
       }
@@ -2147,16 +2147,6 @@ UInt dis_Grp2 ( UChar  sorb,
 
    vassert(sz == 1 || sz == 2 || sz == 4);
 
-#if 0
-   switch (gregOfRM(modrm)) {
-      case 0: op8 = Iop_RolROL; break;  case 1: op8 = ROR; break;
-      case 2: op8 = RCL; break;  case 3: op8 = RCR; break;
-      case 4: op8 = Iop_Shl8; break;  case 5: op8 = Iop_Shr8; break;
-      case 7: op8 = Iop_Sar8; break;
-      default: vpanic("dis_Grp2(Reg): unhandled case(x86)");
-   }
-#endif
-
    /* Put value to shift/rotate in dst0. */
    if (epartIsReg(modrm)) {
       assign(dst0, getIReg(sz, eregOfRM(modrm)));
@@ -2173,6 +2163,11 @@ UInt dis_Grp2 ( UChar  sorb,
    isRotate = False;
    switch (gregOfRM(modrm)) { case 0: case 1: isRotate = True; }
 
+   if (!isShift && !isRotate) {
+      vex_printf("\ncase %d\n", gregOfRM(modrm));
+      vpanic("dis_Grp2(Reg): unhandled case(x86)");
+   }
+
    if (isShift) {
 
       IRTemp subshift  = newTemp(ty);
@@ -2434,7 +2429,7 @@ static void codegen_mulL_A_D ( Int sz, Bool syned,
       setFlags_MUL ( Ity_I32, t1, tmp, thunkOp );
       assign( res64, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
       putIReg(4, R_EDX, unop(Iop_64HIto32,mkexpr(res64)));
-      putIReg(4, R_EAX, unop(Iop_64LOto32,mkexpr(res64)));
+      putIReg(4, R_EAX, unop(Iop_64to32,mkexpr(res64)));
       break;
    }
    default:
@@ -3383,18 +3378,25 @@ UInt dis_SHLRD_Gv_Ev ( UChar sorb,
       tmpRes   = newTemp(Ity_I32);
       tmpSubSh = newTemp(Ity_I32);
       mkpair   = Iop_32HLto64;
-      getres   = left_shift ? Iop_64HIto32 : Iop_64LOto32;
+      getres   = left_shift ? Iop_64HIto32 : Iop_64to32;
       shift    = left_shift ? Iop_Shl64 : Iop_Shr64;
       mask     = mkU8(31);
-      assign( tmpSH, binop(Iop_And8, shift_amt, mask) );
    } else {
       /* sz == 2 */
-      vassert(0);
+      tmpL     = newTemp(Ity_I32);
+      tmpRes   = newTemp(Ity_I16);
+      tmpSubSh = newTemp(Ity_I16);
+      mkpair   = Iop_16HLto32;
+      getres   = left_shift ? Iop_32HIto16 : Iop_32to16;
+      shift    = left_shift ? Iop_Shl32 : Iop_Shr32;
+      mask     = mkU8(15);
    }
 
    /* Do the shift, calculate the subshift value, and set 
       the flag thunk. */
 
+   assign( tmpSH, binop(Iop_And8, shift_amt, mask) );
+
    if (left_shift)
       assign( tmpL, binop(mkpair, mkexpr(esrc), mkexpr(gsrc)) );
    else
@@ -3408,11 +3410,9 @@ UInt dis_SHLRD_Gv_Ev ( UChar sorb,
                       binop(Iop_And8, 
                             binop(Iop_Sub8, mkexpr(tmpSH), mkU8(1) ),
                             mask))) );
-   //assign( guard, binop(Iop_CmpNE8, mkexpr(tmpSH), mkU8(0)) );
 
-   setFlags_DSTus_DST1 ( 
-                       left_shift ? Iop_Shl8 : Iop_Sar8,
-                       tmpSubSh, tmpRes, ty, tmpSH );
+   setFlags_DSTus_DST1 ( left_shift ? Iop_Shl8 : Iop_Sar8,
+                        tmpSubSh, tmpRes, ty, tmpSH );
 
    /* Put result back. */
 
@@ -7261,13 +7261,14 @@ static UInt disInstr ( UInt delta, Bool* isEnd )
                          mkU8(d32), NULL );
       break;
 
-//--    case 0xD2: /* Grp2 CL,Eb */
-//--       modrm = getUChar(eip);
-//--       am_sz = lengthAMode(eip);
-//--       d_sz  = 0;
-//--       sz    = 1;
-//--       eip   = dis_Grp2 ( cb, sorb, eip, modrm, am_sz, d_sz, sz, ArchReg, R_ECX );
-//--       break;
+   case 0xD2: /* Grp2 CL,Eb */
+      modrm = getUChar(delta);
+      am_sz = lengthAMode(delta);
+      d_sz  = 0;
+      sz    = 1;
+      delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
+                         getIReg(1,R_ECX), "%cl" );
+      break;
 
    case 0xD3: /* Grp2 CL,Ev */
       modrm = getIByte(delta);
index 9a313f975e1dcc46e5f172b4102d0472cdd22dc3..aed8aece4c1192ba0cb70df11bce1da58d3499e2 100644 (file)
@@ -281,19 +281,17 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
    case Iex_Binop: {
       X86AluOp   aluOp;
       X86ShiftOp shOp;
+
       /* Is it an addition or logical style op? */
       switch (e->Iex.Binop.op) {
          case Iop_Add8: case Iop_Add16: case Iop_Add32:
             aluOp = Xalu_ADD; break;
-
          case Iop_Sub8: case Iop_Sub16: case Iop_Sub32: 
             aluOp = Xalu_SUB; break;
-
          case Iop_And8: case Iop_And16: case Iop_And32: 
             aluOp = Xalu_AND; break;
          case Iop_Or8: case Iop_Or16: case Iop_Or32:  
             aluOp = Xalu_OR; break;
-
          case Iop_Xor8: case Iop_Xor16: case Iop_Xor32: 
             aluOp = Xalu_XOR; break;
          case Iop_Mul32: aluOp = Xalu_MUL; break;
@@ -309,19 +307,20 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
          addInstr(env, X86Instr_Alu32R(aluOp, rmi, dst));
          return dst;
       }
+
       /* Perhaps a shift op? */
       switch (e->Iex.Binop.op) {
          case Iop_Shl32: case Iop_Shl16: case Iop_Shl8:
             shOp = Xsh_SHL; break;
          case Iop_Shr32: case Iop_Shr16: case Iop_Shr8: 
             shOp = Xsh_SHR; break;
-         case Iop_Sar32: 
+         case Iop_Sar32: case Iop_Sar16: case Iop_Sar8: 
             shOp = Xsh_SAR; break;
          default:
             shOp = Xsh_INVALID; break;
       }
       if (shOp != Xsh_INVALID) {
-         HReg dst    = newVRegI(env);
+         HReg dst = newVRegI(env);
 
          /* regL = the value to be shifted */
          HReg regL   = iselIntExpr_R(env, e->Iex.Binop.arg1);
@@ -337,7 +336,14 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
                addInstr(env, X86Instr_Alu32R(
                                 Xalu_AND, X86RMI_Imm(0xFFFF), dst));
                break;
-            case Iop_Sar8: case Iop_Sar16: vassert(0); // fill this in!
+            case Iop_Sar8:
+               addInstr(env, X86Instr_Sh32(Xsh_SHL, 24, X86RM_Reg(dst)));
+               addInstr(env, X86Instr_Sh32(Xsh_SAR, 24, X86RM_Reg(dst)));
+               break;
+            case Iop_Sar16:
+               addInstr(env, X86Instr_Sh32(Xsh_SHL, 16, X86RM_Reg(dst)));
+               addInstr(env, X86Instr_Sh32(Xsh_SAR, 16, X86RM_Reg(dst)));
+               break;
             default: break;
          }
 
@@ -362,6 +368,21 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
          }
          return dst;
       }
+
+      /* Handle misc other ops. */
+      if (e->Iex.Binop.op == Iop_16HLto32) {
+         HReg hi16  = newVRegI(env);
+         HReg lo16  = newVRegI(env);
+         HReg hi16s = iselIntExpr_R(env, e->Iex.Binop.arg1);
+         HReg lo16s = iselIntExpr_R(env, e->Iex.Binop.arg2);
+         addInstr(env, mk_MOVsd_RR(hi16s, hi16));
+         addInstr(env, mk_MOVsd_RR(lo16s, lo16));
+         addInstr(env, X86Instr_Sh32(Xsh_SHL, 16, X86RM_Reg(hi16)));
+         addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0xFFFF), lo16));
+         addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(lo16), hi16));
+         return hi16;
+      }
+
       break;
    }
 
@@ -405,12 +426,18 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
             iselIntExpr64(&rHi,&rLo, env, e->Iex.Unop.arg);
             return rHi; /* and abandon rLo .. poor wee thing :-) */
          }
-         case Iop_64LOto32: {
+         case Iop_64to32: {
             HReg rHi, rLo;
             iselIntExpr64(&rHi,&rLo, env, e->Iex.Unop.arg);
             return rLo; /* similar stupid comment to the above ... */
          }
-
+         case Iop_32HIto16: {
+            HReg dst = newVRegI(env);
+            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
+            addInstr(env, mk_MOVsd_RR(src,dst) );
+            addInstr(env, X86Instr_Sh32(Xsh_SHR, 16, X86RM_Reg(dst)));
+            return dst;
+         }
          case Iop_32to8:
          case Iop_32to16:
             /* These are both no-ops. */
index 600af3e3c7d96a95138dce28cf231a722aaa8dfc..11d2515fc5b753140d63fa3d0a2660d805492852 100644 (file)
@@ -89,7 +89,6 @@ void ppIROp ( IROp op )
       case Iop_8Sto32:   vex_printf("8Sto32");  return;
       case Iop_16Sto32:  vex_printf("16Sto32"); return;
       case Iop_32to8:    vex_printf("32to8");   return;
-      case Iop_32to16:   vex_printf("32to16");  return;
       case Iop_32to1:    vex_printf("32to1");   return;
       case Iop_1Uto8:    vex_printf("1Uto8");   return;
 
@@ -103,8 +102,12 @@ void ppIROp ( IROp op )
       case Iop_DivModU64to32: vex_printf("DivModU64to32"); return;
       case Iop_DivModS64to32: vex_printf("DivModS64to32"); return;
 
+      case Iop_32HIto16: vex_printf("32HIto16"); return;
+      case Iop_32to16:   vex_printf("32to16");   return;
+      case Iop_16HLto32: vex_printf("16HLto32"); return;
+
       case Iop_64HIto32: vex_printf("64HIto32"); return;
-      case Iop_64LOto32: vex_printf("64LOto32"); return;
+      case Iop_64to32:   vex_printf("64to32");   return;
       case Iop_32HLto64: vex_printf("32HLto64"); return;
 
       default:           vpanic("ppIROp(1)");
@@ -481,7 +484,12 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 )
       case Iop_DivModS64to32:
          BINARY(Ity_I64,Ity_I64,Ity_I32);
 
-      case Iop_64HIto32: case Iop_64LOto32:
+      case Iop_32HIto16: case Iop_32to16:
+         UNARY(Ity_I16,Ity_I32);
+      case Iop_16HLto32:
+         BINARY(Ity_I32,Ity_I16,Ity_I16);
+
+      case Iop_64HIto32: case Iop_64to32:
          UNARY(Ity_I32, Ity_I64);
       case Iop_32HLto64:
          BINARY(Ity_I64,Ity_I32,Ity_I32);
@@ -491,7 +499,6 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 )
       case Iop_8Uto32:  UNARY(Ity_I32,Ity_I8);
       case Iop_16Uto32: UNARY(Ity_I32,Ity_I16);
       case Iop_32to8:   UNARY(Ity_I8,Ity_I32);
-      case Iop_32to16:  UNARY(Ity_I16,Ity_I32);
 
       default:
          ppIROp(op);
index 9c262cdcfb0d07501b1ac4ea6d401cfde6c726fd..959a24f22876fc0c9b7a11026fc6d89091c6390f 100644 (file)
@@ -98,9 +98,13 @@ typedef
       Iop_8Uto16, Iop_8Uto32, Iop_16Uto32,
       Iop_8Sto16, Iop_8Sto32, Iop_16Sto32,
       /* Narrowing conversions */
-      Iop_32to16, Iop_32to8,
+      Iop_32to8,
+      /* 16 <-> 32 bit conversions */
+      Iop_32to16,     // :: I32 -> I16, low half
+      Iop_32HIto16,   // :: I32 -> I16, high half
+      Iop_16HLto32,   // :: (I16,I16) -> I32
       /* 32 <-> 64 bit conversions */
-      Iop_64LOto32,   // :: I64 -> I32, low half
+      Iop_64to32,     // :: I64 -> I32, low half
       Iop_64HIto32,   // :: I64 -> I32, high half
       Iop_32HLto64,   // :: (I32,I32) -> I64
       /* 1-bit stuff */