summaryrefslogtreecommitdiff
path: root/toolchain/gcc
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@openadk.org>2021-04-09 16:34:40 +0200
committerWaldemar Brodkorb <wbx@openadk.org>2021-04-09 16:34:40 +0200
commit34f64dab4829227378994f1a7f8d60d13eb33652 (patch)
tree6f13f38a32aeed8b4e7291c752f01adf449a38e9 /toolchain/gcc
parentd62765dac74142468588229405896043b79bf32d (diff)
gcc: fix sparc toolchain, patch from buildroot
Diffstat (limited to 'toolchain/gcc')
-rw-r--r--toolchain/gcc/patches/10.3.0/revert-sparc.patch23628
1 files changed, 23628 insertions, 0 deletions
diff --git a/toolchain/gcc/patches/10.3.0/revert-sparc.patch b/toolchain/gcc/patches/10.3.0/revert-sparc.patch
new file mode 100644
index 000000000..5df11ce40
--- /dev/null
+++ b/toolchain/gcc/patches/10.3.0/revert-sparc.patch
@@ -0,0 +1,23628 @@
+diff -Nur gcc-10.3.0.orig/gcc/config/sparc/sparc.c gcc-10.3.0/gcc/config/sparc/sparc.c
+--- gcc-10.3.0.orig/gcc/config/sparc/sparc.c 2021-04-08 13:56:28.201742273 +0200
++++ gcc-10.3.0/gcc/config/sparc/sparc.c 2021-04-09 07:51:37.884501308 +0200
+@@ -4157,6 +4157,13 @@
+ static bool
+ sparc_cannot_force_const_mem (machine_mode mode, rtx x)
+ {
++ /* After IRA has run in PIC mode, it is too late to put anything into the
++ constant pool if the PIC register hasn't already been initialized. */
++ if ((lra_in_progress || reload_in_progress)
++ && flag_pic
++ && !crtl->uses_pic_offset_table)
++ return true;
++
+ switch (GET_CODE (x))
+ {
+ case CONST_INT:
+@@ -4192,11 +4199,9 @@
+ }
+
+ /* Global Offset Table support. */
+-static GTY(()) rtx got_symbol_rtx = NULL_RTX;
+-static GTY(()) rtx got_register_rtx = NULL_RTX;
+ static GTY(()) rtx got_helper_rtx = NULL_RTX;
+-
+-static GTY(()) bool got_helper_needed = false;
++static GTY(()) rtx got_register_rtx = NULL_RTX;
++static GTY(()) rtx got_symbol_rtx = NULL_RTX;
+
+ /* Return the SYMBOL_REF for the Global Offset Table. */
+
+@@ -4209,6 +4214,27 @@
+ return got_symbol_rtx;
+ }
+
++#ifdef HAVE_GAS_HIDDEN
++# define USE_HIDDEN_LINKONCE 1
++#else
++# define USE_HIDDEN_LINKONCE 0
++#endif
++
++static void
++get_pc_thunk_name (char name[32], unsigned int regno)
++{
++ const char *reg_name = reg_names[regno];
++
++ /* Skip the leading '%' as that cannot be used in a
++ symbol name. */
++ reg_name += 1;
++
++ if (USE_HIDDEN_LINKONCE)
++ sprintf (name, "__sparc_get_pc_thunk.%s", reg_name);
++ else
++ ASM_GENERATE_INTERNAL_LABEL (name, "LADDPC", regno);
++}
++
+ /* Wrapper around the load_pcrel_sym{si,di} patterns. */
+
+ static rtx
+@@ -4228,78 +4254,30 @@
+ return insn;
+ }
+
+-/* Output the load_pcrel_sym{si,di} patterns. */
+-
+-const char *
+-output_load_pcrel_sym (rtx *operands)
+-{
+- if (flag_delayed_branch)
+- {
+- output_asm_insn ("sethi\t%%hi(%a1-4), %0", operands);
+- output_asm_insn ("call\t%a2", operands);
+- output_asm_insn (" add\t%0, %%lo(%a1+4), %0", operands);
+- }
+- else
+- {
+- output_asm_insn ("sethi\t%%hi(%a1-8), %0", operands);
+- output_asm_insn ("add\t%0, %%lo(%a1-4), %0", operands);
+- output_asm_insn ("call\t%a2", operands);
+- output_asm_insn (" nop", NULL);
+- }
+-
+- if (operands[2] == got_helper_rtx)
+- got_helper_needed = true;
+-
+- return "";
+-}
+-
+-#ifdef HAVE_GAS_HIDDEN
+-# define USE_HIDDEN_LINKONCE 1
+-#else
+-# define USE_HIDDEN_LINKONCE 0
+-#endif
+-
+ /* Emit code to load the GOT register. */
+
+ void
+ load_got_register (void)
+ {
+- rtx insn;
++ if (!got_register_rtx)
++ got_register_rtx = gen_rtx_REG (Pmode, GLOBAL_OFFSET_TABLE_REGNUM);
+
+ if (TARGET_VXWORKS_RTP)
+- {
+- if (!got_register_rtx)
+- got_register_rtx = pic_offset_table_rtx;
+-
+- insn = gen_vxworks_load_got ();
+- }
++ emit_insn (gen_vxworks_load_got ());
+ else
+ {
+- if (!got_register_rtx)
+- got_register_rtx = gen_rtx_REG (Pmode, GLOBAL_OFFSET_TABLE_REGNUM);
+-
+ /* The GOT symbol is subject to a PC-relative relocation so we need a
+ helper function to add the PC value and thus get the final value. */
+ if (!got_helper_rtx)
+ {
+ char name[32];
+-
+- /* Skip the leading '%' as that cannot be used in a symbol name. */
+- if (USE_HIDDEN_LINKONCE)
+- sprintf (name, "__sparc_get_pc_thunk.%s",
+- reg_names[REGNO (got_register_rtx)] + 1);
+- else
+- ASM_GENERATE_INTERNAL_LABEL (name, "LADDPC",
+- REGNO (got_register_rtx));
+-
++ get_pc_thunk_name (name, GLOBAL_OFFSET_TABLE_REGNUM);
+ got_helper_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
+ }
+
+- insn
+- = gen_load_pcrel_sym (got_register_rtx, sparc_got (), got_helper_rtx);
++ emit_insn (gen_load_pcrel_sym (got_register_rtx, sparc_got (),
++ got_helper_rtx));
+ }
+-
+- emit_insn (insn);
+ }
+
+ /* Ensure that we are not using patterns that are not OK with PIC. */
+@@ -5464,7 +5442,7 @@
+ return true;
+
+ /* GOT register (%l7) if needed. */
+- if (got_register_rtx && regno == REGNO (got_register_rtx))
++ if (regno == GLOBAL_OFFSET_TABLE_REGNUM && got_register_rtx)
+ return true;
+
+ /* If the function accesses prior frames, the frame pointer and the return
+@@ -12507,9 +12485,10 @@
+ sparc_file_end (void)
+ {
+ /* If we need to emit the special GOT helper function, do so now. */
+- if (got_helper_needed)
++ if (got_helper_rtx)
+ {
+ const char *name = XSTR (got_helper_rtx, 0);
++ const char *reg_name = reg_names[GLOBAL_OFFSET_TABLE_REGNUM];
+ #ifdef DWARF2_UNWIND_INFO
+ bool do_cfi;
+ #endif
+@@ -12546,22 +12525,17 @@
+ #ifdef DWARF2_UNWIND_INFO
+ do_cfi = dwarf2out_do_cfi_asm ();
+ if (do_cfi)
+- output_asm_insn (".cfi_startproc", NULL);
++ fprintf (asm_out_file, "\t.cfi_startproc\n");
+ #endif
+ if (flag_delayed_branch)
+- {
+- output_asm_insn ("jmp\t%%o7+8", NULL);
+- output_asm_insn (" add\t%%o7, %0, %0", &got_register_rtx);
+- }
++ fprintf (asm_out_file, "\tjmp\t%%o7+8\n\t add\t%%o7, %s, %s\n",
++ reg_name, reg_name);
+ else
+- {
+- output_asm_insn ("add\t%%o7, %0, %0", &got_register_rtx);
+- output_asm_insn ("jmp\t%%o7+8", NULL);
+- output_asm_insn (" nop", NULL);
+- }
++ fprintf (asm_out_file, "\tadd\t%%o7, %s, %s\n\tjmp\t%%o7+8\n\t nop\n",
++ reg_name, reg_name);
+ #ifdef DWARF2_UNWIND_INFO
+ if (do_cfi)
+- output_asm_insn (".cfi_endproc", NULL);
++ fprintf (asm_out_file, "\t.cfi_endproc\n");
+ #endif
+ }
+
+@@ -13056,10 +13030,7 @@
+ edge entry_edge;
+ rtx_insn *seq;
+
+- /* In PIC mode, we need to always initialize the PIC register if optimization
+- is enabled, because we are called from IRA and LRA may later force things
+- to the constant pool for optimization purposes. */
+- if (!flag_pic || (!crtl->uses_pic_offset_table && !optimize))
++ if (!crtl->uses_pic_offset_table)
+ return;
+
+ start_sequence ();
+diff -Nur gcc-10.3.0.orig/gcc/config/sparc/sparc.c.orig gcc-10.3.0/gcc/config/sparc/sparc.c.orig
+--- gcc-10.3.0.orig/gcc/config/sparc/sparc.c.orig 1970-01-01 01:00:00.000000000 +0100
++++ gcc-10.3.0/gcc/config/sparc/sparc.c.orig 2021-04-08 13:56:28.201742273 +0200
+@@ -0,0 +1,13813 @@
++/* Subroutines for insn-output.c for SPARC.
++ Copyright (C) 1987-2020 Free Software Foundation, Inc.
++ Contributed by Michael Tiemann (tiemann@cygnus.com)
++ 64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
++ at Cygnus Support.
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 3, or (at your option)
++any later version.
++
++GCC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++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 "backend.h"
++#include "target.h"
++#include "rtl.h"
++#include "tree.h"
++#include "memmodel.h"
++#include "gimple.h"
++#include "df.h"
++#include "tm_p.h"
++#include "stringpool.h"
++#include "attribs.h"
++#include "expmed.h"
++#include "optabs.h"
++#include "regs.h"
++#include "emit-rtl.h"
++#include "recog.h"
++#include "diagnostic-core.h"
++#include "alias.h"
++#include "fold-const.h"
++#include "stor-layout.h"
++#include "calls.h"
++#include "varasm.h"
++#include "output.h"
++#include "insn-attr.h"
++#include "explow.h"
++#include "expr.h"
++#include "debug.h"
++#include "cfgrtl.h"
++#include "common/common-target.h"
++#include "gimplify.h"
++#include "langhooks.h"
++#include "reload.h"
++#include "tree-pass.h"
++#include "context.h"
++#include "builtins.h"
++#include "tree-vector-builder.h"
++#include "opts.h"
++
++/* This file should be included last. */
++#include "target-def.h"
++
++/* Processor costs */
++
++struct processor_costs {
++ /* Integer load */
++ const int int_load;
++
++ /* Integer signed load */
++ const int int_sload;
++
++ /* Integer zeroed load */
++ const int int_zload;
++
++ /* Float load */
++ const int float_load;
++
++ /* fmov, fneg, fabs */
++ const int float_move;
++
++ /* fadd, fsub */
++ const int float_plusminus;
++
++ /* fcmp */
++ const int float_cmp;
++
++ /* fmov, fmovr */
++ const int float_cmove;
++
++ /* fmul */
++ const int float_mul;
++
++ /* fdivs */
++ const int float_div_sf;
++
++ /* fdivd */
++ const int float_div_df;
++
++ /* fsqrts */
++ const int float_sqrt_sf;
++
++ /* fsqrtd */
++ const int float_sqrt_df;
++
++ /* umul/smul */
++ const int int_mul;
++
++ /* mulX */
++ const int int_mulX;
++
++ /* integer multiply cost for each bit set past the most
++ significant 3, so the formula for multiply cost becomes:
++
++ if (rs1 < 0)
++ highest_bit = highest_clear_bit(rs1);
++ else
++ highest_bit = highest_set_bit(rs1);
++ if (highest_bit < 3)
++ highest_bit = 3;
++ cost = int_mul{,X} + ((highest_bit - 3) / int_mul_bit_factor);
++
++ A value of zero indicates that the multiply costs is fixed,
++ and not variable. */
++ const int int_mul_bit_factor;
++
++ /* udiv/sdiv */
++ const int int_div;
++
++ /* divX */
++ const int int_divX;
++
++ /* movcc, movr */
++ const int int_cmove;
++
++ /* penalty for shifts, due to scheduling rules etc. */
++ const int shift_penalty;
++
++ /* cost of a (predictable) branch. */
++ const int branch_cost;
++};
++
++static const
++struct processor_costs cypress_costs = {
++ COSTS_N_INSNS (2), /* int load */
++ COSTS_N_INSNS (2), /* int signed load */
++ COSTS_N_INSNS (2), /* int zeroed load */
++ COSTS_N_INSNS (2), /* float load */
++ COSTS_N_INSNS (5), /* fmov, fneg, fabs */
++ COSTS_N_INSNS (5), /* fadd, fsub */
++ COSTS_N_INSNS (1), /* fcmp */
++ COSTS_N_INSNS (1), /* fmov, fmovr */
++ COSTS_N_INSNS (7), /* fmul */
++ COSTS_N_INSNS (37), /* fdivs */
++ COSTS_N_INSNS (37), /* fdivd */
++ COSTS_N_INSNS (63), /* fsqrts */
++ COSTS_N_INSNS (63), /* fsqrtd */
++ COSTS_N_INSNS (1), /* imul */
++ COSTS_N_INSNS (1), /* imulX */
++ 0, /* imul bit factor */
++ COSTS_N_INSNS (1), /* idiv */
++ COSTS_N_INSNS (1), /* idivX */
++ COSTS_N_INSNS (1), /* movcc/movr */
++ 0, /* shift penalty */
++ 3 /* branch cost */
++};
++
++static const
++struct processor_costs supersparc_costs = {
++ COSTS_N_INSNS (1), /* int load */
++ COSTS_N_INSNS (1), /* int signed load */
++ COSTS_N_INSNS (1), /* int zeroed load */
++ COSTS_N_INSNS (0), /* float load */
++ COSTS_N_INSNS (3), /* fmov, fneg, fabs */
++ COSTS_N_INSNS (3), /* fadd, fsub */
++ COSTS_N_INSNS (3), /* fcmp */
++ COSTS_N_INSNS (1), /* fmov, fmovr */
++ COSTS_N_INSNS (3), /* fmul */
++ COSTS_N_INSNS (6), /* fdivs */
++ COSTS_N_INSNS (9), /* fdivd */
++ COSTS_N_INSNS (12), /* fsqrts */
++ COSTS_N_INSNS (12), /* fsqrtd */
++ COSTS_N_INSNS (4), /* imul */
++ COSTS_N_INSNS (4), /* imulX */
++ 0, /* imul bit factor */
++ COSTS_N_INSNS (4), /* idiv */
++ COSTS_N_INSNS (4), /* idivX */
++ COSTS_N_INSNS (1), /* movcc/movr */
++ 1, /* shift penalty */
++ 3 /* branch cost */
++};
++
++static const
++struct processor_costs hypersparc_costs = {
++ COSTS_N_INSNS (1), /* int load */
++ COSTS_N_INSNS (1), /* int signed load */
++ COSTS_N_INSNS (1), /* int zeroed load */
++ COSTS_N_INSNS (1), /* float load */
++ COSTS_N_INSNS (1), /* fmov, fneg, fabs */
++ COSTS_N_INSNS (1), /* fadd, fsub */
++ COSTS_N_INSNS (1), /* fcmp */
++ COSTS_N_INSNS (1), /* fmov, fmovr */
++ COSTS_N_INSNS (1), /* fmul */
++ COSTS_N_INSNS (8), /* fdivs */
++ COSTS_N_INSNS (12), /* fdivd */
++ COSTS_N_INSNS (17), /* fsqrts */
++ COSTS_N_INSNS (17), /* fsqrtd */
++ COSTS_N_INSNS (17), /* imul */
++ COSTS_N_INSNS (17), /* imulX */
++ 0, /* imul bit factor */
++ COSTS_N_INSNS (17), /* idiv */
++ COSTS_N_INSNS (17), /* idivX */
++ COSTS_N_INSNS (1), /* movcc/movr */
++ 0, /* shift penalty */
++ 3 /* branch cost */
++};
++
++static const
++struct processor_costs leon_costs = {
++ COSTS_N_INSNS (1), /* int load */
++ COSTS_N_INSNS (1), /* int signed load */
++ COSTS_N_INSNS (1), /* int zeroed load */
++ COSTS_N_INSNS (1), /* float load */
++ COSTS_N_INSNS (1), /* fmov, fneg, fabs */
++ COSTS_N_INSNS (1), /* fadd, fsub */
++ COSTS_N_INSNS (1), /* fcmp */
++ COSTS_N_INSNS (1), /* fmov, fmovr */
++ COSTS_N_INSNS (1), /* fmul */
++ COSTS_N_INSNS (15), /* fdivs */
++ COSTS_N_INSNS (15), /* fdivd */
++ COSTS_N_INSNS (23), /* fsqrts */
++ COSTS_N_INSNS (23), /* fsqrtd */
++ COSTS_N_INSNS (5), /* imul */
++ COSTS_N_INSNS (5), /* imulX */
++ 0, /* imul bit factor */
++ COSTS_N_INSNS (5), /* idiv */
++ COSTS_N_INSNS (5), /* idivX */
++ COSTS_N_INSNS (1), /* movcc/movr */
++ 0, /* shift penalty */
++ 3 /* branch cost */
++};
++
++static const
++struct processor_costs leon3_costs = {
++ COSTS_N_INSNS (1), /* int load */
++ COSTS_N_INSNS (1), /* int signed load */
++ COSTS_N_INSNS (1), /* int zeroed load */
++ COSTS_N_INSNS (1), /* float load */
++ COSTS_N_INSNS (1), /* fmov, fneg, fabs */
++ COSTS_N_INSNS (1), /* fadd, fsub */
++ COSTS_N_INSNS (1), /* fcmp */
++ COSTS_N_INSNS (1), /* fmov, fmovr */
++ COSTS_N_INSNS (1), /* fmul */
++ COSTS_N_INSNS (14), /* fdivs */
++ COSTS_N_INSNS (15), /* fdivd */
++ COSTS_N_INSNS (22), /* fsqrts */
++ COSTS_N_INSNS (23), /* fsqrtd */
++ COSTS_N_INSNS (5), /* imul */
++ COSTS_N_INSNS (5), /* imulX */
++ 0, /* imul bit factor */
++ COSTS_N_INSNS (35), /* idiv */
++ COSTS_N_INSNS (35), /* idivX */
++ COSTS_N_INSNS (1), /* movcc/movr */
++ 0, /* shift penalty */
++ 3 /* branch cost */
++};
++
++static const
++struct processor_costs sparclet_costs = {
++ COSTS_N_INSNS (3), /* int load */
++ COSTS_N_INSNS (3), /* int signed load */
++ COSTS_N_INSNS (1), /* int zeroed load */
++ COSTS_N_INSNS (1), /* float load */
++ COSTS_N_INSNS (1), /* fmov, fneg, fabs */
++ COSTS_N_INSNS (1), /* fadd, fsub */
++ COSTS_N_INSNS (1), /* fcmp */
++ COSTS_N_INSNS (1), /* fmov, fmovr */
++ COSTS_N_INSNS (1), /* fmul */
++ COSTS_N_INSNS (1), /* fdivs */
++ COSTS_N_INSNS (1), /* fdivd */
++ COSTS_N_INSNS (1), /* fsqrts */
++ COSTS_N_INSNS (1), /* fsqrtd */
++ COSTS_N_INSNS (5), /* imul */
++ COSTS_N_INSNS (5), /* imulX */
++ 0, /* imul bit factor */
++ COSTS_N_INSNS (5), /* idiv */
++ COSTS_N_INSNS (5), /* idivX */
++ COSTS_N_INSNS (1), /* movcc/movr */
++ 0, /* shift penalty */
++ 3 /* branch cost */
++};
++
++static const
++struct processor_costs ultrasparc_costs = {
++ COSTS_N_INSNS (2), /* int load */
++ COSTS_N_INSNS (3), /* int signed load */
++ COSTS_N_INSNS (2), /* int zeroed load */
++ COSTS_N_INSNS (2), /* float load */
++ COSTS_N_INSNS (1), /* fmov, fneg, fabs */
++ COSTS_N_INSNS (4), /* fadd, fsub */
++ COSTS_N_INSNS (1), /* fcmp */
++ COSTS_N_INSNS (2), /* fmov, fmovr */
++ COSTS_N_INSNS (4), /* fmul */
++ COSTS_N_INSNS (13), /* fdivs */
++ COSTS_N_INSNS (23), /* fdivd */
++ COSTS_N_INSNS (13), /* fsqrts */
++ COSTS_N_INSNS (23), /* fsqrtd */
++ COSTS_N_INSNS (4), /* imul */
++ COSTS_N_INSNS (4), /* imulX */
++ 2, /* imul bit factor */
++ COSTS_N_INSNS (37), /* idiv */
++ COSTS_N_INSNS (68), /* idivX */
++ COSTS_N_INSNS (2), /* movcc/movr */
++ 2, /* shift penalty */
++ 2 /* branch cost */
++};
++
++static const
++struct processor_costs ultrasparc3_costs = {
++ COSTS_N_INSNS (2), /* int load */
++ COSTS_N_INSNS (3), /* int signed load */
++ COSTS_N_INSNS (3), /* int zeroed load */
++ COSTS_N_INSNS (2), /* float load */
++ COSTS_N_INSNS (3), /* fmov, fneg, fabs */
++ COSTS_N_INSNS (4), /* fadd, fsub */
++ COSTS_N_INSNS (5), /* fcmp */
++ COSTS_N_INSNS (3), /* fmov, fmovr */
++ COSTS_N_INSNS (4), /* fmul */
++ COSTS_N_INSNS (17), /* fdivs */
++ COSTS_N_INSNS (20), /* fdivd */
++ COSTS_N_INSNS (20), /* fsqrts */
++ COSTS_N_INSNS (29), /* fsqrtd */
++ COSTS_N_INSNS (6), /* imul */
++ COSTS_N_INSNS (6), /* imulX */
++ 0, /* imul bit factor */
++ COSTS_N_INSNS (40), /* idiv */
++ COSTS_N_INSNS (71), /* idivX */
++ COSTS_N_INSNS (2), /* movcc/movr */
++ 0, /* shift penalty */
++ 2 /* branch cost */
++};
++
++static const
++struct processor_costs niagara_costs = {
++ COSTS_N_INSNS (3), /* int load */
++ COSTS_N_INSNS (3), /* int signed load */
++ COSTS_N_INSNS (3), /* int zeroed load */
++ COSTS_N_INSNS (9), /* float load */
++ COSTS_N_INSNS (8), /* fmov, fneg, fabs */
++ COSTS_N_INSNS (8), /* fadd, fsub */
++ COSTS_N_INSNS (26), /* fcmp */
++ COSTS_N_INSNS (8), /* fmov, fmovr */
++ COSTS_N_INSNS (29), /* fmul */
++ COSTS_N_INSNS (54), /* fdivs */
++ COSTS_N_INSNS (83), /* fdivd */
++ COSTS_N_INSNS (100), /* fsqrts - not implemented in hardware */
++ COSTS_N_INSNS (100), /* fsqrtd - not implemented in hardware */
++ COSTS_N_INSNS (11), /* imul */
++ COSTS_N_INSNS (11), /* imulX */
++ 0, /* imul bit factor */
++ COSTS_N_INSNS (72), /* idiv */
++ COSTS_N_INSNS (72), /* idivX */
++ COSTS_N_INSNS (1), /* movcc/movr */
++ 0, /* shift penalty */
++ 4 /* branch cost */
++};
++
++static const
++struct processor_costs niagara2_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 (6), /* fmov, fneg, fabs */
++ COSTS_N_INSNS (6), /* fadd, fsub */
++ COSTS_N_INSNS (6), /* fcmp */
++ COSTS_N_INSNS (6), /* fmov, fmovr */
++ COSTS_N_INSNS (6), /* fmul */
++ COSTS_N_INSNS (19), /* fdivs */
++ COSTS_N_INSNS (33), /* fdivd */
++ COSTS_N_INSNS (19), /* fsqrts */
++ COSTS_N_INSNS (33), /* fsqrtd */
++ COSTS_N_INSNS (5), /* imul */
++ COSTS_N_INSNS (5), /* imulX */
++ 0, /* imul bit factor */
++ COSTS_N_INSNS (26), /* idiv, average of 12 - 41 cycle range */
++ COSTS_N_INSNS (26), /* idivX, average of 12 - 41 cycle range */
++ COSTS_N_INSNS (1), /* movcc/movr */
++ 0, /* shift penalty */
++ 5 /* branch cost */
++};
++
++static const
++struct processor_costs niagara3_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 (23), /* fdivs */
++ COSTS_N_INSNS (37), /* fdivd */
++ COSTS_N_INSNS (23), /* fsqrts */
++ COSTS_N_INSNS (37), /* fsqrtd */
++ COSTS_N_INSNS (9), /* imul */
++ COSTS_N_INSNS (9), /* imulX */
++ 0, /* imul bit factor */
++ COSTS_N_INSNS (31), /* idiv, average of 17 - 45 cycle range */
++ COSTS_N_INSNS (30), /* idivX, average of 16 - 44 cycle range */
++ COSTS_N_INSNS (1), /* movcc/movr */
++ 0, /* shift penalty */
++ 5 /* branch cost */
++};
++
++static const
++struct processor_costs niagara4_costs = {
++ COSTS_N_INSNS (5), /* int load */
++ COSTS_N_INSNS (5), /* int signed load */
++ COSTS_N_INSNS (5), /* int zeroed load */
++ COSTS_N_INSNS (5), /* float load */
++ COSTS_N_INSNS (11), /* fmov, fneg, fabs */
++ COSTS_N_INSNS (11), /* fadd, fsub */
++ COSTS_N_INSNS (11), /* fcmp */
++ COSTS_N_INSNS (11), /* fmov, fmovr */
++ COSTS_N_INSNS (11), /* fmul */
++ COSTS_N_INSNS (24), /* fdivs */
++ COSTS_N_INSNS (37), /* fdivd */
++ COSTS_N_INSNS (24), /* fsqrts */
++ COSTS_N_INSNS (37), /* fsqrtd */
++ COSTS_N_INSNS (12), /* imul */
++ COSTS_N_INSNS (12), /* imulX */
++ 0, /* imul bit factor */
++ COSTS_N_INSNS (50), /* idiv, average of 41 - 60 cycle range */
++ COSTS_N_INSNS (35), /* idivX, average of 26 - 44 cycle range */
++ COSTS_N_INSNS (1), /* movcc/movr */
++ 0, /* shift penalty */
++ 2 /* branch cost */
++};
++
++static const
++struct processor_costs niagara7_costs = {
++ COSTS_N_INSNS (5), /* int load */
++ COSTS_N_INSNS (5), /* int signed load */
++ COSTS_N_INSNS (5), /* int zeroed load */
++ COSTS_N_INSNS (5), /* float load */
++ COSTS_N_INSNS (11), /* fmov, fneg, fabs */
++ COSTS_N_INSNS (11), /* fadd, fsub */
++ COSTS_N_INSNS (11), /* fcmp */
++ COSTS_N_INSNS (11), /* fmov, fmovr */
++ COSTS_N_INSNS (11), /* fmul */
++ COSTS_N_INSNS (24), /* fdivs */
++ COSTS_N_INSNS (37), /* fdivd */
++ COSTS_N_INSNS (24), /* fsqrts */
++ COSTS_N_INSNS (37), /* fsqrtd */
++ COSTS_N_INSNS (12), /* imul */
++ COSTS_N_INSNS (12), /* imulX */
++ 0, /* imul bit factor */
++ COSTS_N_INSNS (51), /* idiv, average of 42 - 61 cycle range */
++ COSTS_N_INSNS (35), /* idivX, average of 26 - 44 cycle range */
++ COSTS_N_INSNS (1), /* movcc/movr */
++ 0, /* shift penalty */
++ 1 /* branch cost */
++};
++
++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 */
++ 1 /* branch cost */
++};
++
++static const struct processor_costs *sparc_costs = &cypress_costs;
++
++#ifdef HAVE_AS_RELAX_OPTION
++/* If 'as' and 'ld' are relaxing tail call insns into branch always, use
++ "or %o7,%g0,X; call Y; or X,%g0,%o7" always, so that it can be optimized.
++ With sethi/jmp, neither 'as' nor 'ld' has an easy way how to find out if
++ somebody does not branch between the sethi and jmp. */
++#define LEAF_SIBCALL_SLOT_RESERVED_P 1
++#else
++#define LEAF_SIBCALL_SLOT_RESERVED_P \
++ ((TARGET_ARCH64 && !TARGET_CM_MEDLOW) || flag_pic)
++#endif
++
++/* Vector to say how input registers are mapped to output registers.
++ HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to
++ eliminate it. You must use -fomit-frame-pointer to get that. */
++char leaf_reg_remap[] =
++{ 0, 1, 2, 3, 4, 5, 6, 7,
++ -1, -1, -1, -1, -1, -1, 14, -1,
++ -1, -1, -1, -1, -1, -1, -1, -1,
++ 8, 9, 10, 11, 12, 13, -1, 15,
++
++ 32, 33, 34, 35, 36, 37, 38, 39,
++ 40, 41, 42, 43, 44, 45, 46, 47,
++ 48, 49, 50, 51, 52, 53, 54, 55,
++ 56, 57, 58, 59, 60, 61, 62, 63,
++ 64, 65, 66, 67, 68, 69, 70, 71,
++ 72, 73, 74, 75, 76, 77, 78, 79,
++ 80, 81, 82, 83, 84, 85, 86, 87,
++ 88, 89, 90, 91, 92, 93, 94, 95,
++ 96, 97, 98, 99, 100, 101, 102};
++
++/* Vector, indexed by hard register number, which contains 1
++ for a register that is allowable in a candidate for leaf
++ function treatment. */
++char sparc_leaf_regs[] =
++{ 1, 1, 1, 1, 1, 1, 1, 1,
++ 0, 0, 0, 0, 0, 0, 1, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 1, 1, 1, 1, 1, 1, 0, 1,
++ 1, 1, 1, 1, 1, 1, 1, 1,
++ 1, 1, 1, 1, 1, 1, 1, 1,
++ 1, 1, 1, 1, 1, 1, 1, 1,
++ 1, 1, 1, 1, 1, 1, 1, 1,
++ 1, 1, 1, 1, 1, 1, 1, 1,
++ 1, 1, 1, 1, 1, 1, 1, 1,
++ 1, 1, 1, 1, 1, 1, 1, 1,
++ 1, 1, 1, 1, 1, 1, 1, 1,
++ 1, 1, 1, 1, 1, 1, 1};
++
++struct GTY(()) machine_function
++{
++ /* Size of the frame of the function. */
++ HOST_WIDE_INT frame_size;
++
++ /* Size of the frame of the function minus the register window save area
++ and the outgoing argument area. */
++ HOST_WIDE_INT apparent_frame_size;
++
++ /* Register we pretend the frame pointer is allocated to. Normally, this
++ is %fp, but if we are in a leaf procedure, this is (%sp + offset). We
++ record "offset" separately as it may be too big for (reg + disp). */
++ rtx frame_base_reg;
++ HOST_WIDE_INT frame_base_offset;
++
++ /* Number of global or FP registers to be saved (as 4-byte quantities). */
++ int n_global_fp_regs;
++
++ /* True if the current function is leaf and uses only leaf regs,
++ so that the SPARC leaf function optimization can be applied.
++ Private version of crtl->uses_only_leaf_regs, see
++ sparc_expand_prologue for the rationale. */
++ int leaf_function_p;
++
++ /* True if the prologue saves local or in registers. */
++ bool save_local_in_regs_p;
++
++ /* True if the data calculated by sparc_expand_prologue are valid. */
++ bool prologue_data_valid_p;
++};
++
++#define sparc_frame_size cfun->machine->frame_size
++#define sparc_apparent_frame_size cfun->machine->apparent_frame_size
++#define sparc_frame_base_reg cfun->machine->frame_base_reg
++#define sparc_frame_base_offset cfun->machine->frame_base_offset
++#define sparc_n_global_fp_regs cfun->machine->n_global_fp_regs
++#define sparc_leaf_function_p cfun->machine->leaf_function_p
++#define sparc_save_local_in_regs_p cfun->machine->save_local_in_regs_p
++#define sparc_prologue_data_valid_p cfun->machine->prologue_data_valid_p
++
++/* 1 if the next opcode is to be specially indented. */
++int sparc_indent_opcode = 0;
++
++static void sparc_option_override (void);
++static void sparc_init_modes (void);
++static int function_arg_slotno (const CUMULATIVE_ARGS *, machine_mode,
++ const_tree, bool, bool, int *, int *);
++
++static int supersparc_adjust_cost (rtx_insn *, int, rtx_insn *, int);
++static int hypersparc_adjust_cost (rtx_insn *, int, rtx_insn *, int);
++
++static void sparc_emit_set_const32 (rtx, rtx);
++static void sparc_emit_set_const64 (rtx, rtx);
++static void sparc_output_addr_vec (rtx);
++static void sparc_output_addr_diff_vec (rtx);
++static void sparc_output_deferred_case_vectors (void);
++static bool sparc_legitimate_address_p (machine_mode, rtx, bool);
++static bool sparc_legitimate_constant_p (machine_mode, rtx);
++static rtx sparc_builtin_saveregs (void);
++static int epilogue_renumber (rtx *, int);
++static bool sparc_assemble_integer (rtx, unsigned int, int);
++static int set_extends (rtx_insn *);
++static void sparc_asm_function_prologue (FILE *);
++static void sparc_asm_function_epilogue (FILE *);
++#ifdef TARGET_SOLARIS
++static void sparc_solaris_elf_asm_named_section (const char *, unsigned int,
++ tree) ATTRIBUTE_UNUSED;
++#endif
++static int sparc_adjust_cost (rtx_insn *, int, rtx_insn *, int, unsigned int);
++static int sparc_issue_rate (void);
++static void sparc_sched_init (FILE *, int, int);
++static int sparc_use_sched_lookahead (void);
++
++static void emit_soft_tfmode_libcall (const char *, int, rtx *);
++static void emit_soft_tfmode_binop (enum rtx_code, rtx *);
++static void emit_soft_tfmode_unop (enum rtx_code, rtx *);
++static void emit_soft_tfmode_cvt (enum rtx_code, rtx *);
++static void emit_hard_tfmode_operation (enum rtx_code, rtx *);
++
++static bool sparc_function_ok_for_sibcall (tree, tree);
++static void sparc_init_libfuncs (void);
++static void sparc_init_builtins (void);
++static void sparc_fpu_init_builtins (void);
++static void sparc_vis_init_builtins (void);
++static tree sparc_builtin_decl (unsigned, bool);
++static rtx sparc_expand_builtin (tree, rtx, rtx, machine_mode, int);
++static tree sparc_fold_builtin (tree, int, tree *, bool);
++static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
++ HOST_WIDE_INT, tree);
++static bool sparc_can_output_mi_thunk (const_tree, HOST_WIDE_INT,
++ HOST_WIDE_INT, const_tree);
++static struct machine_function * sparc_init_machine_status (void);
++static bool sparc_cannot_force_const_mem (machine_mode, rtx);
++static rtx sparc_tls_get_addr (void);
++static rtx sparc_tls_got (void);
++static int sparc_register_move_cost (machine_mode,
++ reg_class_t, reg_class_t);
++static bool sparc_rtx_costs (rtx, machine_mode, int, int, int *, bool);
++static machine_mode sparc_promote_function_mode (const_tree, machine_mode,
++ int *, const_tree, int);
++static bool sparc_strict_argument_naming (cumulative_args_t);
++static void sparc_va_start (tree, rtx);
++static tree sparc_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
++static bool sparc_vector_mode_supported_p (machine_mode);
++static bool sparc_tls_referenced_p (rtx);
++static rtx sparc_legitimize_tls_address (rtx);
++static rtx sparc_legitimize_pic_address (rtx, rtx);
++static rtx sparc_legitimize_address (rtx, rtx, machine_mode);
++static rtx sparc_delegitimize_address (rtx);
++static bool sparc_mode_dependent_address_p (const_rtx, addr_space_t);
++static bool sparc_pass_by_reference (cumulative_args_t,
++ const function_arg_info &);
++static void sparc_function_arg_advance (cumulative_args_t,
++ const function_arg_info &);
++static rtx sparc_function_arg (cumulative_args_t, const function_arg_info &);
++static rtx sparc_function_incoming_arg (cumulative_args_t,
++ const function_arg_info &);
++static pad_direction sparc_function_arg_padding (machine_mode, const_tree);
++static unsigned int sparc_function_arg_boundary (machine_mode,
++ const_tree);
++static int sparc_arg_partial_bytes (cumulative_args_t,
++ const function_arg_info &);
++static bool sparc_return_in_memory (const_tree, const_tree);
++static rtx sparc_struct_value_rtx (tree, int);
++static rtx sparc_function_value (const_tree, const_tree, bool);
++static rtx sparc_libcall_value (machine_mode, const_rtx);
++static bool sparc_function_value_regno_p (const unsigned int);
++static unsigned HOST_WIDE_INT sparc_asan_shadow_offset (void);
++static void sparc_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
++static void sparc_file_end (void);
++static bool sparc_frame_pointer_required (void);
++static bool sparc_can_eliminate (const int, const int);
++static void sparc_conditional_register_usage (void);
++static bool sparc_use_pseudo_pic_reg (void);
++static void sparc_init_pic_reg (void);
++#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
++static const char *sparc_mangle_type (const_tree);
++#endif
++static void sparc_trampoline_init (rtx, tree, rtx);
++static machine_mode sparc_preferred_simd_mode (scalar_mode);
++static reg_class_t sparc_preferred_reload_class (rtx x, reg_class_t rclass);
++static bool sparc_lra_p (void);
++static bool sparc_print_operand_punct_valid_p (unsigned char);
++static void sparc_print_operand (FILE *, rtx, int);
++static void sparc_print_operand_address (FILE *, machine_mode, rtx);
++static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t,
++ machine_mode,
++ secondary_reload_info *);
++static bool sparc_secondary_memory_needed (machine_mode, reg_class_t,
++ reg_class_t);
++static machine_mode sparc_secondary_memory_needed_mode (machine_mode);
++static scalar_int_mode sparc_cstore_mode (enum insn_code icode);
++static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *);
++static bool sparc_fixed_condition_code_regs (unsigned int *, unsigned int *);
++static unsigned int sparc_min_arithmetic_precision (void);
++static unsigned int sparc_hard_regno_nregs (unsigned int, machine_mode);
++static bool sparc_hard_regno_mode_ok (unsigned int, machine_mode);
++static bool sparc_modes_tieable_p (machine_mode, machine_mode);
++static bool sparc_can_change_mode_class (machine_mode, machine_mode,
++ reg_class_t);
++static HOST_WIDE_INT sparc_constant_alignment (const_tree, HOST_WIDE_INT);
++static bool sparc_vectorize_vec_perm_const (machine_mode, rtx, rtx, rtx,
++ const vec_perm_indices &);
++static bool sparc_can_follow_jump (const rtx_insn *, const rtx_insn *);
++
++#ifdef SUBTARGET_ATTRIBUTE_TABLE
++/* Table of valid machine attributes. */
++static const struct attribute_spec sparc_attribute_table[] =
++{
++ /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
++ do_diagnostic, handler, exclude } */
++ SUBTARGET_ATTRIBUTE_TABLE,
++ { NULL, 0, 0, false, false, false, false, NULL, NULL }
++};
++#endif
++
++char sparc_hard_reg_printed[8];
++
++/* Initialize the GCC target structure. */
++
++/* The default is to use .half rather than .short for aligned HI objects. */
++#undef TARGET_ASM_ALIGNED_HI_OP
++#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
++
++#undef TARGET_ASM_UNALIGNED_HI_OP
++#define TARGET_ASM_UNALIGNED_HI_OP "\t.uahalf\t"
++#undef TARGET_ASM_UNALIGNED_SI_OP
++#define TARGET_ASM_UNALIGNED_SI_OP "\t.uaword\t"
++#undef TARGET_ASM_UNALIGNED_DI_OP
++#define TARGET_ASM_UNALIGNED_DI_OP "\t.uaxword\t"
++
++/* The target hook has to handle DI-mode values. */
++#undef TARGET_ASM_INTEGER
++#define TARGET_ASM_INTEGER sparc_assemble_integer
++
++#undef TARGET_ASM_FUNCTION_PROLOGUE
++#define TARGET_ASM_FUNCTION_PROLOGUE sparc_asm_function_prologue
++#undef TARGET_ASM_FUNCTION_EPILOGUE
++#define TARGET_ASM_FUNCTION_EPILOGUE sparc_asm_function_epilogue
++
++#undef TARGET_SCHED_ADJUST_COST
++#define TARGET_SCHED_ADJUST_COST sparc_adjust_cost
++#undef TARGET_SCHED_ISSUE_RATE
++#define TARGET_SCHED_ISSUE_RATE sparc_issue_rate
++#undef TARGET_SCHED_INIT
++#define TARGET_SCHED_INIT sparc_sched_init
++#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
++#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD sparc_use_sched_lookahead
++
++#undef TARGET_FUNCTION_OK_FOR_SIBCALL
++#define TARGET_FUNCTION_OK_FOR_SIBCALL sparc_function_ok_for_sibcall
++
++#undef TARGET_INIT_LIBFUNCS
++#define TARGET_INIT_LIBFUNCS sparc_init_libfuncs
++
++#undef TARGET_LEGITIMIZE_ADDRESS
++#define TARGET_LEGITIMIZE_ADDRESS sparc_legitimize_address
++#undef TARGET_DELEGITIMIZE_ADDRESS
++#define TARGET_DELEGITIMIZE_ADDRESS sparc_delegitimize_address
++#undef TARGET_MODE_DEPENDENT_ADDRESS_P
++#define TARGET_MODE_DEPENDENT_ADDRESS_P sparc_mode_dependent_address_p
++
++#undef TARGET_INIT_BUILTINS
++#define TARGET_INIT_BUILTINS sparc_init_builtins
++#undef TARGET_BUILTIN_DECL
++#define TARGET_BUILTIN_DECL sparc_builtin_decl
++#undef TARGET_EXPAND_BUILTIN
++#define TARGET_EXPAND_BUILTIN sparc_expand_builtin
++#undef TARGET_FOLD_BUILTIN
++#define TARGET_FOLD_BUILTIN sparc_fold_builtin
++
++#if TARGET_TLS
++#undef TARGET_HAVE_TLS
++#define TARGET_HAVE_TLS true
++#endif
++
++#undef TARGET_CANNOT_FORCE_CONST_MEM
++#define TARGET_CANNOT_FORCE_CONST_MEM sparc_cannot_force_const_mem
++
++#undef TARGET_ASM_OUTPUT_MI_THUNK
++#define TARGET_ASM_OUTPUT_MI_THUNK sparc_output_mi_thunk
++#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
++#define TARGET_ASM_CAN_OUTPUT_MI_THUNK sparc_can_output_mi_thunk
++
++#undef TARGET_RTX_COSTS
++#define TARGET_RTX_COSTS sparc_rtx_costs
++#undef TARGET_ADDRESS_COST
++#define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
++#undef TARGET_REGISTER_MOVE_COST
++#define TARGET_REGISTER_MOVE_COST sparc_register_move_cost
++
++#undef TARGET_PROMOTE_FUNCTION_MODE
++#define TARGET_PROMOTE_FUNCTION_MODE sparc_promote_function_mode
++#undef TARGET_STRICT_ARGUMENT_NAMING
++#define TARGET_STRICT_ARGUMENT_NAMING sparc_strict_argument_naming
++
++#undef TARGET_MUST_PASS_IN_STACK
++#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
++#undef TARGET_PASS_BY_REFERENCE
++#define TARGET_PASS_BY_REFERENCE sparc_pass_by_reference
++#undef TARGET_ARG_PARTIAL_BYTES
++#define TARGET_ARG_PARTIAL_BYTES sparc_arg_partial_bytes
++#undef TARGET_FUNCTION_ARG_ADVANCE
++#define TARGET_FUNCTION_ARG_ADVANCE sparc_function_arg_advance
++#undef TARGET_FUNCTION_ARG
++#define TARGET_FUNCTION_ARG sparc_function_arg
++#undef TARGET_FUNCTION_INCOMING_ARG
++#define TARGET_FUNCTION_INCOMING_ARG sparc_function_incoming_arg
++#undef TARGET_FUNCTION_ARG_PADDING
++#define TARGET_FUNCTION_ARG_PADDING sparc_function_arg_padding
++#undef TARGET_FUNCTION_ARG_BOUNDARY