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

📄 isel.c

📁 The Valgrind distribution has multiple tools. The most popular is the memory checking tool (called M
💻 C
📖 第 1 页 / 共 5 页
字号:
/*---------------------------------------------------------------*//*---                                                         ---*//*--- This file (host-amd64/isel.c) is                        ---*//*--- Copyright (C) OpenWorks LLP.  All rights reserved.      ---*//*---                                                         ---*//*---------------------------------------------------------------*//*   This file is part of LibVEX, a library for dynamic binary   instrumentation and translation.   Copyright (C) 2004-2006 OpenWorks LLP.  All rights reserved.   This library is made available under a dual licensing scheme.   If you link LibVEX against other code all of which is itself   licensed under the GNU General Public License, version 2 dated June   1991 ("GPL v2"), then you may use LibVEX under the terms of the GPL   v2, as appearing in the file LICENSE.GPL.  If the file LICENSE.GPL   is missing, you can obtain a copy of the GPL v2 from the Free   Software Foundation Inc., 51 Franklin St, Fifth Floor, Boston, MA   02110-1301, USA.   For any other uses of LibVEX, you must first obtain a commercial   license from OpenWorks LLP.  Please contact info@open-works.co.uk   for information about commercial licensing.   This software is provided by OpenWorks LLP "as is" and any express   or implied warranties, including, but not limited to, the implied   warranties of merchantability and fitness for a particular purpose   are disclaimed.  In no event shall OpenWorks LLP be liable for any   direct, indirect, incidental, special, exemplary, or consequential   damages (including, but not limited to, procurement of substitute   goods or services; loss of use, data, or profits; or business   interruption) however caused and on any theory of liability,   whether in contract, strict liability, or tort (including   negligence or otherwise) arising in any way out of the use of this   software, even if advised of the possibility of such damage.   Neither the names of the U.S. Department of Energy nor the   University of California nor the names of its contributors may be   used to endorse or promote products derived from this software   without prior written permission.*/#include "libvex_basictypes.h"#include "libvex_ir.h"#include "libvex.h"#include "ir/irmatch.h"#include "main/vex_util.h"#include "main/vex_globals.h"#include "host-generic/h_generic_regs.h"#include "host-generic/h_generic_simd64.h"#include "host-amd64/hdefs.h"/*---------------------------------------------------------*//*--- x87/SSE control word stuff                        ---*//*---------------------------------------------------------*//* Vex-generated code expects to run with the FPU set as follows: all   exceptions masked, round-to-nearest, precision = 53 bits.  This   corresponds to a FPU control word value of 0x027F.   Similarly the SSE control word (%mxcsr) should be 0x1F80.   %fpucw and %mxcsr should have these values on entry to   Vex-generated code, and should those values should be   unchanged at exit.*/#define DEFAULT_FPUCW 0x027F#define DEFAULT_MXCSR 0x1F80/* debugging only, do not use *//* define DEFAULT_FPUCW 0x037F *//*---------------------------------------------------------*//*--- misc helpers                                      ---*//*---------------------------------------------------------*//* These are duplicated in guest-amd64/toIR.c */static IRExpr* unop ( IROp op, IRExpr* a ){   return IRExpr_Unop(op, a);}static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 ){   return IRExpr_Binop(op, a1, a2);}static IRExpr* bind ( Int binder ){   return IRExpr_Binder(binder);}/*---------------------------------------------------------*//*--- ISelEnv                                           ---*//*---------------------------------------------------------*//* This carries around:   - A mapping from IRTemp to IRType, giving the type of any IRTemp we     might encounter.  This is computed before insn selection starts,     and does not change.   - A mapping from IRTemp to HReg.  This tells the insn selector     which virtual register is associated with each IRTemp     temporary.  This is computed before insn selection starts, and     does not change.  We expect this mapping to map precisely the     same set of IRTemps as the type mapping does.        - vregmap   holds the primary register for the IRTemp.        - vregmapHI is only used for 128-bit integer-typed             IRTemps.  It holds the identity of a second             64-bit virtual HReg, which holds the high half             of the value.   - The code array, that is, the insns selected so far.   - A counter, for generating new virtual registers.   - The host subarchitecture we are selecting insns for.       This is set at the start and does not change.   Note, this is all host-independent.  (JRS 20050201: well, kinda   ... not completely.  Compare with ISelEnv for X86.)*/typedef   struct {      IRTypeEnv*   type_env;      HReg*        vregmap;      HReg*        vregmapHI;      Int          n_vregmap;      HInstrArray* code;      Int          vreg_ctr;      /* Currently (27 Jan 06) unused */      UInt         hwcaps;   }   ISelEnv;static HReg lookupIRTemp ( ISelEnv* env, IRTemp tmp ){   vassert(tmp >= 0);   vassert(tmp < env->n_vregmap);   return env->vregmap[tmp];}static void lookupIRTemp128 ( HReg* vrHI, HReg* vrLO,                               ISelEnv* env, IRTemp tmp ){   vassert(tmp >= 0);   vassert(tmp < env->n_vregmap);   vassert(env->vregmapHI[tmp] != INVALID_HREG);   *vrLO = env->vregmap[tmp];   *vrHI = env->vregmapHI[tmp];}static void addInstr ( ISelEnv* env, AMD64Instr* instr ){   addHInstr(env->code, instr);   if (vex_traceflags & VEX_TRACE_VCODE) {      ppAMD64Instr(instr, True);      vex_printf("\n");   }}static HReg newVRegI ( ISelEnv* env ){   HReg reg = mkHReg(env->vreg_ctr, HRcInt64, True/*virtual reg*/);   env->vreg_ctr++;   return reg;}//.. static HReg newVRegF ( ISelEnv* env )//.. {//..    HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True/*virtual reg*/);//..    env->vreg_ctr++;//..    return reg;//.. }static HReg newVRegV ( ISelEnv* env ){   HReg reg = mkHReg(env->vreg_ctr, HRcVec128, True/*virtual reg*/);   env->vreg_ctr++;   return reg;}/*---------------------------------------------------------*//*--- ISEL: Forward declarations                        ---*//*---------------------------------------------------------*//* These are organised as iselXXX and iselXXX_wrk pairs.  The   iselXXX_wrk do the real work, but are not to be called directly.   For each XXX, iselXXX calls its iselXXX_wrk counterpart, then   checks that all returned registers are virtual.  You should not   call the _wrk version directly.*/static AMD64RMI*     iselIntExpr_RMI_wrk ( ISelEnv* env, IRExpr* e );static AMD64RMI*     iselIntExpr_RMI     ( ISelEnv* env, IRExpr* e );static AMD64RI*      iselIntExpr_RI_wrk  ( ISelEnv* env, IRExpr* e );static AMD64RI*      iselIntExpr_RI      ( ISelEnv* env, IRExpr* e );static AMD64RM*      iselIntExpr_RM_wrk  ( ISelEnv* env, IRExpr* e );static AMD64RM*      iselIntExpr_RM      ( ISelEnv* env, IRExpr* e );static HReg          iselIntExpr_R_wrk   ( ISelEnv* env, IRExpr* e );static HReg          iselIntExpr_R       ( ISelEnv* env, IRExpr* e );static AMD64AMode*   iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e );static AMD64AMode*   iselIntExpr_AMode     ( ISelEnv* env, IRExpr* e );static void          iselInt128Expr_wrk ( HReg* rHi, HReg* rLo,                                           ISelEnv* env, IRExpr* e );static void          iselInt128Expr     ( HReg* rHi, HReg* rLo,                                           ISelEnv* env, IRExpr* e );static AMD64CondCode iselCondCode_wrk    ( ISelEnv* env, IRExpr* e );static AMD64CondCode 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                                ---*//*---------------------------------------------------------*/static Bool sane_AMode ( AMD64AMode* am ){   switch (am->tag) {      case Aam_IR:         return             toBool( hregClass(am->Aam.IR.reg) == HRcInt64                    && (hregIsVirtual(am->Aam.IR.reg)                        || am->Aam.IR.reg == hregAMD64_RBP()) );      case Aam_IRRS:         return             toBool( hregClass(am->Aam.IRRS.base) == HRcInt64                    && hregIsVirtual(am->Aam.IRRS.base)                    && hregClass(am->Aam.IRRS.index) == HRcInt64                    && hregIsVirtual(am->Aam.IRRS.index) );      default:        vpanic("sane_AMode: unknown amd64 amode tag");   }}/* Can the lower 32 bits be signedly widened to produce the whole   64-bit value?  In other words, are the top 33 bits either all 0 or   all 1 ? */static Bool fitsIn32Bits ( ULong x ){   Long y0 = (Long)x;   Long y1 = y0;   y1 <<= 32;   y1 >>=/*s*/ 32;   return toBool(x == y1);}//.. /* Is this a 32-bit zero expression? *///.. //.. static Bool isZero32 ( IRExpr* e )//.. {//..    return e->tag == Iex_Const//..           && e->Iex.Const.con->tag == Ico_U32//..           && e->Iex.Const.con->Ico.U32 == 0;//.. }/* Make a int reg-reg move. */static AMD64Instr* mk_iMOVsd_RR ( HReg src, HReg dst ){   vassert(hregClass(src) == HRcInt64);   vassert(hregClass(dst) == HRcInt64);   return AMD64Instr_Alu64R(Aalu_MOV, AMD64RMI_Reg(src), dst);}/* Make a vector reg-reg move. */static AMD64Instr* mk_vMOVsd_RR ( HReg src, HReg dst ){   vassert(hregClass(src) == HRcVec128);   vassert(hregClass(dst) == HRcVec128);   return AMD64Instr_SseReRg(Asse_MOV, src, dst);}/* Advance/retreat %rsp by n. */static void add_to_rsp ( ISelEnv* env, Int n ){   vassert(n > 0 && n < 256 && (n%8) == 0);   addInstr(env,             AMD64Instr_Alu64R(Aalu_ADD, AMD64RMI_Imm(n),                                         hregAMD64_RSP()));}static void sub_from_rsp ( ISelEnv* env, Int n ){   vassert(n > 0 && n < 256 && (n%8) == 0);   addInstr(env,             AMD64Instr_Alu64R(Aalu_SUB, AMD64RMI_Imm(n),                                         hregAMD64_RSP()));}//.. /* Given an amode, return one which references 4 bytes further//..    along. *///.. //.. static X86AMode* advance4 ( X86AMode* am )//.. {//..    X86AMode* am4 = dopyX86AMode(am);//..    switch (am4->tag) {//..       case Xam_IRRS://..          am4->Xam.IRRS.imm += 4; break;//..       case Xam_IR://..          am4->Xam.IR.imm += 4; break;//..       default://..          vpanic("advance4(x86,host)");//..    }//..    return am4;//.. }//.. //.. //.. /* Push an arg onto the host stack, in preparation for a call to a//..    helper function of some kind.  Returns the number of 32-bit words//..    pushed. *///.. //.. static Int pushArg ( ISelEnv* env, IRExpr* arg )//.. {//..    IRType arg_ty = typeOfIRExpr(env->type_env, arg);//..    if (arg_ty == Ity_I32) {//..       addInstr(env, X86Instr_Push(iselIntExpr_RMI(env, arg)));//..       return 1;//..    } else //..    if (arg_ty == Ity_I64) {//..       HReg rHi, rLo;//..       iselInt64Expr(&rHi, &rLo, env, arg);//..       addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));//..       addInstr(env, X86Instr_Push(X86RMI_Reg(rLo)));//..       return 2;//..    }//..    ppIRExpr(arg);//..    vpanic("pushArg(x86): can't handle arg of this type");//.. }/* Used only in doHelperCall.  See big comment in doHelperCall re

⌨️ 快捷键说明

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