static void pa_asm_out_destructor (rtx, int);
#endif
static void pa_init_builtins (void);
+static rtx hppa_builtin_saveregs (void);
static void copy_fp_args (rtx) ATTRIBUTE_UNUSED;
static int length_fp_args (rtx) ATTRIBUTE_UNUSED;
static struct deferred_plabel *get_plabel (const char *)
#ifdef HPUX_LONG_DOUBLE_LIBRARY
static void pa_hpux_init_libfuncs (void);
#endif
+static rtx pa_struct_value_rtx (tree, int);
/* Save the operands last given to a compare for use when we
generate a scc or bcc insn. */
#define TARGET_INIT_LIBFUNCS pa_hpux_init_libfuncs
#endif
+#undef TARGET_PROMOTE_FUNCTION_RETURN
+#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
+
+#undef TARGET_STRUCT_VALUE_RTX
+#define TARGET_STRUCT_VALUE_RTX pa_struct_value_rtx
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY pa_return_in_memory
+
+#undef TARGET_EXPAND_BUILTIN_SAVEREGS
+#define TARGET_EXPAND_BUILTIN_SAVEREGS hppa_builtin_saveregs
+
struct gcc_target targetm = TARGET_INITIALIZER;
\f
void
if (register_operand (op, mode))
return 1;
- if (GET_CODE (op) == CONSTANT_P_RTX)
- return 1;
-
if (GET_CODE (op) == CONST_INT)
return cint_ok_for_move (INTVAL (op));
if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
&& shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))
- && (GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == 'o'
+ && (OBJECT_P (XEXP (x, 1))
|| GET_CODE (XEXP (x, 1)) == SUBREG)
&& GET_CODE (XEXP (x, 1)) != CONST)
{
We have to do this because the REG_POINTER flag is not correctly
carried through various optimization passes and CSE may substitute
a pseudo without the pointer set for one with the pointer set. As
- a result, we loose various opportunites to create insns with
+ a result, we loose various opportunities to create insns with
unscaled indexed addresses. */
if (!TARGET_NO_SPACE_REGS
&& !cse_not_expected
{
rtx insn, temp;
rtx op1 = operand1;
- HOST_WIDE_INT value = INTVAL (operand1);
+ HOST_WIDE_INT value = 0;
HOST_WIDE_INT insv = 0;
int insert = 0;
+ if (GET_CODE (operand1) == CONST_INT)
+ value = INTVAL (operand1);
+
if (TARGET_64BIT
&& GET_CODE (operand1) == CONST_INT
&& HOST_BITS_PER_WIDE_INT > 32
\f
/* Return the best assembler insn template
- for moving operands[1] into operands[0] as a fullword. */
+ for moving operands[1] into operands[0] as a fullword. */
const char *
singlemove_string (rtx *operands)
{
OPERANDS[3] is a register for temporary storage.
OPERANDS[4] is the size as a CONST_INT
OPERANDS[5] is the alignment safe to use, as a CONST_INT.
- OPERANDS[6] is another temporary register. */
+ OPERANDS[6] is another temporary register. */
const char *
output_block_move (rtx *operands, int size_is_constant ATTRIBUTE_UNUSED)
{
int i;
int chars_output;
- unsigned char partial_output[16]; /* Max space 4 chars can occupy. */
+ unsigned char partial_output[16]; /* Max space 4 chars can occupy. */
/* The HP assembler can only take strings of 256 characters at one
time. This is a limitation on input line length, *not* the
emit_move_insn (gen_rtx_REG (SImode, 26), operands[1]);
emit
- (gen_rtx
- (PARALLEL, VOIDmode,
+ (gen_rtx_PARALLEL
+ (VOIDmode,
gen_rtvec (6, gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, 29),
gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
SImode,
to determine if stdargs or varargs is used and fill in an initial
va_list. A pointer to this constructor is returned. */
-struct rtx_def *
+static rtx
hppa_builtin_saveregs (void)
{
rtx offset, dest;
else
{
/* Reload loop counter from memory, the store back to memory
- happens in the branch's delay slot. */
+ happens in the branch's delay slot. */
output_asm_insn ("ldw %0,%4", operands);
if (get_attr_length (insn) == 12)
return "addib,%C2 %1,%4,%3\n\tstw %4,%0";
else if (which_alternative == 2)
{
/* Reload loop counter from memory, the store back to memory
- happens in the branch's delay slot. */
+ happens in the branch's delay slot. */
if (get_attr_length (insn) == 8)
return "{comb|cmpb},%S2 %%r0,%1,%3\n\tstw %1,%0";
else
markers disables output of the branch table to readonly memory,
and any alignment directives that might be needed. Possibly,
the begin_brtab insn should be output before the label for the
- table. This doesn matter at the moment since the tables are
+ table. This doesn't matter at the moment since the tables are
always output in the text section. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
the mode is SF or DF. Then the value is returned in fr4 (32).
This must perform the same promotions as PROMOTE_MODE, else
- PROMOTE_FUNCTION_RETURN will not work correctly.
+ TARGET_PROMOTE_FUNCTION_RETURN will not work correctly.
Small structures must be returned in a PARALLEL on PA64 in order
to match the HP Compiler ABI. */
&& !reloc)
readonly_data_section ();
else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c'
- && !(TREE_CODE (exp) == STRING_CST && flag_writable_strings)
&& !reloc)
readonly_data_section ();
else
fputs (",DATA\n", stream);
}
}
+
+/* Worker function for TARGET_STRUCT_VALUE_RTX. */
+
+static rtx
+pa_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+ int incoming ATTRIBUTE_UNUSED)
+{
+ return gen_rtx_REG (Pmode, PA_STRUCT_VALUE_REGNUM);
+}
+
+/* Worker function for TARGET_RETURN_IN_MEMORY. */
+
+bool
+pa_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
+{
+ /* SOM ABI says that objects larger than 64 bits are returned in memory.
+ PA64 ABI says that objects larger than 128 bits are returned in memory.
+ Note, int_size_in_bytes can return -1 if the size of the object is
+ variable or larger than the maximum value that can be expressed as
+ a HOST_WIDE_INT. It can also return zero for an empty type. The
+ simplest way to handle variable and empty types is to pass them in
+ memory. This avoids problems in defining the boundaries of argument
+ slots, allocating registers, etc. */
+ return (int_size_in_bytes (type) > (TARGET_64BIT ? 16 : 8)
+ || int_size_in_bytes (type) <= 0);
+}
+
#include "gt-pa.h"