case Iop_CmpLT64U: vex_printf("CmpLT64U"); return;
case Iop_CmpLE64U: vex_printf("CmpLE64U"); return;
+ case Iop_CmpNEZ8: vex_printf("CmpNEZ8"); return;
+ case Iop_CmpNEZ16: vex_printf("CmpNEZ16"); return;
+ case Iop_CmpNEZ32: vex_printf("CmpNEZ32"); return;
+ case Iop_CmpNEZ64: vex_printf("CmpNEZ64"); return;
+
+ case Iop_Neg8: vex_printf("Neg8"); return;
+ case Iop_Neg16: vex_printf("Neg16"); return;
+ case Iop_Neg32: vex_printf("Neg32"); return;
+ case Iop_Neg64: vex_printf("Neg64"); return;
+
case Iop_DivU32: vex_printf("DivU32"); return;
case Iop_DivS32: vex_printf("DivS32"); return;
*t_dst = (_td); *t_arg1 = (_ta1); *t_arg2 = (_ta2); break
# define COMPARISON(_ta) \
*t_dst = Ity_I1; *t_arg1 = *t_arg2 = (_ta); break;
+# define UNARY_COMPARISON(_ta) \
+ *t_dst = Ity_I1; *t_arg1 = (_ta); break;
*t_dst = Ity_INVALID;
*t_arg1 = Ity_INVALID;
case Iop_Shl64: case Iop_Shr64: case Iop_Sar64:
BINARY(Ity_I64, Ity_I64,Ity_I8);
- case Iop_Not8: UNARY(Ity_I8,Ity_I8);
- case Iop_Not16: UNARY(Ity_I16,Ity_I16);
- case Iop_Not32: UNARY(Ity_I32,Ity_I32);
+ case Iop_Not8: case Iop_Neg8:
+ UNARY(Ity_I8,Ity_I8);
+ case Iop_Not16: case Iop_Neg16:
+ UNARY(Ity_I16,Ity_I16);
+ case Iop_Not32: case Iop_Neg32:
+ UNARY(Ity_I32,Ity_I32);
- case Iop_Not64:
+ case Iop_Neg64:
+ case Iop_Not64:
case Iop_CmpNEZ32x2: case Iop_CmpNEZ16x4: case Iop_CmpNEZ8x8:
UNARY(Ity_I64,Ity_I64);
case Iop_CmpLT64U: case Iop_CmpLE64U:
COMPARISON(Ity_I64);
+ case Iop_CmpNEZ8: UNARY_COMPARISON(Ity_I8);
+ case Iop_CmpNEZ16: UNARY_COMPARISON(Ity_I16);
+ case Iop_CmpNEZ32: UNARY_COMPARISON(Ity_I32);
+ case Iop_CmpNEZ64: UNARY_COMPARISON(Ity_I64);
+
case Iop_MullU8: case Iop_MullS8:
BINARY(Ity_I16, Ity_I8,Ity_I8);
case Iop_MullU16: case Iop_MullS16:
# undef UNARY
# undef BINARY
# undef COMPARISON
+# undef UNARY_COMPARISON
}
vpanic("notBool");
}
+/* Make a zero which has the same type as the result of the given
+ primop. */
+static IRExpr* mkZeroForXor ( IROp op )
+{
+ switch (op) {
+ case Iop_Xor8: return IRExpr_Const(IRConst_U8(0));
+ case Iop_Xor16: return IRExpr_Const(IRConst_U16(0));
+ case Iop_Xor32: return IRExpr_Const(IRConst_U32(0));
+ case Iop_Xor64: return IRExpr_Const(IRConst_U64(0));
+ default: vpanic("mkZeroForXor: bad primop");
+ }
+}
+
+
static IRExpr* fold_Expr ( IRExpr* e )
{
Int shift;
notBool(e->Iex.Unop.arg->Iex.Const.con->Ico.U1)));
break;
+ case Iop_Neg32:
+ e2 = IRExpr_Const(IRConst_U32(
+ - (e->Iex.Unop.arg->Iex.Const.con->Ico.U32)));
+ break;
+ case Iop_Neg8:
+ e2 = IRExpr_Const(IRConst_U8(
+ - (e->Iex.Unop.arg->Iex.Const.con->Ico.U8)));
+ break;
+
case Iop_64to32: {
ULong w64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
w64 &= 0x00000000FFFFFFFFULL;
& e->Iex.Unop.arg->Iex.Const.con->Ico.U32));
break;
+ case Iop_CmpNEZ8:
+ e2 = IRExpr_Const(IRConst_U1(toBool(
+ 0 !=
+ (0xFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U8)
+ )));
+ break;
+ case Iop_CmpNEZ32:
+ e2 = IRExpr_Const(IRConst_U1(toBool(
+ 0 !=
+ (0xFFFFFFFF & e->Iex.Unop.arg->Iex.Const.con->Ico.U32)
+ )));
+ break;
+ case Iop_CmpNEZ64:
+ e2 = IRExpr_Const(IRConst_U1(toBool(
+ 0ULL != e->Iex.Unop.arg->Iex.Const.con->Ico.U64
+ )));
+ break;
+
default:
goto unhandled;
}
e2 = e->Iex.Binop.arg1;
} else
+ /* Or16(x,0) ==> x */
+ if ((e->Iex.Binop.op == Iop_Or16)
+ && e->Iex.Binop.arg2->tag == Iex_Const
+ && e->Iex.Binop.arg2->Iex.Const.con->Ico.U16 == 0) {
+ e2 = e->Iex.Binop.arg1;
+ } else
+
/* Or32/Add32(x,0) ==> x */
if ((e->Iex.Binop.op == Iop_Add32 || e->Iex.Binop.op == Iop_Or32)
&& e->Iex.Binop.arg2->tag == Iex_Const
e2 = e->Iex.Binop.arg1;
}
+ /* Xor8/16/32/64(t,t) ==> 0, for some IRTemp t */
+ if ( (e->Iex.Binop.op == Iop_Xor64
+ || e->Iex.Binop.op == Iop_Xor32
+ || e->Iex.Binop.op == Iop_Xor16
+ || e->Iex.Binop.op == Iop_Xor8)
+ && sameIRTemps(e->Iex.Binop.arg1, e->Iex.Binop.arg2)) {
+ vassert(0); /* awaiting test case */
+ e2 = mkZeroForXor(e->Iex.Binop.op);
+ }
+
}
}
Iop_CmpLT32U, Iop_CmpLT64U,
Iop_CmpLE32U, Iop_CmpLE64U,
+ /* As a sop to Valgrind-Memcheck, the following are useful. */
+ Iop_CmpNEZ8, Iop_CmpNEZ16, Iop_CmpNEZ32, Iop_CmpNEZ64,
+ Iop_Neg8, Iop_Neg16, Iop_Neg32, Iop_Neg64,
+
/* Division */
/* TODO: clarify semantics wrt rounding, negative values, whatever */
Iop_DivU32, // :: I32,I32 -> I32 (simple div, no mod)
// of which lo half is div and hi half is mod
Iop_DivModS128to64, // ditto, signed
+ /* Integer conversions. Some of these are redundant (eg
+ Iop_64to8 is the same as Iop_64to32 and then Iop_32to8), but
+ having a complete set reduces the typical dynamic size of IR
+ and makes the instruction selectors easier to write. */
+
/* Widening conversions */
- Iop_8Uto16, Iop_8Uto32, Iop_16Uto32, Iop_32Uto64,
- Iop_8Sto16, Iop_8Sto32, Iop_16Sto32, Iop_32Sto64,
+ Iop_8Uto16, Iop_8Uto32, Iop_8Uto64,
+ Iop_16Uto32, Iop_16Uto64,
+ Iop_32Uto64,
+ Iop_8Sto16, Iop_8Sto32, Iop_8Sto64,
+ Iop_16Sto32, Iop_16Sto64,
+ Iop_32Sto64,
+
/* Narrowing conversions */
- Iop_32to8,
+ Iop_64to8, Iop_32to8, Iop_64to16,
/* 8 <-> 16 bit conversions */
Iop_16to8, // :: I16 -> I8, low half
Iop_16HIto8, // :: I16 -> I8, high half