⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isel.c

📁 unix下调试内存泄露的工具源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Given an amode, return one which references 4 bytes further   along. */static PPC32AMode* advance4 ( ISelEnv* env, PPC32AMode* am ){   PPC32AMode* am4 = dopyPPC32AMode(am);   if (am4->tag == Pam_IR        && am4->Pam.IR.index + 4 <= 32767) {      am4->Pam.IR.index += 4;   } else {      vpanic("advance4(ppc32,host)");   }   return am4;}/* Used only in doHelperCall.  See big comment in doHelperCall re   handling of register-parameter args.  This function figures out   whether evaluation of an expression might require use of a fixed   register.  If in doubt return True (safe but suboptimal).*/staticBool mightRequireFixedRegs ( IRExpr* e ){   switch (e->tag) {   case Iex_Tmp: case Iex_Const: case Iex_Get:       return False;   default:      return True;   }}/* Do a complete function call.  guard is a Ity_Bit expression   indicating whether or not the call happens.  If guard==NULL, the   call is unconditional. */staticvoid doHelperCall ( ISelEnv* env,                     Bool passBBP,                     IRExpr* guard, IRCallee* cee, IRExpr** args ){   PPC32CondCode cc;   HReg          argregs[PPC32_N_REGPARMS];   HReg          tmpregs[PPC32_N_REGPARMS];   Bool          go_fast;   Int           n_args, i, argreg;   /* Marshal args for a call and do the call.      If passBBP is True, %rbp (the baseblock pointer) is to be passed      as the first arg.      This function only deals with a tiny set of possibilities, which      cover all helpers in practice.  The restrictions are that only      arguments in registers are supported, hence only PPC32_N_REGPARMSx32      integer bits in total can be passed.  In fact the only supported      arg type is I32.      Generating code which is both efficient and correct when      parameters are to be passed in registers is difficult, for the      reasons elaborated in detail in comments attached to      doHelperCall() in priv/host-x86/isel.c.  Here, we use a variant      of the method described in those comments.      The problem is split into two cases: the fast scheme and the      slow scheme.  In the fast scheme, arguments are computed      directly into the target (real) registers.  This is only safe      when we can be sure that computation of each argument will not      trash any real registers set by computation of any other      argument.      In the slow scheme, all args are first computed into vregs, and      once they are all done, they are moved to the relevant real      regs.  This always gives correct code, but it also gives a bunch      of vreg-to-rreg moves which are usually redundant but are hard      for the register allocator to get rid of.      To decide which scheme to use, all argument expressions are      first examined.  If they are all so simple that it is clear they      will be evaluated without use of any fixed registers, use the      fast scheme, else use the slow scheme.  Note also that only      unconditional calls may use the fast scheme, since having to      compute a condition expression could itself trash real      registers.      Note this requires being able to examine an expression and      determine whether or not evaluation of it might use a fixed      register.  That requires knowledge of how the rest of this insn      selector works.  Currently just the following 3 are regarded as      safe -- hopefully they cover the majority of arguments in      practice: IRExpr_Tmp IRExpr_Const IRExpr_Get.   */   /* Note that the cee->regparms field is meaningless on PPC32 host      (since there is only one calling convention) and so we always      ignore it. */   n_args = 0;   for (i = 0; args[i]; i++)      n_args++;   if (PPC32_N_REGPARMS < n_args + (passBBP ? 1 : 0)) {      vpanic("doHelperCall(PPC32): cannot currently handle > 8 args");      // PPC32_N_REGPARMS   }      argregs[0] = hregPPC32_GPR3();   argregs[1] = hregPPC32_GPR4();   argregs[2] = hregPPC32_GPR5();   argregs[3] = hregPPC32_GPR6();   argregs[4] = hregPPC32_GPR7();   argregs[5] = hregPPC32_GPR8();   argregs[6] = hregPPC32_GPR9();   argregs[7] = hregPPC32_GPR10();   tmpregs[0] = tmpregs[1] = tmpregs[2] =   tmpregs[3] = tmpregs[4] = tmpregs[5] =   tmpregs[6] = tmpregs[7] = INVALID_HREG;   /* First decide which scheme (slow or fast) is to be used.  First      assume the fast scheme, and select slow if any contraindications      (wow) appear. */   go_fast = True;   if (guard) {      if (guard->tag == Iex_Const           && guard->Iex.Const.con->tag == Ico_U1          && guard->Iex.Const.con->Ico.U1 == True) {         /* unconditional */      } else {         /* Not manifestly unconditional -- be conservative. */         go_fast = False;      }   }   if (go_fast) {      for (i = 0; i < n_args; i++) {         if (mightRequireFixedRegs(args[i])) {            go_fast = False;            break;         }      }   }   /* At this point the scheme to use has been established.  Generate      code to get the arg values into the argument rregs. */   if (go_fast) {      /* FAST SCHEME */      argreg = 0;      if (passBBP) {         addInstr(env, mk_iMOVds_RR( argregs[argreg], GuestStatePtr ));         argreg++;      }      for (i = 0; i < n_args; i++) {         vassert(argreg < PPC32_N_REGPARMS);         vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32 ||                 typeOfIRExpr(env->type_env, args[i]) == Ity_I64);         if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32) {             addInstr(env, mk_iMOVds_RR( argregs[argreg],                                        iselIntExpr_R(env, args[i]) ));         } else { // Ity_I64            HReg rHi, rLo;            if (argreg%2 == 1) // ppc32 abi spec for passing a LONG_LONG               argreg++;       // XXX: odd argreg => even rN            vassert(argreg < PPC32_N_REGPARMS-1);            iselInt64Expr(&rHi,&rLo, env, args[i]);            addInstr(env, mk_iMOVds_RR( argregs[argreg++], rHi ));            addInstr(env, mk_iMOVds_RR( argregs[argreg], rLo));         }         argreg++;      }      /* Fast scheme only applies for unconditional calls.  Hence: */      cc.test = Pct_ALWAYS;   } else {      /* SLOW SCHEME; move via temporaries */      argreg = 0;      if (passBBP) {         /* This is pretty stupid; better to move directly to r3            after the rest of the args are done. */         tmpregs[argreg] = newVRegI(env);         addInstr(env, mk_iMOVds_RR( tmpregs[argreg], GuestStatePtr ));         argreg++;      }      for (i = 0; i < n_args; i++) {         vassert(argreg < PPC32_N_REGPARMS);         vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32 ||                 typeOfIRExpr(env->type_env, args[i]) == Ity_I64);         if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32) {             tmpregs[argreg] = iselIntExpr_R(env, args[i]);         } else { // Ity_I64            HReg rHi, rLo;            if (argreg%2 == 1) // ppc32 abi spec for passing a LONG_LONG               argreg++;       // XXX: odd argreg => even rN            vassert(argreg < PPC32_N_REGPARMS-1);            iselInt64Expr(&rHi,&rLo, env, args[i]);            tmpregs[argreg++] = rHi;            tmpregs[argreg]   = rLo;         }         argreg++;      }      /* Now we can compute the condition.  We can't do it earlier         because the argument computations could trash the condition         codes.  Be a bit clever to handle the common case where the         guard is 1:Bit. */      cc.test = Pct_ALWAYS;      if (guard) {         if (guard->tag == Iex_Const              && guard->Iex.Const.con->tag == Ico_U1             && guard->Iex.Const.con->Ico.U1 == True) {            /* unconditional -- do nothing */         } else {            cc = iselCondCode( env, guard );         }      }      /* Move the args to their final destinations. */      for (i = 0; i < argreg; i++) {         if (tmpregs[i] == INVALID_HREG)  // Skip invalid regs            continue;         /* None of these insns, including any spill code that might            be generated, may alter the condition codes. */         addInstr( env, mk_iMOVds_RR( argregs[i], tmpregs[i] ) );      }   }   /* Finally, the call itself. */   addInstr(env, PPC32Instr_Call( cc,                                  (Addr32)toUInt(Ptr_to_ULong(cee->addr)),                                  n_args + (passBBP ? 1 : 0) ));}/* Set FPU's rounding mode to the default */static void set_FPU_rounding_default ( ISelEnv* env ){   HReg fr_src  = newVRegF(env);   HReg r_srcHi = newVRegI(env);   HReg r_srcLo = newVRegI(env);   /* Default rounding mode = 0x0      Only supporting the rounding-mode bits - the rest of FPSCR is 0x0       - so we can set the whole register at once (faster)   */   addInstr(env, PPC32Instr_LI32(r_srcLo, 0x0));   // r_srcHi = 0: upper 32 bits ignored by FpLdFPSCR   addInstr(env, PPC32Instr_LI32(r_srcHi, 0x0));   fr_src = mk_LoadRRtoFPR( env, r_srcHi, r_srcLo );   addInstr(env, PPC32Instr_FpLdFPSCR( fr_src ));}/* Convert IR rounding mode to PPC32 encoding */static HReg roundModeIRtoPPC32 ( ISelEnv* env, HReg r_rmIR ){/*    rounding mode | PPC | IR   ------------------------   to nearest    | 00  | 00   to zero       | 01  | 11   to +infinity  | 10  | 10   to -infinity  | 11  | 01*/   HReg r_rmPPC32 = newVRegI(env);   HReg r_tmp     = newVRegI(env);   // AND r_rmRI,3   -- shouldn't be needed; paranoia   addInstr(env,       PPC32Instr_Alu32(Palu_AND, r_rmIR, r_rmIR, PPC32RH_Imm(False,3)));   // r_rmPPC32 = XOR( r_rmIR, (r_rmIR << 1) & 2)   addInstr(env,       PPC32Instr_Alu32(Palu_SHL, r_tmp, r_rmIR, PPC32RH_Imm(False,1)));   addInstr(env,       PPC32Instr_Alu32(Palu_AND, r_tmp, r_tmp, PPC32RH_Imm(False,2)));   addInstr(env,       PPC32Instr_Alu32(Palu_XOR, r_rmPPC32, r_rmIR, PPC32RH_Reg(r_tmp)));   return r_rmPPC32;}/* Mess with the FPU's rounding mode: 'mode' is an I32-typed   expression denoting a value in the range 0 .. 3, indicating a round   mode encoded as per type IRRoundingMode.  Set the PPC32 FPSCR to have   the same rounding.   For speed & simplicity, we're setting the *entire* FPSCR here.*/staticvoid set_FPU_rounding_mode ( ISelEnv* env, IRExpr* mode ){   HReg fr_src  = newVRegF(env);   HReg r_srcHi = newVRegI(env);   /* Only supporting the rounding-mode bits - the rest of FPSCR is 0x0       - so we can set the whole register at once (faster)   */   // Resolve rounding mode and convert to PPC32 representation   HReg r_srcLo = roundModeIRtoPPC32( env, iselIntExpr_R(env, mode) );   // srcHi = 0: upper 32 bits ignored by FpLdFPSCR   addInstr(env, PPC32Instr_LI32(r_srcHi, 0));   // Load 2*I32 regs to fp reg:   fr_src = mk_LoadRRtoFPR( env, r_srcHi, r_srcLo );   // Move to FPSCR   addInstr(env, PPC32Instr_FpLdFPSCR( fr_src ));}//.. /* Generate !src into a new vector register, and be sure that the code//..    is SSE1 compatible.  Amazing that Intel doesn't offer a less crappy//..    way to do this. //.. *///.. static HReg do_sse_Not128 ( ISelEnv* env, HReg src )//.. {//..    HReg dst = newVRegV(env);//..    /* Set dst to zero.  Not strictly necessary, but the idea of doing//..       a FP comparison on whatever junk happens to be floating around//..       in it is just too scary. *///..    addInstr(env, X86Instr_SseReRg(Xsse_XOR, dst, dst));//..    /* And now make it all 1s ... *///..    addInstr(env, X86Instr_Sse32Fx4(Xsse_CMPEQF, dst, dst));//..    /* Finally, xor 'src' into it. *///..    addInstr(env, X86Instr_SseReRg(Xsse_XOR, src, dst));//..    return dst;//.. }//.. /* Round an x87 FPU value to 53-bit-mantissa precision, to be used//..    after most non-simple FPU operations (simple = +, -, *, / and//..    sqrt).//.. //..    This could be done a lot more efficiently if needed, by loading//..    zero and adding it to the value to be rounded (fldz ; faddp?).//.. *///.. static void roundToF64 ( ISelEnv* env, HReg reg )//.. {//..    X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());//..    sub_from_esp(env, 8);//..    addInstr(env, X86Instr_FpLdSt(False/*store*/, 8, reg, zero_esp));//..    addInstr(env, X86Instr_FpLdSt(True/*load*/, 8, reg, zero_esp));//..    add_to_esp(env, 8);//.. }/*---------------------------------------------------------*//*--- ISEL: Integer expressions (32/16/8 bit)           ---*//*---------------------------------------------------------*//* Select insns for an integer-typed expression, and add them to the   code list.  Return a reg holding the result.  This reg will be a   virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you

⌨️ 快捷键说明

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