return dst;
}
- addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn, 2 ));
+ case Iop_GetMSBs8x16: {
+ /* Note: the following assumes the helper is of signature
+ UInt fn ( ULong w64hi, ULong w64Lo ),
+ and is not a regparm fn. */
+ HReg dst = newVRegI(env);
+ HReg vec = iselVecExpr(env, e->Iex.Unop.arg);
+ HReg rsp = hregAMD64_RSP();
+ fn = (HWord)h_generic_calc_GetMSBs8x16;
+ AMD64AMode* m8_rsp = AMD64AMode_IR( -8, rsp);
+ AMD64AMode* m16_rsp = AMD64AMode_IR(-16, rsp);
+ addInstr(env, AMD64Instr_SseLdSt(False/*store*/,
+ 16, vec, m16_rsp));
+ /* hi 64 bits into RDI -- the first arg */
+ addInstr(env, AMD64Instr_Alu64R( Aalu_MOV,
+ AMD64RMI_Mem(m8_rsp),
+ hregAMD64_RDI() )); /* 1st arg */
+ /* lo 64 bits into RSI -- the 2nd arg */
+ addInstr(env, AMD64Instr_Alu64R( Aalu_MOV,
+ AMD64RMI_Mem(m16_rsp),
+ hregAMD64_RSI() )); /* 2nd arg */
++ addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn,
++ 2, RetLocInt ));
+ /* MovxLQ is not exactly the right thing here. We just
+ need to get the bottom 16 bits of RAX into dst, and zero
+ out everything else. Assuming that the helper returns
+ a UInt with the top 16 bits zeroed out, it'll do,
+ though. */
+ addInstr(env, AMD64Instr_MovxLQ(False, hregAMD64_RAX(), dst));
+ return dst;
+ }
+
default:
break;
}
fold_Expr(env, subst_Expr(env, st->Ist.Store.data))
);
- we can replace it with a NoOp, but if the guard folds down
- to 'true', we can't conveniently replace it with an
- unconditional load, because doing so requires generating a
- new temporary, and that is not easy to do at this
- point. */
+ case Ist_StoreG: {
+ IRStoreG* sg = st->Ist.StoreG.details;
+ vassert(isIRAtom(sg->addr));
+ vassert(isIRAtom(sg->data));
+ vassert(isIRAtom(sg->guard));
+ IRExpr* faddr = fold_Expr(env, subst_Expr(env, sg->addr));
+ IRExpr* fdata = fold_Expr(env, subst_Expr(env, sg->data));
+ IRExpr* fguard = fold_Expr(env, subst_Expr(env, sg->guard));
+ if (fguard->tag == Iex_Const) {
+ /* The condition on this store has folded down to a constant. */
+ vassert(fguard->Iex.Const.con->tag == Ico_U1);
+ if (fguard->Iex.Const.con->Ico.U1 == False) {
+ return IRStmt_NoOp();
+ } else {
+ vassert(fguard->Iex.Const.con->Ico.U1 == True);
+ return IRStmt_Store(sg->end, faddr, fdata);
+ }
+ }
+ return IRStmt_StoreG(sg->end, faddr, fdata, fguard);
+ }
+
+ case Ist_LoadG: {
+ /* This is complicated. If the guard folds down to 'false',
++ we can replace it with an assignment 'dst := alt', but if
++ the guard folds down to 'true', we can't conveniently
++ replace it with an unconditional load, because doing so
++ requires generating a new temporary, and that is not easy
++ to do at this point. */
+ IRLoadG* lg = st->Ist.LoadG.details;
+ vassert(isIRAtom(lg->addr));
+ vassert(isIRAtom(lg->alt));
+ vassert(isIRAtom(lg->guard));
+ IRExpr* faddr = fold_Expr(env, subst_Expr(env, lg->addr));
+ IRExpr* falt = fold_Expr(env, subst_Expr(env, lg->alt));
+ IRExpr* fguard = fold_Expr(env, subst_Expr(env, lg->guard));
+ if (fguard->tag == Iex_Const) {
+ /* The condition on this load has folded down to a constant. */
+ vassert(fguard->Iex.Const.con->tag == Ico_U1);
+ if (fguard->Iex.Const.con->Ico.U1 == False) {
+ /* The load is not going to happen -- instead 'alt' is
+ assigned to 'dst'. */
+ return IRStmt_WrTmp(lg->dst, falt);
+ } else {
+ vassert(fguard->Iex.Const.con->Ico.U1 == True);
+ /* The load is always going to happen. We want to
+ convert to an unconditional load and assign to 'dst'
+ (IRStmt_WrTmp). Problem is we need an extra temp to
+ hold the loaded value, but none is available.
+ Instead, reconstitute the conditional load (with
+ folded args, of course) and let the caller of this
+ routine deal with the problem. */
+ }
+ }
+ return IRStmt_LoadG(lg->end, lg->cvt, lg->dst, faddr, falt, fguard);
+ }
+
case Ist_CAS: {
IRCAS *cas, *cas2;
cas = st->Ist.CAS.details;
In order that instrumentation is possible, the call must state, and
state correctly:
- * whether it reads, writes or modifies memory, and if so where
- (only one chunk can be stated)
- * whether it reads, writes or modifies memory, and if so where Only
- one chunk can be stated, although it is allowed to repeat some
- number of times at a fixed interval.
++ * Whether it reads, writes or modifies memory, and if so where.
-- * whether it reads, writes or modifies guest state, and if so which
- pieces (several pieces may be stated, and currently their extents
- must be known at translation-time).
++ * Whether it reads, writes or modifies guest state, and if so which
+ pieces. Several pieces may be stated, and their extents must be
- known at translation-time.
++ known at translation-time. Each piece is allowed to repeat some
++ number of times at a fixed interval, if required.
Normally, code is generated to pass just the args to the helper.
However, if .needsBBP is set, then an extra first argument is