📄 toir.c
字号:
{ switch (size) { case 4: return getUDisp32(delta); case 2: return getSDisp16(delta); case 1: return getSDisp8(delta); default: vpanic("getSDisp(ARM)"); } return 0; /*notreached*/}#endif/*------------------------------------------------------------*//*--- Helpers for constructing IR. ---*//*------------------------------------------------------------*//* Create a 1/2/4 byte read of an x86 integer registers. For 16/8 bit register references, we need to take the host endianness into account. Supplied value is 0 .. 7 and in the Intel instruction encoding. */#if 0static IRType szToITy ( Int n ){ switch (n) { case 1: return Ity_I8; case 2: return Ity_I16; case 4: return Ity_I32; default: vpanic("szToITy(ARM)"); }}#endifstatic Int integerGuestRegOffset ( UInt archreg ){ vassert(archreg < 16); vassert(!host_is_bigendian); //TODO: is this necessary? // jrs: probably not; only matters if we reference sub-parts // of the arm registers, but that isn't the case switch (archreg) { case 0: return offsetof(VexGuestARMState,guest_R0); case 1: return offsetof(VexGuestARMState,guest_R1); case 2: return offsetof(VexGuestARMState,guest_R2); case 3: return offsetof(VexGuestARMState,guest_R3); case 4: return offsetof(VexGuestARMState,guest_R4); case 5: return offsetof(VexGuestARMState,guest_R5); case 6: return offsetof(VexGuestARMState,guest_R6); case 7: return offsetof(VexGuestARMState,guest_R7); case 8: return offsetof(VexGuestARMState,guest_R8); case 9: return offsetof(VexGuestARMState,guest_R9); case 10: return offsetof(VexGuestARMState,guest_R10); case 11: return offsetof(VexGuestARMState,guest_R11); case 12: return offsetof(VexGuestARMState,guest_R12); case 13: return offsetof(VexGuestARMState,guest_R13); case 14: return offsetof(VexGuestARMState,guest_R14); case 15: return offsetof(VexGuestARMState,guest_R15); } vpanic("integerGuestRegOffset(arm,le)"); /*notreached*/}static IRExpr* getIReg ( UInt archreg ){ vassert(archreg < 16); return IRExpr_Get( integerGuestRegOffset(archreg), Ity_I32 );}/* Ditto, but write to a reg instead. */static void putIReg ( UInt archreg, IRExpr* e ){ vassert(archreg < 16); stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );}static void assign ( IRTemp dst, IRExpr* e ){ stmt( IRStmt_Tmp(dst, e) );}static void storeLE ( IRExpr* addr, IRExpr* data ){ stmt( IRStmt_Store(Iend_LE,addr,data) );}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* mkexpr ( IRTemp tmp ){ return IRExpr_Tmp(tmp);}static IRExpr* mkU8 ( UChar i ){ return IRExpr_Const(IRConst_U8(i));}#if 0static IRExpr* mkU16 ( UInt i ){ vassert(i < 65536); return IRExpr_Const(IRConst_U16(i));}#endifstatic IRExpr* mkU32 ( UInt i ){ return IRExpr_Const(IRConst_U32(i));}#if 0static IRExpr* mkU ( IRType ty, UInt i ){ if (ty == Ity_I8) return mkU8(i); if (ty == Ity_I16) return mkU16(i); if (ty == Ity_I32) return mkU32(i); /* If this panics, it usually means you passed a size (1,2,4) value as the IRType, rather than a real IRType. */ vpanic("mkU(ARM)");}#endifstatic IRExpr* loadLE ( IRType ty, IRExpr* data ){ return IRExpr_Load(Iend_LE,ty,data);}#if 0static IROp mkSizedOp ( IRType ty, IROp op8 ){ Int adj; vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32); vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 || op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || op8 == Iop_Not8 ); adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2); return adj + op8;}#endif#if 0static IROp mkWidenOp ( Int szSmall, Int szBig, Bool signd ){ if (szSmall == 1 && szBig == 4) { return signd ? Iop_8Sto32 : Iop_8Uto32; } if (szSmall == 1 && szBig == 2) { return signd ? Iop_8Sto16 : Iop_8Uto16; } if (szSmall == 2 && szBig == 4) { return signd ? Iop_16Sto32 : Iop_16Uto32; } vpanic("mkWidenOp(ARM,guest)");}#endif/*------------------------------------------------------------*//*--- Helpers for %flags. ---*//*------------------------------------------------------------*//* -------------- Evaluating the flags-thunk. -------------- */#if 0/* Build IR to calculate all the flags from stored CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression :: Ity_I32. */static IRExpr* mk_armg_calculate_flags_all ( void ){ IRExpr** args = mkIRExprVec_3( IRExpr_Get(OFFB_CC_OP, Ity_I32), IRExpr_Get(OFFB_CC_DEP1, Ity_I32), IRExpr_Get(OFFB_CC_DEP2, Ity_I32) ); IRExpr* call = mkIRExprCCall( Ity_I32, 0/*regparm*/, "armg_calculate_flags_all", &armg_calculate_flags_all, args ); /* Exclude OP from definedness checking. We're only interested in DEP1 and DEP2. */ call->Iex.CCall.cee->mcx_mask = 1; return call;}#endif/* Build IR to calculate just the carry flag from stored CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression :: Ity_I32. */static IRExpr* mk_armg_calculate_flags_c ( void ){ IRExpr** args = mkIRExprVec_3( IRExpr_Get(OFFB_CC_OP, Ity_I32), IRExpr_Get(OFFB_CC_DEP1, Ity_I32), IRExpr_Get(OFFB_CC_DEP2, Ity_I32) ); IRExpr* call = mkIRExprCCall( Ity_I32, 0/*regparm*/, "armg_calculate_flags_c", &armg_calculate_flags_c, args ); /* Exclude OP from definedness checking. We're only interested in DEP1 and DEP2. */ call->Iex.CCall.cee->mcx_mask = 1; return call;}/* Build IR to calculate some particular condition from stored CC_OP/CC_DEP1/CC_DEP2. Returns an expression of type Ity_I1.*/static IRExpr* mk_armg_calculate_condition ( ARMCondcode cond ){ IRExpr** args = mkIRExprVec_4( mkU32(cond), IRExpr_Get(OFFB_CC_OP, Ity_I32), IRExpr_Get(OFFB_CC_DEP1, Ity_I32), IRExpr_Get(OFFB_CC_DEP2, Ity_I32) ); IRExpr* call = mkIRExprCCall( Ity_I32, 0/*regparm*/, "armg_calculate_condition", &armg_calculate_condition, args ); /* Exclude the requested condition and OP from definedness checking. We're only interested in DEP1 and DEP2. */ call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<1); return unop(Iop_32to1, call);}/* -------------- Building the flags-thunk. -------------- *//* The machinery in this section builds the flag-thunk following a flag-setting operation. Hence the various setFlags_* functions.*/#if 0static Bool isAddSub ( IROp op8 ){ return op8 == Iop_Add8 || op8 == Iop_Sub8;}#endif#if 0static Bool isLogic ( IROp op8 ){ return op8 == Iop_And8 || op8 == Iop_Or8 || op8 == Iop_Xor8;}#endif/* U-widen 8/16/32 bit int expr to 32. */static IRExpr* widenUto32 ( IRExpr* e ){ switch (typeOfIRExpr(irbb->tyenv,e)) { case Ity_I32: return e; case Ity_I16: return unop(Iop_16Uto32,e); case Ity_I8: return unop(Iop_8Uto32,e); default: vpanic("widenUto32"); }}#if 0/* S-widen 8/16/32 bit int expr to 32. */static IRExpr* widenSto32 ( IRExpr* e ){ switch (typeOfIRExpr(irbb->tyenv,e)) { case Ity_I32: return e; case Ity_I16: return unop(Iop_16Sto32,e); case Ity_I8: return unop(Iop_8Sto32,e); default: vpanic("widenSto32"); }}#endif/* Narrow 8/16/32 bit int expr to 8/16/32. Clearly only some of these combinations make sense. */static IRExpr* narrowTo ( IRType dst_ty, IRExpr* e ){ IRType src_ty = typeOfIRExpr(irbb->tyenv,e); if (src_ty == dst_ty) return e; if (src_ty == Ity_I32 && dst_ty == Ity_I16) return unop(Iop_32to16, e); if (src_ty == Ity_I32 && dst_ty == Ity_I8) return unop(Iop_32to8, e); vex_printf("\nsrc, dst tys are: "); ppIRType(src_ty); vex_printf(", "); ppIRType(dst_ty); vex_printf("\n"); vpanic("narrowTo(ARM)");}/* Set the flags thunk OP, DEP1 and DEP2 fields. The supplied op is auto-sized up to the real op. */static void setFlags_DEP1_DEP2 ( IROp op, IRTemp dep1, IRTemp dep2 ){ stmt( IRStmt_Put( OFFB_CC_OP, mkU32(op)) ); stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(dep1))) ); stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(dep2))) );}/* Set the OP and DEP1 fields only, and write zero to DEP2. */#if 0static void setFlags_DEP1 ( IROp op, IRTemp dep1 ){ stmt( IRStmt_Put( OFFB_CC_OP, mkU32(op)) ); stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(dep1))) ); stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0)) );}#endif#if 0/* For shift operations, we put in the result and the undershifted result. Except if the shift amount is zero, the thunk is left unchanged. */static void setFlags_DEP1_DEP2_shift ( IROp op, IRTemp res, IRTemp resUS, IRTemp guard ){ vassert(guard); /* DEP1 contains the result, DEP2 contains the undershifted value. */ stmt( IRStmt_Put( OFFB_CC_OP, IRExpr_Mux0X( mkexpr(guard), IRExpr_Get(OFFB_CC_OP,Ity_I32), mkU32(op))) ); stmt( IRStmt_Put( OFFB_CC_DEP1, IRExpr_Mux0X( mkexpr(guard), IRExpr_Get(OFFB_CC_DEP1,Ity_I32), widenUto32(mkexpr(res)))) ); stmt( IRStmt_Put( OFFB_CC_DEP2, IRExpr_Mux0X( mkexpr(guard), IRExpr_Get(OFFB_CC_DEP2,Ity_I32), widenUto32(mkexpr(resUS)))) );}#endif#if 0/* Multiplies are pretty much like add and sub: DEP1 and DEP2 hold the two arguments. */staticvoid setFlags_MUL ( IRTemp arg1, IRTemp arg2, UInt op ){ stmt( IRStmt_Put( OFFB_CC_OP, mkU32(op) ) ); stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(arg1)) )); stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(arg2)) ));}#endif/* -------------- Condition codes. -------------- *//* Condition codes, using the ARM encoding. */static HChar* name_ARMCondcode ( ARMCondcode cond ){ switch (cond) { case ARMCondEQ: return "{eq}"; case ARMCondNE: return "{ne}";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -