Commit 0d7839da by Steve Ellcey Committed by Janis Johnson

tm.texi (FUNCTION_ARG_REG_LITTLE_ENDIAN): New.

2001-12-11  Steve Ellcey  <sje@cup.hp.com>

	* doc/tm.texi (FUNCTION_ARG_REG_LITTLE_ENDIAN): New.
	* defaults.h (FUNCTION_ARG_REG_LITTLE_ENDIAN): New.
	* calls.c (store_unaligned_arguments_into_pseudos): Check
	FUNCTION_ARG_REG_LITTLE_ENDIAN to see how structures
	are passed/returned.
	* expr.c (move_block_from_reg): Ditto.
	(move_block_from_reg): Ditto.
	(copy_blkmode_from_reg): Ditto.
	* stmt.c (expand_return): Ditto.
	* stor-layout.c (compute_record_mode): If
	FUNCTION_ARG_REG_LITTLE_ENDIAN is set then check
	MEMBER_TYPE_FORCES_BLK even if mode == VOIDmode.
	* config/ia64/hpux.h (MEMBER_TYPE_FORCES_BLK): Set to true
	so that Structures of one field are still treated as structures.
	(FUNCTION_ARG_REG_LITTLE_ENDIAN): New, set it to true.
	(FUNCTION_ARG_PADDING): Set to ia64_hpux_function_arg_padding().
	(PAD_VARARGS_DOWN): Modify from default to not pad structures down.
	* config/ia64/ia64-protos.h (ia64_hpux_function_arg_padding): New.
	* config/ia64/ia64.c (ia64_hpux_function_arg_padding): New function
	to special case handling of structure padding.

From-SVN: r47904
parent 81deb0a3
2001-12-11 Steve Ellcey <sje@cup.hp.com>
* doc/tm.texi (FUNCTION_ARG_REG_LITTLE_ENDIAN): New.
* defaults.h (FUNCTION_ARG_REG_LITTLE_ENDIAN): New.
* calls.c (store_unaligned_arguments_into_pseudos): Check
FUNCTION_ARG_REG_LITTLE_ENDIAN to see how structures
are passed/returned.
* expr.c (move_block_from_reg): Ditto.
(move_block_from_reg): Ditto.
(copy_blkmode_from_reg): Ditto.
* stmt.c (expand_return): Ditto.
* stor-layout.c (compute_record_mode): If
FUNCTION_ARG_REG_LITTLE_ENDIAN is set then check
MEMBER_TYPE_FORCES_BLK even if mode == VOIDmode.
* config/ia64/hpux.h (MEMBER_TYPE_FORCES_BLK): Set to true
so that Structures of one field are still treated as structures.
(FUNCTION_ARG_REG_LITTLE_ENDIAN): New, set it to true.
(FUNCTION_ARG_PADDING): Set to ia64_hpux_function_arg_padding().
(PAD_VARARGS_DOWN): Modify from default to not pad structures down.
* config/ia64/ia64-protos.h (ia64_hpux_function_arg_padding): New.
* config/ia64/ia64.c (ia64_hpux_function_arg_padding): New function
to special case handling of structure padding.
2001-12-11 Daniel Berlin <dan@cgsoftware.com> 2001-12-11 Daniel Berlin <dan@cgsoftware.com>
* sched-rgn.c (CONST_BASED_ADDRESS_P): CONST_INT -> CONSTANT_P. * sched-rgn.c (CONST_BASED_ADDRESS_P): CONST_INT -> CONSTANT_P.
......
...@@ -1029,7 +1029,9 @@ store_unaligned_arguments_into_pseudos (args, num_actuals) ...@@ -1029,7 +1029,9 @@ store_unaligned_arguments_into_pseudos (args, num_actuals)
significant byte (to the right). On a BYTES_BIG_ENDIAN machine, significant byte (to the right). On a BYTES_BIG_ENDIAN machine,
this means we must skip the empty high order bytes when this means we must skip the empty high order bytes when
calculating the bit offset. */ calculating the bit offset. */
if (BYTES_BIG_ENDIAN && bytes < UNITS_PER_WORD) if (BYTES_BIG_ENDIAN
&& !FUNCTION_ARG_REG_LITTLE_ENDIAN
&& bytes < UNITS_PER_WORD)
big_endian_correction = (BITS_PER_WORD - (bytes * BITS_PER_UNIT)); big_endian_correction = (BITS_PER_WORD - (bytes * BITS_PER_UNIT));
for (j = 0; j < args[i].n_aligned_regs; j++) for (j = 0; j < args[i].n_aligned_regs; j++)
......
...@@ -95,3 +95,30 @@ Boston, MA 02111-1307, USA. */ ...@@ -95,3 +95,30 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_DEFAULT #undef TARGET_DEFAULT
#define TARGET_DEFAULT (MASK_DWARF2_ASM | MASK_BIG_ENDIAN) #define TARGET_DEFAULT (MASK_DWARF2_ASM | MASK_BIG_ENDIAN)
/* This needs to be set to force structure arguments with a single
field to be treated as structures and not as the type of their
field. Without this a structure with a single char will be
returned just like a char variable and that is wrong on HP-UX
IA64. TARGET_STRUCT_ARG_REG_LITTLE_ENDIAN triggers the special
structure handling, this macro simply ensures that single field
structures are always treated like structures. */
#define MEMBER_TYPE_FORCES_BLK(FIELD) 1
/* Override the setting of FUNCTION_ARG_REG_LITTLE_ENDIAN in
defaults.h. Setting this to true means that we are not passing
structures in registers in the "normal" big-endian way. See
See section 8.5 of the "Itanium Software Conventions and Runtime
Architecture", specifically Table 8-1 and the explanation of Byte 0
alignment and LSB alignment and a description of how structures
are passed. */
#define FUNCTION_ARG_REG_LITTLE_ENDIAN 1
#undef FUNCTION_ARG_PADDING
#define FUNCTION_ARG_PADDING(MODE, TYPE) \
ia64_hpux_function_arg_padding ((MODE), (TYPE))
#undef PAD_VARARGS_DOWN
#define PAD_VARARGS_DOWN (!AGGREGATE_TYPE_P (type))
...@@ -134,3 +134,8 @@ extern void sdata_section PARAMS ((void)); ...@@ -134,3 +134,8 @@ extern void sdata_section PARAMS ((void));
#ifdef SBSS_SECTION_ASM_OP #ifdef SBSS_SECTION_ASM_OP
extern void sbss_section PARAMS ((void)); extern void sbss_section PARAMS ((void));
#endif #endif
#ifdef ARGS_SIZE_RTX
/* expr.h defines ARGS_SIZE_RTX and `enum direction'. */
extern enum direction ia64_hpux_function_arg_padding PARAMS ((enum machine_mode, tree));
#endif /* ARGS_SIZE_RTX */
...@@ -7724,3 +7724,27 @@ ia64_expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -7724,3 +7724,27 @@ ia64_expand_builtin (exp, target, subtarget, mode, ignore)
return NULL_RTX; return NULL_RTX;
} }
/* For the HP-UX IA64 aggregate parameters are passed stored in the
most significant bits of the stack slot. */
enum direction
ia64_hpux_function_arg_padding (mode, type)
enum machine_mode mode;
tree type;
{
/* Exception to normal case for structures/unions/etc. */
if (type && AGGREGATE_TYPE_P (type)
&& int_size_in_bytes (type) < UNITS_PER_WORD)
return upward;
/* This is the standard FUNCTION_ARG_PADDING with !BYTES_BIG_ENDIAN
hardwired to be true. */
return((mode == BLKmode
? (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
&& int_size_in_bytes (type) < (PARM_BOUNDARY / BITS_PER_UNIT))
: GET_MODE_BITSIZE (mode) < PARM_BOUNDARY)
? downward : upward);
}
...@@ -457,4 +457,14 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE! ...@@ -457,4 +457,14 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
#define PREFERRED_DEBUGGING_TYPE NO_DEBUG #define PREFERRED_DEBUGGING_TYPE NO_DEBUG
#endif #endif
/* This is set to 1 if BYTES_BIG_ENDIAN is defined but the target uses a
little-endian method of passing and returning structures in registers.
On the HP-UX IA64 and PA64 platforms structures are aligned differently
then integral values and setting this value to 1 will allow for the
special handling of structure arguments and return values in regs. */
#ifndef FUNCTION_ARG_REG_LITTLE_ENDIAN
#define FUNCTION_ARG_REG_LITTLE_ENDIAN 0
#endif
#endif /* ! GCC_DEFAULTS_H */ #endif /* ! GCC_DEFAULTS_H */
...@@ -3435,6 +3435,14 @@ nonzero, the caller does not make a copy. Instead, it passes a pointer to the ...@@ -3435,6 +3435,14 @@ nonzero, the caller does not make a copy. Instead, it passes a pointer to the
determined that the value won't be modified, it need not make a copy; determined that the value won't be modified, it need not make a copy;
otherwise a copy must be made. otherwise a copy must be made.
@findex FUNCTION_ARG_REG_LITTLE_ENDIAN
@item FUNCTION_ARG_REG_LITTLE_ENDIAN
If defined TRUE on a big-endian system then structure arguments passed
(and returned) in registers are passed in a little-endian manner instead of
the big-endian manner. On the HP-UX IA64 and PA64 platforms structures are
aligned differently then integral values and setting this value to true will
allow for the special handling of structure arguments and return values.
@findex CUMULATIVE_ARGS @findex CUMULATIVE_ARGS
@item CUMULATIVE_ARGS @item CUMULATIVE_ARGS
A C type for declaring a variable that is used as the first argument of A C type for declaring a variable that is used as the first argument of
......
...@@ -1868,7 +1868,8 @@ move_block_from_reg (regno, x, nregs, size) ...@@ -1868,7 +1868,8 @@ move_block_from_reg (regno, x, nregs, size)
/* If SIZE is that of a mode no bigger than a word, just use that /* If SIZE is that of a mode no bigger than a word, just use that
mode's store operation. */ mode's store operation. */
if (size <= UNITS_PER_WORD if (size <= UNITS_PER_WORD
&& (mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0)) != BLKmode) && (mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0)) != BLKmode
&& !FUNCTION_ARG_REG_LITTLE_ENDIAN)
{ {
emit_move_insn (adjust_address (x, mode, 0), gen_rtx_REG (mode, regno)); emit_move_insn (adjust_address (x, mode, 0), gen_rtx_REG (mode, regno));
return; return;
...@@ -1877,7 +1878,9 @@ move_block_from_reg (regno, x, nregs, size) ...@@ -1877,7 +1878,9 @@ move_block_from_reg (regno, x, nregs, size)
/* Blocks smaller than a word on a BYTES_BIG_ENDIAN machine must be aligned /* Blocks smaller than a word on a BYTES_BIG_ENDIAN machine must be aligned
to the left before storing to memory. Note that the previous test to the left before storing to memory. Note that the previous test
doesn't handle all cases (e.g. SIZE == 3). */ doesn't handle all cases (e.g. SIZE == 3). */
if (size < UNITS_PER_WORD && BYTES_BIG_ENDIAN) if (size < UNITS_PER_WORD
&& BYTES_BIG_ENDIAN
&& !FUNCTION_ARG_REG_LITTLE_ENDIAN)
{ {
rtx tem = operand_subword (x, 0, 1, BLKmode); rtx tem = operand_subword (x, 0, 1, BLKmode);
rtx shift; rtx shift;
...@@ -2162,15 +2165,25 @@ copy_blkmode_from_reg (tgtblk, srcreg, type) ...@@ -2162,15 +2165,25 @@ copy_blkmode_from_reg (tgtblk, srcreg, type)
/* This code assumes srcreg is at least a full word. If it isn't, /* This code assumes srcreg is at least a full word. If it isn't,
copy it into a new pseudo which is a full word. */ copy it into a new pseudo which is a full word. */
/* If FUNCTION_ARG_REG_LITTLE_ENDIAN is set and convert_to_mode does
a copy, the wrong part of the register gets copied so we fake
a type conversion in place. */
if (GET_MODE (srcreg) != BLKmode if (GET_MODE (srcreg) != BLKmode
&& GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD) && GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD)
if (FUNCTION_ARG_REG_LITTLE_ENDIAN)
srcreg = simplify_gen_subreg (word_mode, srcreg, GET_MODE (srcreg), 0);
else
srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type)); srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type));
/* Structures whose size is not a multiple of a word are aligned /* Structures whose size is not a multiple of a word are aligned
to the least significant byte (to the right). On a BYTES_BIG_ENDIAN to the least significant byte (to the right). On a BYTES_BIG_ENDIAN
machine, this means we must skip the empty high order bytes when machine, this means we must skip the empty high order bytes when
calculating the bit offset. */ calculating the bit offset. */
if (BYTES_BIG_ENDIAN && bytes % UNITS_PER_WORD) if (BYTES_BIG_ENDIAN
&& !FUNCTION_ARG_REG_LITTLE_ENDIAN
&& bytes % UNITS_PER_WORD)
big_endian_correction big_endian_correction
= (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT)); = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT));
......
...@@ -3197,7 +3197,9 @@ expand_return (retval) ...@@ -3197,7 +3197,9 @@ expand_return (retval)
to the least significant byte (to the right). On a BYTES_BIG_ENDIAN to the least significant byte (to the right). On a BYTES_BIG_ENDIAN
machine, this means we must skip the empty high order bytes when machine, this means we must skip the empty high order bytes when
calculating the bit offset. */ calculating the bit offset. */
if (BYTES_BIG_ENDIAN && bytes % UNITS_PER_WORD) if (BYTES_BIG_ENDIAN
&& !FUNCTION_ARG_REG_LITTLE_ENDIAN
&& bytes % UNITS_PER_WORD)
big_endian_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) big_endian_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
* BITS_PER_UNIT)); * BITS_PER_UNIT));
......
...@@ -1149,7 +1149,17 @@ compute_record_mode (type) ...@@ -1149,7 +1149,17 @@ compute_record_mode (type)
#ifdef MEMBER_TYPE_FORCES_BLK #ifdef MEMBER_TYPE_FORCES_BLK
/* With some targets, eg. c4x, it is sub-optimal /* With some targets, eg. c4x, it is sub-optimal
to access an aligned BLKmode structure as a scalar. */ to access an aligned BLKmode structure as a scalar. */
if (mode == VOIDmode && MEMBER_TYPE_FORCES_BLK (field))
/* On ia64-*-hpux we need to ensure that we don't change the
mode of a structure containing a single field or else we
will pass it incorrectly. Since a structure with a single
field causes mode to get set above we can't allow the
check for mode == VOIDmode in this case. Perhaps
MEMBER_TYPE_FORCES_BLK should be extended to include mode
as an argument and the check could be put in there for c4x. */
if ((mode == VOIDmode || FUNCTION_ARG_REG_LITTLE_ENDIAN)
&& MEMBER_TYPE_FORCES_BLK (field))
return; return;
#endif /* MEMBER_TYPE_FORCES_BLK */ #endif /* MEMBER_TYPE_FORCES_BLK */
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment