summaryrefslogtreecommitdiff
path: root/gcc/config/sparc/sparc.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/sparc/sparc.c')
-rw-r--r--gcc/config/sparc/sparc.c457
1 files changed, 417 insertions, 40 deletions
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 790a0367b67..83ca1dcc617 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -448,6 +448,30 @@ struct processor_costs niagara7_costs = {
0, /* shift penalty */
};
+static const
+struct processor_costs m8_costs = {
+ COSTS_N_INSNS (3), /* int load */
+ COSTS_N_INSNS (3), /* int signed load */
+ COSTS_N_INSNS (3), /* int zeroed load */
+ COSTS_N_INSNS (3), /* float load */
+ COSTS_N_INSNS (9), /* fmov, fneg, fabs */
+ COSTS_N_INSNS (9), /* fadd, fsub */
+ COSTS_N_INSNS (9), /* fcmp */
+ COSTS_N_INSNS (9), /* fmov, fmovr */
+ COSTS_N_INSNS (9), /* fmul */
+ COSTS_N_INSNS (26), /* fdivs */
+ COSTS_N_INSNS (30), /* fdivd */
+ COSTS_N_INSNS (33), /* fsqrts */
+ COSTS_N_INSNS (41), /* fsqrtd */
+ COSTS_N_INSNS (12), /* imul */
+ COSTS_N_INSNS (10), /* imulX */
+ 0, /* imul bit factor */
+ COSTS_N_INSNS (57), /* udiv/sdiv */
+ COSTS_N_INSNS (30), /* udivx/sdivx */
+ COSTS_N_INSNS (1), /* movcc/movr */
+ 0, /* shift penalty */
+};
+
static const struct processor_costs *sparc_costs = &cypress_costs;
#ifdef HAVE_AS_RELAX_OPTION
@@ -896,6 +920,12 @@ mem_ref (rtx x)
to properly detect the various hazards. Therefore, this machine specific
pass runs as late as possible. */
+/* True if INSN is a md pattern or asm statement. */
+#define USEFUL_INSN_P(INSN) \
+ (NONDEBUG_INSN_P (INSN) \
+ && GET_CODE (PATTERN (INSN)) != USE \
+ && GET_CODE (PATTERN (INSN)) != CLOBBER)
+
static unsigned int
sparc_do_work_around_errata (void)
{
@@ -915,6 +945,81 @@ sparc_do_work_around_errata (void)
if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (PATTERN (insn)))
insn = seq->insn (1);
+ /* Look for either of these two sequences:
+
+ Sequence A:
+ 1. store of word size or less (e.g. st / stb / sth / stf)
+ 2. any single instruction that is not a load or store
+ 3. any store instruction (e.g. st / stb / sth / stf / std / stdf)
+
+ Sequence B:
+ 1. store of double word size (e.g. std / stdf)
+ 2. any store instruction (e.g. st / stb / sth / stf / std / stdf) */
+ if (sparc_fix_b2bst
+ && NONJUMP_INSN_P (insn)
+ && (set = single_set (insn)) != NULL_RTX
+ && MEM_P (SET_DEST (set)))
+ {
+ /* Sequence B begins with a double-word store. */
+ bool seq_b = GET_MODE_SIZE (GET_MODE (SET_DEST (set))) == 8;
+ rtx_insn *after;
+ int i;
+
+ next = next_active_insn (insn);
+ if (!next)
+ break;
+
+ for (after = next, i = 0; i < 2; i++)
+ {
+ /* Skip empty assembly statements. */
+ if ((GET_CODE (PATTERN (after)) == UNSPEC_VOLATILE)
+ || (USEFUL_INSN_P (after)
+ && (asm_noperands (PATTERN (after))>=0)
+ && !strcmp (decode_asm_operands (PATTERN (after),
+ NULL, NULL, NULL,
+ NULL, NULL), "")))
+ after = next_active_insn (after);
+ if (!after)
+ break;
+
+ /* If the insn is a branch, then it cannot be problematic. */
+ if (!NONJUMP_INSN_P (after)
+ || GET_CODE (PATTERN (after)) == SEQUENCE)
+ break;
+
+ /* Sequence B is only two instructions long. */
+ if (seq_b)
+ {
+ /* Add NOP if followed by a store. */
+ if ((set = single_set (after)) != NULL_RTX
+ && MEM_P (SET_DEST (set)))
+ insert_nop = true;
+
+ /* Otherwise it is ok. */
+ break;
+ }
+
+ /* If the second instruction is a load or a store,
+ then the sequence cannot be problematic. */
+ if (i == 0)
+ {
+ if (((set = single_set (after)) != NULL_RTX)
+ && (MEM_P (SET_DEST (set)) || MEM_P (SET_SRC (set))))
+ break;
+
+ after = next_active_insn (after);
+ if (!after)
+ break;
+ }
+
+ /* Add NOP if third instruction is a store. */
+ if (i == 1
+ && ((set = single_set (after)) != NULL_RTX)
+ && MEM_P (SET_DEST (set)))
+ insert_nop = true;
+ }
+ }
+ else
/* Look for a single-word load into an odd-numbered FP register. */
if (sparc_fix_at697f
&& NONJUMP_INSN_P (insn)
@@ -1167,8 +1272,7 @@ public:
/* opt_pass methods: */
virtual bool gate (function *)
{
- /* The only errata we handle are those of the AT697F and UT699. */
- return sparc_fix_at697f != 0 || sparc_fix_ut699 != 0;
+ return sparc_fix_at697f || sparc_fix_ut699 || sparc_fix_b2bst;
}
virtual unsigned int execute (function *)
@@ -1200,6 +1304,8 @@ dump_target_flag_bits (const int flags)
fprintf (stderr, "FLAT ");
if (flags & MASK_FMAF)
fprintf (stderr, "FMAF ");
+ if (flags & MASK_FSMULD)
+ fprintf (stderr, "FSMULD ");
if (flags & MASK_FPU)
fprintf (stderr, "FPU ");
if (flags & MASK_HARD_QUAD)
@@ -1222,6 +1328,8 @@ dump_target_flag_bits (const int flags)
fprintf (stderr, "VIS3 ");
if (flags & MASK_VIS4)
fprintf (stderr, "VIS4 ");
+ if (flags & MASK_VIS4B)
+ fprintf (stderr, "VIS4B ");
if (flags & MASK_CBCOND)
fprintf (stderr, "CBCOND ");
if (flags & MASK_DEPRECATED_V8_INSNS)
@@ -1286,6 +1394,7 @@ sparc_option_override (void)
{ TARGET_CPU_niagara3, PROCESSOR_NIAGARA3 },
{ TARGET_CPU_niagara4, PROCESSOR_NIAGARA4 },
{ TARGET_CPU_niagara7, PROCESSOR_NIAGARA7 },
+ { TARGET_CPU_m8, PROCESSOR_M8 },
{ -1, PROCESSOR_V7 }
};
const struct cpu_default *def;
@@ -1296,24 +1405,24 @@ sparc_option_override (void)
const int disable;
const int enable;
} const cpu_table[] = {
- { "v7", MASK_ISA, 0 },
- { "cypress", MASK_ISA, 0 },
+ { "v7", MASK_ISA|MASK_FSMULD, 0 },
+ { "cypress", MASK_ISA|MASK_FSMULD, 0 },
{ "v8", MASK_ISA, MASK_V8 },
/* TI TMS390Z55 supersparc */
{ "supersparc", MASK_ISA, MASK_V8 },
- { "hypersparc", MASK_ISA, MASK_V8|MASK_FPU },
- { "leon", MASK_ISA, MASK_V8|MASK_LEON|MASK_FPU },
- { "leon3", MASK_ISA, MASK_V8|MASK_LEON3|MASK_FPU },
- { "leon3v7", MASK_ISA, MASK_LEON3|MASK_FPU },
- { "sparclite", MASK_ISA, MASK_SPARCLITE },
+ { "hypersparc", MASK_ISA, MASK_V8 },
+ { "leon", MASK_ISA|MASK_FSMULD, MASK_V8|MASK_LEON },
+ { "leon3", MASK_ISA, MASK_V8|MASK_LEON3 },
+ { "leon3v7", MASK_ISA|MASK_FSMULD, MASK_LEON3 },
+ { "sparclite", MASK_ISA|MASK_FSMULD, MASK_SPARCLITE },
/* The Fujitsu MB86930 is the original sparclite chip, with no FPU. */
{ "f930", MASK_ISA|MASK_FPU, MASK_SPARCLITE },
/* The Fujitsu MB86934 is the recent sparclite chip, with an FPU. */
- { "f934", MASK_ISA, MASK_SPARCLITE|MASK_FPU },
+ { "f934", MASK_ISA|MASK_FSMULD, MASK_SPARCLITE },
{ "sparclite86x", MASK_ISA|MASK_FPU, MASK_SPARCLITE },
- { "sparclet", MASK_ISA, MASK_SPARCLET },
+ { "sparclet", MASK_ISA|MASK_FSMULD, MASK_SPARCLET },
/* TEMIC sparclet */
- { "tsc701", MASK_ISA, MASK_SPARCLET },
+ { "tsc701", MASK_ISA|MASK_FSMULD, MASK_SPARCLET },
{ "v9", MASK_ISA, MASK_V9 },
/* UltraSPARC I, II, IIi */
{ "ultrasparc", MASK_ISA,
@@ -1337,7 +1446,10 @@ sparc_option_override (void)
MASK_V9|MASK_POPC|MASK_VIS3|MASK_FMAF|MASK_CBCOND },
/* UltraSPARC M7 */
{ "niagara7", MASK_ISA,
- MASK_V9|MASK_POPC|MASK_VIS4|MASK_FMAF|MASK_CBCOND|MASK_SUBXC }
+ MASK_V9|MASK_POPC|MASK_VIS4|MASK_FMAF|MASK_CBCOND|MASK_SUBXC },
+ /* UltraSPARC M8 */
+ { "m8", MASK_ISA,
+ MASK_V9|MASK_POPC|MASK_VIS4|MASK_FMAF|MASK_CBCOND|MASK_SUBXC|MASK_VIS4B }
};
const struct cpu_table *cpu;
unsigned int i;
@@ -1376,6 +1488,11 @@ sparc_option_override (void)
}
}
+ /* Enable the FsMULd instruction by default if not explicitly specified by
+ the user. It may be later disabled by the CPU (explicitly or not). */
+ if (TARGET_FPU && !(target_flags_explicit & MASK_FSMULD))
+ target_flags |= MASK_FSMULD;
+
if (TARGET_DEBUG_OPTIONS)
{
dump_target_flags("Initial target_flags", target_flags);
@@ -1421,7 +1538,7 @@ sparc_option_override (void)
sparc_cmodel = cmodel->value;
}
else
- error ("-mcmodel= is not supported on 32 bit systems");
+ error ("-mcmodel= is not supported on 32-bit systems");
}
/* Check that -fcall-saved-REG wasn't specified for out registers. */
@@ -1432,7 +1549,7 @@ sparc_option_override (void)
call_used_regs [i] = 1;
}
- /* Set the default CPU. */
+ /* Set the default CPU if no -mcpu option was specified. */
if (!global_options_set.x_sparc_cpu_and_features)
{
for (def = &cpu_default[0]; def->cpu != -1; ++def)
@@ -1442,6 +1559,7 @@ sparc_option_override (void)
sparc_cpu_and_features = def->processor;
}
+ /* Set the default CPU if no -mtune option was specified. */
if (!global_options_set.x_sparc_cpu)
sparc_cpu = sparc_cpu_and_features;
@@ -1450,8 +1568,6 @@ sparc_option_override (void)
if (TARGET_DEBUG_OPTIONS)
{
fprintf (stderr, "sparc_cpu_and_features: %s\n", cpu->name);
- fprintf (stderr, "sparc_cpu: %s\n",
- cpu_table[(int) sparc_cpu].name);
dump_target_flags ("cpu->disable", cpu->disable);
dump_target_flags ("cpu->enable", cpu->enable);
}
@@ -1467,6 +1583,9 @@ sparc_option_override (void)
#ifndef HAVE_AS_SPARC5_VIS4
& ~(MASK_VIS4 | MASK_SUBXC)
#endif
+#ifndef HAVE_AS_SPARC6
+ & ~(MASK_VIS4B)
+#endif
#ifndef HAVE_AS_LEON
& ~(MASK_LEON | MASK_LEON3)
#endif
@@ -1485,11 +1604,15 @@ sparc_option_override (void)
if (TARGET_VIS4)
target_flags |= MASK_VIS3 | MASK_VIS2 | MASK_VIS;
- /* Don't allow -mvis, -mvis2, -mvis3, -mvis4 or -mfmaf if FPU is
- disabled. */
- if (! TARGET_FPU)
+ /* -mvis4b implies -mvis4, -mvis3, -mvis2 and -mvis */
+ if (TARGET_VIS4B)
+ target_flags |= MASK_VIS4 | MASK_VIS3 | MASK_VIS2 | MASK_VIS;
+
+ /* Don't allow -mvis, -mvis2, -mvis3, -mvis4, -mvis4b, -mfmaf and -mfsmuld if
+ FPU is disabled. */
+ if (!TARGET_FPU)
target_flags &= ~(MASK_VIS | MASK_VIS2 | MASK_VIS3 | MASK_VIS4
- | MASK_FMAF);
+ | MASK_VIS4B | MASK_FMAF | MASK_FSMULD);
/* -mvis assumes UltraSPARC+, so we are sure v9 instructions
are available; -m64 also implies v9. */
@@ -1500,18 +1623,18 @@ sparc_option_override (void)
}
/* -mvis also implies -mv8plus on 32-bit. */
- if (TARGET_VIS && ! TARGET_ARCH64)
+ if (TARGET_VIS && !TARGET_ARCH64)
target_flags |= MASK_V8PLUS;
- /* Use the deprecated v8 insns for sparc64 in 32 bit mode. */
+ /* Use the deprecated v8 insns for sparc64 in 32-bit mode. */
if (TARGET_V9 && TARGET_ARCH32)
target_flags |= MASK_DEPRECATED_V8_INSNS;
- /* V8PLUS requires V9, makes no sense in 64 bit mode. */
- if (! TARGET_V9 || TARGET_ARCH64)
+ /* V8PLUS requires V9 and makes no sense in 64-bit mode. */
+ if (!TARGET_V9 || TARGET_ARCH64)
target_flags &= ~MASK_V8PLUS;
- /* Don't use stack biasing in 32 bit mode. */
+ /* Don't use stack biasing in 32-bit mode. */
if (TARGET_ARCH32)
target_flags &= ~MASK_STACK_BIAS;
@@ -1519,6 +1642,14 @@ sparc_option_override (void)
if (!(target_flags_explicit & MASK_LRA))
target_flags |= MASK_LRA;
+ /* Enable the back-to-back store errata workaround for LEON3FT. */
+ if (sparc_fix_ut699 || sparc_fix_ut700 || sparc_fix_gr712rc)
+ sparc_fix_b2bst = 1;
+
+ /* Disable FsMULd for the UT699 since it doesn't work correctly. */
+ if (sparc_fix_ut699)
+ target_flags &= ~MASK_FSMULD;
+
/* Supply a default value for align_functions. */
if (align_functions == 0)
{
@@ -1529,7 +1660,8 @@ sparc_option_override (void)
|| sparc_cpu == PROCESSOR_NIAGARA3
|| sparc_cpu == PROCESSOR_NIAGARA4)
align_functions = 32;
- else if (sparc_cpu == PROCESSOR_NIAGARA7)
+ else if (sparc_cpu == PROCESSOR_NIAGARA7
+ || sparc_cpu == PROCESSOR_M8)
align_functions = 64;
}
@@ -1597,6 +1729,9 @@ sparc_option_override (void)
case PROCESSOR_NIAGARA7:
sparc_costs = &niagara7_costs;
break;
+ case PROCESSOR_M8:
+ sparc_costs = &m8_costs;
+ break;
case PROCESSOR_NATIVE:
gcc_unreachable ();
};
@@ -1659,13 +1794,14 @@ sparc_option_override (void)
|| sparc_cpu == PROCESSOR_NIAGARA4)
? 2
: (sparc_cpu == PROCESSOR_ULTRASPARC3
- ? 8 : (sparc_cpu == PROCESSOR_NIAGARA7
+ ? 8 : ((sparc_cpu == PROCESSOR_NIAGARA7
+ || sparc_cpu == PROCESSOR_M8)
? 32 : 3))),
global_options.x_param_values,
global_options_set.x_param_values);
- /* For PARAM_L1_CACHE_LINE_SIZE we use the default 32 bytes (see
- params.def), so no maybe_set_param_value is needed.
+ /* PARAM_L1_CACHE_LINE_SIZE is the size of the L1 cache line, in
+ bytes.
The Oracle SPARC Architecture (previously the UltraSPARC
Architecture) specification states that when a PREFETCH[A]
@@ -1681,6 +1817,11 @@ sparc_option_override (void)
L2 and L3, but only 32B are brought into the L1D$. (Assuming it
is a read_n prefetch, which is the only type which allocates to
the L1.) */
+ maybe_set_param_value (PARAM_L1_CACHE_LINE_SIZE,
+ (sparc_cpu == PROCESSOR_M8
+ ? 64 : 32),
+ global_options.x_param_values,
+ global_options_set.x_param_values);
/* PARAM_L1_CACHE_SIZE is the size of the L1D$ (most SPARC chips use
Hardvard level-1 caches) in kilobytes. Both UltraSPARC and
@@ -1692,7 +1833,8 @@ sparc_option_override (void)
|| sparc_cpu == PROCESSOR_NIAGARA2
|| sparc_cpu == PROCESSOR_NIAGARA3
|| sparc_cpu == PROCESSOR_NIAGARA4
- || sparc_cpu == PROCESSOR_NIAGARA7)
+ || sparc_cpu == PROCESSOR_NIAGARA7
+ || sparc_cpu == PROCESSOR_M8)
? 16 : 64),
global_options.x_param_values,
global_options_set.x_param_values);
@@ -1701,7 +1843,8 @@ sparc_option_override (void)
/* PARAM_L2_CACHE_SIZE is the size fo the L2 in kilobytes. Note
that 512 is the default in params.def. */
maybe_set_param_value (PARAM_L2_CACHE_SIZE,
- (sparc_cpu == PROCESSOR_NIAGARA4
+ ((sparc_cpu == PROCESSOR_NIAGARA4
+ || sparc_cpu == PROCESSOR_M8)
? 128 : (sparc_cpu == PROCESSOR_NIAGARA7
? 256 : 512)),
global_options.x_param_values,
@@ -4829,7 +4972,7 @@ enum sparc_mode_class {
??? Note that, despite the settings, non-double-aligned parameter
registers can hold double-word quantities in 32-bit mode. */
-/* This points to either the 32 bit or the 64 bit version. */
+/* This points to either the 32-bit or the 64-bit version. */
const int *hard_regno_mode_classes;
static const int hard_32bit_mode_classes[] = {
@@ -7163,7 +7306,7 @@ sparc_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
}
/* Handle the FUNCTION_ARG_PADDING macro.
- For the 64 bit ABI structs are always stored left shifted in their
+ For the 64-bit ABI structs are always stored left shifted in their
argument slot. */
enum direction
@@ -8281,7 +8424,7 @@ output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
if (reversed ^ far)
code = reverse_condition (code);
- /* Only 64 bit versions of these instructions exist. */
+ /* Only 64-bit versions of these instructions exist. */
gcc_assert (mode == DImode);
/* Start by writing the branch condition. */
@@ -8709,7 +8852,7 @@ mems_ok_for_ldd_peep (rtx mem1, rtx mem2, rtx dependent_reg_rtx)
return 0;
/* The first offset must be evenly divisible by 8 to ensure the
- address is 64 bit aligned. */
+ address is 64-bit aligned. */
if (offset1 % 8 != 0)
return 0;
@@ -9478,7 +9621,8 @@ sparc32_initialize_trampoline (rtx m_tramp, rtx fnaddr, rtx cxt)
&& sparc_cpu != PROCESSOR_NIAGARA2
&& sparc_cpu != PROCESSOR_NIAGARA3
&& sparc_cpu != PROCESSOR_NIAGARA4
- && sparc_cpu != PROCESSOR_NIAGARA7)
+ && sparc_cpu != PROCESSOR_NIAGARA7
+ && sparc_cpu != PROCESSOR_M8)
emit_insn (gen_flushsi (validize_mem (adjust_address (m_tramp, SImode, 8))));
/* Call __enable_execute_stack after writing onto the stack to make sure
@@ -9524,7 +9668,8 @@ sparc64_initialize_trampoline (rtx m_tramp, rtx fnaddr, rtx cxt)
&& sparc_cpu != PROCESSOR_NIAGARA2
&& sparc_cpu != PROCESSOR_NIAGARA3
&& sparc_cpu != PROCESSOR_NIAGARA4
- && sparc_cpu != PROCESSOR_NIAGARA7)
+ && sparc_cpu != PROCESSOR_NIAGARA7
+ && sparc_cpu != PROCESSOR_M8)
emit_insn (gen_flushdi (validize_mem (adjust_address (m_tramp, DImode, 8))));
/* Call __enable_execute_stack after writing onto the stack to make sure
@@ -9724,7 +9869,8 @@ sparc_use_sched_lookahead (void)
|| sparc_cpu == PROCESSOR_NIAGARA3)
return 0;
if (sparc_cpu == PROCESSOR_NIAGARA4
- || sparc_cpu == PROCESSOR_NIAGARA7)
+ || sparc_cpu == PROCESSOR_NIAGARA7
+ || sparc_cpu == PROCESSOR_M8)
return 2;
if (sparc_cpu == PROCESSOR_ULTRASPARC
|| sparc_cpu == PROCESSOR_ULTRASPARC3)
@@ -9758,6 +9904,7 @@ sparc_issue_rate (void)
return 2;
case PROCESSOR_ULTRASPARC:
case PROCESSOR_ULTRASPARC3:
+ case PROCESSOR_M8:
return 4;
}
}
@@ -10340,6 +10487,45 @@ enum sparc_builtins
SPARC_BUILTIN_FPSUBS8,
SPARC_BUILTIN_FPSUBUS8,
SPARC_BUILTIN_FPSUBUS16,
+
+ /* VIS 4.0B builtins. */
+
+ /* Note that all the DICTUNPACK* entries should be kept
+ contiguous. */
+ SPARC_BUILTIN_FIRST_DICTUNPACK,
+ SPARC_BUILTIN_DICTUNPACK8 = SPARC_BUILTIN_FIRST_DICTUNPACK,
+ SPARC_BUILTIN_DICTUNPACK16,
+ SPARC_BUILTIN_DICTUNPACK32,
+ SPARC_BUILTIN_LAST_DICTUNPACK = SPARC_BUILTIN_DICTUNPACK32,
+
+ /* Note that all the FPCMP*SHL entries should be kept
+ contiguous. */
+ SPARC_BUILTIN_FIRST_FPCMPSHL,
+ SPARC_BUILTIN_FPCMPLE8SHL = SPARC_BUILTIN_FIRST_FPCMPSHL,
+ SPARC_BUILTIN_FPCMPGT8SHL,
+ SPARC_BUILTIN_FPCMPEQ8SHL,
+ SPARC_BUILTIN_FPCMPNE8SHL,
+ SPARC_BUILTIN_FPCMPLE16SHL,
+ SPARC_BUILTIN_FPCMPGT16SHL,
+ SPARC_BUILTIN_FPCMPEQ16SHL,
+ SPARC_BUILTIN_FPCMPNE16SHL,
+ SPARC_BUILTIN_FPCMPLE32SHL,
+ SPARC_BUILTIN_FPCMPGT32SHL,
+ SPARC_BUILTIN_FPCMPEQ32SHL,
+ SPARC_BUILTIN_FPCMPNE32SHL,
+ SPARC_BUILTIN_FPCMPULE8SHL,
+ SPARC_BUILTIN_FPCMPUGT8SHL,
+ SPARC_BUILTIN_FPCMPULE16SHL,
+ SPARC_BUILTIN_FPCMPUGT16SHL,
+ SPARC_BUILTIN_FPCMPULE32SHL,
+ SPARC_BUILTIN_FPCMPUGT32SHL,
+ SPARC_BUILTIN_FPCMPDE8SHL,
+ SPARC_BUILTIN_FPCMPDE16SHL,
+ SPARC_BUILTIN_FPCMPDE32SHL,
+ SPARC_BUILTIN_FPCMPUR8SHL,
+ SPARC_BUILTIN_FPCMPUR16SHL,
+ SPARC_BUILTIN_FPCMPUR32SHL,
+ SPARC_BUILTIN_LAST_FPCMPSHL = SPARC_BUILTIN_FPCMPUR32SHL,
SPARC_BUILTIN_MAX
};
@@ -10347,6 +10533,27 @@ enum sparc_builtins
static GTY (()) tree sparc_builtins[(int) SPARC_BUILTIN_MAX];
static enum insn_code sparc_builtins_icode[(int) SPARC_BUILTIN_MAX];
+/* Return true if OPVAL can be used for operand OPNUM of instruction ICODE.
+ The instruction should require a constant operand of some sort. The
+ function prints an error if OPVAL is not valid. */
+
+static int
+check_constant_argument (enum insn_code icode, int opnum, rtx opval)
+{
+ if (GET_CODE (opval) != CONST_INT)
+ {
+ error ("%qs expects a constant argument", insn_data[icode].name);
+ return false;
+ }
+
+ if (!(*insn_data[icode].operand[opnum].predicate) (opval, VOIDmode))
+ {
+ error ("constant argument out of range for %qs", insn_data[icode].name);
+ return false;
+ }
+ return true;
+}
+
/* Add a SPARC builtin function with NAME, ICODE, CODE and TYPE. Return the
function decl or NULL_TREE if the builtin was not added. */
@@ -10440,6 +10647,12 @@ sparc_vis_init_builtins (void)
v8qi, v8qi, 0);
tree si_ftype_v8qi_v8qi = build_function_type_list (intSI_type_node,
v8qi, v8qi, 0);
+ tree v8qi_ftype_df_si = build_function_type_list (v8qi, double_type_node,
+ intSI_type_node, 0);
+ tree v4hi_ftype_df_si = build_function_type_list (v4hi, double_type_node,
+ intSI_type_node, 0);
+ tree v2si_ftype_df_si = build_function_type_list (v2si, double_type_node,
+ intDI_type_node, 0);
tree di_ftype_di_di = build_function_type_list (intDI_type_node,
intDI_type_node,
intDI_type_node, 0);
@@ -10894,6 +11107,156 @@ sparc_vis_init_builtins (void)
def_builtin_const ("__builtin_vis_fpsubus16", CODE_FOR_ussubv4hi3,
SPARC_BUILTIN_FPSUBUS16, v4hi_ftype_v4hi_v4hi);
}
+
+ if (TARGET_VIS4B)
+ {
+ def_builtin_const ("__builtin_vis_dictunpack8", CODE_FOR_dictunpack8,
+ SPARC_BUILTIN_DICTUNPACK8, v8qi_ftype_df_si);
+ def_builtin_const ("__builtin_vis_dictunpack16", CODE_FOR_dictunpack16,
+ SPARC_BUILTIN_DICTUNPACK16, v4hi_ftype_df_si);
+ def_builtin_const ("__builtin_vis_dictunpack32", CODE_FOR_dictunpack32,
+ SPARC_BUILTIN_DICTUNPACK32, v2si_ftype_df_si);
+
+ if (TARGET_ARCH64)
+ {
+ tree di_ftype_v8qi_v8qi_si = build_function_type_list (intDI_type_node,
+ v8qi, v8qi,
+ intSI_type_node, 0);
+ tree di_ftype_v4hi_v4hi_si = build_function_type_list (intDI_type_node,
+ v4hi, v4hi,
+ intSI_type_node, 0);
+ tree di_ftype_v2si_v2si_si = build_function_type_list (intDI_type_node,
+ v2si, v2si,
+ intSI_type_node, 0);
+
+ def_builtin_const ("__builtin_vis_fpcmple8shl", CODE_FOR_fpcmple8dishl,
+ SPARC_BUILTIN_FPCMPLE8SHL, di_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpgt8shl", CODE_FOR_fpcmpgt8dishl,
+ SPARC_BUILTIN_FPCMPGT8SHL, di_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpeq8shl", CODE_FOR_fpcmpeq8dishl,
+ SPARC_BUILTIN_FPCMPEQ8SHL, di_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpne8shl", CODE_FOR_fpcmpne8dishl,
+ SPARC_BUILTIN_FPCMPNE8SHL, di_ftype_v8qi_v8qi_si);
+
+ def_builtin_const ("__builtin_vis_fpcmple16shl", CODE_FOR_fpcmple16dishl,
+ SPARC_BUILTIN_FPCMPLE16SHL, di_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpgt16shl", CODE_FOR_fpcmpgt16dishl,
+ SPARC_BUILTIN_FPCMPGT16SHL, di_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpeq16shl", CODE_FOR_fpcmpeq16dishl,
+ SPARC_BUILTIN_FPCMPEQ16SHL, di_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpne16shl", CODE_FOR_fpcmpne16dishl,
+ SPARC_BUILTIN_FPCMPNE16SHL, di_ftype_v4hi_v4hi_si);
+
+ def_builtin_const ("__builtin_vis_fpcmple32shl", CODE_FOR_fpcmple32dishl,
+ SPARC_BUILTIN_FPCMPLE32SHL, di_ftype_v2si_v2si_si);
+ def_builtin_const ("__builtin_vis_fpcmpgt32shl", CODE_FOR_fpcmpgt32dishl,
+ SPARC_BUILTIN_FPCMPGT32SHL, di_ftype_v2si_v2si_si);
+ def_builtin_const ("__builtin_vis_fpcmpeq32shl", CODE_FOR_fpcmpeq32dishl,
+ SPARC_BUILTIN_FPCMPEQ32SHL, di_ftype_v2si_v2si_si);
+ def_builtin_const ("__builtin_vis_fpcmpne32shl", CODE_FOR_fpcmpne32dishl,
+ SPARC_BUILTIN_FPCMPNE32SHL, di_ftype_v2si_v2si_si);
+
+
+ def_builtin_const ("__builtin_vis_fpcmpule8shl", CODE_FOR_fpcmpule8dishl,
+ SPARC_BUILTIN_FPCMPULE8SHL, di_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpugt8shl", CODE_FOR_fpcmpugt8dishl,
+ SPARC_BUILTIN_FPCMPUGT8SHL, di_ftype_v8qi_v8qi_si);
+
+ def_builtin_const ("__builtin_vis_fpcmpule16shl", CODE_FOR_fpcmpule16dishl,
+ SPARC_BUILTIN_FPCMPULE16SHL, di_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpugt16shl", CODE_FOR_fpcmpugt16dishl,
+ SPARC_BUILTIN_FPCMPUGT16SHL, di_ftype_v4hi_v4hi_si);
+
+ def_builtin_const ("__builtin_vis_fpcmpule32shl", CODE_FOR_fpcmpule32dishl,
+ SPARC_BUILTIN_FPCMPULE32SHL, di_ftype_v2si_v2si_si);
+ def_builtin_const ("__builtin_vis_fpcmpugt32shl", CODE_FOR_fpcmpugt32dishl,
+ SPARC_BUILTIN_FPCMPUGT32SHL, di_ftype_v2si_v2si_si);
+
+ def_builtin_const ("__builtin_vis_fpcmpde8shl", CODE_FOR_fpcmpde8dishl,
+ SPARC_BUILTIN_FPCMPDE8SHL, di_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpde16shl", CODE_FOR_fpcmpde16dishl,
+ SPARC_BUILTIN_FPCMPDE16SHL, di_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpde32shl", CODE_FOR_fpcmpde32dishl,
+ SPARC_BUILTIN_FPCMPDE32SHL, di_ftype_v2si_v2si_si);
+
+ def_builtin_const ("__builtin_vis_fpcmpur8shl", CODE_FOR_fpcmpur8dishl,
+ SPARC_BUILTIN_FPCMPUR8SHL, di_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpur16shl", CODE_FOR_fpcmpur16dishl,
+ SPARC_BUILTIN_FPCMPUR16SHL, di_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpur32shl", CODE_FOR_fpcmpur32dishl,
+ SPARC_BUILTIN_FPCMPUR32SHL, di_ftype_v2si_v2si_si);
+
+ }
+ else
+ {
+ tree si_ftype_v8qi_v8qi_si = build_function_type_list (intSI_type_node,
+ v8qi, v8qi,
+ intSI_type_node, 0);
+ tree si_ftype_v4hi_v4hi_si = build_function_type_list (intSI_type_node,
+ v4hi, v4hi,
+ intSI_type_node, 0);
+ tree si_ftype_v2si_v2si_si = build_function_type_list (intSI_type_node,
+ v2si, v2si,
+ intSI_type_node, 0);
+
+ def_builtin_const ("__builtin_vis_fpcmple8shl", CODE_FOR_fpcmple8sishl,
+ SPARC_BUILTIN_FPCMPLE8SHL, si_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpgt8shl", CODE_FOR_fpcmpgt8sishl,
+ SPARC_BUILTIN_FPCMPGT8SHL, si_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpeq8shl", CODE_FOR_fpcmpeq8sishl,
+ SPARC_BUILTIN_FPCMPEQ8SHL, si_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpne8shl", CODE_FOR_fpcmpne8sishl,
+ SPARC_BUILTIN_FPCMPNE8SHL, si_ftype_v8qi_v8qi_si);
+
+ def_builtin_const ("__builtin_vis_fpcmple16shl", CODE_FOR_fpcmple16sishl,
+ SPARC_BUILTIN_FPCMPLE16SHL, si_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpgt16shl", CODE_FOR_fpcmpgt16sishl,
+ SPARC_BUILTIN_FPCMPGT16SHL, si_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpeq16shl", CODE_FOR_fpcmpeq16sishl,
+ SPARC_BUILTIN_FPCMPEQ16SHL, si_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpne16shl", CODE_FOR_fpcmpne16sishl,
+ SPARC_BUILTIN_FPCMPNE16SHL, si_ftype_v4hi_v4hi_si);
+
+ def_builtin_const ("__builtin_vis_fpcmple32shl", CODE_FOR_fpcmple32sishl,
+ SPARC_BUILTIN_FPCMPLE32SHL, si_ftype_v2si_v2si_si);
+ def_builtin_const ("__builtin_vis_fpcmpgt32shl", CODE_FOR_fpcmpgt32sishl,
+ SPARC_BUILTIN_FPCMPGT32SHL, si_ftype_v2si_v2si_si);
+ def_builtin_const ("__builtin_vis_fpcmpeq32shl", CODE_FOR_fpcmpeq32sishl,
+ SPARC_BUILTIN_FPCMPEQ32SHL, si_ftype_v2si_v2si_si);
+ def_builtin_const ("__builtin_vis_fpcmpne32shl", CODE_FOR_fpcmpne32sishl,
+ SPARC_BUILTIN_FPCMPNE32SHL, si_ftype_v2si_v2si_si);
+
+
+ def_builtin_const ("__builtin_vis_fpcmpule8shl", CODE_FOR_fpcmpule8sishl,
+ SPARC_BUILTIN_FPCMPULE8SHL, si_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpugt8shl", CODE_FOR_fpcmpugt8sishl,
+ SPARC_BUILTIN_FPCMPUGT8SHL, si_ftype_v8qi_v8qi_si);
+
+ def_builtin_const ("__builtin_vis_fpcmpule16shl", CODE_FOR_fpcmpule16sishl,
+ SPARC_BUILTIN_FPCMPULE16SHL, si_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpugt16shl", CODE_FOR_fpcmpugt16sishl,
+ SPARC_BUILTIN_FPCMPUGT16SHL, si_ftype_v4hi_v4hi_si);
+
+ def_builtin_const ("__builtin_vis_fpcmpule32shl", CODE_FOR_fpcmpule32sishl,
+ SPARC_BUILTIN_FPCMPULE32SHL, si_ftype_v2si_v2si_si);
+ def_builtin_const ("__builtin_vis_fpcmpugt32shl", CODE_FOR_fpcmpugt32sishl,
+ SPARC_BUILTIN_FPCMPUGT32SHL, si_ftype_v2si_v2si_si);
+
+ def_builtin_const ("__builtin_vis_fpcmpde8shl", CODE_FOR_fpcmpde8sishl,
+ SPARC_BUILTIN_FPCMPDE8SHL, si_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpde16shl", CODE_FOR_fpcmpde16sishl,
+ SPARC_BUILTIN_FPCMPDE16SHL, si_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpde32shl", CODE_FOR_fpcmpde32sishl,
+ SPARC_BUILTIN_FPCMPDE32SHL, si_ftype_v2si_v2si_si);
+
+ def_builtin_const ("__builtin_vis_fpcmpur8shl", CODE_FOR_fpcmpur8sishl,
+ SPARC_BUILTIN_FPCMPUR8SHL, si_ftype_v8qi_v8qi_si);
+ def_builtin_const ("__builtin_vis_fpcmpur16shl", CODE_FOR_fpcmpur16sishl,
+ SPARC_BUILTIN_FPCMPUR16SHL, si_ftype_v4hi_v4hi_si);
+ def_builtin_const ("__builtin_vis_fpcmpur32shl", CODE_FOR_fpcmpur32sishl,
+ SPARC_BUILTIN_FPCMPUR32SHL, si_ftype_v2si_v2si_si);
+ }
+ }
}
/* Implement TARGET_BUILTIN_DECL hook. */
@@ -10948,6 +11311,19 @@ sparc_expand_builtin (tree exp, rtx target,
insn_op = &insn_data[icode].operand[idx];
op[arg_count] = expand_normal (arg);
+ /* Some of the builtins require constant arguments. We check
+ for this here. */
+ if ((code >= SPARC_BUILTIN_FIRST_FPCMPSHL
+ && code <= SPARC_BUILTIN_LAST_FPCMPSHL
+ && arg_count == 3)
+ || (code >= SPARC_BUILTIN_FIRST_DICTUNPACK
+ && code <= SPARC_BUILTIN_LAST_DICTUNPACK
+ && arg_count == 2))
+ {
+ if (!check_constant_argument (icode, idx, op[arg_count]))
+ return const0_rtx;
+ }
+
if (code == SPARC_BUILTIN_LDFSR || code == SPARC_BUILTIN_STFSR)
{
if (!address_operand (op[arg_count], SImode))
@@ -11458,7 +11834,8 @@ sparc_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
|| sparc_cpu == PROCESSOR_NIAGARA2
|| sparc_cpu == PROCESSOR_NIAGARA3
|| sparc_cpu == PROCESSOR_NIAGARA4
- || sparc_cpu == PROCESSOR_NIAGARA7)
+ || sparc_cpu == PROCESSOR_NIAGARA7
+ || sparc_cpu == PROCESSOR_M8)
return 12;
return 6;