for (i = 1; i <= 5; ++i) {
addHRegUse(u, HRmWrite, mkHReg(i, HRcInt64, False));
}
+ if (insn->variant.helper_call.dst != INVALID_HREG)
+ addHRegUse(u, HRmWrite, insn->variant.helper_call.dst);
/* Ditto for floating point registers. f0 - f7 are volatile */
for (i = 0; i <= 7; ++i) {
As for the arguments of the helper call -- they will be loaded into
non-virtual registers. Again, we don't need to do anything for those
here. */
+ if (insn->variant.helper_call.dst != INVALID_HREG)
+ insn->variant.helper_call.dst = lookupHRegRemap(m, insn->variant.helper_call.dst);
break;
case S390_INSN_BFP_TRIOP:
s390_insn *
s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
- HChar *name)
+ HChar *name, HReg dst)
{
s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
insn->variant.helper_call.target = target;
insn->variant.helper_call.num_args = num_args;
insn->variant.helper_call.name = name;
+ insn->variant.helper_call.dst = dst;
return insn;
}
break;
case S390_INSN_HELPER_CALL: {
- s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
- insn->variant.helper_call.cond,
- insn->variant.helper_call.name,
- insn->variant.helper_call.target,
- insn->variant.helper_call.num_args);
+ if (insn->variant.helper_call.dst != INVALID_HREG) {
+ s390_sprintf(buf, "%M if (%C) %R = %s{%I}(%L)", "v-call",
+ insn->variant.helper_call.cond,
+ insn->variant.helper_call.dst,
+ insn->variant.helper_call.name,
+ insn->variant.helper_call.target,
+ insn->variant.helper_call.num_args);
+ } else {
+ s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
+ insn->variant.helper_call.cond,
+ insn->variant.helper_call.name,
+ insn->variant.helper_call.target,
+ insn->variant.helper_call.num_args);
+ }
return buf; /* avoid printing "size = ..." which is meaningless */
}
buf = s390_emit_STG(buf, S390_REGNO_LINK_REGISTER, 0, // save LR
S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1); // call helper
+
+ /* Move the return value to the destination register */
+ if (insn->variant.helper_call.dst != INVALID_HREG) {
+ buf = s390_emit_LGR(buf, hregNumber(insn->variant.helper_call.dst),
+ S390_REGNO_RETURN_VALUE);
+ }
+
buf = s390_emit_LG(buf, S390_REGNO_LINK_REGISTER, 0, // restore LR
S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER, // restore FPC
s390_cc_t cond;
Addr64 target;
UInt num_args;
+ HReg dst; /* if not INVALID_HREG, put return value here */
HChar *name; /* callee's name (for debugging) */
} helper_call;
struct {
s390_insn *s390_insn_compare(UChar size, HReg dst, s390_opnd_RMI opnd,
Bool signed_comparison);
s390_insn *s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
- HChar *name);
+ HChar *name, HReg dst);
s390_insn *s390_insn_bfp_triop(UChar size, s390_bfp_triop_t, HReg dst, HReg op2,
HReg op3, s390_round_t);
s390_insn *s390_insn_bfp_binop(UChar size, s390_bfp_binop_t, HReg dst, HReg op2,
*/
static void
doHelperCall(ISelEnv *env, Bool passBBP, IRExpr *guard,
- IRCallee *callee, IRExpr **args)
+ IRCallee *callee, IRExpr **args, HReg dst)
{
UInt n_args, i, argreg, size;
ULong target;
/* Finally, the call itself. */
addInstr(env, s390_insn_helper_call(cc, (Addr64)target, n_args,
- callee->name));
+ callee->name, dst));
}
HReg dst = newVRegI(env);
doHelperCall(env, False, NULL, expr->Iex.CCall.cee,
- expr->Iex.CCall.args);
-
- /* Move the returned value into the return register */
- addInstr(env, s390_insn_move(sizeofIRType(expr->Iex.CCall.retty), dst,
- make_gpr(S390_REGNO_RETURN_VALUE)));
+ expr->Iex.CCall.args, dst);
return dst;
}
IRType retty;
IRDirty* d = stmt->Ist.Dirty.details;
Bool passBBP;
+ HReg dst;
Int i;
/* Invalidate tracked values of those guest state registers that are
passBBP = toBool(d->nFxState > 0 && d->needsBBP);
- doHelperCall(env, passBBP, d->guard, d->cee, d->args);
-
- /* Now figure out what to do with the returned value, if any. */
- if (d->tmp == IRTemp_INVALID)
- /* No return value. Nothing to do. */
+ if (d->tmp == IRTemp_INVALID) {
+ /* No return value. */
+ dst = INVALID_HREG;
+ doHelperCall(env, passBBP, d->guard, d->cee, d->args, dst);
return;
+ }
retty = typeOfIRTemp(env->type_env, d->tmp);
if (retty == Ity_I64 || retty == Ity_I32
|| retty == Ity_I16 || retty == Ity_I8) {
/* Move the returned value to the destination register */
- HReg dst = lookupIRTemp(env, d->tmp);
- addInstr(env, s390_insn_move(sizeofIRType(retty), dst,
- make_gpr(S390_REGNO_RETURN_VALUE)));
+ dst = lookupIRTemp(env, d->tmp);
+ doHelperCall(env, passBBP, d->guard, d->cee, d->args, dst);
return;
}
break;