📄 toir.c
字号:
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(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. */static IRExpr* /* :: 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)) ); }}/* Synthesise the entire CR into a single word. Expensive. */static IRExpr* /* :: Ity_I32 */ getEntireCR ( void ){# define FIELD(_n) \ binop(Iop_Shl32, \ unop(Iop_8Uto32, \ binop(Iop_Or8, \ binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \ binop(Iop_And8, getCR0(_n), mkU8(1)) \ ) \ ), \ mkU8(4 * (7-(_n))) \ ) return binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32, FIELD(0), FIELD(1)), binop(Iop_Or32, FIELD(2), FIELD(3)) ), binop(Iop_Or32, binop(Iop_Or32, FIELD(4), FIELD(5)), binop(Iop_Or32, FIELD(6), FIELD(7)) ) );# undef FIELD}static void putCRfields ( IRExpr* w32, UInt mask ){ IRTemp t; Int cr; vassert(typeOfIRExpr(irbb->tyenv,w32) == Ity_I32); vassert(mask < 256); for (cr = 0; cr < 8; cr++) { if ((mask & (1 << (7-cr))) == 0) continue; t = newTemp(Ity_I32); assign( t, binop(Iop_Shr32, w32, mkU8(4*(7-cr))) ); putCR0( cr, unop(Iop_32to8, binop(Iop_And32, mkexpr(t), mkU32(1))) ); putCR321( cr, unop(Iop_32to8, binop(Iop_And32, mkexpr(t), mkU32(7<<1))) ); }}//zz /* -------------- Evaluating the flags-thunk. -------------- *///zz //zz /* Calculate CR7 (IBM CR0) conditional flags *///zz static IRExpr* mk_ppc32g_calculate_cr7 ( void )//zz {//zz IRExpr** args =//zz mkIRExprVec_3( IRExpr_Get(OFFB_CC_OP, Ity_I32),//zz IRExpr_Get(OFFB_CC_DEP1, Ity_I32),//zz IRExpr_Get(OFFB_CC_DEP2, Ity_I32) );//zz IRExpr* call//zz = mkIRExprCCall(//zz Ity_I32,//zz 0/*regparm*/, //zz "ppc32g_calculate_cr7", &ppc32g_calculate_cr7,//zz args//zz );//zz //zz // TODO//zz // 02/02/05 - leaving definedness stuff 'till get memcheck working well.//zz //zz /* Exclude OP from definedness checking. We're only//zz interested in DEP1 and DEP2. *///zz // call->Iex.CCall.cee->mcx_mask = 1;//zz //zz return call;//zz }//zz //zz /* Calculate XER_OV flag *///zz static IRExpr* mk_ppc32g_calculate_xer_ov ( UInt op, IRExpr* res,//zz IRExpr* argL, IRExpr* argR )//zz {//zz IRExpr** args;//zz IRExpr* call;//zz vassert(op < PPC32G_FLAG_OP_NUMBER);//zz vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I32);//zz vassert(typeOfIRExpr(irbb->tyenv,argL) == Ity_I32);//zz vassert(typeOfIRExpr(irbb->tyenv,argR) == Ity_I32);//zz //zz args = mkIRExprVec_4( mkU32(op), res, argL, argR );//zz //zz call//zz = mkIRExprCCall(//zz Ity_I32,//zz 0/*regparm*/,//zz "ppc32g_calculate_xer_ov", &ppc32g_calculate_xer_ov,//zz args//zz );//zz return binop(Iop_And32, mkU32(1), call);//zz }//uu /* Calculate XER_CA flag. RES is the result of applying OP to ARGL//uu and ARGR, and OLDCA is the old carry flag. The latter may be zero//uu if it is known that OP does not need to consult it. *///uu //uu static IRExpr* mk_ppc32g_calculate_xer_ca ( UInt op, //uu IRExpr* res,//uu IRExpr* argL, //uu IRExpr* argR,//uu IRExpr* oldca )//uu {//uu IRExpr** args;//uu IRExpr* call;//uu vassert(op < PPC32G_FLAG_OP_NUMBER);//uu vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I32);//uu vassert(typeOfIRExpr(irbb->tyenv,argL) == Ity_I32);//uu vassert(typeOfIRExpr(irbb->tyenv,argR) == Ity_I32);//uu vassert(typeOfIRExpr(irbb->tyenv,oldca) == Ity_I32);//uu //uu args = mkIRExprVec_5( mkU32(op), res, argL, argR, oldca );//uu //uu call//uu = mkIRExprCCall(//uu Ity_I32,//uu 0/*regparm*/,//uu "ppc32g_calculate_xer_ca", &ppc32g_calculate_xer_ca,//uu args//uu );//uu return binop(Iop_And32, mkU32(1), call);//uu }/* Set the CR0 flags following an arithmetic operation. (Condition Register CR0 Field Definition, PPC32 p60)*/static void set_CR0 ( IRExpr* result ){ vassert(typeOfIRExpr(irbb->tyenv,result) == Ity_I32); putCR321( 0, unop(Iop_32to8, binop(Iop_CmpORD32S, result, mkU32(0))) ); putCR0( 0, getXER_SO() );}/* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and %XER.SO accordingly. */static void set_XER_OV( UInt op, IRExpr* res, IRExpr* argL, IRExpr* argR ){ IRTemp t64; IRExpr* xer_ov; vassert(op < PPC32G_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 */ PPC32G_FLAG_OP_ADD: case /* 1 */ PPC32G_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 */ PPC32G_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 */ PPC32G_FLAG_OP_DIVWU: /* argR == 0 */ xer_ov = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0))); break; case /* 4 */ PPC32G_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 */ PPC32G_FLAG_OP_NEG: /* argL == INT32_MIN */ xer_ov = unop( Iop_1Uto32, binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) ); break; case /* 6 */ PPC32G_FLAG_OP_SUBF: case /* 7 */ PPC32G_FLAG_OP_SUBFC: case /* 8 */ PPC32G_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 = %d\n", op); vpanic("set_XER_OV(ppc32)"); } /* xer_ov MUST denote either 0 or 1, no other value allowed */ stmt( IRStmt_Put( OFFB_XER_OV, unop(Iop_32to8, xer_ov) ) ); /* Update the summary overflow */ stmt( IRStmt_Put( OFFB_XER_SO, binop(Iop_Or8, IRExpr_Get( OFFB_XER_SO, Ity_I8 ), IRExpr_Get( OFFB_XER_OV, Ity_I8 ) ) ));# undef INT32_MIN# undef AND3# undef XOR3# undef XOR2# undef NOT}/* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA value being OLDCA. Set %XER.CA accordingly. */static void set_XER_CA( UInt op, IRExpr* res, IRExpr* argL, IRExpr* argR, IRExpr* oldca ){ IRExpr* xer_ca; vassert(op < PPC32G_FLAG_OP_NUMBER); vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I32); vassert(typeOfIRExpr(irbb->tyenv,argL) == Ity_I32); vassert(typeOfIRExpr(irbb->tyenv,argR) == Ity_I32); vassert(typeOfIRExpr(irbb->tyenv,oldca) == Ity_I32); /* Incoming oldca is assumed to hold the values 0 or 1 only. This seems reasonable given that it's always generated by get_XER_CA(), which masks it accordingly. In any case it being 0 or 1 is an invariant of the ppc32 guest state representation; if it has any other value, that invariant has been violated. */ switch (op) { case /* 0 */ PPC32G_FLAG_OP_ADD: /* res <u argL */ xer_ca = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL)); break; case /* 1 */ PPC32G_FLAG_OP_ADDE: /* res <u argL || (old_ca==1 && res==argL) */ xer_ca = mkOR1( binop(Iop_CmpLT32U, res, argL), mkAND1( binop(Iop_CmpEQ32, oldca, mkU32(1)), binop(Iop_CmpEQ32, res, argL) ) ); xer_ca = unop(Iop_1Uto32, xer_ca); break; case /* 8 */ PPC32G_FLAG_OP_SUBFE: /* res <u argR || (old_ca==1 && res==argR) */ xer_ca = mkOR1( binop(Iop_CmpLT32U, res, argR), mkAND1( binop(Iop_CmpEQ32, oldca, mkU32(1)), binop(Iop_CmpEQ32, res, argR) ) ); xer_ca = unop(Iop_1Uto32, xer_ca); break; case /* 7 */ PPC32G_FLAG_OP_SUBFC: case /* 9 */ PPC32G_FLAG_OP_SUBFI: /* res <=u argR */ xer_ca = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR)); break; case /* 10 */ PPC32G_FLAG_OP_SRAW: /* The shift amount is guaranteed to be in 0 .. 63 inclusive. If it is <= 31, behave like SRAWI; else XER.CA is the sign
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -