return i;
}
ARMInstr* ARMInstr_Call ( ARMCondCode cond, HWord target, Int nArgRegs,
- RetLoc rloc, IRDefault dflt ) {
+ RetLoc rloc ) {
ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
i->tag = ARMin_Call;
i->ARMin.Call.cond = cond;
i->ARMin.Call.target = target;
i->ARMin.Call.nArgRegs = nArgRegs;
i->ARMin.Call.rloc = rloc;
- i->ARMin.Call.dflt = dflt;
vassert(rloc != RetLocINVALID);
return i;
}
vex_printf("0x%lx [nArgRegs=%d, ",
i->ARMin.Call.target, i->ARMin.Call.nArgRegs);
ppRetLoc(i->ARMin.Call.rloc);
- if (i->ARMin.Call.dflt != Idflt_None) {
- vex_printf(", ");
- ppIRDefault(i->ARMin.Call.dflt);
- }
vex_printf("]");
return;
case ARMin_Mul:
// preElse:
// b after:
// else:
- // {mov,mvn} r0, #0 // possibly
- // {mov,mvn} r1, #0 // possibly
+ // mov r0, #0x55555555 // possibly
+ // mov r1, r0 // possibly
// after:
- /* Since we're generating default-return code in the else:
- clause, there had better be a sane default-value
- specification. */
- vassert(i->ARMin.Call.dflt == Idflt_Zeroes
- || i->ARMin.Call.dflt == Idflt_Ones);
-
// before:
UInt* pBefore = p;
= XX______(1 ^ i->ARMin.Call.cond, X1010) | (delta & 0xFFFFFF);
/* Do the 'else' actions */
- /* Useful:
- e3a00000 mov r0, #0
- e3a01000 mov r1, #0
- e3e00000 mvn r0, #0
- e3e01000 mvn r1, #0
- */
switch (i->ARMin.Call.rloc) {
- case RetLocInt: {
- switch (i->ARMin.Call.dflt) {
- case Idflt_Ones: *p++ = 0xE3E00000; break; // mvn r0, #0
- case Idflt_Zeroes: *p++ = 0xE3A00000; break; // mov r0, #0
- default: goto elsefail;
- }
+ case RetLocInt:
+ p = imm32_to_iregNo_EXACTLY2(p, /*r*/0, 0x55555555);
break;
- }
- case RetLoc2Int: {
- if (i->ARMin.Call.dflt == Idflt_Ones) {
- // mvn r0, #0 ; mvn r1, #0
- vassert(0); //ATC
- *p++ = 0xE3E00000; *p++ = 0xE3E01000; break;
- }
- goto elsefail;
- }
- case RetLocNone:
- case RetLocINVALID:
- default:
- elsefail:
+ case RetLoc2Int:
+ vassert(0); //ATC
+ p = imm32_to_iregNo_EXACTLY2(p, /*r*/0, 0x55555555);
+ /* mov r1, r0 */
+ *p++ = 0xE1A01000;
+ break;
+ case RetLocNone: case RetLocINVALID: default:
vassert(0);
}
goto done;
}
+
case ARMin_Mul: {
/* E0000392 mul r0, r2, r3
E0810392 umull r0(LO), r1(HI), r2, r3
HWord target;
Int nArgRegs; /* # regs carrying args: 0 .. 4 */
RetLoc rloc; /* where the return value will be */
- IRDefault dflt; /* default return, if conditional */
} Call;
/* (PLAIN) 32 * 32 -> 32: r0 = r2 * r3
(ZX) 32 *u 32 -> 64: r1:r0 = r2 *u r3
ARMCondCode cond, IRJumpKind jk );
extern ARMInstr* ARMInstr_CMov ( ARMCondCode, HReg dst, ARMRI84* src );
extern ARMInstr* ARMInstr_Call ( ARMCondCode, HWord, Int nArgRegs,
- RetLoc rloc, IRDefault dflt );
+ RetLoc rloc );
extern ARMInstr* ARMInstr_Mul ( ARMMulOp op );
extern ARMInstr* ARMInstr_LdrEX ( Int szB );
extern ARMInstr* ARMInstr_StrEX ( Int szB );
Bool doHelperCall ( ISelEnv* env,
Bool passBBP,
IRExpr* guard, IRCallee* cee, IRExpr** args,
- RetLoc rloc, IRDefault dflt )
+ RetLoc rloc )
{
ARMCondCode cc;
HReg argregs[ARM_N_ARGREGS];
values. But that's too much hassle. */
/* Finally, the call itself. */
- addInstr(env, ARMInstr_Call( cc, target, nextArgReg, rloc, dflt ));
+ addInstr(env, ARMInstr_Call( cc, target, nextArgReg, rloc ));
return True; /* success */
}
addInstr(env, mk_iMOVds_RR(hregARM_R0(), regL));
addInstr(env, mk_iMOVds_RR(hregARM_R1(), regR));
addInstr(env, ARMInstr_Call( ARMcc_AL, (HWord)Ptr_to_ULong(fn),
- 2, RetLocInt, Idflt_None ));
+ 2, RetLocInt ));
addInstr(env, mk_iMOVds_RR(res, hregARM_R0()));
return res;
}
HReg res = newVRegI(env);
addInstr(env, mk_iMOVds_RR(hregARM_R0(), arg));
addInstr(env, ARMInstr_Call( ARMcc_AL, (HWord)Ptr_to_ULong(fn),
- 1, RetLocInt, Idflt_None ));
+ 1, RetLocInt ));
addInstr(env, mk_iMOVds_RR(res, hregARM_R0()));
return res;
}
/* Marshal args, do the call, clear stack. */
Bool ok = doHelperCall( env, False,
NULL, e->Iex.CCall.cee, e->Iex.CCall.args,
- RetLocInt, Idflt_None );
+ RetLocInt );
if (ok) {
addInstr(env, mk_iMOVds_RR(dst, hregARM_R0()));
return dst;
if (rloc == RetLocINVALID)
break; /* will go to stmt_fail: */
- Bool ok = doHelperCall( env, passBBP, d->guard, d->cee, d->args,
- rloc, d->dflt );
+ Bool ok = doHelperCall( env, passBBP, d->guard, d->cee, d->args, rloc );
if (!ok)
break; /* will go to stmt_fail: */
}
}
-void ppIRDefault ( IRDefault dflt )
-{
- switch (dflt) {
- case Idflt_None: vex_printf("Dflt-None"); return;
- case Idflt_Zeroes: vex_printf("Dflt-Zero"); return;
- case Idflt_Ones: vex_printf("Dflt-One"); return;
- default: vpanic("ppIRDefault");
- }
-}
-
void ppIRDirty ( IRDirty* d )
{
Int i;
ppIRTemp(d->tmp);
vex_printf(" = ");
}
- if (d->dflt != Idflt_None) {
- vex_printf("(");
- ppIRDefault(d->dflt);
- vex_printf(") ");
- }
vex_printf("DIRTY ");
ppIRExpr(d->guard);
if (d->needsBBP)
d->guard = NULL;
d->args = NULL;
d->tmp = IRTemp_INVALID;
- d->dflt = Idflt_None;
d->mFx = Ifx_None;
d->mAddr = NULL;
d->mSize = 0;
d2->guard = deepCopyIRExpr(d->guard);
d2->args = deepCopyIRExprVec(d->args);
d2->tmp = d->tmp;
- d2->dflt = d->dflt;
d2->mFx = d->mFx;
d2->mAddr = d->mAddr==NULL ? NULL : deepCopyIRExpr(d->mAddr);
d2->mSize = d->mSize;
if (typeOfIRExpr(tyenv, d->args[i]) == Ity_I1)
sanityCheckFail(bb,stmt,"IRStmt.Dirty.arg[i] :: Ity_I1");
}
- /* if the call returns a value and isn't obviously
- unconditional, check there's a reasonable default-spec for
- the return value. */
- if (d->tmp != IRTemp_INVALID) {
- IRExpr* guard = d->guard;
- Bool obviouslyUncond = False;
- if (guard->tag == Iex_Const
- && guard->Iex.Const.con->tag == Ico_U1
- && guard->Iex.Const.con->Ico.U1 == True) {
- obviouslyUncond = True;
- }
- if (!obviouslyUncond
- && d->dflt != Idflt_Ones && d->dflt != Idflt_Zeroes)
- goto bad_dirty;
- }
break;
bad_dirty:
sanityCheckFail(bb,stmt,"IRStmt.Dirty: ill-formed");
/* Pretty-print an IREffect */
extern void ppIREffect ( IREffect );
-/* Default values for guarded dirty calls which return a result. */
-typedef
- enum {
- Idflt_None=0x1B80, /* default unspecified */
- Idflt_Zeroes, /* all zeroes */
- Idflt_Ones /* all ones */
- }
- IRDefault;
-
-/* Pretty-print an IRDefault */
-extern void ppIRDefault ( IRDefault );
-
typedef
struct _IRDirty {
/* What to call, and details of args/results. .guard must be
non-NULL. If .tmp is not IRTemp_INVALID, then the call
returns a result which is placed in .tmp. If at runtime the
- guard evaluates to false, .tmp has an all-zeroes or all-ones
- bit pattern written to it, as specified by .dflt. Hence
- conditional calls that assign .tmp are allowed. */
+ guard evaluates to false, .tmp has an 0x555..555 bit pattern
+ written to it. Hence conditional calls that assign .tmp are
+ allowed. */
IRCallee* cee; /* where to call */
IRExpr* guard; /* :: Ity_Bit. Controls whether call happens */
IRExpr** args; /* arg list, ends in NULL */
IRTemp tmp; /* to assign result to, or IRTemp_INVALID if none */
- IRDefault dflt; /* for result, if guarded and tmp != INVALID */
/* Mem effects; we allow only one R/W/M region to be stated */
IREffect mFx; /* indicates memory effects, if any */