📄 toir.c
字号:
that the stack red zone (viz, -288(r1) .. -1(r1)) becomes undefined. That is at function calls and returns. Only in 64-bit mode - ELF ppc32 doesn't have this "feature".*/static void make_redzone_AbiHint ( HChar* who ){ if (0) vex_printf("AbiHint: %s\n", who); vassert(mode64); stmt( IRStmt_AbiHint( binop(Iop_Sub64, getIReg(1), mkU64(288)), 288 ));}/*------------------------------------------------------------*//*--- Helpers for condition codes. ---*//*------------------------------------------------------------*//* Condition register layout. In the hardware, CR is laid out like this. The leftmost end is the most significant bit in the register; however the IBM documentation numbers the bits backwards for some reason. CR0 CR1 .......... CR6 CR7 0 .. 3 ....................... 28 .. 31 (IBM bit numbering) 31 28 3 0 (normal bit numbering) Each CR field is 4 bits: [<,>,==,SO] Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc. Indexing from BI to guest state: let n = BI / 4 off = BI % 4 this references CR n: off==0 -> guest_CRn_321 >> 3 off==1 -> guest_CRn_321 >> 2 off==2 -> guest_CRn_321 >> 1 off==3 -> guest_CRn_SO Bear in mind the only significant bit in guest_CRn_SO is bit 0 (normal notation) and in guest_CRn_321 the significant bits are 3, 2 and 1 (normal notation).*/static void putCR321 ( UInt cr, IRExpr* e ){ vassert(cr < 8); vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8); stmt( IRStmt_Put(guestCR321offset(cr), e) );}static void putCR0 ( UInt cr, IRExpr* e ){ vassert(cr < 8); vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8); stmt( IRStmt_Put(guestCR0offset(cr), e) );}static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr ){ vassert(cr < 8); return IRExpr_Get(guestCR0offset(cr), Ity_I8);}static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr ){ vassert(cr < 8); return IRExpr_Get(guestCR321offset(cr), Ity_I8);}/* Fetch the specified CR bit (as per IBM/hardware notation) and return it at the bottom of an I32; the top 31 bits are guaranteed to be zero. */static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi ){ UInt n = bi / 4; UInt off = bi % 4; vassert(bi < 32); if (off == 3) { /* Fetch the SO bit for this CR field */ /* Note: And32 is redundant paranoia iff guest state only has 0 or 1 in that slot. */ return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); } else { /* Fetch the <, > or == bit for this CR field */ return binop( Iop_And32, binop( Iop_Shr32, unop(Iop_8Uto32, getCR321(n)), mkU8(toUChar(3-off)) ), mkU32(1) ); }}/* Dually, write the least significant bit of BIT to the specified CR bit. Indexing as per getCRbit. */static void putCRbit ( UInt bi, IRExpr* bit ){ UInt n, off; IRExpr* safe; vassert(typeOfIRExpr(irbb->tyenv,bit) == Ity_I32); safe = binop(Iop_And32, bit, mkU32(1)); n = bi / 4; off = bi % 4; vassert(bi < 32); if (off == 3) { /* This is the SO bit for this CR field */ putCR0(n, unop(Iop_32to8, safe)); } else { off = 3 - off; vassert(off == 1 || off == 2 || off == 3); putCR321( n, unop( Iop_32to8, binop( Iop_Or32, /* old value with field masked out */ binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)), mkU32(~(1 << off))), /* new value in the right place */ binop(Iop_Shl32, safe, mkU8(toUChar(off))) ) ) ); }}/* Fetch the specified CR bit (as per IBM/hardware notation) and return it somewhere in an I32; it does not matter where, but whichever bit it is, all other bits are guaranteed to be zero. In other words, the I32-typed expression will be zero if the bit is zero and nonzero if the bit is 1. Write into *where the index of where the bit will be. */staticIRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where ){ UInt n = bi / 4; UInt off = bi % 4; vassert(bi < 32); if (off == 3) { /* Fetch the SO bit for this CR field */ /* Note: And32 is redundant paranoia iff guest state only has 0 or 1 in that slot. */ *where = 0; return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); } else { /* Fetch the <, > or == bit for this CR field */ *where = 3-off; return binop( Iop_And32, unop(Iop_8Uto32, getCR321(n)), mkU32(1 << (3-off)) ); }}/* Set the CR0 flags following an arithmetic operation. (Condition Register CR0 Field Definition, PPC32 p60)*/static IRExpr* getXER_SO ( void );static void set_CR0 ( IRExpr* result ){ vassert(typeOfIRExpr(irbb->tyenv,result) == Ity_I32 || typeOfIRExpr(irbb->tyenv,result) == Ity_I64); if (mode64) { putCR321( 0, unop(Iop_64to8, binop(Iop_CmpORD64S, result, mkU64(0))) ); } else { putCR321( 0, unop(Iop_32to8, binop(Iop_CmpORD32S, result, mkU32(0))) ); } putCR0( 0, getXER_SO() );}/* Set the CR6 flags following an AltiVec compare operation. */static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones ){ /* CR6[0:3] = {all_ones, 0, all_zeros, 0} all_ones = (v[0] && v[1] && v[2] && v[3]) all_zeros = ~(v[0] || v[1] || v[2] || v[3]) */ IRTemp v0 = newTemp(Ity_V128); IRTemp v1 = newTemp(Ity_V128); IRTemp v2 = newTemp(Ity_V128); IRTemp v3 = newTemp(Ity_V128); IRTemp rOnes = newTemp(Ity_I8); IRTemp rZeros = newTemp(Ity_I8); vassert(typeOfIRExpr(irbb->tyenv,result) == Ity_V128); assign( v0, result ); assign( v1, binop(Iop_ShrV128, result, mkU8(32)) ); assign( v2, binop(Iop_ShrV128, result, mkU8(64)) ); assign( v3, binop(Iop_ShrV128, result, mkU8(96)) ); assign( rZeros, unop(Iop_1Uto8, binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), unop(Iop_Not32, unop(Iop_V128to32, binop(Iop_OrV128, binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)), binop(Iop_OrV128, mkexpr(v2), mkexpr(v3)))) ))) ); if (test_all_ones) { assign( rOnes, unop(Iop_1Uto8, binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), unop(Iop_V128to32, binop(Iop_AndV128, binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)), binop(Iop_AndV128, mkexpr(v2), mkexpr(v3))) ))) ); putCR321( 6, binop(Iop_Or8, binop(Iop_Shl8, mkexpr(rOnes), mkU8(3)), binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) ); } else { putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) ); } putCR0( 6, mkU8(0) );} /*------------------------------------------------------------*//*--- Helpers for XER flags. ---*//*------------------------------------------------------------*/static void putXER_SO ( IRExpr* e ){ IRExpr* so; vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8); so = binop(Iop_And8, e, mkU8(1)); stmt( IRStmt_Put( OFFB_XER_SO, so ) );}static void putXER_OV ( IRExpr* e ){ IRExpr* ov; vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8); ov = binop(Iop_And8, e, mkU8(1)); stmt( IRStmt_Put( OFFB_XER_OV, ov ) );}static void putXER_CA ( IRExpr* e ){ IRExpr* ca; vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8); ca = binop(Iop_And8, e, mkU8(1)); stmt( IRStmt_Put( OFFB_XER_CA, ca ) );}static void putXER_BC ( IRExpr* e ){ IRExpr* bc; vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8); bc = binop(Iop_And8, e, mkU8(0x7F)); stmt( IRStmt_Put( OFFB_XER_BC, bc ) );}static IRExpr* /* :: Ity_I8 */ getXER_SO ( void ){ return IRExpr_Get( OFFB_XER_SO, Ity_I8 );}static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void ){ return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );}static IRExpr* /* :: Ity_I8 */ getXER_OV ( void ){ return IRExpr_Get( OFFB_XER_OV, Ity_I8 );}static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void ){ return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );}static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void ){ IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 ); return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );}static IRExpr* /* :: Ity_I8 */ getXER_BC ( void ){ return IRExpr_Get( OFFB_XER_BC, Ity_I8 );}static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void ){ IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 ); return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );}/* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and %XER.SO accordingly. */static void set_XER_OV_32( UInt op, IRExpr* res, IRExpr* argL, IRExpr* argR ){ IRTemp t64; IRExpr* xer_ov; vassert(op < PPCG_FLAG_OP_NUMBER); vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I32); vassert(typeOfIRExpr(irbb->tyenv,argL) == Ity_I32); vassert(typeOfIRExpr(irbb->tyenv,argR) == Ity_I32);# define INT32_MIN 0x80000000# define XOR2(_aa,_bb) \ binop(Iop_Xor32,(_aa),(_bb))# define XOR3(_cc,_dd,_ee) \ binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))# define AND3(_ff,_gg,_hh) \ binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))#define NOT(_jj) \ unop(Iop_Not32, (_jj)) switch (op) { case /* 0 */ PPCG_FLAG_OP_ADD: case /* 1 */ PPCG_FLAG_OP_ADDE: /* (argL^argR^-1) & (argL^res) & (1<<31) ?1:0 */ // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) xer_ov = AND3( XOR3(argL,argR,mkU32(-1)), XOR2(argL,res), mkU32(INT32_MIN) ); /* xer_ov can only be 0 or 1<<31 */ xer_ov = binop(Iop_Shr32, xer_ov, mkU8(31) ); break; case /* 2 */ PPCG_FLAG_OP_DIVW: /* (argL == INT32_MIN && argR == -1) || argR == 0 */ xer_ov = mkOR1( mkAND1( binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)), binop(Iop_CmpEQ32, argR, mkU32(-1)) ), binop(Iop_CmpEQ32, argR, mkU32(0) ) ); xer_ov = unop(Iop_1Uto32, xer_ov); break; case /* 3 */ PPCG_FLAG_OP_DIVWU: /* argR == 0 */ xer_ov = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0))); break; case /* 4 */ PPCG_FLAG_OP_MULLW: /* OV true if result can't be represented in 32 bits i.e sHi != sign extension of sLo */ t64 = newTemp(Ity_I64); assign( t64, binop(Iop_MullS32, argL, argR) ); xer_ov = binop( Iop_CmpNE32, unop(Iop_64HIto32, mkexpr(t64)), binop( Iop_Sar32, unop(Iop_64to32, mkexpr(t64)), mkU8(31)) ); xer_ov = unop(Iop_1Uto32, xer_ov); break; case /* 5 */ PPCG_FLAG_OP_NEG: /* argL == INT32_MIN */ xer_ov = unop( Iop_1Uto32, binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) ); break; case /* 6 */ PPCG_FLAG_OP_SUBF: case /* 7 */ PPCG_FLAG_OP_SUBFC: case /* 8 */ PPCG_FLAG_OP_SUBFE: /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */ xer_ov = AND3( XOR3(NOT(argL),argR,mkU32(-1)), XOR2(NOT(argL),res), mkU32(INT32_MIN) ); /* xer_ov can only be 0 or 1<<31 */ xer_ov = binop(Iop_Shr32, xer_ov, mkU8(31) ); break; default: vex_printf("set_XER_OV: op = %u\n", op); vpanic("set_XER_OV(ppc)"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -