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

📄 isel.c

📁 The Valgrind distribution has multiple tools. The most popular is the memory checking tool (called M
💻 C
📖 第 1 页 / 共 5 页
字号:
   as signed or not.  If yes, this will never return -32768 as an   immediate; this guaranteed that all signed immediates that are   return can have their sign inverted if need be. */static PPCRH*        iselWordExpr_RH_wrk ( ISelEnv* env,                                            Bool syned, IRExpr* e );static PPCRH*        iselWordExpr_RH     ( ISelEnv* env,                                            Bool syned, IRExpr* e );/* 32-bit mode: compute an I32 into a RI (reg or 32-bit immediate).   64-bit mode: compute an I64 into a RI (reg or 64-bit immediate). */static PPCRI*        iselWordExpr_RI_wrk ( ISelEnv* env, IRExpr* e );static PPCRI*        iselWordExpr_RI     ( ISelEnv* env, IRExpr* e );/* In 32 bit mode ONLY, compute an I8 into a   reg-or-5-bit-unsigned-immediate, the latter being an immediate in   the range 1 .. 31 inclusive.  Used for doing shift amounts. */static PPCRH*        iselWordExpr_RH5u_wrk ( ISelEnv* env, IRExpr* e );static PPCRH*        iselWordExpr_RH5u     ( ISelEnv* env, IRExpr* e );/* In 64-bit mode ONLY, compute an I8 into a Compute an I8 into a   reg-or-6-bit-unsigned-immediate, the latter being an immediate in   the range 1 .. 63 inclusive.  Used for doing shift amounts. */static PPCRH*        iselWordExpr_RH6u_wrk ( ISelEnv* env, IRExpr* e );static PPCRH*        iselWordExpr_RH6u     ( ISelEnv* env, IRExpr* e );/* 32-bit mode: compute an I32 into an AMode.   64-bit mode: compute an I64 into an AMode. */static PPCAMode*     iselWordExpr_AMode_wrk ( ISelEnv* env, IRExpr* e );static PPCAMode*     iselWordExpr_AMode     ( ISelEnv* env, IRExpr* e );/* 32-bit mode ONLY: compute an I64 into a GPR pair. */static void          iselInt64Expr_wrk ( HReg* rHi, HReg* rLo,                                          ISelEnv* env, IRExpr* e );static void          iselInt64Expr     ( HReg* rHi, HReg* rLo,                                          ISelEnv* env, IRExpr* e );/* 64-bit mode ONLY: compute an I128 into a GPR64 pair. */static void          iselInt128Expr_wrk ( HReg* rHi, HReg* rLo,                                           ISelEnv* env, IRExpr* e );static void          iselInt128Expr     ( HReg* rHi, HReg* rLo,                                           ISelEnv* env, IRExpr* e );static PPCCondCode   iselCondCode_wrk ( ISelEnv* env, IRExpr* e );static PPCCondCode   iselCondCode     ( ISelEnv* env, IRExpr* e );static HReg          iselDblExpr_wrk ( ISelEnv* env, IRExpr* e );static HReg          iselDblExpr     ( ISelEnv* env, IRExpr* e );static HReg          iselFltExpr_wrk ( ISelEnv* env, IRExpr* e );static HReg          iselFltExpr     ( ISelEnv* env, IRExpr* e );static HReg          iselVecExpr_wrk ( ISelEnv* env, IRExpr* e );static HReg          iselVecExpr     ( ISelEnv* env, IRExpr* e );/*---------------------------------------------------------*//*--- ISEL: Misc helpers                                ---*//*---------------------------------------------------------*//* Make an int reg-reg move. */static PPCInstr* mk_iMOVds_RR ( HReg r_dst, HReg r_src ){   vassert(hregClass(r_dst) == hregClass(r_src));   vassert(hregClass(r_src) ==  HRcInt32 ||           hregClass(r_src) ==  HRcInt64);   return PPCInstr_Alu(Palu_OR, r_dst, r_src, PPCRH_Reg(r_src));}/* Advance/retreat %r1 by n. */static void add_to_sp ( ISelEnv* env, UInt n ){   HReg sp = StackFramePtr(env->mode64);   vassert(n < 256 && (n%16) == 0);   addInstr(env, PPCInstr_Alu( Palu_ADD, sp, sp,                               PPCRH_Imm(True,toUShort(n)) ));}static void sub_from_sp ( ISelEnv* env, UInt n ){   HReg sp = StackFramePtr(env->mode64);   vassert(n < 256 && (n%16) == 0);   addInstr(env, PPCInstr_Alu( Palu_SUB, sp, sp,                               PPCRH_Imm(True,toUShort(n)) ));}/*  returns a quadword aligned address on the stack   - copies SP, adds 16bytes, aligns to quadword.  use sub_from_sp(32) before calling this,  as expects to have 32 bytes to play with.*/static HReg get_sp_aligned16 ( ISelEnv* env ){   HReg       r = newVRegI(env);   HReg align16 = newVRegI(env);   addInstr(env, mk_iMOVds_RR(r, StackFramePtr(env->mode64)));   // add 16   addInstr(env, PPCInstr_Alu( Palu_ADD, r, r,                               PPCRH_Imm(True,toUShort(16)) ));   // mask to quadword   addInstr(env,            PPCInstr_LI(align16, 0xFFFFFFFFFFFFFFF0ULL, env->mode64));   addInstr(env, PPCInstr_Alu(Palu_AND, r,r, PPCRH_Reg(align16)));   return r;}/* Load 2*I32 regs to fp reg */static HReg mk_LoadRR32toFPR ( ISelEnv* env,                               HReg r_srcHi, HReg r_srcLo ){   HReg fr_dst = newVRegF(env);   PPCAMode *am_addr0, *am_addr1;   vassert(!env->mode64);   vassert(hregClass(r_srcHi) == HRcInt32);   vassert(hregClass(r_srcLo) == HRcInt32);   sub_from_sp( env, 16 );        // Move SP down 16 bytes   am_addr0 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );   am_addr1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );   // store hi,lo as Ity_I32's   addInstr(env, PPCInstr_Store( 4, am_addr0, r_srcHi, env->mode64 ));   addInstr(env, PPCInstr_Store( 4, am_addr1, r_srcLo, env->mode64 ));   // load as float   addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_dst, am_addr0));      add_to_sp( env, 16 );          // Reset SP   return fr_dst;}/* Load I64 reg to fp reg */static HReg mk_LoadR64toFPR ( ISelEnv* env, HReg r_src ){   HReg fr_dst = newVRegF(env);   PPCAMode *am_addr0;   vassert(env->mode64);   vassert(hregClass(r_src) == HRcInt64);   sub_from_sp( env, 16 );        // Move SP down 16 bytes   am_addr0 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );   // store as Ity_I64   addInstr(env, PPCInstr_Store( 8, am_addr0, r_src, env->mode64 ));   // load as float   addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_dst, am_addr0));      add_to_sp( env, 16 );          // Reset SP   return fr_dst;}/* Given an amode, return one which references 4 bytes further   along. */static PPCAMode* advance4 ( ISelEnv* env, PPCAMode* am ){   PPCAMode* am4 = dopyPPCAMode( am );   if (am4->tag == Pam_IR        && am4->Pam.IR.index + 4 <= 32767) {      am4->Pam.IR.index += 4;   } else {      vpanic("advance4(ppc,host)");   }   return am4;}/* Given a guest-state array descriptor, an index expression and a   bias, generate a PPCAMode pointing at the relevant piece of    guest state.  Only needed in 64-bit mode. */staticPPCAMode* genGuestArrayOffset ( ISelEnv* env, IRArray* descr,                                IRExpr* off, Int bias ){   HReg rtmp, roff;   Int  elemSz = sizeofIRType(descr->elemTy);   Int  nElems = descr->nElems;   Int  shift  = 0;   vassert(env->mode64);   /* Throw out any cases we don't need.  In theory there might be a      day where we need to handle others, but not today. */   if (nElems != 16 && nElems != 32)      vpanic("genGuestArrayOffset(ppc64 host)(1)");   switch (elemSz) {      case 8:  shift = 3; break;      default: vpanic("genGuestArrayOffset(ppc64 host)(2)");   }   if (bias < -100 || bias > 100) /* somewhat arbitrarily */      vpanic("genGuestArrayOffset(ppc64 host)(3)");   if (descr->base < 0 || descr->base > 2000) /* somewhat arbitrarily */     vpanic("genGuestArrayOffset(ppc64 host)(4)");   /* Compute off into a reg, %off.  Then return:         addi %tmp, %off, bias (if bias != 0)         andi %tmp, nElems-1         sldi %tmp, shift         addi %tmp, %tmp, base         ... Baseblockptr + %tmp ...   */   roff = iselWordExpr_R(env, off);   rtmp = newVRegI(env);   addInstr(env, PPCInstr_Alu(                    Palu_ADD,                     rtmp, roff,                     PPCRH_Imm(True/*signed*/, toUShort(bias))));   addInstr(env, PPCInstr_Alu(                    Palu_AND,                     rtmp, rtmp,                     PPCRH_Imm(False/*signed*/, toUShort(nElems-1))));   addInstr(env, PPCInstr_Shft(                    Pshft_SHL,                     False/*64-bit shift*/,                    rtmp, rtmp,                     PPCRH_Imm(False/*unsigned*/, toUShort(shift))));   addInstr(env, PPCInstr_Alu(                    Palu_ADD,                     rtmp, rtmp,                     PPCRH_Imm(True/*signed*/, toUShort(descr->base))));   return      PPCAMode_RR( GuestStatePtr(env->mode64), rtmp );}/*---------------------------------------------------------*//*--- ISEL: Function call helpers                       ---*//*---------------------------------------------------------*//* 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 ){   PPCCondCode cc;   HReg        argregs[PPC_N_REGPARMS];   HReg        tmpregs[PPC_N_REGPARMS];   Bool        go_fast;   Int         n_args, i, argreg;   UInt        argiregs;   ULong       target;   Bool        mode64 = env->mode64;   /* 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 PPC_N_REGPARMS x      (mode32:32 | mode64:64) integer bits in total can be passed.      In fact the only supported arg type is (mode32:I32 | mode64:I64).      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/64 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 (PPC_N_REGPARMS < n_args + (passBBP ? 1 : 0)) {      vpanic("doHelperCall(PPC): cannot currently handle > 8 args");      // PPC_N_REGPARMS   }      argregs[0] = hregPPC_GPR3(mode64);   argregs[1] = hregPPC_GPR4(mode64);   argregs[2] = hregPPC_GPR5(mode64);   argregs[3] = hregPPC_GPR6(mode64);   argregs[4] = hregPPC_GPR7(mode64);   argregs[5] = hregPPC_GPR8(mode64);   argregs[6] = hregPPC_GPR9(mode64);   argregs[7] = hregPPC_GPR10(mode64);   argiregs = 0;   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;

⌨️ 快捷键说明

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