ghelpers.c

来自「The Valgrind distribution has multiple t」· C语言 代码 · 共 1,898 行 · 第 1/5 页

C
1,898
字号
   }   vex_state->guest_CC_OP   = X86G_CC_OP_COPY;   vex_state->guest_CC_DEP1 = oszacp;   vex_state->guest_CC_DEP2 = 0;   vex_state->guest_CC_NDEP = 0;}/*---------------------------------------------------------------*//*--- %eflags translation-time function specialisers.         ---*//*--- These help iropt specialise calls the above run-time    ---*//*--- %eflags functions.                                      ---*//*---------------------------------------------------------------*//* Used by the optimiser to try specialisations.  Returns an   equivalent expression, or NULL if none. */static inline Bool isU32 ( IRExpr* e, UInt n ){   return       toBool( e->tag == Iex_Const              && e->Iex.Const.con->tag == Ico_U32              && e->Iex.Const.con->Ico.U32 == n );}IRExpr* guest_x86_spechelper ( HChar* function_name,                               IRExpr** args ){#  define unop(_op,_a1) IRExpr_Unop((_op),(_a1))#  define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))#  define mkU32(_n) IRExpr_Const(IRConst_U32(_n))#  define mkU8(_n)  IRExpr_Const(IRConst_U8(_n))   Int i, arity = 0;   for (i = 0; args[i]; i++)      arity++;#  if 0   vex_printf("spec request:\n");   vex_printf("   %s  ", function_name);   for (i = 0; i < arity; i++) {      vex_printf("  ");      ppIRExpr(args[i]);   }   vex_printf("\n");#  endif   /* --------- specialising "x86g_calculate_condition" --------- */   if (vex_streq(function_name, "x86g_calculate_condition")) {      /* specialise calls to above "calculate condition" function */      IRExpr *cond, *cc_op, *cc_dep1, *cc_dep2;      vassert(arity == 5);      cond    = args[0];      cc_op   = args[1];      cc_dep1 = args[2];      cc_dep2 = args[3];      /*---------------- ADDL ----------------*/      if (isU32(cc_op, X86G_CC_OP_ADDL) && isU32(cond, X86CondZ)) {         /* long add, then Z --> test (dst+src == 0) */         return unop(Iop_1Uto32,                     binop(Iop_CmpEQ32,                            binop(Iop_Add32, cc_dep1, cc_dep2),                           mkU32(0)));      }      /*---------------- SUBL ----------------*/      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondZ)) {         /* long sub/cmp, then Z --> test dst==src */         return unop(Iop_1Uto32,                     binop(Iop_CmpEQ32, cc_dep1, cc_dep2));      }      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondNZ)) {         /* long sub/cmp, then NZ --> test dst!=src */         return unop(Iop_1Uto32,                     binop(Iop_CmpNE32, cc_dep1, cc_dep2));      }      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondL)) {         /* long sub/cmp, then L (signed less than)             --> test dst <s src */         return unop(Iop_1Uto32,                     binop(Iop_CmpLT32S, cc_dep1, cc_dep2));      }      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondLE)) {         /* long sub/cmp, then LE (signed less than or equal)            --> test dst <=s src */         return unop(Iop_1Uto32,                     binop(Iop_CmpLE32S, cc_dep1, cc_dep2));      }      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondBE)) {         /* long sub/cmp, then BE (unsigned less than or equal)            --> test dst <=u src */         return unop(Iop_1Uto32,                     binop(Iop_CmpLE32U, cc_dep1, cc_dep2));      }      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondB)) {         /* long sub/cmp, then B (unsigned less than)            --> test dst <u src */         return unop(Iop_1Uto32,                     binop(Iop_CmpLT32U, cc_dep1, cc_dep2));      }      if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondS)) {         /* long sub/cmp, then S --> test (dst-src <s 0) */         return unop(Iop_1Uto32,                     binop(Iop_CmpLT32S,                            binop(Iop_Sub32, cc_dep1, cc_dep2),                           mkU32(0)));      }      /*---------------- SUBW ----------------*/      if (isU32(cc_op, X86G_CC_OP_SUBW) && isU32(cond, X86CondZ)) {         /* word sub/cmp, then Z --> test dst==src */         return unop(Iop_1Uto32,                     binop(Iop_CmpEQ16,                            unop(Iop_32to16,cc_dep1),                            unop(Iop_32to16,cc_dep2)));      }      /*---------------- SUBB ----------------*/      if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondZ)) {         /* byte sub/cmp, then Z --> test dst==src */         return unop(Iop_1Uto32,                     binop(Iop_CmpEQ8,                            unop(Iop_32to8,cc_dep1),                            unop(Iop_32to8,cc_dep2)));      }      if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondNZ)) {         /* byte sub/cmp, then NZ --> test dst!=src */         return unop(Iop_1Uto32,                     binop(Iop_CmpNE8,                            unop(Iop_32to8,cc_dep1),                            unop(Iop_32to8,cc_dep2)));      }      if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondNBE)) {         /* byte sub/cmp, then NBE (unsigned greater than)            --> test src <u dst */         /* Note, args are opposite way round from the usual */         return unop(Iop_1Uto32,                     binop(Iop_CmpLT32U,                            binop(Iop_And32,cc_dep2,mkU32(0xFF)),			   binop(Iop_And32,cc_dep1,mkU32(0xFF))));      }      if (isU32(cc_op, X86G_CC_OP_SUBB) && isU32(cond, X86CondS)                                        && isU32(cc_dep2, 0)) {         /* byte sub/cmp of zero, then S --> test (dst-0 <s 0)                                          --> test dst <s 0                                         --> (UInt)dst[7]             This is yet another scheme by which gcc figures out if the            top bit of a byte is 1 or 0.  See also LOGICB/CondS below. */         /* Note: isU32(cc_dep2, 0) is correct, even though this is            for an 8-bit comparison, since the args to the helper            function are always U32s. */         return binop(Iop_And32,                      binop(Iop_Shr32,cc_dep1,mkU8(7)),                      mkU32(1));      }      /*---------------- LOGICL ----------------*/      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondZ)) {         /* long and/or/xor, then Z --> test dst==0 */         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));      }      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondNZ)) {         /* long and/or/xor, then NZ --> test dst!=0 */         return unop(Iop_1Uto32,binop(Iop_CmpNE32, cc_dep1, mkU32(0)));      }      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondLE)) {         /* long and/or/xor, then LE            This is pretty subtle.  LOGIC sets SF and ZF according to the            result and makes OF be zero.  LE computes (SZ ^ OF) | ZF, but            OF is zero, so this reduces to SZ | ZF -- which will be 1 iff            the result is <=signed 0.  Hence ...         */         return unop(Iop_1Uto32,binop(Iop_CmpLE32S, cc_dep1, mkU32(0)));      }      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondBE)) {         /* long and/or/xor, then BE            LOGIC sets ZF according to the result and makes CF be zero.            BE computes (CF | ZF), but CF is zero, so this reduces ZF             -- which will be 1 iff the result is zero.  Hence ...         */         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));      }      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondS)) {         /* see comment below for (LOGICB, CondS) */         /* long and/or/xor, then S --> (UInt)result[31] */         return binop(Iop_And32,                      binop(Iop_Shr32,cc_dep1,mkU8(31)),                      mkU32(1));      }      if (isU32(cc_op, X86G_CC_OP_LOGICL) && isU32(cond, X86CondNS)) {         /* see comment below for (LOGICB, CondNS) */         /* long and/or/xor, then S --> (UInt) ~ result[31] */         return binop(Iop_Xor32,                binop(Iop_And32,                      binop(Iop_Shr32,cc_dep1,mkU8(31)),                      mkU32(1)),                mkU32(1));      }      /*---------------- LOGICW ----------------*/      if (isU32(cc_op, X86G_CC_OP_LOGICW) && isU32(cond, X86CondZ)) {         /* word and/or/xor, then Z --> test dst==0 */         return unop(Iop_1Uto32,                     binop(Iop_CmpEQ32, binop(Iop_And32,cc_dep1,mkU32(0xFFFF)),                                         mkU32(0)));      }      if (isU32(cc_op, X86G_CC_OP_LOGICW) && isU32(cond, X86CondS)) {         /* see comment below for (LOGICB, CondS) */         /* word and/or/xor, then S --> (UInt)result[15] */         return binop(Iop_And32,                      binop(Iop_Shr32,cc_dep1,mkU8(15)),                      mkU32(1));      }      //Probably correct, but no test case for it yet found      //if (isU32(cc_op, X86G_CC_OP_LOGICW) && isU32(cond, X86CondNS)) {      //   /* see comment below for (LOGICB, CondNS) */      //   /* word and/or/xor, then S --> (UInt) ~ result[15] */      //   vassert(0+0);      //   return binop(Iop_Xor32,      //          binop(Iop_And32,      //                binop(Iop_Shr32,cc_dep1,mkU8(15)),      //                mkU32(1)),      //          mkU32(1));      //}      /*---------------- LOGICB ----------------*/      if (isU32(cc_op, X86G_CC_OP_LOGICB) && isU32(cond, X86CondZ)) {         /* byte and/or/xor, then Z --> test dst==0 */         return unop(Iop_1Uto32,                     binop(Iop_CmpEQ32, binop(Iop_And32,cc_dep1,mkU32(255)),                                         mkU32(0)));      }      if (isU32(cc_op, X86G_CC_OP_LOGICB) && isU32(cond, X86CondNZ)) {         /* byte and/or/xor, then Z --> test dst!=0 */         /* b9ac9:       84 c0                   test   %al,%al            b9acb:       75 0d                   jne    b9ada */         return unop(Iop_1Uto32,                     binop(Iop_CmpNE32, binop(Iop_And32,cc_dep1,mkU32(255)),                                         mkU32(0)));      }      if (isU32(cc_op, X86G_CC_OP_LOGICB) && isU32(cond, X86CondS)) {         /* this is an idiom gcc sometimes uses to find out if the top            bit of a byte register is set: eg testb %al,%al; js ..            Since it just depends on the top bit of the byte, extract            that bit and explicitly get rid of all the rest.  This            helps memcheck avoid false positives in the case where any            of the other bits in the byte are undefined. */         /* byte and/or/xor, then S --> (UInt)result[7] */         return binop(Iop_And32,                      binop(Iop_Shr32,cc_dep1,mkU8(7)),                      mkU32(1));      }      if (isU32(cc_op, X86G_CC_OP_LOGICB) && isU32(cond, X86CondNS)) {         /* ditto, for negation-of-S. */         /* byte and/or/xor, then S --> (UInt) ~ result[7] */         return binop(Iop_Xor32,                binop(Iop_And32,                      binop(Iop_Shr32,cc_dep1,mkU8(7)),                      mkU32(1)),                mkU32(1));      }      /*---------------- DECL ----------------*/      if (isU32(cc_op, X86G_CC_OP_DECL) && isU32(cond, X86CondZ)) {         /* dec L, then Z --> test dst == 0 */         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));      }      if (isU32(cc_op, X86G_CC_OP_DECL) && isU32(cond, X86CondS)) {         /* dec L, then S --> compare DST <s 0 */         return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dep1, mkU32(0)));      }      /*---------------- DECW ----------------*/      if (isU32(cc_op, X86G_CC_OP_DECW) && isU32(cond, X86CondZ)) {         /* dec W, then Z --> test dst == 0 */         return unop(Iop_1Uto32,                     binop(Iop_CmpEQ32,                            binop(Iop_Shl32,cc_dep1,mkU8(16)),                            mkU32(0)));      }      /*---------------- INCW ----------------*/      if (isU32(cc_op, X86G_CC_OP_INCW) && isU32(cond, X86CondZ)) {         /* This rewrite helps memcheck on 'incw %ax ; je ...'. */         /* inc W, then Z --> test dst == 0 */         return unop(Iop_1Uto32,                     binop(Iop_CmpEQ32,                            binop(Iop_Shl32,cc_dep1,mkU8(16)),                           mkU32(0)));      }      /*---------------- SHRL ----------------*/      if (isU32(cc_op, X86G_CC_OP_SHRL) && isU32(cond, X86CondZ)) {         /* SHRL, then Z --> test dep1 == 0 */         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));      }      /*---------------- COPY ----------------*/      /* This can happen, as a result of x87 FP compares: "fcom ... ;         fnstsw %ax ; sahf ; jbe" for example. */      if (isU32(cc_op, X86G_CC_OP_COPY) &&           (isU32(cond, X86CondBE) || isU32(cond, X86CondNBE))) {         /* COPY, then BE --> extract C and Z from dep1, and test (C            or Z == 1). */         /* COPY, then NBE --> extract C and Z from dep1, and test (C            or Z == 0). */         UInt nnn = isU32(cond, X86CondBE) ? 1 : 0;         return            unop(               Iop_1Uto32,               binop(                  Iop_CmpEQ32,                  binop(                     Iop_And32,                     binop(                        Iop_Or32,                        binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),                        binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_Z))                     ),                     mkU32(1)                  ),                  mkU32(nnn)               )            );      }            if (isU32(cc_op, X86G_CC_OP_COPY) &&           (isU32(cond, X86CondB) || isU32(cond, X86CondNB))) {         /* COPY, then B --> extract C from dep1, and test (C == 1). */         /* COPY, then NB --> extract C from dep1, and test (C == 0). */         UInt nnn = isU32(cond, X86CondB) ? 1 : 0;         return            unop(               Iop_1Uto32,               binop(                  Iop_CmpEQ32,                  binop(                     Iop_And32,                     binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)),                     mkU32(1)                  ),                  mkU32(nnn)               )            );      }      if (isU32(cc_op, X86G_CC_OP_COPY) && isU32(cond, X86CondZ)) {         /* COPY, then Z --> extract Z from dep1, and test (Z == 1). */         return            unop(

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?