📄 toir.c
字号:
case Ity_I8: return unop(Iop_8Uto32,e); default: vpanic("widenUto32"); }}/* 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"); }}/* 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(x86)");}/* 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 op8, IRTemp dep1, IRTemp dep2, IRType ty ){ Int ccOp = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2); vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32); switch (op8) { case Iop_Add8: ccOp += X86G_CC_OP_ADDB; break; case Iop_Sub8: ccOp += X86G_CC_OP_SUBB; break; default: ppIROp(op8); vpanic("setFlags_DEP1_DEP2(x86)"); } stmt( IRStmt_Put( OFFB_CC_OP, mkU32(ccOp)) ); stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(dep1))) ); stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(dep2))) ); /* Set NDEP even though it isn't used. This makes redundant-PUT elimination of previous stores to this field work better. */ stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));}/* Set the OP and DEP1 fields only, and write zero to DEP2. */static void setFlags_DEP1 ( IROp op8, IRTemp dep1, IRType ty ){ Int ccOp = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2); vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32); switch (op8) { case Iop_Or8: case Iop_And8: case Iop_Xor8: ccOp += X86G_CC_OP_LOGICB; break; default: ppIROp(op8); vpanic("setFlags_DEP1(x86)"); } stmt( IRStmt_Put( OFFB_CC_OP, mkU32(ccOp)) ); stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(dep1))) ); stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0)) ); /* Set NDEP even though it isn't used. This makes redundant-PUT elimination of previous stores to this field work better. */ stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(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 op32, IRTemp res, IRTemp resUS, IRType ty, IRTemp guard ){ Int ccOp = ty==Ity_I8 ? 2 : (ty==Ity_I16 ? 1 : 0); vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32); vassert(guard); /* Both kinds of right shifts are handled by the same thunk operation. */ switch (op32) { case Iop_Shr32: case Iop_Sar32: ccOp = X86G_CC_OP_SHRL - ccOp; break; case Iop_Shl32: ccOp = X86G_CC_OP_SHLL - ccOp; break; default: ppIROp(op32); vpanic("setFlags_DEP1_DEP2_shift(x86)"); } /* 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(ccOp))) ); 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)))) ); /* Set NDEP even though it isn't used. This makes redundant-PUT elimination of previous stores to this field work better. */ stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));}/* For the inc/dec case, we store in DEP1 the result value and in NDEP the former value of the carry flag, which unfortunately we have to compute. */static void setFlags_INC_DEC ( Bool inc, IRTemp res, IRType ty ){ Int ccOp = inc ? X86G_CC_OP_INCB : X86G_CC_OP_DECB; ccOp += ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2); vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32); /* This has to come first, because calculating the C flag may require reading all four thunk fields. */ stmt( IRStmt_Put( OFFB_CC_NDEP, mk_x86g_calculate_eflags_c()) ); stmt( IRStmt_Put( OFFB_CC_OP, mkU32(ccOp)) ); stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(res)) ); stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0)) );}/* Multiplies are pretty much like add and sub: DEP1 and DEP2 hold the two arguments. */staticvoid setFlags_MUL ( IRType ty, IRTemp arg1, IRTemp arg2, UInt base_op ){ switch (ty) { case Ity_I8: stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+0) ) ); break; case Ity_I16: stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+1) ) ); break; case Ity_I32: stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+2) ) ); break; default: vpanic("setFlags_MUL(x86)"); } stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(arg1)) )); stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(arg2)) )); /* Set NDEP even though it isn't used. This makes redundant-PUT elimination of previous stores to this field work better. */ stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));}/* -------------- Condition codes. -------------- *//* Condition codes, using the Intel encoding. */static HChar* name_X86Condcode ( X86Condcode cond ){ switch (cond) { case X86CondO: return "o"; case X86CondNO: return "no"; case X86CondB: return "b"; case X86CondNB: return "nb"; case X86CondZ: return "z"; case X86CondNZ: return "nz"; case X86CondBE: return "be"; case X86CondNBE: return "nbe"; case X86CondS: return "s"; case X86CondNS: return "ns"; case X86CondP: return "p"; case X86CondNP: return "np"; case X86CondL: return "l"; case X86CondNL: return "nl"; case X86CondLE: return "le"; case X86CondNLE: return "nle"; case X86CondAlways: return "ALWAYS"; default: vpanic("name_X86Condcode"); }}static X86Condcode positiveIse_X86Condcode ( X86Condcode cond, Bool* needInvert ){ vassert(cond >= X86CondO && cond <= X86CondNLE); if (cond & 1) { *needInvert = True; return cond-1; } else { *needInvert = False; return cond; }}/* -------------- Helpers for ADD/SUB with carry. -------------- *//* Given ta1, ta2 and tres, compute tres = ADC(ta1,ta2) and set flags appropriately.*/static void helper_ADC ( Int sz, IRTemp tres, IRTemp ta1, IRTemp ta2 ){ UInt thunkOp; IRType ty = szToITy(sz); IRTemp oldc = newTemp(Ity_I32); IRTemp oldcn = newTemp(ty); IROp plus = mkSizedOp(ty, Iop_Add8); IROp xor = mkSizedOp(ty, Iop_Xor8); vassert(sz == 1 || sz == 2 || sz == 4); thunkOp = sz==4 ? X86G_CC_OP_ADCL : (sz==2 ? X86G_CC_OP_ADCW : X86G_CC_OP_ADCB); /* oldc = old carry flag, 0 or 1 */ assign( oldc, binop(Iop_And32, mk_x86g_calculate_eflags_c(), mkU32(1)) ); assign( oldcn, narrowTo(ty, mkexpr(oldc)) ); assign( tres, binop(plus, binop(plus,mkexpr(ta1),mkexpr(ta2)), mkexpr(oldcn)) ); stmt( IRStmt_Put( OFFB_CC_OP, mkU32(thunkOp) ) ); stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(ta1)) )); stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(binop(xor, mkexpr(ta2), mkexpr(oldcn)) )) ); stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(oldc) ) );}/* Given ta1, ta2 and tres, compute tres = SBB(ta1,ta2) and set flags appropriately.*/static void helper_SBB ( Int sz, IRTemp tres, IRTemp ta1, IRTemp ta2 ){ UInt thunkOp; IRType ty = szToITy(sz); IRTemp oldc = newTemp(Ity_I32); IRTemp oldcn = newTemp(ty); IROp minus = mkSizedOp(ty, Iop_Sub8); IROp xor = mkSizedOp(ty, Iop_Xor8); vassert(sz == 1 || sz == 2 || sz == 4); thunkOp = sz==4 ? X86G_CC_OP_SBBL : (sz==2 ? X86G_CC_OP_SBBW : X86G_CC_OP_SBBB); /* oldc = old carry flag, 0 or 1 */ assign( oldc, binop(Iop_And32, mk_x86g_calculate_eflags_c(), mkU32(1)) ); assign( oldcn, narrowTo(ty, mkexpr(oldc)) ); assign( tres, binop(minus, binop(minus,mkexpr(ta1),mkexpr(ta2)), mkexpr(oldcn)) ); stmt( IRStmt_Put( OFFB_CC_OP, mkU32(thunkOp) ) ); stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(ta1) )) ); stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(binop(xor, mkexpr(ta2), mkexpr(oldcn)) )) ); stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(oldc) ) );}/* -------------- Helpers for disassembly printing. -------------- */static HChar* nameGrp1 ( Int opc_aux ){ static HChar* grp1_names[8] = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" }; if (opc_aux < 0 || opc_aux > 7) vpanic("nameGrp1(x86)"); return grp1_names[opc_aux];}static HChar* nameGrp2 ( Int opc_aux ){ static HChar* grp2_names[8] = { "rol", "ror", "rcl", "rcr", "shl", "shr", "shl", "sar" }; if (opc_aux < 0 || opc_aux > 7) vpanic("nameGrp2(x86)"); return grp2_names[opc_aux];}static HChar* nameGrp4 ( Int opc_aux ){ static HChar* grp4_names[8] = { "inc", "dec", "???", "???", "???", "???", "???", "???" }; if (opc_aux < 0 || opc_aux > 1) vpanic("nameGrp4(x86)"); return grp4_names[opc_aux];}static HChar* nameGrp5 ( Int opc_aux ){ static HChar* grp5_names[8] = { "inc", "dec", "call*", "call*", "jmp*", "jmp*", "push", "???" }; if (opc_aux < 0 || opc_aux > 6) vpanic("nameGrp5(x86)"); return grp5_names[opc_aux];}static HChar* nameGrp8 ( Int opc_aux ){ static HChar* grp8_names[8] = { "???", "???", "???", "???", "bt", "bts", "btr", "btc" }; if (opc_aux < 4 || opc_aux > 7) vpanic("nameGrp8(x86)"); return grp8_names[opc_aux];}static HChar* nameIReg ( Int size, Int reg ){ static HChar* ireg32_names[8] = { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi" }; static HChar* ireg16_names[8] = { "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di" }; static HChar* ireg8_names[8] = { "%al", "%cl", "%dl", "%bl", "%ah{sp}", "%ch{bp}", "%dh{si}", "%bh{di}" }; if (reg < 0 || reg > 7) goto bad; switch (size) { case 4: return ireg32_names[reg]; case 2: return ireg16_names[reg]; case 1: return ireg8_names[reg]; } bad: vpanic("nameIReg(X86)"); return NULL; /*notreached*/}static HChar* nameSReg ( UInt sreg ){ switch (sreg) { case R_ES: return "%es"; case R_CS: return "%cs"; case R_SS: return "%ss"; case R_DS: return "%ds"; case R_FS: return "%fs"; case R_GS: return "%gs"; default: vpanic("nameSReg(x86)"); }}static HChar* nameMMXReg ( Int mmxreg ){ static HChar* mmx_names[8] = { "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" }; if (mmxreg < 0 || mmxreg > 7) vpanic("nameMMXReg(x86,guest)"); return mmx_names[mmxreg];}static HChar* nameXMMReg ( Int xmmreg ){ static HChar* xmm_names[8] = { "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" }; if (xmmreg < 0 || xmmreg > 7) vpanic("name_of_xmm_reg"); return xmm_names[xmmreg];} static HChar* nameMMXGran ( Int gran ){ switch (gran) { case 0: return "b"; case 1: return "w"; case 2: return "d"; case 3: return "q"; default: vpanic("nameMMXGran(x86,guest)"); }}static HChar nameISize ( Int size ){ switch (size) { case 4: return 'l'; case 2: return 'w'; case 1: return 'b'; default: vpanic("nameISize(x86)"); }}/*------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -