|
From: <sv...@va...> - 2012-05-27 16:52:51
|
florian 2012-05-27 17:52:43 +0100 (Sun, 27 May 2012)
New Revision: 2356
Log:
Change S390_INSN_HELPER_CALL such that returning a value is part
of the call. Previously, this was a separate insn.
Modified files:
trunk/priv/host_s390_defs.c
trunk/priv/host_s390_defs.h
trunk/priv/host_s390_isel.c
Modified: trunk/priv/host_s390_isel.c (+11 -15)
===================================================================
--- trunk/priv/host_s390_isel.c 2012-05-27 17:18:13 +01:00 (rev 2355)
+++ trunk/priv/host_s390_isel.c 2012-05-27 17:52:43 +01:00 (rev 2356)
@@ -450,7 +450,7 @@
*/
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;
@@ -507,7 +507,7 @@
/* Finally, the call itself. */
addInstr(env, s390_insn_helper_call(cc, (Addr64)target, n_args,
- callee->name));
+ callee->name, dst));
}
@@ -1325,11 +1325,7 @@
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;
}
@@ -2417,6 +2413,7 @@
IRType retty;
IRDirty* d = stmt->Ist.Dirty.details;
Bool passBBP;
+ HReg dst;
Int i;
/* Invalidate tracked values of those guest state registers that are
@@ -2434,20 +2431,19 @@
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;
Modified: trunk/priv/host_s390_defs.h (+2 -1)
===================================================================
--- trunk/priv/host_s390_defs.h 2012-05-27 17:18:13 +01:00 (rev 2355)
+++ trunk/priv/host_s390_defs.h 2012-05-27 17:52:43 +01:00 (rev 2356)
@@ -353,6 +353,7 @@
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 {
@@ -472,7 +473,7 @@
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,
Modified: trunk/priv/host_s390_defs.c (+27 -6)
===================================================================
--- trunk/priv/host_s390_defs.c 2012-05-27 17:18:13 +01:00 (rev 2355)
+++ trunk/priv/host_s390_defs.c 2012-05-27 17:52:43 +01:00 (rev 2356)
@@ -624,6 +624,8 @@
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) {
@@ -849,6 +851,8 @@
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:
@@ -4332,7 +4336,7 @@
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));
@@ -4342,6 +4346,7 @@
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;
}
@@ -4939,11 +4944,20 @@
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 */
}
@@ -6739,6 +6753,13 @@
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
|