/* Subroutines for insn-output.c for Matsushita MN10300 series
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
Contributed by Jeff Law (law@cygnus.com).
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
|| regs_ever_live[16] || regs_ever_live[17]))
-static int mn10300_address_cost_1 PARAMS ((rtx, int *));
-static int mn10300_address_cost PARAMS ((rtx));
-static bool mn10300_rtx_costs PARAMS ((rtx, int, int, int *));
-static void mn10300_file_start PARAMS ((void));
-
+static int mn10300_address_cost_1 (rtx, int *);
+static int mn10300_address_cost (rtx);
+static bool mn10300_rtx_costs (rtx, int, int, int *);
+static void mn10300_file_start (void);
+static bool mn10300_return_in_memory (tree, tree);
+static rtx mn10300_builtin_saveregs (void);
+static bool mn10300_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
+ tree, bool);
\f
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
#undef TARGET_ENCODE_SECTION_INFO
#define TARGET_ENCODE_SECTION_INFO mn10300_encode_section_info
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY mn10300_return_in_memory
+#undef TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE mn10300_pass_by_reference
+#undef TARGET_CALLEE_COPIES
+#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
+
+#undef TARGET_EXPAND_BUILTIN_SAVEREGS
+#define TARGET_EXPAND_BUILTIN_SAVEREGS mn10300_builtin_saveregs
+
static void mn10300_encode_section_info (tree, rtx, int);
struct gcc_target targetm = TARGET_INITIALIZER;
\f
static void
-mn10300_file_start ()
+mn10300_file_start (void)
{
default_file_start ();
FILE. */
void
-print_operand (file, x, code)
- FILE *file;
- rtx x;
- int code;
+print_operand (FILE *file, rtx x, int code)
{
switch (code)
{
case 'A':
fputc ('(', file);
if (GET_CODE (XEXP (x, 0)) == REG)
- output_address (gen_rtx_PLUS (SImode, XEXP (x, 0), GEN_INT (0)));
+ output_address (gen_rtx_PLUS (SImode, XEXP (x, 0), const0_rtx));
else
output_address (XEXP (x, 0));
fputc (')', file);
/* Output assembly language output for the address ADDR to FILE. */
void
-print_operand_address (file, addr)
- FILE *file;
- rtx addr;
+print_operand_address (FILE *file, rtx addr)
{
switch (GET_CODE (addr))
{
/* Count the number of FP registers that have to be saved. */
static int
-fp_regs_to_save ()
+fp_regs_to_save (void)
{
int i, n = 0;
Register K is saved if bit K of MASK is set. The data and address
registers can be stored individually, but the extended registers cannot.
We assume that the mask alread takes that into account. For instance,
- bits 14 to 17 must have the same value. */
+ bits 14 to 17 must have the same value. */
void
-mn10300_print_reg_list (file, mask)
- FILE *file;
- int mask;
+mn10300_print_reg_list (FILE *file, int mask)
{
int need_comma;
int i;
}
int
-can_use_return_insn ()
+can_use_return_insn (void)
{
/* size includes the fixed stack space needed for function calls. */
int size = get_frame_size () + current_function_outgoing_args_size;
/* Returns the set of live, callee-saved registers as a bitmask. The
callee-saved extended registers cannot be stored individually, so
- all of them will be included in the mask if any one of them is used. */
+ all of them will be included in the mask if any one of them is used. */
int
-mn10300_get_live_callee_saved_regs ()
+mn10300_get_live_callee_saved_regs (void)
{
int mask;
int i;
(reg:SI R1))) */
void
-mn10300_gen_multiple_store (mask)
- int mask;
+mn10300_gen_multiple_store (int mask)
{
if (mask != 0)
{
rtx par;
int pari;
- /* Count how many registers need to be saved. */
+ /* Count how many registers need to be saved. */
count = 0;
for (i = 0; i <= LAST_EXTENDED_REGNUM; i++)
if ((mask & (1 << i)) != 0)
count += 1;
/* We need one PARALLEL element to update the stack pointer and
- an additional element for each register that is stored. */
+ an additional element for each register that is stored. */
par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count + 1));
- /* Create the instruction that updates the stack pointer. */
+ /* Create the instruction that updates the stack pointer. */
XVECEXP (par, 0, 0)
= gen_rtx_SET (SImode,
stack_pointer_rtx,
stack_pointer_rtx,
GEN_INT (-count * 4)));
- /* Create each store. */
+ /* Create each store. */
pari = 1;
for (i = LAST_EXTENDED_REGNUM; i >= 0; i--)
if ((mask & (1 << i)) != 0)
}
void
-expand_prologue ()
+expand_prologue (void)
{
HOST_WIDE_INT size;
size = get_frame_size () + current_function_outgoing_args_size;
size += (current_function_outgoing_args_size ? 4 : 0);
- /* If we use any of the callee-saved registers, save them now. */
+ /* If we use any of the callee-saved registers, save them now. */
mn10300_gen_multiple_store (mn10300_get_live_callee_saved_regs ());
if (TARGET_AM33_2 && fp_regs_to_save ())
#define SIZE_FMOV_SP(S,N) (SIZE_FMOV_SP_ ((unsigned HOST_WIDE_INT)(S), (N)))
/* Consider alternative save_sp_merge only if we don't need the
- frame pointer and size is non-zero. */
+ frame pointer and size is nonzero. */
if (! frame_pointer_needed && size)
{
/* Insn: add -(size + 4 * num_regs_to_save), sp. */
}
/* Consider alternative save_a0_merge only if we don't need a
- frame pointer, size is non-zero and the user hasn't
+ frame pointer, size is nonzero and the user hasn't
changed the calling conventions of a0. */
if (! frame_pointer_needed && size
&& call_used_regs[FIRST_ADDRESS_REGNUM]
}
/* Consider alternative save_a0_no_merge if the user hasn't
- changed the calling conventions of a0. */
+ changed the calling conventions of a0. */
if (call_used_regs[FIRST_ADDRESS_REGNUM]
&& ! fixed_regs[FIRST_ADDRESS_REGNUM])
{
stack_pointer_rtx,
GEN_INT (-(size + 4 * num_regs_to_save))));
/* We'll have to adjust FP register saves according to the
- frame size. */
+ frame size. */
xsize = size;
/* Since we've already created the stack frame, don't do it
- again at the end of the function. */
+ again at the end of the function. */
size = 0;
break;
}
void
-expand_epilogue ()
+expand_epilogue (void)
{
HOST_WIDE_INT size;
/* Insn: fmov (##,sp),fs#, for each fs# to be restored. */
this_strategy_size += SIZE_FMOV_SP (0, num_regs_to_save);
/* We're going to use ret to release the FP registers
- save area, so, no savings. */
+ save area, so, no savings. */
if (this_strategy_size < strategy_size)
{
- 4 * num_regs_to_save,
num_regs_to_save);
/* We're going to use ret to release the FP registers
- save area, so, no savings. */
+ save area, so, no savings. */
if (this_strategy_size < strategy_size)
{
else if (size)
{
/* If we aren't using a post-increment register, use an
- SP offset. */
+ SP offset. */
addr = gen_rtx_PLUS (SImode,
stack_pointer_rtx,
GEN_INT (size));
/* Update the condition code from the insn. */
void
-notice_update_cc (body, insn)
- rtx body;
- rtx insn;
+notice_update_cc (rtx body, rtx insn)
{
switch (get_attr_cc (insn))
{
cc_status.mdep.fpCC = 1;
break;
- case CC_INVERT:
- /* The insn is a compare instruction. */
- CC_STATUS_INIT;
- cc_status.value1 = SET_SRC (body);
- cc_status.flags |= CC_INVERTED;
- break;
-
case CC_CLOBBER:
/* Insn doesn't leave CC in a usable state. */
CC_STATUS_INIT;
registers it saves. Return 0 otherwise. */
int
-store_multiple_operation (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+store_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
int count;
int mask;
/* Check that A is the stack pointer and B is the expected stack size.
For OP to match, each subsequent instruction should push a word onto
the stack. We therefore expect the first instruction to create
- COUNT-1 stack slots. */
+ COUNT-1 stack slots. */
elt = SET_SRC (elt);
if (GET_CODE (XEXP (elt, 0)) != REG
|| REGNO (XEXP (elt, 0)) != STACK_POINTER_REGNUM
store a lower-numbered register to the slot below.
LAST keeps track of the smallest-numbered register stored so far.
- MASK is the set of stored registers. */
+ MASK is the set of stored registers. */
last = LAST_EXTENDED_REGNUM + 1;
mask = 0;
for (i = 1; i < count; i++)
{
- /* Check that element i is a (set (mem M) R) and that R is valid. */
+ /* Check that element i is a (set (mem M) R) and that R is valid. */
elt = XVECEXP (op, 0, i);
if (GET_CODE (elt) != SET
|| GET_CODE (SET_DEST (elt)) != MEM
return 0;
/* R was OK, so provisionally add it to MASK. We return 0 in any
- case if the rest of the instruction has a flaw. */
+ case if the rest of the instruction has a flaw. */
last = REGNO (SET_SRC (elt));
mask |= (1 << last);
return 0;
}
- /* All or none of the callee-saved extended registers must be in the set. */
+ /* All or none of the callee-saved extended registers must be in the set. */
if ((mask & 0x3c000) != 0
&& (mask & 0x3c000) != 0x3c000)
return 0;
/* Return true if OP is a valid call operand. */
int
-call_address_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+call_address_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (flag_pic)
return (EXTRA_CONSTRAINT (op, 'S') || GET_CODE (op) == REG);
We might be able to simplify this. */
enum reg_class
-secondary_reload_class (class, mode, in)
- enum reg_class class;
- enum machine_mode mode;
- rtx in;
+secondary_reload_class (enum reg_class class, enum machine_mode mode, rtx in)
{
/* Memory loads less than a full word wide can't have an
address or stack pointer destination. They must use
}
int
-initial_offset (from, to)
- int from, to;
+initial_offset (int from, int to)
{
/* The difference between the argument pointer and the frame pointer
is the size of the callee register save area. */
abort ();
}
+/* Worker function for TARGET_RETURN_IN_MEMORY. */
+
+static bool
+mn10300_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
+{
+ /* Return values > 8 bytes in length in memory. */
+ return int_size_in_bytes (type) > 8 || TYPE_MODE (type) == BLKmode;
+}
+
/* Flush the argument registers to the stack for a stdarg function;
return the new argument pointer. */
-rtx
-mn10300_builtin_saveregs ()
+static rtx
+mn10300_builtin_saveregs (void)
{
rtx offset, mem;
tree fntype = TREE_TYPE (current_function_decl);
}
void
-mn10300_va_start (valist, nextarg)
- tree valist;
- rtx nextarg;
+mn10300_va_start (tree valist, rtx nextarg)
{
nextarg = expand_builtin_saveregs ();
std_expand_builtin_va_start (valist, nextarg);
}
-rtx
-mn10300_va_arg (valist, type)
- tree valist, type;
-{
- HOST_WIDE_INT align, rsize;
- tree t, ptr, pptr;
-
- /* Compute the rounded size of the type. */
- align = PARM_BOUNDARY / BITS_PER_UNIT;
- rsize = (((int_size_in_bytes (type) + align - 1) / align) * align);
+/* Return true when a parameter should be passed by reference. */
- t = build (POSTINCREMENT_EXPR, TREE_TYPE (valist), valist,
- build_int_2 ((rsize > 8 ? 4 : rsize), 0));
- TREE_SIDE_EFFECTS (t) = 1;
-
- ptr = build_pointer_type (type);
-
- /* "Large" types are passed by reference. */
- if (rsize > 8)
- {
- pptr = build_pointer_type (ptr);
- t = build1 (NOP_EXPR, pptr, t);
- TREE_SIDE_EFFECTS (t) = 1;
+static bool
+mn10300_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
+ enum machine_mode mode, tree type,
+ bool named ATTRIBUTE_UNUSED)
+{
+ unsigned HOST_WIDE_INT size;
- t = build1 (INDIRECT_REF, ptr, t);
- TREE_SIDE_EFFECTS (t) = 1;
- }
+ if (type)
+ size = int_size_in_bytes (type);
else
- {
- t = build1 (NOP_EXPR, ptr, t);
- TREE_SIDE_EFFECTS (t) = 1;
- }
+ size = GET_MODE_SIZE (mode);
- /* Calculate! */
- return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
+ return size > 8;
}
/* Return an RTX to represent where a value with mode MODE will be returned
from a function. If the result is 0, the argument is pushed. */
rtx
-function_arg (cum, mode, type, named)
- CUMULATIVE_ARGS *cum;
- enum machine_mode mode;
- tree type;
- int named ATTRIBUTE_UNUSED;
+function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, int named ATTRIBUTE_UNUSED)
{
rtx result = 0;
int size, align;
in registers and partially in memory. */
int
-function_arg_partial_nregs (cum, mode, type, named)
- CUMULATIVE_ARGS *cum;
- enum machine_mode mode;
- tree type;
- int named ATTRIBUTE_UNUSED;
+function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, int named ATTRIBUTE_UNUSED)
{
int size, align;
/* Output a tst insn. */
const char *
-output_tst (operand, insn)
- rtx operand, insn;
+output_tst (rtx operand, rtx insn)
{
rtx temp;
int past_call = 0;
continue;
}
- /* It must be an insn, see if it is a simple set. */
+ /* It must be an insn, see if it is a simple set. */
set = single_set (temp);
if (!set)
{
}
int
-impossible_plus_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+impossible_plus_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (GET_CODE (op) != PLUS)
return 0;
for the btst insn which may examine memory or a register (the memory
variant only allows an unsigned 8 bit integer). */
int
-const_8bit_operand (op, mode)
- register rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+const_8bit_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return (GET_CODE (op) == CONST_INT
&& INTVAL (op) >= 0
/* Return true if the operand is the 1.0f constant. */
int
-const_1f_operand (op, mode)
- register rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+const_1f_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return (op == CONST1_RTX (SFmode));
}
/* Similarly, but when using a zero_extract pattern for a btst where
the source operand might end up in memory. */
int
-mask_ok_for_mem_btst (len, bit)
- int len;
- int bit;
+mask_ok_for_mem_btst (int len, int bit)
{
unsigned int mask = 0;
expressions will have one of a few well defined forms, so
we need only check those forms. */
int
-symbolic_operand (op, mode)
- register rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+symbolic_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
switch (GET_CODE (op))
{
But on a few ports with segmented architectures and indexed addressing
(mn10300, hppa) it is used to rewrite certain problematical addresses. */
rtx
-legitimize_address (x, oldx, mode)
- rtx x;
- rtx oldx ATTRIBUTE_UNUSED;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (flag_pic && ! legitimate_pic_operand_p (x))
x = legitimize_pic_address (oldx, NULL_RTX);
regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0));
regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0));
regx1 = force_reg (Pmode,
- gen_rtx (GET_CODE (y), Pmode, regx1, regy2));
+ gen_rtx_fmt_ee (GET_CODE (y), Pmode, regx1, regy2));
return force_reg (Pmode, gen_rtx_PLUS (Pmode, regx1, regy1));
}
}
}
/* Convert a non-PIC address in `orig' to a PIC address using @GOT or
- @GOTOFF in `reg'. */
+ @GOTOFF in `reg'. */
rtx
-legitimize_pic_address (orig, reg)
- rtx orig;
- rtx reg;
+legitimize_pic_address (rtx orig, rtx reg)
{
if (GET_CODE (orig) == LABEL_REF
|| (GET_CODE (orig) == SYMBOL_REF
}
/* Return zero if X references a SYMBOL_REF or LABEL_REF whose symbol
- isn't protected by a PIC unspec; non-zero otherwise. */
+ isn't protected by a PIC unspec; nonzero otherwise. */
int
-legitimate_pic_operand_p (x)
- rtx x;
+legitimate_pic_operand_p (rtx x)
{
register const char *fmt;
register int i;
|| XINT (x, 1) == UNSPEC_PLT))
return 1;
- if (GET_CODE (x) == QUEUED)
- return legitimate_pic_operand_p (QUEUED_VAR (x));
-
fmt = GET_RTX_FORMAT (GET_CODE (x));
for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
{
return 1;
}
+/* Return TRUE if the address X, taken from a (MEM:MODE X) rtx, is
+ legitimate, and FALSE otherwise. */
+bool
+legitimate_address_p (enum machine_mode mode, rtx x, int strict)
+{
+ if (CONSTANT_ADDRESS_P (x)
+ && (! flag_pic || legitimate_pic_operand_p (x)))
+ return TRUE;
+
+ if (RTX_OK_FOR_BASE_P (x, strict))
+ return TRUE;
+
+ if (TARGET_AM33
+ && GET_CODE (x) == POST_INC
+ && RTX_OK_FOR_BASE_P (XEXP (x, 0), strict)
+ && (mode == SImode || mode == SFmode || mode == HImode))
+ return TRUE;
+
+ if (GET_CODE (x) == PLUS)
+ {
+ rtx base = 0, index = 0;
+
+ if (REG_P (XEXP (x, 0))
+ && REGNO_STRICT_OK_FOR_BASE_P (REGNO (XEXP (x, 0)), strict))
+ {
+ base = XEXP (x, 0);
+ index = XEXP (x, 1);
+ }
+
+ if (REG_P (XEXP (x, 1))
+ && REGNO_STRICT_OK_FOR_BASE_P (REGNO (XEXP (x, 1)), strict))
+ {
+ base = XEXP (x, 1);
+ index = XEXP (x, 0);
+ }
+
+ if (base != 0 && index != 0)
+ {
+ if (GET_CODE (index) == CONST_INT)
+ return TRUE;
+ if (GET_CODE (index) == CONST
+ && GET_CODE (XEXP (index, 0)) != PLUS
+ && (! flag_pic
+ || legitimate_pic_operand_p (index)))
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
static int
-mn10300_address_cost_1 (x, unsig)
- rtx x;
- int *unsig;
+mn10300_address_cost_1 (rtx x, int *unsig)
{
switch (GET_CODE (x))
{
case LABEL_REF:
return 8;
- case ADDRESSOF:
- switch (GET_CODE (XEXP (x, 0)))
- {
- case MEM:
- return mn10300_address_cost (XEXP (x, 0));
-
- case REG:
- return 1;
-
- default:
- abort ();
- }
-
default:
abort ();
}
static int
-mn10300_address_cost (x)
- rtx x;
+mn10300_address_cost (rtx x)
{
int s = 0;
return mn10300_address_cost_1 (x, &s);
}
static bool
-mn10300_rtx_costs (x, code, outer_code, total)
- rtx x;
- int code, outer_code;
- int *total;
+mn10300_rtx_costs (rtx x, int code, int outer_code, int *total)
{
switch (code)
{
movdf and movdi. */
bool
-mn10300_wide_const_load_uses_clr (operands)
- rtx operands[2];
+mn10300_wide_const_load_uses_clr (rtx operands[2])
{
long val[2];
may access it using GOTOFF instead of GOT. */
static void
-mn10300_encode_section_info (decl, rtl, first)
- tree decl;
- rtx rtl;
- int first;
+mn10300_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
{
rtx symbol;