📄 toir.c
字号:
/* xer_ov MUST denote either 0 or 1, no other value allowed */ putXER_OV( unop(Iop_32to8, xer_ov) ); /* Update the summary overflow */ putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );# undef INT32_MIN# undef AND3# undef XOR3# undef XOR2# undef NOT}static void set_XER_OV_64( UInt op, IRExpr* res, IRExpr* argL, IRExpr* argR ){ IRExpr* xer_ov; vassert(op < PPCG_FLAG_OP_NUMBER); vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I64); vassert(typeOfIRExpr(irbb->tyenv,argL) == Ity_I64); vassert(typeOfIRExpr(irbb->tyenv,argR) == Ity_I64);# define INT64_MIN 0x8000000000000000ULL# define XOR2(_aa,_bb) \ binop(Iop_Xor64,(_aa),(_bb))# define XOR3(_cc,_dd,_ee) \ binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))# define AND3(_ff,_gg,_hh) \ binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))#define NOT(_jj) \ unop(Iop_Not64, (_jj)) switch (op) { case /* 0 */ PPCG_FLAG_OP_ADD: case /* 1 */ PPCG_FLAG_OP_ADDE: /* (argL^argR^-1) & (argL^res) & (1<<63) ? 1:0 */ // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) xer_ov = AND3( XOR3(argL,argR,mkU64(-1)), XOR2(argL,res), mkU64(INT64_MIN) ); /* xer_ov can only be 0 or 1<<63 */ xer_ov = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); break; case /* 2 */ PPCG_FLAG_OP_DIVW: /* (argL == INT64_MIN && argR == -1) || argR == 0 */ xer_ov = mkOR1( mkAND1( binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)), binop(Iop_CmpEQ64, argR, mkU64(-1)) ), binop(Iop_CmpEQ64, argR, mkU64(0) ) ); break; case /* 3 */ PPCG_FLAG_OP_DIVWU: /* argR == 0 */ xer_ov = binop(Iop_CmpEQ64, argR, mkU64(0)); break; case /* 4 */ PPCG_FLAG_OP_MULLW: { /* OV true if result can't be represented in 64 bits i.e sHi != sign extension of sLo */ xer_ov = binop( Iop_CmpNE32, unop(Iop_64HIto32, res), binop( Iop_Sar32, unop(Iop_64to32, res), mkU8(31)) ); break; } case /* 5 */ PPCG_FLAG_OP_NEG: /* argL == INT64_MIN */ xer_ov = binop(Iop_CmpEQ64, argL, mkU64(INT64_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<<63) ?1:0; */ xer_ov = AND3( XOR3(NOT(argL),argR,mkU64(-1)), XOR2(NOT(argL),res), mkU64(INT64_MIN) ); /* xer_ov can only be 0 or 1<<63 */ xer_ov = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); break; default: vex_printf("set_XER_OV: op = %u\n", op); vpanic("set_XER_OV(ppc64)"); } /* xer_ov MUST denote either 0 or 1, no other value allowed */ putXER_OV( unop(Iop_1Uto8, xer_ov) ); /* Update the summary overflow */ putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );# undef INT64_MIN# undef AND3# undef XOR3# undef XOR2# undef NOT}static void set_XER_OV ( IRType ty, UInt op, IRExpr* res, IRExpr* argL, IRExpr* argR ){ if (ty == Ity_I32) set_XER_OV_32( op, res, argL, argR ); else set_XER_OV_64( op, res, argL, argR );}/* 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_32 ( UInt op, IRExpr* res, IRExpr* argL, IRExpr* argR, IRExpr* oldca ){ IRExpr* xer_ca; 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); 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 getXER_CA32(), which masks it accordingly. In any case it being 0 or 1 is an invariant of the ppc guest state representation; if it has any other value, that invariant has been violated. */ switch (op) { case /* 0 */ PPCG_FLAG_OP_ADD: /* res <u argL */ xer_ca = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL)); break; case /* 1 */ PPCG_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 */ PPCG_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 */ PPCG_FLAG_OP_SUBFC: case /* 9 */ PPCG_FLAG_OP_SUBFI: /* res <=u argR */ xer_ca = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR)); break; case /* 10 */ PPCG_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 bit of argL. */ /* This term valid for shift amount < 32 only */ xer_ca = binop( Iop_And32, binop(Iop_Sar32, argL, mkU8(31)), binop( Iop_And32, argL, binop( Iop_Sub32, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,argR)), mkU32(1) ) ) ); xer_ca = IRExpr_Mux0X( /* shift amt > 31 ? */ unop(Iop_1Uto8, binop(Iop_CmpLT32U, mkU32(31), argR)), /* no -- be like srawi */ unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))), /* yes -- get sign bit of argL */ binop(Iop_Shr32, argL, mkU8(31)) ); break; case /* 11 */ PPCG_FLAG_OP_SRAWI: /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. Since the shift amount is known to be in the range 0 .. 31 inclusive the following seems viable: xer.ca == 1 iff the following is nonzero: (argL >>s 31) -- either all 0s or all 1s & (argL & (1<<argR)-1) -- the stuff shifted out */ xer_ca = binop( Iop_And32, binop(Iop_Sar32, argL, mkU8(31)), binop( Iop_And32, argL, binop( Iop_Sub32, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,argR)), mkU32(1) ) ) ); xer_ca = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))); break; default: vex_printf("set_XER_CA: op = %u\n", op); vpanic("set_XER_CA(ppc)"); } /* xer_ca MUST denote either 0 or 1, no other value allowed */ putXER_CA( unop(Iop_32to8, xer_ca) );}static void set_XER_CA_64 ( UInt op, IRExpr* res, IRExpr* argL, IRExpr* argR, IRExpr* oldca ){ IRExpr* xer_ca; vassert(op < PPCG_FLAG_OP_NUMBER); vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I64); vassert(typeOfIRExpr(irbb->tyenv,argL) == Ity_I64); vassert(typeOfIRExpr(irbb->tyenv,argR) == Ity_I64); vassert(typeOfIRExpr(irbb->tyenv,oldca) == Ity_I64); /* Incoming oldca is assumed to hold the values 0 or 1 only. This seems reasonable given that it's always generated by getXER_CA32(), which masks it accordingly. In any case it being 0 or 1 is an invariant of the ppc guest state representation; if it has any other value, that invariant has been violated. */ switch (op) { case /* 0 */ PPCG_FLAG_OP_ADD: /* res <u argL */ xer_ca = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL)); break; case /* 1 */ PPCG_FLAG_OP_ADDE: /* res <u argL || (old_ca==1 && res==argL) */ xer_ca = mkOR1( binop(Iop_CmpLT64U, res, argL), mkAND1( binop(Iop_CmpEQ64, oldca, mkU64(1)), binop(Iop_CmpEQ64, res, argL) ) ); xer_ca = unop(Iop_1Uto32, xer_ca); break; case /* 8 */ PPCG_FLAG_OP_SUBFE: /* res <u argR || (old_ca==1 && res==argR) */ xer_ca = mkOR1( binop(Iop_CmpLT64U, res, argR), mkAND1( binop(Iop_CmpEQ64, oldca, mkU64(1)), binop(Iop_CmpEQ64, res, argR) ) ); xer_ca = unop(Iop_1Uto32, xer_ca); break; case /* 7 */ PPCG_FLAG_OP_SUBFC: case /* 9 */ PPCG_FLAG_OP_SUBFI: /* res <=u argR */ xer_ca = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR)); break; case /* 10 */ PPCG_FLAG_OP_SRAW: /* The shift amount is guaranteed to be in 0 .. 31 inclusive. If it is <= 31, behave like SRAWI; else XER.CA is the sign bit of argL. */ /* This term valid for shift amount < 31 only */ xer_ca = binop( Iop_And64, binop(Iop_Sar64, argL, mkU8(31)), binop( Iop_And64, argL, binop( Iop_Sub64, binop(Iop_Shl64, mkU64(1), unop(Iop_64to8,argR)), mkU64(1) ) ) ); xer_ca = IRExpr_Mux0X( /* shift amt > 31 ? */ unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(31), argR)), /* no -- be like srawi */ unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))), /* yes -- get sign bit of argL */ unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))) ); break; case /* 11 */ PPCG_FLAG_OP_SRAWI: /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. Since the shift amount is known to be in the range 0 .. 31 inclusive the following seems viable: xer.ca == 1 iff the following is nonzero: (argL >>s 31) -- either all 0s or all 1s & (argL & (1<<argR)-1) -- the stuff shifted out */ xer_ca = binop( Iop_And64, binop(Iop_Sar64, argL, mkU8(31)), binop( Iop_And64, argL, binop( Iop_Sub64, binop(Iop_Shl64, mkU64(1), unop(Iop_64to8,argR)), mkU64(1) ) ) ); xer_ca = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); break; case /* 12 */ PPCG_FLAG_OP_SRAD: /* The shift amount is guaranteed to be in 0 .. 63 inclusive. If it is <= 63, behave like SRADI; else XER.CA is the sign bit of argL. */ /* This term valid for shift amount < 63 only */ xer_ca = binop( Iop_And64, binop(Iop_Sar64, argL, mkU8(63)), binop( Iop_And64, argL, binop( Iop_Sub64, binop(Iop_Shl64, mkU64(1), unop(Iop_64to8,argR)), mkU64(1) ) ) ); xer_ca = IRExpr_Mux0X( /* shift amt > 63 ? */ unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(63), argR)), /* no -- be like sradi */ unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))), /* yes -- get sign bit of argL */ unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))) ); break; case /* 13 */ PPCG_FLAG_OP_SRADI: /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. Since the shift amount is known to be in the range 0 .. 63 inclusive, the following seems viable: xer.ca == 1 iff the following is nonzero: (argL >>s 63) -- either all 0s or all
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -