diff options
Diffstat (limited to 'gcc/config/sparc/sparc.c')
-rw-r--r-- | gcc/config/sparc/sparc.c | 457 |
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; |