/* Subroutines for insn-output.c for Renesas H8/300.
- Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
- 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"
-#include "tm.h"
+#include "backend.h"
+#include "target.h"
#include "rtl.h"
#include "tree.h"
+#include "df.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "optabs.h"
#include "regs.h"
-#include "hard-reg-set.h"
-#include "insn-config.h"
+#include "emit-rtl.h"
+#include "recog.h"
+#include "diagnostic-core.h"
+#include "alias.h"
+#include "stor-layout.h"
+#include "varasm.h"
+#include "calls.h"
#include "conditions.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
-#include "recog.h"
+#include "explow.h"
#include "expr.h"
-#include "function.h"
-#include "optabs.h"
-#include "diagnostic-core.h"
-#include "c-family/c-pragma.h" /* ??? */
-#include "tm_p.h"
#include "tm-constrs.h"
-#include "ggc.h"
-#include "target.h"
+#include "builtins.h"
+
+/* This file should be included last. */
#include "target-def.h"
-#include "df.h"
/* Classifies a h8300_src_operand or h8300_dst_operand.
static tree h8300_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
static tree h8300_handle_eightbit_data_attribute (tree *, tree, tree, int, bool *);
static tree h8300_handle_tiny_data_attribute (tree *, tree, tree, int, bool *);
-static void h8300_print_operand_address (FILE *, rtx);
+static void h8300_print_operand_address (FILE *, machine_mode, rtx);
static void h8300_print_operand (FILE *, rtx, int);
static bool h8300_print_operand_punct_valid_p (unsigned char code);
#ifndef OBJECT_FORMAT_ELF
static void h8300_asm_named_section (const char *, unsigned int, tree);
#endif
-static int h8300_register_move_cost (enum machine_mode, reg_class_t, reg_class_t);
+static int h8300_register_move_cost (machine_mode, reg_class_t, reg_class_t);
static int h8300_and_costs (rtx);
static int h8300_shift_costs (rtx);
static void h8300_push_pop (int, int, bool, bool);
static unsigned int h8300_unary_length (rtx);
static unsigned int h8300_short_immediate_length (rtx);
static unsigned int h8300_bitfield_length (rtx, rtx);
-static unsigned int h8300_binary_length (rtx, const h8300_length_table *);
+static unsigned int h8300_binary_length (rtx_insn *, const h8300_length_table *);
static bool h8300_short_move_mem_p (rtx, enum rtx_code);
static unsigned int h8300_move_length (rtx *, const h8300_length_table *);
static bool h8300_hard_regno_scratch_ok (unsigned int);
-static rtx h8300_get_index (rtx, enum machine_mode mode, int *);
+static rtx h8300_get_index (rtx, machine_mode mode, int *);
/* CPU_TYPE, says what cpu we're compiling for. */
int cpu_type;
static const char *const h8_pop_ops[2] = { "pop" , "pop.l" };
static const char *const h8_mov_ops[2] = { "mov.w", "mov.l" };
+#ifndef OBJECT_FORMAT_ELF
+ if (TARGET_H8300SX)
+ {
+ error ("%<-msx%> is not supported in coff");
+ target_flags |= MASK_H8300S;
+ }
+#endif
+
if (TARGET_H8300)
{
cpu_type = (int) CPU_H8300;
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");
+ 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%>");
+ target_flags |= MASK_H8300S_1;
+ }
+
+ if (TARGET_H8300 && TARGET_INT32)
+ {
+ 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%>");
+ 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!");
+ }
+
+#ifdef H8300_LINUX
+ if ((TARGET_NORMAL_MODE))
+ {
+ error ("%<-mn%> is not supported for linux targets");
+ target_flags ^= MASK_NORMAL_MODE;
+ }
+#endif
+
/* Some of the shifts are optimized for speed by default.
See http://gcc.gnu.org/ml/gcc-patches/2002-07/msg01858.html
If optimizing for size, change shift_alg for those shift to
}
/* This target defaults to strict volatile bitfields. */
- if (flag_strict_volatile_bitfields < 0)
+ if (flag_strict_volatile_bitfields < 0 && abi_version_at_least(2))
flag_strict_volatile_bitfields = 1;
}
&& ! 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] \
- && !current_function_is_leaf)))
+ && call_used_or_fixed_reg_p (regno) \
+ && !crtl->is_leaf)))
/* We use this to wrap all emitted insns in the prologue. */
-static rtx
-F (rtx x, bool set_it)
+static rtx_insn *
+F (rtx_insn *x, bool set_it)
{
if (set_it)
RTX_FRAME_RELATED_P (x) = 1;
int i;
for (i = 0; i < len; i++)
- F (XVECEXP (par, 0, i), true);
+ RTX_FRAME_RELATED_P (XVECEXP (par, 0, i)) = 1;
return par;
}
the splitter will do. */
if (Pmode == HImode)
{
- rtx x = emit_insn (gen_addhi3 (stack_pointer_rtx,
- stack_pointer_rtx, GEN_INT (sign * size)));
+ rtx_insn *x = emit_insn (gen_addhi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (sign * size)));
if (size < 4)
F (x, in_prologue);
}
/* Emit an insn to push register RN. */
static rtx
-push (int rn)
+push (int rn, bool in_prologue)
{
rtx reg = gen_rtx_REG (word_mode, rn);
rtx x;
x = gen_push_h8300hs_advanced (reg);
else
x = gen_push_h8300hs_normal (reg);
- x = F (emit_insn (x), true);
+ x = F (emit_insn (x), in_prologue);
add_reg_note (x, REG_INC, stack_pointer_rtx);
return x;
}
if (pop_p)
pop (regno);
else
- push (regno);
+ push (regno, false);
return;
}
/* Register REGNO + NREGS - 1 is popped first. Before the
stack adjustment, its slot is at address @sp. */
lhs = gen_rtx_REG (SImode, regno + j);
- rhs = gen_rtx_MEM (SImode, plus_constant (sp, (nregs - j - 1) * 4));
+ rhs = gen_rtx_MEM (SImode, plus_constant (Pmode, sp,
+ (nregs - j - 1) * 4));
}
else
{
/* Register REGNO is pushed first and will be stored at @(-4,sp). */
- lhs = gen_rtx_MEM (SImode, plus_constant (sp, (j + 1) * -4));
+ lhs = gen_rtx_MEM (SImode, plus_constant (Pmode, sp, (j + 1) * -4));
rhs = gen_rtx_REG (SImode, regno + j);
}
- RTVEC_ELT (vec, i + j) = gen_rtx_SET (VOIDmode, lhs, rhs);
+ RTVEC_ELT (vec, i + j) = gen_rtx_SET (lhs, rhs);
}
/* Add the stack adjustment. */
offset = GEN_INT ((pop_p ? nregs : -nregs) * 4);
- RTVEC_ELT (vec, i + j) = gen_rtx_SET (VOIDmode, sp,
- gen_rtx_PLUS (Pmode, sp, offset));
+ RTVEC_ELT (vec, i + j) = gen_rtx_SET (sp, gen_rtx_PLUS (Pmode, sp, offset));
x = gen_rtx_PARALLEL (VOIDmode, vec);
if (!pop_p)
return;
if (h8300_monitor_function_p (current_function_decl))
- /* My understanding of monitor functions is they act just like
- interrupt functions, except the prologue must mask
- interrupts. */
+ /* The monitor function act as normal functions, which means it
+ can accept parameters and return values. In addition to this,
+ interrupts are masked in prologue and return with "rte" in epilogue. */
emit_insn (gen_monitor_prologue ());
if (frame_pointer_needed)
{
/* Push fp. */
- push (HARD_FRAME_POINTER_REGNUM);
+ push (HARD_FRAME_POINTER_REGNUM, true);
F (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx), true);
}
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;
}
/* Leave room for locals. */
h8300_emit_stack_adjustment (-1, round_frame_size (get_frame_size ()), true);
+
+ if (flag_stack_usage_info)
+ current_function_static_stack_size
+ = round_frame_size (get_frame_size ())
+ + (__builtin_popcount (saved_regs) * UNITS_PER_WORD)
+ + (frame_pointer_needed ? UNITS_PER_WORD : 0);
}
/* Return nonzero if we can use "rts" for the function currently being
int
h8300_current_function_interrupt_function_p (void)
{
- return (h8300_interrupt_function_p (current_function_decl)
- || h8300_monitor_function_p (current_function_decl));
+ return (h8300_interrupt_function_p (current_function_decl));
+}
+
+int
+h8300_current_function_monitor_function_p ()
+{
+ return (h8300_monitor_function_p (current_function_decl));
}
/* Output assembly code for the start of the file. */
{
default_file_start ();
- if (TARGET_H8300H)
- fputs (TARGET_NORMAL_MODE ? "\t.h8300hn\n" : "\t.h8300h\n", asm_out_file);
- else if (TARGET_H8300SX)
+ if (TARGET_H8300SX)
fputs (TARGET_NORMAL_MODE ? "\t.h8300sxn\n" : "\t.h8300sx\n", asm_out_file);
else if (TARGET_H8300S)
fputs (TARGET_NORMAL_MODE ? "\t.h8300sn\n" : "\t.h8300s\n", asm_out_file);
+ else if (TARGET_H8300H)
+ fputs (TARGET_NORMAL_MODE ? "\t.h8300hn\n" : "\t.h8300h\n", asm_out_file);
}
/* Output assembly language code for the end of file. */
instead of adds/subs. */
void
-split_adds_subs (enum machine_mode mode, rtx *operands)
+split_adds_subs (machine_mode mode, rtx *operands)
{
HOST_WIDE_INT val = INTVAL (operands[1]);
rtx reg = operands[0];
switch (mode)
{
- case HImode:
+ case E_HImode:
gen_add = gen_addhi3;
break;
- case SImode:
+ case E_SImode:
gen_add = gen_addsi3;
break;
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, enum 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, enum 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
shortcuts. */
static int
-h8300_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+h8300_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
reg_class_t from, reg_class_t to)
{
if (from == MAC_REGS || to == MAC_REG)
/* Worker function for TARGET_RTX_COSTS. */
static bool
-h8300_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed)
+h8300_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
+ int opno ATTRIBUTE_UNUSED, int *total, bool speed)
{
+ int code = GET_CODE (x);
+
if (TARGET_H8300SX && outer_code == MEM)
{
/* Estimate the number of execution states needed to calculate
*total = 0;
return true;
}
- if (-4 <= n || n <= 4)
+ if (n >= -4 && n <= 4)
{
switch ((int) n)
{
if (TARGET_H8300SX)
switch (GET_MODE (x))
{
- case QImode:
- case HImode:
+ case E_QImode:
+ case E_HImode:
*total = COSTS_N_INSNS (!speed ? 4 : 10);
return false;
- case SImode:
+ case E_SImode:
*total = COSTS_N_INSNS (!speed ? 4 : 18);
return false;
if (TARGET_H8300SX)
switch (GET_MODE (x))
{
- case QImode:
- case HImode:
+ case E_QImode:
+ case E_HImode:
*total = COSTS_N_INSNS (2);
return false;
- case SImode:
+ case E_SImode:
*total = COSTS_N_INSNS (5);
return false;
switch (code)
{
+ case 'C':
+ if (h8300_constant_length (x) == 2)
+ fprintf (file, ":16");
+ else
+ fprintf (file, ":32");
+ return;
case 'E':
switch (GET_CODE (x))
{
case CONST_DOUBLE:
{
long val;
- REAL_VALUE_TYPE rv;
- REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
- REAL_VALUE_TO_TARGET_SINGLE (rv, val);
+ REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
fprintf (file, "#%ld", ((val >> 16) & 0xffff));
break;
}
case CONST_DOUBLE:
{
long val;
- REAL_VALUE_TYPE rv;
- REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
- REAL_VALUE_TO_TARGET_SINGLE (rv, val);
+ REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
fprintf (file, "#%ld", (val & 0xffff));
break;
}
}
break;
case 'o':
- h8300_print_operand_address (file, x);
+ h8300_print_operand_address (file, VOIDmode, x);
break;
case 's':
if (GET_CODE (x) == CONST_INT)
case REG:
switch (GET_MODE (x))
{
- case QImode:
+ case E_QImode:
#if 0 /* Is it asm ("mov.b %0,r2l", ...) */
fprintf (file, "%s", byte_reg (x, 0));
#else /* ... or is it asm ("mov.b %0l,r2l", ...) */
fprintf (file, "%s", names_big[REGNO (x)]);
#endif
break;
- case HImode:
+ case E_HImode:
fprintf (file, "%s", names_big[REGNO (x)]);
break;
- case SImode:
- case SFmode:
+ case E_SImode:
+ case E_SFmode:
fprintf (file, "%s", names_extended[REGNO (x)]);
break;
default:
rtx addr = XEXP (x, 0);
fprintf (file, "@");
- output_address (addr);
+ output_address (GET_MODE (x), addr);
/* Add a length suffix to constant addresses. Although this
is often unnecessary, it helps to avoid ambiguity in the
break;
}
- /* Fall through. We should not get here if we are
- processing bit operations on H8/300 or H8/300H
- because 'U' constraint does not allow bit
- operations on the tiny area on these machines. */
+ /* FALLTHRU */
+
+ /* We should not get here if we are processing bit
+ operations on H8/300 or H8/300H because 'U'
+ constraint does not allow bit operations on the
+ tiny area on these machines. */
case 'X':
case 'T':
case CONST:
case LABEL_REF:
fprintf (file, "#");
- h8300_print_operand_address (file, x);
+ h8300_print_operand_address (file, VOIDmode, x);
break;
case CONST_DOUBLE:
{
long val;
- REAL_VALUE_TYPE rv;
- REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
- REAL_VALUE_TO_TARGET_SINGLE (rv, val);
+ REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
fprintf (file, "#%ld", val);
break;
}
/* Output assembly language output for the address ADDR to FILE. */
static void
-h8300_print_operand_address (FILE *file, rtx addr)
+h8300_print_operand_address (FILE *file, machine_mode mode, rtx addr)
{
rtx index;
int size;
if (GET_CODE (index) == REG)
{
/* reg,foo */
- h8300_print_operand_address (file, XEXP (addr, 1));
+ h8300_print_operand_address (file, mode, XEXP (addr, 1));
fprintf (file, ",");
switch (size)
{
case 0:
- h8300_print_operand_address (file, index);
+ h8300_print_operand_address (file, mode, index);
break;
case 1:
else
{
/* foo+k */
- h8300_print_operand_address (file, XEXP (addr, 0));
+ h8300_print_operand_address (file, mode, XEXP (addr, 0));
fprintf (file, "+");
- h8300_print_operand_address (file, XEXP (addr, 1));
+ h8300_print_operand_address (file, mode, XEXP (addr, 1));
}
fprintf (file, ")");
break;
option. */
void
-final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,
+final_prescan_insn (rtx_insn *insn, rtx *operand ATTRIBUTE_UNUSED,
int num_operands ATTRIBUTE_UNUSED)
{
/* This holds the last insn address. */
else
ret = gen_rtx_MEM (Pmode,
memory_address (Pmode,
- plus_constant (frame, UNITS_PER_WORD)));
+ plus_constant (Pmode, frame,
+ UNITS_PER_WORD)));
set_mem_alias_set (ret, get_frame_alias_set ());
return ret;
}
/* Update the condition code from the insn. */
void
-notice_update_cc (rtx body, rtx insn)
+notice_update_cc (rtx body, rtx_insn *insn)
{
rtx set;
if the address is known to be valid, but its mode is unknown. */
static rtx
-h8300_get_index (rtx x, enum machine_mode mode, int *size)
+h8300_get_index (rtx x, machine_mode mode, int *size)
{
int dummy, factor;
(the amount of decrement or increment being the length of the operand). */
static bool
-h8300_mode_dependent_address_p (const_rtx addr)
+h8300_mode_dependent_address_p (const_rtx addr,
+ addr_space_t as ATTRIBUTE_UNUSED)
{
if (GET_CODE (addr) == PLUS
&& h8300_get_index (XEXP (addr, 0), VOIDmode, 0) != XEXP (addr, 0))
/* Calculate the length of general binary instruction INSN using TABLE. */
static unsigned int
-h8300_binary_length (rtx insn, const h8300_length_table *table)
+h8300_binary_length (rtx_insn *insn, const h8300_length_table *table)
{
rtx set;
OPERANDS is the array of its operands. */
unsigned int
-h8300_insn_length_from_table (rtx insn, rtx * operands)
+h8300_insn_length_from_table (rtx_insn *insn, rtx * operands)
{
switch (get_attr_length_table (insn))
{
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);
void
h8300_swap_into_er6 (rtx addr)
{
- rtx insn = push (HARD_FRAME_POINTER_REGNUM);
+ rtx insn = push (HARD_FRAME_POINTER_REGNUM, false);
if (frame_pointer_needed)
add_reg_note (insn, REG_CFA_DEF_CFA,
- plus_constant (gen_rtx_MEM (Pmode, stack_pointer_rtx),
+ plus_constant (Pmode, gen_rtx_MEM (Pmode, stack_pointer_rtx),
2 * UNITS_PER_WORD));
else
add_reg_note (insn, REG_CFA_ADJUST_CFA,
- gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- plus_constant (stack_pointer_rtx, 4)));
+ gen_rtx_SET (stack_pointer_rtx,
+ plus_constant (Pmode, stack_pointer_rtx, 4)));
emit_move_insn (hard_frame_pointer_rtx, addr);
if (REGNO (addr) == SP_REG)
emit_move_insn (hard_frame_pointer_rtx,
- plus_constant (hard_frame_pointer_rtx,
+ plus_constant (Pmode, hard_frame_pointer_rtx,
GET_MODE_SIZE (word_mode)));
}
emit_move_insn (addr, hard_frame_pointer_rtx);
insn = pop (HARD_FRAME_POINTER_REGNUM);
- RTX_FRAME_RELATED_P (insn) = 1;
if (frame_pointer_needed)
add_reg_note (insn, REG_CFA_DEF_CFA,
- plus_constant (hard_frame_pointer_rtx, 2 * UNITS_PER_WORD));
+ plus_constant (Pmode, hard_frame_pointer_rtx,
+ 2 * UNITS_PER_WORD));
else
add_reg_note (insn, REG_CFA_ADJUST_CFA,
- gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- plus_constant (stack_pointer_rtx, -4)));
+ gen_rtx_SET (stack_pointer_rtx,
+ plus_constant (Pmode, stack_pointer_rtx, -4)));
}
\f
/* Return the length of mov instruction. */
length, assuming the largest addressing mode is used, and then
adjust later in the function. Otherwise, we compute and return
the exact length in one step. */
- enum machine_mode mode = GET_MODE (operands[0]);
+ machine_mode mode = GET_MODE (operands[0]);
rtx dest = operands[0];
rtx src = operands[1];
rtx addr;
switch (mode)
{
- case QImode:
+ case E_QImode:
if (addr == NULL_RTX)
return 2;
base_length = 4;
break;
- case HImode:
+ case E_HImode:
if (addr == NULL_RTX)
{
if (REG_P (src))
base_length = 4;
break;
- case SImode:
+ case E_SImode:
if (addr == NULL_RTX)
{
if (REG_P (src))
base_length = 8;
break;
- case SFmode:
+ case E_SFmode:
if (addr == NULL_RTX)
{
if (REG_P (src))
switch (mode)
{
- case QImode:
+ case E_QImode:
if (addr == NULL_RTX)
return 2;
base_length = 8;
break;
- case HImode:
+ case E_HImode:
if (addr == NULL_RTX)
{
if (REG_P (src))
base_length = 8;
break;
- case SImode:
+ case E_SImode:
if (addr == NULL_RTX)
{
if (REG_P (src))
base_length = 10;
break;
- case SFmode:
+ case E_SFmode:
if (addr == NULL_RTX)
{
if (REG_P (src))
const char *
output_plussi (rtx *operands)
{
- enum machine_mode mode = GET_MODE (operands[0]);
+ machine_mode mode = GET_MODE (operands[0]);
gcc_assert (mode == SImode);
unsigned int
compute_plussi_length (rtx *operands)
{
- enum machine_mode mode = GET_MODE (operands[0]);
+ machine_mode mode = GET_MODE (operands[0]);
gcc_assert (mode == SImode);
enum attr_cc
compute_plussi_cc (rtx *operands)
{
- enum machine_mode mode = GET_MODE (operands[0]);
+ machine_mode mode = GET_MODE (operands[0]);
gcc_assert (mode == SImode);
/* Output a logical insn. */
const char *
-output_logical_op (enum machine_mode mode, rtx *operands)
+output_logical_op (machine_mode mode, rtx *operands)
{
/* Figure out the logical op that we need to perform. */
enum rtx_code code = GET_CODE (operands[3]);
switch (mode)
{
- case HImode:
+ case E_HImode:
/* First, see if we can finish with one insn. */
if ((TARGET_H8300H || TARGET_H8300S)
&& b0 != 0
}
}
break;
- case SImode:
+ case E_SImode:
if (TARGET_H8300H || TARGET_H8300S)
{
/* Determine if the lower half can be taken care of in no more
/* Compute the length of a logical insn. */
unsigned int
-compute_logical_op_length (enum machine_mode mode, rtx *operands)
+compute_logical_op_length (machine_mode mode, rtx *operands)
{
/* Figure out the logical op that we need to perform. */
enum rtx_code code = GET_CODE (operands[3]);
switch (mode)
{
- case HImode:
+ case E_HImode:
/* First, see if we can finish with one insn. */
if ((TARGET_H8300H || TARGET_H8300S)
&& b0 != 0
length += 2;
}
break;
- case SImode:
+ case E_SImode:
if (TARGET_H8300H || TARGET_H8300S)
{
/* Determine if the lower half can be taken care of in no more
/* Compute which flag bits are valid after a logical insn. */
enum attr_cc
-compute_logical_op_cc (enum machine_mode mode, rtx *operands)
+compute_logical_op_cc (machine_mode mode, rtx *operands)
{
/* Figure out the logical op that we need to perform. */
enum rtx_code code = GET_CODE (operands[3]);
switch (mode)
{
- case HImode:
+ case E_HImode:
/* First, see if we can finish with one insn. */
if ((TARGET_H8300H || TARGET_H8300S)
&& b0 != 0
cc = CC_SET_ZNV;
}
break;
- case SImode:
+ case E_SImode:
if (TARGET_H8300H || TARGET_H8300S)
{
/* Determine if the lower half can be taken care of in no more
rtx tmp;
tmp = gen_rtx_COMPARE (VOIDmode, op0, op1);
- emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, tmp));
+ emit_insn (gen_rtx_SET (cc0_rtx, tmp));
tmp = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
gen_rtx_LABEL_REF (VOIDmode, label),
pc_rtx);
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
+ emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
}
rtx tmp;
tmp = gen_rtx_COMPARE (VOIDmode, op0, op1);
- emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, tmp));
+ emit_insn (gen_rtx_SET (cc0_rtx, tmp));
tmp = gen_rtx_fmt_ee (code, GET_MODE (dest), cc0_rtx, const0_rtx);
- emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
+ emit_insn (gen_rtx_SET (dest, tmp));
}
\f
/* Shifts.
/* Classify a shift with the given mode and code. OP is the shift amount. */
enum h8sx_shift_type
-h8sx_classify_shift (enum machine_mode mode, enum rtx_code code, rtx op)
+h8sx_classify_shift (machine_mode mode, enum rtx_code code, rtx op)
{
if (!TARGET_H8300SX)
return H8SX_SHIFT_NONE;
/* Emit code to do shifts. */
bool
-expand_a_shift (enum machine_mode mode, enum rtx_code code, rtx operands[])
+expand_a_shift (machine_mode mode, enum rtx_code code, rtx operands[])
{
switch (h8sx_classify_shift (mode, code, operands[2]))
{
emit_insn (gen_rtx_PARALLEL
(VOIDmode,
gen_rtvec (2,
- gen_rtx_SET (VOIDmode, copy_rtx (operands[0]),
+ gen_rtx_SET (copy_rtx (operands[0]),
gen_rtx_fmt_ee (code, mode,
copy_rtx (operands[0]), operands[2])),
gen_rtx_CLOBBER (VOIDmode,
/* Find the target CPU. */
if (TARGET_H8300)
cpu = H8_300;
- else if (TARGET_H8300H)
- cpu = H8_300H;
- else
+ else if (TARGET_H8300S)
cpu = H8_S;
+ else
+ cpu = H8_300H;
/* Find the shift algorithm. */
info->alg = SHIFT_LOOP;
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;
info->cc_inline = CC_SET_ZNV;
goto end;
case SHIFT_ASHIFTRT:
- info->special = "mov.b\t%z0,%w0\n\tbld\t#7,%w0\n\tsubx\t%x0,%x0\n\tsubx\t%x0,%x0\n\tsubx\t%x0,%x0";
+ info->special = "mov.b\t%z0,%w0\n\tbld\t#7,%w0\n\tsubx\t%x0,%x0\n\tsubx\t%y0,%y0\n\tsubx\t%z0,%z0";
info->shift1 = "shar.b\t%w0";
info->cc_inline = CC_SET_ZNV;
goto end;
}
}
else if ((TARGET_H8300H && count == 24)
- || (TARGET_H8300S && 24 <= count && count <= 25))
+ || (TARGET_H8300S && count >= 24 && count <= 25))
{
info->remainder = count - 24;
needed for some shift with COUNT and MODE. Return 0 otherwise. */
int
-h8300_shift_needs_scratch_p (int count, enum machine_mode mode)
+h8300_shift_needs_scratch_p (int count, machine_mode mode)
{
enum h8_cpu cpu;
int a, lr, ar;
/* Find out the target CPU. */
if (TARGET_H8300)
cpu = H8_300;
- else if (TARGET_H8300H)
- cpu = H8_300H;
- else
+ else if (TARGET_H8300S)
cpu = H8_S;
+ else
+ cpu = H8_300H;
/* Find the shift algorithm. */
switch (mode)
{
- case QImode:
+ case E_QImode:
a = shift_alg_qi[cpu][SHIFT_ASHIFT][count];
lr = shift_alg_qi[cpu][SHIFT_LSHIFTRT][count];
ar = shift_alg_qi[cpu][SHIFT_ASHIFTRT][count];
break;
- case HImode:
+ case E_HImode:
a = shift_alg_hi[cpu][SHIFT_ASHIFT][count];
lr = shift_alg_hi[cpu][SHIFT_LSHIFTRT][count];
ar = shift_alg_hi[cpu][SHIFT_ASHIFTRT][count];
break;
- case SImode:
+ case E_SImode:
a = shift_alg_si[cpu][SHIFT_ASHIFT][count];
lr = shift_alg_si[cpu][SHIFT_LSHIFTRT][count];
ar = shift_alg_si[cpu][SHIFT_ASHIFTRT][count];
{
static int loopend_lab;
rtx shift = operands[3];
- enum machine_mode mode = GET_MODE (shift);
+ machine_mode mode = GET_MODE (shift);
enum rtx_code code = GET_CODE (shift);
enum shift_type shift_type;
enum shift_mode shift_mode;
switch (mode)
{
- case QImode:
+ case E_QImode:
shift_mode = QIshift;
break;
- case HImode:
+ case E_HImode:
shift_mode = HIshift;
break;
- case SImode:
+ case E_SImode:
shift_mode = SIshift;
break;
default:
/* Now mask off the high bits. */
switch (mode)
{
- case QImode:
+ case E_QImode:
sprintf (insn_buf, "and\t#%d,%%X0", mask);
break;
- case HImode:
+ case E_HImode:
gcc_assert (TARGET_H8300H || TARGET_H8300S);
sprintf (insn_buf, "and.w\t#%d,%%T0", mask);
break;
compute_a_shift_length (rtx insn ATTRIBUTE_UNUSED, rtx *operands)
{
rtx shift = operands[3];
- enum machine_mode mode = GET_MODE (shift);
+ machine_mode mode = GET_MODE (shift);
enum rtx_code code = GET_CODE (shift);
enum shift_type shift_type;
enum shift_mode shift_mode;
switch (mode)
{
- case QImode:
+ case E_QImode:
shift_mode = QIshift;
break;
- case HImode:
+ case E_HImode:
shift_mode = HIshift;
break;
- case SImode:
+ case E_SImode:
shift_mode = SIshift;
break;
default:
/* Now mask off the high bits. */
switch (mode)
{
- case QImode:
+ case E_QImode:
wlength += 1;
break;
- case HImode:
+ case E_HImode:
wlength += 2;
break;
- case SImode:
+ case E_SImode:
gcc_assert (!TARGET_H8300);
wlength += 3;
break;
compute_a_shift_cc (rtx insn ATTRIBUTE_UNUSED, rtx *operands)
{
rtx shift = operands[3];
- enum machine_mode mode = GET_MODE (shift);
+ machine_mode mode = GET_MODE (shift);
enum rtx_code code = GET_CODE (shift);
enum shift_type shift_type;
enum shift_mode shift_mode;
switch (mode)
{
- case QImode:
+ case E_QImode:
shift_mode = QIshift;
break;
- case HImode:
+ case E_HImode:
shift_mode = HIshift;
break;
- case SImode:
+ case E_SImode:
shift_mode = SIshift;
break;
default:
rtx dst = operands[0];
rtx src = operands[1];
rtx rotate_amount = operands[2];
- enum machine_mode mode = GET_MODE (dst);
+ machine_mode mode = GET_MODE (dst);
if (h8sx_classify_shift (mode, ROTATE, rotate_amount) == H8SX_SHIFT_UNARY)
return false;
if (GET_CODE (rotate_amount) != CONST_INT)
{
rtx counter = gen_reg_rtx (QImode);
- rtx start_label = gen_label_rtx ();
- rtx end_label = gen_label_rtx ();
+ rtx_code_label *start_label = gen_label_rtx ();
+ rtx_code_label *end_label = gen_label_rtx ();
/* If the rotate amount is less than or equal to 0,
we go out of the loop. */
/* Rotate by one bit. */
switch (mode)
{
- case QImode:
+ case E_QImode:
emit_insn (gen_rotlqi3_1 (dst, dst, const1_rtx));
break;
- case HImode:
+ case E_HImode:
emit_insn (gen_rotlhi3_1 (dst, dst, const1_rtx));
break;
- case SImode:
+ case E_SImode:
emit_insn (gen_rotlsi3_1 (dst, dst, const1_rtx));
break;
default:
/* Rotate by AMOUNT bits. */
switch (mode)
{
- case QImode:
+ case E_QImode:
emit_insn (gen_rotlqi3_1 (dst, dst, rotate_amount));
break;
- case HImode:
+ case E_HImode:
emit_insn (gen_rotlhi3_1 (dst, dst, rotate_amount));
break;
- case SImode:
+ case E_SImode:
emit_insn (gen_rotlsi3_1 (dst, dst, rotate_amount));
break;
default:
const char *insn_buf;
int bits;
int amount;
- enum machine_mode mode = GET_MODE (dst);
+ machine_mode mode = GET_MODE (dst);
gcc_assert (GET_CODE (rotate_amount) == CONST_INT);
switch (mode)
{
- case QImode:
+ case E_QImode:
rotate_mode = QIshift;
break;
- case HImode:
+ case E_HImode:
rotate_mode = HIshift;
break;
- case SImode:
+ case E_SImode:
rotate_mode = SIshift;
break;
default:
{
switch (mode)
{
- case HImode:
+ case E_HImode:
/* This code works on any family. */
insn_buf = "xor.b\t%s0,%t0\n\txor.b\t%t0,%s0\n\txor.b\t%s0,%t0";
output_asm_insn (insn_buf, operands);
break;
- case SImode:
+ case E_SImode:
/* This code works on the H8/300H and H8S. */
insn_buf = "xor.w\t%e0,%f0\n\txor.w\t%f0,%e0\n\txor.w\t%e0,%f0";
output_asm_insn (insn_buf, operands);
{
rtx src = operands[1];
rtx amount_rtx = operands[2];
- enum machine_mode mode = GET_MODE (src);
+ machine_mode mode = GET_MODE (src);
int amount;
unsigned int length = 0;
static const struct attribute_spec h8300_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { "interrupt_handler", 0, 0, true, false, false,
- h8300_handle_fndecl_attribute, false },
- { "saveall", 0, 0, true, false, false,
- h8300_handle_fndecl_attribute, false },
- { "OS_Task", 0, 0, true, false, false,
- h8300_handle_fndecl_attribute, false },
- { "monitor", 0, 0, true, false, false,
- h8300_handle_fndecl_attribute, false },
- { "function_vector", 0, 0, true, false, false,
- h8300_handle_fndecl_attribute, false },
- { "eightbit_data", 0, 0, true, false, false,
- h8300_handle_eightbit_data_attribute, false },
- { "tiny_data", 0, 0, true, false, false,
- h8300_handle_tiny_data_attribute, false },
- { NULL, 0, 0, false, false, false, NULL, false }
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+ affects_type_identity, handler, exclude } */
+ { "interrupt_handler", 0, 0, true, false, false, false,
+ h8300_handle_fndecl_attribute, NULL },
+ { "saveall", 0, 0, true, false, false, false,
+ h8300_handle_fndecl_attribute, NULL },
+ { "OS_Task", 0, 0, true, false, false, false,
+ h8300_handle_fndecl_attribute, NULL },
+ { "monitor", 0, 0, true, false, false, false,
+ h8300_handle_fndecl_attribute, NULL },
+ { "function_vector", 0, 0, true, false, false, false,
+ h8300_handle_fndecl_attribute, NULL },
+ { "eightbit_data", 0, 0, true, false, false, false,
+ h8300_handle_eightbit_data_attribute, NULL },
+ { "tiny_data", 0, 0, true, false, false, false,
+ h8300_handle_tiny_data_attribute, NULL },
+ { NULL, 0, 0, false, false, false, false, NULL, NULL }
};
if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
{
- DECL_SECTION_NAME (decl) = build_string (7, ".eight");
+ set_decl_section_name (decl, ".eight");
}
else
{
if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
{
- DECL_SECTION_NAME (decl) = build_string (6, ".tiny");
+ set_decl_section_name (decl, ".tiny");
}
else
{
if (GET_CODE (x) == SYMBOL_REF)
return (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_EIGHTBIT_DATA) != 0;
+ if (GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+ && (SYMBOL_REF_FLAGS (XEXP (XEXP (x, 0), 0)) & SYMBOL_FLAG_EIGHTBIT_DATA) != 0)
+ return 1;
+
if (GET_CODE (x) != CONST_INT)
return 0;
before I3. I3 is assumed to be a comparison insn. */
int
-same_cmp_preceding_p (rtx i3)
+same_cmp_preceding_p (rtx_insn *i3)
{
- rtx i1, i2;
+ rtx_insn *i1, *i2;
/* Make sure we have a sequence of three insns. */
i2 = prev_nonnote_insn (i3);
- if (i2 == NULL_RTX)
+ if (i2 == NULL)
return 0;
i1 = prev_nonnote_insn (i2);
- if (i1 == NULL_RTX)
+ if (i1 == NULL)
return 0;
return (INSN_P (i1) && rtx_equal_p (PATTERN (i1), PATTERN (i3))
after I1. I1 is assumed to be a comparison insn. */
int
-same_cmp_following_p (rtx i1)
+same_cmp_following_p (rtx_insn *i1)
{
- rtx i2, i3;
+ rtx_insn *i2, *i3;
/* Make sure we have a sequence of three insns. */
i2 = next_nonnote_insn (i1);
- if (i2 == NULL_RTX)
+ if (i2 == NULL)
return 0;
i3 = next_nonnote_insn (i2);
- if (i3 == NULL_RTX)
+ if (i3 == NULL)
return 0;
return (INSN_P (i3) && rtx_equal_p (PATTERN (i1), PATTERN (i3))
CONSTANT_ADDRESS. */
static bool
-h8300_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
+h8300_legitimate_address_p (machine_mode mode, rtx x, bool strict)
{
/* The register indirect addresses like @er0 is always valid. */
if (h8300_rtx_ok_for_base_p (x, strict))
return 0;
}
-/* Worker function for HARD_REGNO_NREGS.
-
- We pretend the MAC register is 32bits -- we don't have any data
- types on the H8 series to handle more than 32bits. */
-
-int
-h8300_hard_regno_nregs (int regno ATTRIBUTE_UNUSED, enum machine_mode mode)
-{
- return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
-}
-
-/* Worker function for HARD_REGNO_MODE_OK. */
+/* Implement TARGET_HARD_REGNO_MODE_OK. */
-int
-h8300_hard_regno_mode_ok (int regno, enum machine_mode mode)
+static bool
+h8300_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
{
if (TARGET_H8300)
/* If an even reg, then anything goes. Otherwise the mode must be
return regno == MAC_REG ? mode == SImode : 1;
}
+/* Implement TARGET_MODES_TIEABLE_P. */
+
+static bool
+h8300_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+ return (mode1 == mode2
+ || ((mode1 == QImode
+ || mode1 == HImode
+ || ((TARGET_H8300H || TARGET_H8300S) && mode1 == SImode))
+ && (mode2 == QImode
+ || mode2 == HImode
+ || ((TARGET_H8300H || TARGET_H8300S) && mode2 == SImode))));
+}
+
/* Helper function for the move patterns. Make sure a move is legitimate. */
bool
On the H8 the return value is in R0/R1. */
static rtx
-h8300_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
+h8300_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
{
return gen_rtx_REG (mode, R0_REG);
}
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_HARD_REGNO_SCRATCH_OK
#define TARGET_HARD_REGNO_SCRATCH_OK h8300_hard_regno_scratch_ok
+#undef TARGET_HARD_REGNO_MODE_OK
+#define TARGET_HARD_REGNO_MODE_OK h8300_hard_regno_mode_ok
+
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P h8300_modes_tieable_p
+
+#undef TARGET_LRA_P
+#define TARGET_LRA_P hook_bool_void_false
+
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P h8300_legitimate_address_p
#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;