This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
ia64-hpux fix compat/struct-by-value-5
- From: "Zack Weinberg" <zack at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Jim Wilson <wilson at specifixinc dot com>
- Date: Tue, 17 Feb 2004 00:16:06 -0800
- Subject: ia64-hpux fix compat/struct-by-value-5
On a big-endian ia64 target, the type (struct { float x; }), when
passed as an anonymous (variadic) function argument, is supposed to be
put in the integer registers and padded at the low end of the
register: XXXX XXXX 0000 0000. GCC (3.4 and HEAD) expects the
argument in that position, but passes it as 0000 0000 XXXX XXXX,
which is the correct position for a little-endian ia64 target.
This patch fixes the problem, but I do not understand why it works;
I discovered the idiom by staring at other parts of ia64_function_arg.
ia64-hpux bootstrap in progress; comments?
zw
* config/ia64/ia64.c (ia64_function_arg): In big-endian mode,
when passing single SFmode quantities in general registers,
put them in the high half.
===================================================================
Index: config/ia64/ia64.c
--- config/ia64/ia64.c 31 Jan 2004 06:18:23 -0000 1.265.2.2
+++ config/ia64/ia64.c 17 Feb 2004 08:15:30 -0000
@@ -3748,21 +3748,34 @@ ia64_function_arg (CUMULATIVE_ARGS *cum,
named, and in a GR register when unnamed. */
else if (cum->prototype)
{
- if (! named)
- return gen_rtx_REG (mode, basereg + cum->words + offset);
- else
+ if (named)
return gen_rtx_REG (mode, FR_ARG_FIRST + cum->fp_regs);
+ /* In big-endian mode, an anonymous SFmode value must be represented
+ as (parallel:SF [(expr_list (reg:DI n) (const_int 0))]) to force
+ the value into the high half of the general register. */
+ else if (BYTES_BIG_ENDIAN && mode == SFmode)
+ return gen_rtx_PARALLEL (mode,
+ gen_rtvec (1,
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (DImode, basereg + cum->words + offset),
+ const0_rtx)));
+ else
+ return gen_rtx_REG (mode, basereg + cum->words + offset);
}
/* If there is no prototype, then FP values go in both FR and GR
registers. */
else
{
+ /* See comment above. */
+ enum machine_mode inner_mode =
+ (BYTES_BIG_ENDIAN && mode == SFmode) ? DImode : mode;
+
rtx fp_reg = gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (mode, (FR_ARG_FIRST
+ cum->fp_regs)),
const0_rtx);
rtx gr_reg = gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (mode,
+ gen_rtx_REG (inner_mode,
(basereg + cum->words
+ offset)),
const0_rtx);