/* Subroutines for insn-output.c for Renesas H8/300.
- Copyright (C) 1992-2017 Free Software Foundation, Inc.
+ Copyright (C) 1992-2020 Free Software Foundation, Inc.
Contributed by Steve Chamberlain (sac@cygnus.com),
Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com).
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+#define IN_TARGET_CODE 1
+
#include "config.h"
#include "system.h"
#include "coretypes.h"
#ifndef OBJECT_FORMAT_ELF
if (TARGET_H8300SX)
{
- error ("-msx is not supported in coff");
+ error ("%<-msx%> is not supported in coff");
target_flags |= MASK_H8300S;
}
#endif
if (!TARGET_H8300S && TARGET_MAC)
{
- error ("-ms2600 is used without -ms");
+ error ("%<-ms2600%> is used without %<-ms%>");
target_flags |= MASK_H8300S_1;
}
if (TARGET_H8300 && TARGET_NORMAL_MODE)
{
- error ("-mn is used without -mh or -ms or -msx");
+ error ("%<-mn%> is used without %<-mh%> or %<-ms%> or %<-msx%>");
target_flags ^= MASK_NORMAL_MODE;
}
if (! TARGET_H8300S && TARGET_EXR)
{
- error ("-mexr is used without -ms");
+ error ("%<-mexr%> is used without %<-ms%>");
target_flags |= MASK_H8300S_1;
}
if (TARGET_H8300 && TARGET_INT32)
{
- error ("-mint32 is not supported for H8300 and H8300L targets");
+ error ("%<-mint32%> is not supported for H8300 and H8300L targets");
target_flags ^= MASK_INT32;
}
if ((!TARGET_H8300S && TARGET_EXR) && (!TARGET_H8300SX && TARGET_EXR))
{
- error ("-mexr is used without -ms or -msx");
+ error ("%<-mexr%> is used without %<-ms%> or %<-msx%>");
target_flags |= MASK_H8300S_1;
}
if ((!TARGET_H8300S && TARGET_NEXR) && (!TARGET_H8300SX && TARGET_NEXR))
{
- warning (OPT_mno_exr, "-mno-exr valid only with -ms or -msx \
- - Option ignored!");
+ warning (OPT_mno_exr, "%<-mno-exr%> valid only with %<-ms%> or "
+ "%<-msx%> - Option ignored!");
}
#ifdef H8300_LINUX
if ((TARGET_NORMAL_MODE))
{
- error ("-mn is not supported for linux targets");
+ error ("%<-mn%> is not supported for linux targets");
target_flags ^= MASK_NORMAL_MODE;
}
#endif
&& ! TREE_THIS_VOLATILE (current_function_decl) \
&& (h8300_saveall_function_p (current_function_decl) \
/* Save any call saved register that was used. */ \
- || (df_regs_ever_live_p (regno) && !call_used_regs[regno]) \
+ || (df_regs_ever_live_p (regno) \
+ && !call_used_or_fixed_reg_p (regno)) \
/* Save the frame pointer if it was used. */ \
|| (regno == HARD_FRAME_POINTER_REGNUM && df_regs_ever_live_p (regno)) \
/* Save any register used in an interrupt handler. */ \
/* Save call clobbered registers in non-leaf interrupt \
handlers. */ \
|| (h8300_current_function_interrupt_function_p () \
- && call_used_regs[regno] \
+ && call_used_or_fixed_reg_p (regno) \
&& !crtl->is_leaf)))
/* We use this to wrap all emitted insns in the prologue. */
if (TARGET_H8300S)
{
/* See how many registers we can push at the same time. */
- if ((!TARGET_H8300SX || (regno & 3) == 0)
+ if ((TARGET_H8300SX || (regno & 3) == 0)
&& ((saved_regs >> regno) & 0x0f) == 0x0f)
n_regs = 4;
- else if ((!TARGET_H8300SX || (regno & 3) == 0)
+ else if ((TARGET_H8300SX || (regno & 3) == 0)
&& ((saved_regs >> regno) & 0x07) == 0x07)
n_regs = 3;
- else if ((!TARGET_H8300SX || (regno & 1) == 0)
+ else if ((TARGET_H8300SX || (regno & 1) == 0)
&& ((saved_regs >> regno) & 0x03) == 0x03)
n_regs = 2;
}
pragma_saveall = 1;
}
-/* If the next function argument with MODE and TYPE is to be passed in
- a register, return a reg RTX for the hard register in which to pass
- the argument. CUM represents the state after the last argument.
- If the argument is to be pushed, NULL_RTX is returned.
+/* If the next function argument ARG is to be passed in a register, return
+ a reg RTX for the hard register in which to pass the argument. CUM
+ represents the state after the last argument. If the argument is to
+ be pushed, NULL_RTX is returned.
On the H8/300 all normal args are pushed, unless -mquickcall in which
case the first 3 arguments are passed in registers. */
static rtx
-h8300_function_arg (cumulative_args_t cum_v, machine_mode mode,
- const_tree type, bool named)
+h8300_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
int regpass = 0;
/* Never pass unnamed arguments in registers. */
- if (!named)
+ if (!arg.named)
return NULL_RTX;
/* Pass 3 regs worth of data in regs when user asked on the command line. */
if (regpass)
{
- int size;
-
- if (mode == BLKmode)
- size = int_size_in_bytes (type);
- else
- size = GET_MODE_SIZE (mode);
-
+ int size = arg.promoted_size_in_bytes ();
if (size + cum->nbytes <= regpass * UNITS_PER_WORD
&& cum->nbytes / UNITS_PER_WORD <= 3)
- result = gen_rtx_REG (mode, cum->nbytes / UNITS_PER_WORD);
+ result = gen_rtx_REG (arg.mode, cum->nbytes / UNITS_PER_WORD);
}
return result;
}
-/* Update the data in CUM to advance over an argument
- of mode MODE and data type TYPE.
- (TYPE is null for libcalls where that information may not be available.) */
+/* Update the data in CUM to advance over argument ARG. */
static void
-h8300_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
- const_tree type, bool named ATTRIBUTE_UNUSED)
+h8300_function_arg_advance (cumulative_args_t cum_v,
+ const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
- cum->nbytes += (mode != BLKmode
- ? (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD
- : (int_size_in_bytes (type) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD);
+ cum->nbytes += ((arg.promoted_size_in_bytes () + UNITS_PER_WORD - 1)
+ & -UNITS_PER_WORD);
}
\f
*total = 0;
return true;
}
- if (-4 <= n && n <= 4)
+ if (n >= -4 && n <= 4)
{
switch ((int) n)
{
case LENGTH_TABLE_NONE:
gcc_unreachable ();
- case LENGTH_TABLE_ADDB:
- return h8300_binary_length (insn, &addb_length_table);
-
- case LENGTH_TABLE_ADDW:
- return h8300_binary_length (insn, &addw_length_table);
-
- case LENGTH_TABLE_ADDL:
- return h8300_binary_length (insn, &addl_length_table);
+ case LENGTH_TABLE_ADD:
+ if (GET_MODE (operands[0]) == QImode)
+ return h8300_binary_length (insn, &addb_length_table);
+ else if (GET_MODE (operands[0]) == HImode)
+ return h8300_binary_length (insn, &addw_length_table);
+ else if (GET_MODE (operands[0]) == SImode)
+ return h8300_binary_length (insn, &addl_length_table);
+ gcc_unreachable ();
case LENGTH_TABLE_LOGICB:
return h8300_binary_length (insn, &logicb_length_table);
goto end;
}
}
- else if ((8 <= count && count <= 13)
+ else if ((count >= 8 && count <= 13)
|| (TARGET_H8300S && count == 14))
{
info->remainder = count - 8;
gcc_unreachable ();
case SIshift:
- if (TARGET_H8300 && 8 <= count && count <= 9)
+ if (TARGET_H8300 && count >= 8 && count <= 9)
{
info->remainder = count - 8;
gcc_unreachable ();
}
}
- else if ((TARGET_H8300 && 16 <= count && count <= 20)
- || (TARGET_H8300H && 16 <= count && count <= 19)
- || (TARGET_H8300S && 16 <= count && count <= 21))
+ else if ((TARGET_H8300 && count >= 16 && count <= 20)
+ || (TARGET_H8300H && count >= 16 && count <= 19)
+ || (TARGET_H8300S && count >= 16 && count <= 21))
{
info->remainder = count - 16;
goto end;
}
}
- else if (TARGET_H8300 && 24 <= count && count <= 28)
+ else if (TARGET_H8300 && count >= 24 && count <= 28)
{
info->remainder = count - 24;
}
}
else if ((TARGET_H8300H && count == 24)
- || (TARGET_H8300S && 24 <= count && count <= 25))
+ || (TARGET_H8300S && count >= 24 && count <= 25))
{
info->remainder = count - 24;
emit_move_insn (mem, tem);
}
}
+
+/* Implement PUSH_ROUNDING.
+
+ On the H8/300, @-sp really pushes a byte if you ask it to - but that's
+ dangerous, so we claim that it always pushes a word, then we catch
+ the mov.b rx,@-sp and turn it into a mov.w rx,@-sp on output.
+
+ On the H8/300H, we simplify TARGET_QUICKCALL by setting this to 4
+ and doing a similar thing. */
+
+poly_int64
+h8300_push_rounding (poly_int64 bytes)
+{
+ return ((bytes + PARM_BOUNDARY / 8 - 1) & (-PARM_BOUNDARY / 8));
+}
\f
/* Initialize the GCC target structure. */
#undef TARGET_ATTRIBUTE_TABLE
#undef TARGET_MODE_DEPENDENT_ADDRESS_P
#define TARGET_MODE_DEPENDENT_ADDRESS_P h8300_mode_dependent_address_p
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;