/* Output routines for Visium.
- Copyright (C) 2002-2017 Free Software Foundation, Inc.
+ Copyright (C) 2002-2019 Free Software Foundation, Inc.
Contributed by C.Nettleton, J.P.Parkes and P.Garbett.
This file is part of GCC.
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"
interrupt -- specifies this function is an interrupt handler. */
static const struct attribute_spec visium_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- {"interrupt", 0, 0, true, false, false, visium_handle_interrupt_attr, 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", 0, 0, true, false, false, false, visium_handle_interrupt_attr,
+ NULL},
+ { NULL, 0, 0, false, false, false, false, NULL, NULL },
};
static struct machine_function *visium_init_machine_status (void);
static unsigned int visium_reorg (void);
+static unsigned int visium_hard_regno_nregs (unsigned int, machine_mode);
+
static bool visium_hard_regno_mode_ok (unsigned int, machine_mode);
static bool visium_modes_tieable_p (machine_mode, machine_mode);
+static bool visium_can_change_mode_class (machine_mode, machine_mode,
+ reg_class_t);
+
+static HOST_WIDE_INT visium_constant_alignment (const_tree, HOST_WIDE_INT);
+
/* Setup the global target hooks structure. */
#undef TARGET_MAX_ANCHOR_OFFSET
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P visium_legitimate_constant_p
-#undef TARGET_LRA_P
+#undef TARGET_LRA_P
#define TARGET_LRA_P hook_bool_void_false
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P visium_legitimate_address_p
-#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
+#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
#define TARGET_PRINT_OPERAND_PUNCT_VALID_P visium_print_operand_punct_valid_p
-#undef TARGET_PRINT_OPERAND
+
+#undef TARGET_PRINT_OPERAND
#define TARGET_PRINT_OPERAND visium_print_operand
-#undef TARGET_PRINT_OPERAND_ADDRESS
+
+#undef TARGET_PRINT_OPERAND_ADDRESS
#define TARGET_PRINT_OPERAND_ADDRESS visium_print_operand_address
#undef TARGET_ATTRIBUTE_TABLE
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT visium_trampoline_init
-#undef TARGET_MD_ASM_ADJUST
+#undef TARGET_MD_ASM_ADJUST
#define TARGET_MD_ASM_ADJUST visium_md_asm_adjust
-#undef TARGET_FLAGS_REGNUM
+#undef TARGET_FLAGS_REGNUM
#define TARGET_FLAGS_REGNUM FLAGS_REGNUM
-#undef TARGET_HARD_REGNO_MODE_OK
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS visium_hard_regno_nregs
+
+#undef TARGET_HARD_REGNO_MODE_OK
#define TARGET_HARD_REGNO_MODE_OK visium_hard_regno_mode_ok
-#undef TARGET_MODES_TIEABLE_P
+#undef TARGET_MODES_TIEABLE_P
#define TARGET_MODES_TIEABLE_P visium_modes_tieable_p
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS visium_can_change_mode_class
+
+#undef TARGET_CONSTANT_ALIGNMENT
+#define TARGET_CONSTANT_ALIGNMENT visium_constant_alignment
+
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
namespace {
visium_option_override (void)
{
if (flag_pic == 1)
- warning (OPT_fpic, "-fpic is not supported");
+ warning (OPT_fpic, "%<-fpic%> is not supported");
if (flag_pic == 2)
- warning (OPT_fPIC, "-fPIC is not supported");
+ warning (OPT_fPIC, "%<-fPIC%> is not supported");
/* MCM is the default in the GR5/GR6 era. */
target_flags |= MASK_MCM;
/* Align functions on 256-byte (32-quadword) for GR5 and 64-byte (8-quadword)
boundaries for GR6 so they start a new burst mode window. */
- if (align_functions == 0)
+ if (flag_align_functions && !str_align_functions)
{
if (visium_cpu == PROCESSOR_GR6)
- align_functions = 64;
+ str_align_functions = "64";
else
- align_functions = 256;
+ str_align_functions = "256";
/* Allow the size of compilation units to double because of inlining.
In practice the global size of the object code is hardly affected
}
/* Likewise for loops. */
- if (align_loops == 0)
+ if (flag_align_loops && !str_align_loops)
{
if (visium_cpu == PROCESSOR_GR6)
- align_loops = 64;
+ str_align_loops = "64";
else
{
- align_loops = 256;
/* But not if they are too far away from a 256-byte boundary. */
- align_loops_max_skip = 31;
+ str_align_loops = "256:32:8";
}
}
/* Align all jumps on quadword boundaries for the burst mode, and even
on 8-quadword boundaries for GR6 so they start a new window. */
- if (align_jumps == 0)
+ if (flag_align_jumps && !str_align_jumps)
{
if (visium_cpu == PROCESSOR_GR6)
- align_jumps = 64;
+ str_align_jumps = "64";
else
- align_jumps = 8;
+ str_align_jumps = "8";
}
-
- /* We register a machine-specific pass. This pass must be scheduled as
- late as possible so that we have the (essentially) final form of the
- insn stream to work on. Registering the pass must be done at start up.
- It's convenient to do it here. */
- opt_pass *visium_reorg_pass = make_pass_visium_reorg (g);
- struct register_pass_info insert_pass_visium_reorg =
- {
- visium_reorg_pass, /* pass */
- "dbr", /* reference_pass_name */
- 1, /* ref_pass_instance_number */
- PASS_POS_INSERT_AFTER /* po_op */
- };
- register_pass (&insert_pass_visium_reorg);
}
/* Register the Visium-specific libfuncs with the middle-end. */
}
else if (!TARGET_SV_MODE)
{
- error ("an interrupt handler cannot be compiled with -muser-mode");
+ error ("an interrupt handler cannot be compiled with %<-muser-mode%>");
*no_add_attrs = true;
}
return align;
}
+/* Implement TARGET_CONSTANT_ALIGNMENT. */
+
+static HOST_WIDE_INT
+visium_constant_alignment (const_tree exp, HOST_WIDE_INT align)
+{
+ return visium_data_alignment (TREE_TYPE (exp), align);
+}
+
/* Helper function for HARD_REGNO_RENAME_OK (FROM, TO). Return non-zero if
it is OK to rename a hard register FROM to another hard register TO. */
return 1;
}
+/* Implement TARGET_HARD_REGNO_NREGS. */
+
+static unsigned int
+visium_hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+ if (regno == MDB_REGNUM)
+ return CEIL (GET_MODE_SIZE (mode), 2 * UNITS_PER_WORD);
+ return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
+}
+
/* Implement TARGET_HARD_REGNO_MODE_OK.
Modes with sizes which cross from the one register class to the
return mode == SFmode || (mode == SImode && TARGET_FPU_IEEE);
return (GET_MODE_CLASS (mode) == MODE_INT
- && HARD_REGNO_NREGS (regno, mode) == 1);
+ && visium_hard_regno_nregs (regno, mode) == 1);
}
/* Implement TARGET_MODES_TIEABLE_P. */
int offset_base = offset & ~mask;
/* Check that all of the words can be accessed. */
- if (4 < size && 0x80 < size + offset - offset_base)
+ if (size > 4 && size + offset - offset_base > 0x80)
offset_base = offset & ~0x3f;
if (offset_base != 0 && offset_base != offset && (offset & mask1) == 0)
{
int offset_base = offset & ~mask;
/* Check that all of the words can be accessed. */
- if (4 < size && 0x80 < size + offset - offset_base)
+ if (size > 4 && size + offset - offset_base > 0x80)
offset_base = offset & ~0x3f;
if (offset_base && (offset & mask1) == 0)
moviu r9,%u FUNCTION
movil r9,%l FUNCTION
+ [nop]
moviu r20,%u STATIC
bra tr,r9,r9
movil r20,%l STATIC
NULL_RTX),
0x04890000));
+ if (visium_cpu == PROCESSOR_GR6)
+ {
+ /* For the GR6, the BRA insn must be aligned on a 64-bit boundary. */
+ gcc_assert (TRAMPOLINE_ALIGNMENT >= 64);
+ emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, addr, 12)),
+ gen_int_mode (0, SImode));
+ }
+
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, addr, 8)),
plus_constant (SImode,
expand_shift (RSHIFT_EXPR, SImode,
/* This is a btst, the result is in C instead of Z. */
return CCCmode;
- case CONST_INT:
- /* This is a degenerate case, typically an uninitialized variable. */
- gcc_assert (op0 == constm1_rtx);
-
- /* ... fall through ... */
-
case REG:
case AND:
case IOR:
when applied to a comparison with zero. */
return CCmode;
+ /* ??? Cater to the junk RTXes sent by try_merge_compare. */
+ case ASM_OPERANDS:
+ case CALL:
+ case CONST_INT:
+ case LO_SUM:
+ case HIGH:
+ case MEM:
+ case UNSPEC:
+ case ZERO_EXTEND:
+ return CCmode;
+
default:
gcc_unreachable ();
}
gcc_assert (cond);
operands[0] = label;
- /* If the length of the instruction is greater than 8, then this is a
+ /* If the length of the instruction is greater than 12, then this is a
long branch and we need to work harder to emit it properly. */
- if (get_attr_length (insn) > 8)
+ if (get_attr_length (insn) > 12)
{
bool spilled;
if (final_sequence)
{
rtx_insn *delay = NEXT_INSN (insn);
- int seen;
gcc_assert (delay);
- final_scan_insn (delay, asm_out_file, optimize, 0, &seen);
+ final_scan_insn (delay, asm_out_file, optimize, 0, NULL);
PATTERN (delay) = gen_blockage ();
INSN_CODE (delay) = -1;
}
return regno;
}
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.
+
+ It's not obvious from the documentation of the hook that MDB cannot
+ change mode. However difficulties arise from expressions of the form
+
+ (subreg:SI (reg:DI R_MDB) 0)
+
+ There is no way to convert that reference to a single machine
+ register and, without the following definition, reload will quietly
+ convert it to
+
+ (reg:SI R_MDB). */
+
+static bool
+visium_can_change_mode_class (machine_mode from, machine_mode to,
+ reg_class_t rclass)
+{
+ return (rclass != MDB || GET_MODE_SIZE (from) == GET_MODE_SIZE (to));
+}
+
#include "gt-visium.h"