===================================================================
@@ -3481,6 +3481,7 @@ emit_library_call_value_1 (int retval, r
{
rtx val = va_arg (p, rtx);
enum machine_mode mode = (enum machine_mode) va_arg (p, int);
+ int unsigned_p = 0;
/* We cannot convert the arg value to the mode the library wants here;
must do it earlier where we know the signedness of the arg. */
@@ -3528,9 +3529,9 @@ emit_library_call_value_1 (int retval, r
val = force_operand (XEXP (slot, 0), NULL_RTX);
}
- argvec[count].value = val;
+ mode = promote_libcall_mode (mode, &unsigned_p, fntype, 1);
argvec[count].mode = mode;
-
+ argvec[count].value = convert_modes (mode, GET_MODE (val), val, unsigned_p);
argvec[count].reg = targetm.calls.function_arg (&args_so_far, mode,
NULL_TREE, true);
===================================================================
@@ -968,6 +968,15 @@ also define the hook to @code{default_pr
if you would like to apply the same rules given by @code{PROMOTE_MODE}.
@end deftypefn
+@hook TARGET_PROMOTE_LIBCALL_MODE
+Like @code{TARGET_PROMOTE_FUNCTION_MODE}, but it is applied to libcall
+arguments only. Define this if your target requires function
+arguments to be promoted to a larger mode and uses C compiled libcall
+routines (e.g. libdecnumber).
+
+The default is not promote arguments and return values.
+@end deftypefn
+
@defmac PARM_BOUNDARY
Normal alignment required for function parameters on the stack, in
bits. All stack parameters receive at least this much alignment
===================================================================
@@ -783,6 +783,25 @@ promote_function_mode (const_tree type,
return mode;
}
}
+
+/* Return the mode to use to pass or return a scalar of MODE for a libcall.
+ PUNSIGNEDP points to the signedness of the type and may be adjusted
+ to show what signedness to use on extension operations.
+
+ FOR_RETURN is nonzero if the caller is promoting the return value
+ of FNDECL, else it is for promoting args. */
+
+enum machine_mode
+promote_libcall_mode (enum machine_mode mode, int *punsignedp,
+ const_tree funtype, int for_return)
+{
+ if (INTEGRAL_MODE_P (mode))
+ return targetm.calls.promote_libcall_mode (mode, punsignedp, funtype,
+ for_return);
+ else
+ return mode;
+}
+
/* Return the mode to use to store a scalar of TYPE and MODE.
PUNSIGNEDP points to the signedness of the type and may be adjusted
to show what signedness to use on extension operations. */
===================================================================
@@ -613,6 +613,11 @@ extern rtx force_not_mem (rtx);
extern enum machine_mode promote_function_mode (const_tree, enum machine_mode, int *,
const_tree, int);
+/* Return mode and signedness to use when an libcall argument or
+ result in the given mode is promoted. */
+extern enum machine_mode promote_libcall_mode (enum machine_mode, int *,
+ const_tree, int);
+
/* Return mode and signedness to use when an object in the given mode
is promoted. */
extern enum machine_mode promote_mode (const_tree, enum machine_mode, int *);
===================================================================
@@ -1918,6 +1918,13 @@ DEFHOOK
default_promote_function_mode)
DEFHOOK
+(promote_libcall_mode,
+ "",
+ enum machine_mode, (enum machine_mode mode, int *punsignedp,
+ const_tree funtype, int for_return),
+ default_promote_libcall_mode)
+
+DEFHOOK
(promote_prototypes,
"",
bool, (const_tree fntype),
===================================================================
@@ -139,6 +139,15 @@ default_promote_function_mode_always_pro
return promote_mode (type, mode, punsignedp);
}
+enum machine_mode
+default_promote_libcall_mode (enum machine_mode mode,
+ int *punsignedp ATTRIBUTE_UNUSED,
+ const_tree funtype ATTRIBUTE_UNUSED,
+ int for_return ATTRIBUTE_UNUSED)
+{
+ return mode;
+}
+
enum machine_mode
default_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
===================================================================
@@ -28,6 +28,8 @@ extern enum machine_mode default_promote
int *, const_tree, int);
extern enum machine_mode default_promote_function_mode_always_promote
(const_tree, enum machine_mode, int *, const_tree, int);
+extern enum machine_mode default_promote_libcall_mode (enum machine_mode,
+ int *, const_tree, int);
extern enum machine_mode default_cc_modes_compatible (enum machine_mode,
enum machine_mode);
===================================================================
@@ -8687,6 +8687,20 @@ s390_promote_function_mode (const_tree t
return mode;
}
+/* Libcall arguments and return values are promoted to word size. */
+
+static enum machine_mode
+s390_promote_libcall_mode (enum machine_mode mode,
+ int *punsignedp ATTRIBUTE_UNUSED,
+ const_tree fntype ATTRIBUTE_UNUSED,
+ int for_return ATTRIBUTE_UNUSED)
+{
+ if (GET_MODE_SIZE (mode) < UNITS_PER_LONG)
+ return Pmode;
+
+ return mode;
+}
+
/* Define where to return a (scalar) value of type TYPE.
If TYPE is null, define where to return a (scalar)
value of mode MODE from a libcall. */
@@ -10685,6 +10699,9 @@ s390_loop_unroll_adjust (unsigned nunrol
#undef TARGET_PROMOTE_FUNCTION_MODE
#define TARGET_PROMOTE_FUNCTION_MODE s390_promote_function_mode
+#undef TARGET_PROMOTE_LIBCALL_MODE
+#define TARGET_PROMOTE_LIBCALL_MODE s390_promote_libcall_mode
+
#undef TARGET_PASS_BY_REFERENCE
#define TARGET_PASS_BY_REFERENCE s390_pass_by_reference
===================================================================
@@ -978,6 +978,15 @@ also define the hook to @code{default_pr
if you would like to apply the same rules given by @code{PROMOTE_MODE}.
@end deftypefn
+@deftypefn {Target Hook} {enum machine_mode} TARGET_PROMOTE_LIBCALL_MODE (enum machine_mode @var{mode}, int *@var{punsignedp}, const_tree @var{funtype}, int @var{for_return})
+Like @code{TARGET_PROMOTE_FUNCTION_MODE}, but it is applied to libcall
+arguments only. Define this if your target requires function
+arguments to be promoted to a larger mode and uses C compiled libcall
+routines (e.g. libdecnumber).
+
+The default is not promote arguments and return values.
+@end deftypefn
+
@defmac PARM_BOUNDARY
Normal alignment required for function parameters on the stack, in
bits. All stack parameters receive at least this much alignment