18dd4bdcdSmrg /* Common hooks for IBM RS/6000.
2*760c2415Smrg    Copyright (C) 1991-2019 Free Software Foundation, Inc.
38dd4bdcdSmrg 
48dd4bdcdSmrg    This file is part of GCC.
58dd4bdcdSmrg 
68dd4bdcdSmrg    GCC is free software; you can redistribute it and/or modify it
78dd4bdcdSmrg    under the terms of the GNU General Public License as published
88dd4bdcdSmrg    by the Free Software Foundation; either version 3, or (at your
98dd4bdcdSmrg    option) any later version.
108dd4bdcdSmrg 
118dd4bdcdSmrg    GCC is distributed in the hope that it will be useful, but WITHOUT
128dd4bdcdSmrg    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
138dd4bdcdSmrg    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
148dd4bdcdSmrg    License for more details.
158dd4bdcdSmrg 
168dd4bdcdSmrg    You should have received a copy of the GNU General Public License
178dd4bdcdSmrg    along with GCC; see the file COPYING3.  If not see
188dd4bdcdSmrg    <http://www.gnu.org/licenses/>.  */
198dd4bdcdSmrg 
208dd4bdcdSmrg #include "config.h"
218dd4bdcdSmrg #include "system.h"
228dd4bdcdSmrg #include "coretypes.h"
238dd4bdcdSmrg #include "diagnostic-core.h"
248dd4bdcdSmrg #include "tm.h"
258dd4bdcdSmrg #include "common/common-target.h"
268dd4bdcdSmrg #include "common/common-target-def.h"
278dd4bdcdSmrg #include "opts.h"
288dd4bdcdSmrg #include "flags.h"
298dd4bdcdSmrg #include "params.h"
308dd4bdcdSmrg 
318dd4bdcdSmrg /* Implement TARGET_OPTION_OPTIMIZATION_TABLE.  */
328dd4bdcdSmrg static const struct default_options rs6000_option_optimization_table[] =
338dd4bdcdSmrg   {
348dd4bdcdSmrg     /* Enable -fsched-pressure for first pass instruction scheduling.  */
358dd4bdcdSmrg     { OPT_LEVELS_1_PLUS, OPT_fsched_pressure, NULL, 1 },
368dd4bdcdSmrg     { OPT_LEVELS_NONE, 0, NULL, 0 }
378dd4bdcdSmrg   };
388dd4bdcdSmrg 
398dd4bdcdSmrg /* Implement TARGET_OPTION_INIT_STRUCT.  */
408dd4bdcdSmrg 
418dd4bdcdSmrg static void
rs6000_option_init_struct(struct gcc_options * opts)428dd4bdcdSmrg rs6000_option_init_struct (struct gcc_options *opts)
438dd4bdcdSmrg {
448dd4bdcdSmrg   if (DEFAULT_ABI == ABI_DARWIN)
458dd4bdcdSmrg     /* The Darwin libraries never set errno, so we might as well
468dd4bdcdSmrg        avoid calling them when that's the only reason we would.  */
478dd4bdcdSmrg     opts->x_flag_errno_math = 0;
488dd4bdcdSmrg 
498dd4bdcdSmrg   /* Enable section anchors by default.  */
508dd4bdcdSmrg   if (!TARGET_MACHO)
518dd4bdcdSmrg     opts->x_flag_section_anchors = 1;
528dd4bdcdSmrg }
538dd4bdcdSmrg 
548dd4bdcdSmrg /* Implement TARGET_OPTION_DEFAULT_PARAMS.  */
558dd4bdcdSmrg 
568dd4bdcdSmrg static void
rs6000_option_default_params(void)578dd4bdcdSmrg rs6000_option_default_params (void)
588dd4bdcdSmrg {
598dd4bdcdSmrg   /* Double growth factor to counter reduced min jump length.  */
608dd4bdcdSmrg   set_default_param_value (PARAM_MAX_GROW_COPY_BB_INSNS, 16);
618dd4bdcdSmrg }
628dd4bdcdSmrg 
638dd4bdcdSmrg /* If not otherwise specified by a target, make 'long double' equivalent to
648dd4bdcdSmrg    'double'.  */
658dd4bdcdSmrg 
668dd4bdcdSmrg #ifndef RS6000_DEFAULT_LONG_DOUBLE_SIZE
678dd4bdcdSmrg #define RS6000_DEFAULT_LONG_DOUBLE_SIZE 64
688dd4bdcdSmrg #endif
698dd4bdcdSmrg 
708dd4bdcdSmrg /* Implement TARGET_HANDLE_OPTION.  */
718dd4bdcdSmrg 
728dd4bdcdSmrg static bool
rs6000_handle_option(struct gcc_options * opts,struct gcc_options * opts_set,const struct cl_decoded_option * decoded,location_t loc)738dd4bdcdSmrg rs6000_handle_option (struct gcc_options *opts, struct gcc_options *opts_set,
748dd4bdcdSmrg 		      const struct cl_decoded_option *decoded,
758dd4bdcdSmrg 		      location_t loc)
768dd4bdcdSmrg {
778dd4bdcdSmrg   enum fpu_type_t fpu_type = FPU_NONE;
788dd4bdcdSmrg   char *p, *q;
798dd4bdcdSmrg   size_t code = decoded->opt_index;
808dd4bdcdSmrg   const char *arg = decoded->arg;
818dd4bdcdSmrg   int value = decoded->value;
828dd4bdcdSmrg 
838dd4bdcdSmrg   switch (code)
848dd4bdcdSmrg     {
858dd4bdcdSmrg     case OPT_mfull_toc:
868dd4bdcdSmrg       opts->x_rs6000_isa_flags &= ~OPTION_MASK_MINIMAL_TOC;
878dd4bdcdSmrg       opts->x_TARGET_NO_FP_IN_TOC = 0;
888dd4bdcdSmrg       opts->x_TARGET_NO_SUM_IN_TOC = 0;
898dd4bdcdSmrg       opts_set->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC;
908dd4bdcdSmrg #ifdef TARGET_USES_SYSV4_OPT
918dd4bdcdSmrg       /* Note, V.4 no longer uses a normal TOC, so make -mfull-toc, be
928dd4bdcdSmrg 	 just the same as -mminimal-toc.  */
938dd4bdcdSmrg       opts->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC;
948dd4bdcdSmrg       opts_set->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC;
958dd4bdcdSmrg #endif
968dd4bdcdSmrg       break;
978dd4bdcdSmrg 
988dd4bdcdSmrg #ifdef TARGET_USES_SYSV4_OPT
998dd4bdcdSmrg     case OPT_mtoc:
1008dd4bdcdSmrg       /* Make -mtoc behave like -mminimal-toc.  */
1018dd4bdcdSmrg       opts->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC;
1028dd4bdcdSmrg       opts_set->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC;
1038dd4bdcdSmrg       break;
1048dd4bdcdSmrg #endif
1058dd4bdcdSmrg 
1068dd4bdcdSmrg #ifdef TARGET_USES_AIX64_OPT
1078dd4bdcdSmrg     case OPT_maix64:
1088dd4bdcdSmrg #else
1098dd4bdcdSmrg     case OPT_m64:
1108dd4bdcdSmrg #endif
1118dd4bdcdSmrg       opts->x_rs6000_isa_flags |= OPTION_MASK_POWERPC64;
1128dd4bdcdSmrg       opts->x_rs6000_isa_flags |= (~opts_set->x_rs6000_isa_flags
1138dd4bdcdSmrg 				   & OPTION_MASK_PPC_GFXOPT);
1148dd4bdcdSmrg       opts_set->x_rs6000_isa_flags |= OPTION_MASK_POWERPC64;
1158dd4bdcdSmrg       break;
1168dd4bdcdSmrg 
1178dd4bdcdSmrg #ifdef TARGET_USES_AIX64_OPT
1188dd4bdcdSmrg     case OPT_maix32:
1198dd4bdcdSmrg #else
1208dd4bdcdSmrg     case OPT_m32:
1218dd4bdcdSmrg #endif
1228dd4bdcdSmrg       opts->x_rs6000_isa_flags &= ~OPTION_MASK_POWERPC64;
1238dd4bdcdSmrg       opts_set->x_rs6000_isa_flags |= OPTION_MASK_POWERPC64;
1248dd4bdcdSmrg       break;
1258dd4bdcdSmrg 
1268dd4bdcdSmrg     case OPT_mminimal_toc:
1278dd4bdcdSmrg       if (value == 1)
1288dd4bdcdSmrg 	{
1298dd4bdcdSmrg 	  opts->x_TARGET_NO_FP_IN_TOC = 0;
1308dd4bdcdSmrg 	  opts->x_TARGET_NO_SUM_IN_TOC = 0;
1318dd4bdcdSmrg 	}
1328dd4bdcdSmrg       break;
1338dd4bdcdSmrg 
1348dd4bdcdSmrg     case OPT_mpowerpc_gpopt:
1358dd4bdcdSmrg     case OPT_mpowerpc_gfxopt:
1368dd4bdcdSmrg       break;
1378dd4bdcdSmrg 
1388dd4bdcdSmrg     case OPT_mdebug_:
1398dd4bdcdSmrg       p = ASTRDUP (arg);
1408dd4bdcdSmrg       opts->x_rs6000_debug = 0;
1418dd4bdcdSmrg 
1428dd4bdcdSmrg       while ((q = strtok (p, ",")) != NULL)
1438dd4bdcdSmrg 	{
1448dd4bdcdSmrg 	  unsigned mask = 0;
1458dd4bdcdSmrg 	  bool invert;
1468dd4bdcdSmrg 
1478dd4bdcdSmrg 	  p = NULL;
1488dd4bdcdSmrg 	  if (*q == '!')
1498dd4bdcdSmrg 	    {
1508dd4bdcdSmrg 	      invert = true;
1518dd4bdcdSmrg 	      q++;
1528dd4bdcdSmrg 	    }
1538dd4bdcdSmrg 	  else
1548dd4bdcdSmrg 	    invert = false;
1558dd4bdcdSmrg 
1568dd4bdcdSmrg 	  if (! strcmp (q, "all"))
1578dd4bdcdSmrg 	    mask = MASK_DEBUG_ALL;
1588dd4bdcdSmrg 	  else if (! strcmp (q, "stack"))
1598dd4bdcdSmrg 	    mask = MASK_DEBUG_STACK;
1608dd4bdcdSmrg 	  else if (! strcmp (q, "arg"))
1618dd4bdcdSmrg 	    mask = MASK_DEBUG_ARG;
1628dd4bdcdSmrg 	  else if (! strcmp (q, "reg"))
1638dd4bdcdSmrg 	    mask = MASK_DEBUG_REG;
1648dd4bdcdSmrg 	  else if (! strcmp (q, "addr"))
1658dd4bdcdSmrg 	    mask = MASK_DEBUG_ADDR;
1668dd4bdcdSmrg 	  else if (! strcmp (q, "cost"))
1678dd4bdcdSmrg 	    mask = MASK_DEBUG_COST;
1688dd4bdcdSmrg 	  else if (! strcmp (q, "target"))
1698dd4bdcdSmrg 	    mask = MASK_DEBUG_TARGET;
1708dd4bdcdSmrg 	  else if (! strcmp (q, "builtin"))
1718dd4bdcdSmrg 	    mask = MASK_DEBUG_BUILTIN;
1728dd4bdcdSmrg 	  else
173*760c2415Smrg 	    error_at (loc, "unknown %<-mdebug-%s%> switch", q);
1748dd4bdcdSmrg 
1758dd4bdcdSmrg 	  if (invert)
1768dd4bdcdSmrg 	    opts->x_rs6000_debug &= ~mask;
1778dd4bdcdSmrg 	  else
1788dd4bdcdSmrg 	    opts->x_rs6000_debug |= mask;
1798dd4bdcdSmrg 	}
1808dd4bdcdSmrg       break;
1818dd4bdcdSmrg 
1828dd4bdcdSmrg #ifdef TARGET_USES_SYSV4_OPT
1838dd4bdcdSmrg     case OPT_mrelocatable:
1848dd4bdcdSmrg       if (value == 1)
1858dd4bdcdSmrg 	{
1868dd4bdcdSmrg 	  opts->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC;
1878dd4bdcdSmrg 	  opts_set->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC;
1888dd4bdcdSmrg 	  opts->x_TARGET_NO_FP_IN_TOC = 1;
1898dd4bdcdSmrg 	}
1908dd4bdcdSmrg       break;
1918dd4bdcdSmrg 
1928dd4bdcdSmrg     case OPT_mrelocatable_lib:
1938dd4bdcdSmrg       if (value == 1)
1948dd4bdcdSmrg 	{
1958dd4bdcdSmrg 	  opts->x_rs6000_isa_flags |= (OPTION_MASK_RELOCATABLE
1968dd4bdcdSmrg 				       | OPTION_MASK_MINIMAL_TOC);
1978dd4bdcdSmrg 	  opts_set->x_rs6000_isa_flags |= (OPTION_MASK_RELOCATABLE
1988dd4bdcdSmrg 					   | OPTION_MASK_MINIMAL_TOC);
1998dd4bdcdSmrg 	  opts->x_TARGET_NO_FP_IN_TOC = 1;
2008dd4bdcdSmrg 	}
2018dd4bdcdSmrg       else
2028dd4bdcdSmrg 	{
2038dd4bdcdSmrg 	  opts->x_rs6000_isa_flags &= ~OPTION_MASK_RELOCATABLE;
2048dd4bdcdSmrg 	  opts_set->x_rs6000_isa_flags |= OPTION_MASK_RELOCATABLE;
2058dd4bdcdSmrg 	}
2068dd4bdcdSmrg       break;
2078dd4bdcdSmrg #endif
2088dd4bdcdSmrg 
2098dd4bdcdSmrg     case OPT_mabi_altivec:
2108dd4bdcdSmrg       /* Enabling the AltiVec ABI turns off the SPE ABI.  */
2118dd4bdcdSmrg       opts->x_rs6000_spe_abi = 0;
2128dd4bdcdSmrg       break;
2138dd4bdcdSmrg 
2148dd4bdcdSmrg     case OPT_mabi_spe:
2158dd4bdcdSmrg       opts->x_rs6000_altivec_abi = 0;
2168dd4bdcdSmrg       break;
2178dd4bdcdSmrg 
2188dd4bdcdSmrg     case OPT_mlong_double_:
2198dd4bdcdSmrg       if (value != 64 && value != 128)
2208dd4bdcdSmrg 	{
221*760c2415Smrg 	  error_at (loc, "unknown switch %<-mlong-double-%s%>", arg);
2228dd4bdcdSmrg 	  opts->x_rs6000_long_double_type_size
2238dd4bdcdSmrg 	    = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
2248dd4bdcdSmrg 	  return false;
2258dd4bdcdSmrg 	}
2268dd4bdcdSmrg       break;
2278dd4bdcdSmrg 
2288dd4bdcdSmrg     case OPT_msingle_float:
2298dd4bdcdSmrg       if (!TARGET_SINGLE_FPU)
2308dd4bdcdSmrg 	warning_at (loc, 0,
231*760c2415Smrg 		    "%<-msingle-float%> option equivalent to %<-mhard-float%>");
2328dd4bdcdSmrg       /* -msingle-float implies -mno-double-float and TARGET_HARD_FLOAT. */
2338dd4bdcdSmrg       opts->x_rs6000_double_float = 0;
2348dd4bdcdSmrg       opts->x_rs6000_isa_flags &= ~OPTION_MASK_SOFT_FLOAT;
2358dd4bdcdSmrg       opts_set->x_rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT;
2368dd4bdcdSmrg       break;
2378dd4bdcdSmrg 
2388dd4bdcdSmrg     case OPT_mdouble_float:
2398dd4bdcdSmrg       /* -mdouble-float implies -msingle-float and TARGET_HARD_FLOAT. */
2408dd4bdcdSmrg       opts->x_rs6000_single_float = 1;
2418dd4bdcdSmrg       opts->x_rs6000_isa_flags &= ~OPTION_MASK_SOFT_FLOAT;
2428dd4bdcdSmrg       opts_set->x_rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT;
2438dd4bdcdSmrg       break;
2448dd4bdcdSmrg 
2458dd4bdcdSmrg     case OPT_msimple_fpu:
2468dd4bdcdSmrg       if (!TARGET_SINGLE_FPU)
247*760c2415Smrg 	warning_at (loc, 0, "%<-msimple-fpu%> option ignored");
2488dd4bdcdSmrg       break;
2498dd4bdcdSmrg 
2508dd4bdcdSmrg     case OPT_mhard_float:
2518dd4bdcdSmrg       /* -mhard_float implies -msingle-float and -mdouble-float. */
2528dd4bdcdSmrg       opts->x_rs6000_single_float = opts->x_rs6000_double_float = 1;
2538dd4bdcdSmrg       break;
2548dd4bdcdSmrg 
2558dd4bdcdSmrg     case OPT_msoft_float:
2568dd4bdcdSmrg       /* -msoft_float implies -mnosingle-float and -mnodouble-float. */
2578dd4bdcdSmrg       opts->x_rs6000_single_float = opts->x_rs6000_double_float = 0;
2588dd4bdcdSmrg       break;
2598dd4bdcdSmrg 
2608dd4bdcdSmrg     case OPT_mfpu_:
2618dd4bdcdSmrg       fpu_type = (enum fpu_type_t) value;
2628dd4bdcdSmrg       if (fpu_type != FPU_NONE)
2638dd4bdcdSmrg 	{
2648dd4bdcdSmrg 	  /* If -mfpu is not none, then turn off SOFT_FLOAT, turn on
2658dd4bdcdSmrg 	     HARD_FLOAT. */
2668dd4bdcdSmrg 	  opts->x_rs6000_isa_flags &= ~OPTION_MASK_SOFT_FLOAT;
2678dd4bdcdSmrg 	  opts_set->x_rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT;
2688dd4bdcdSmrg 	  opts->x_rs6000_xilinx_fpu = 1;
2698dd4bdcdSmrg 	  if (fpu_type == FPU_SF_LITE || fpu_type == FPU_SF_FULL)
2708dd4bdcdSmrg 	    opts->x_rs6000_single_float = 1;
2718dd4bdcdSmrg 	  if (fpu_type == FPU_DF_LITE || fpu_type == FPU_DF_FULL)
2728dd4bdcdSmrg 	    opts->x_rs6000_single_float = opts->x_rs6000_double_float = 1;
2738dd4bdcdSmrg 	  if (fpu_type == FPU_SF_LITE || fpu_type == FPU_DF_LITE)
2748dd4bdcdSmrg 	    opts->x_rs6000_simple_fpu = 1;
2758dd4bdcdSmrg 	}
2768dd4bdcdSmrg       else
2778dd4bdcdSmrg 	{
2788dd4bdcdSmrg 	  /* -mfpu=none is equivalent to -msoft-float.  */
2798dd4bdcdSmrg 	  opts->x_rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT;
2808dd4bdcdSmrg 	  opts_set->x_rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT;
2818dd4bdcdSmrg 	  opts->x_rs6000_single_float = opts->x_rs6000_double_float = 0;
2828dd4bdcdSmrg 	}
2838dd4bdcdSmrg       break;
2848dd4bdcdSmrg 
2858dd4bdcdSmrg     case OPT_mrecip:
2868dd4bdcdSmrg       opts->x_rs6000_recip_name = (value) ? "default" : "none";
2878dd4bdcdSmrg       break;
2888dd4bdcdSmrg     }
2898dd4bdcdSmrg   return true;
2908dd4bdcdSmrg }
2918dd4bdcdSmrg 
2928dd4bdcdSmrg /* -fsplit-stack uses a field in the TCB, available with glibc-2.19.
2938dd4bdcdSmrg    We also allow 2.18 because alignment padding guarantees that the
2948dd4bdcdSmrg    space is available there too.  */
2958dd4bdcdSmrg 
2968dd4bdcdSmrg static bool
rs6000_supports_split_stack(bool report,struct gcc_options * opts ATTRIBUTE_UNUSED)2978dd4bdcdSmrg rs6000_supports_split_stack (bool report,
2988dd4bdcdSmrg 			     struct gcc_options *opts ATTRIBUTE_UNUSED)
2998dd4bdcdSmrg {
3008dd4bdcdSmrg #ifndef TARGET_GLIBC_MAJOR
3018dd4bdcdSmrg #define TARGET_GLIBC_MAJOR 0
3028dd4bdcdSmrg #endif
3038dd4bdcdSmrg #ifndef TARGET_GLIBC_MINOR
3048dd4bdcdSmrg #define TARGET_GLIBC_MINOR 0
3058dd4bdcdSmrg #endif
3068dd4bdcdSmrg   /* Note: Can't test DEFAULT_ABI here, it isn't set until later.  */
3078dd4bdcdSmrg   if (TARGET_GLIBC_MAJOR * 1000 + TARGET_GLIBC_MINOR >= 2018
3088dd4bdcdSmrg       && TARGET_64BIT
3098dd4bdcdSmrg       && TARGET_ELF)
3108dd4bdcdSmrg     return true;
3118dd4bdcdSmrg 
3128dd4bdcdSmrg   if (report)
3138dd4bdcdSmrg     error ("%<-fsplit-stack%> currently only supported on PowerPC64 GNU/Linux with glibc-2.18 or later");
3148dd4bdcdSmrg   return false;
3158dd4bdcdSmrg }
3168dd4bdcdSmrg 
3178dd4bdcdSmrg #undef TARGET_HANDLE_OPTION
3188dd4bdcdSmrg #define TARGET_HANDLE_OPTION rs6000_handle_option
3198dd4bdcdSmrg 
3208dd4bdcdSmrg #undef TARGET_OPTION_INIT_STRUCT
3218dd4bdcdSmrg #define TARGET_OPTION_INIT_STRUCT rs6000_option_init_struct
3228dd4bdcdSmrg 
3238dd4bdcdSmrg #undef TARGET_OPTION_DEFAULT_PARAMS
3248dd4bdcdSmrg #define TARGET_OPTION_DEFAULT_PARAMS rs6000_option_default_params
3258dd4bdcdSmrg 
3268dd4bdcdSmrg #undef TARGET_OPTION_OPTIMIZATION_TABLE
3278dd4bdcdSmrg #define TARGET_OPTION_OPTIMIZATION_TABLE rs6000_option_optimization_table
3288dd4bdcdSmrg 
3298dd4bdcdSmrg #undef TARGET_SUPPORTS_SPLIT_STACK
3308dd4bdcdSmrg #define TARGET_SUPPORTS_SPLIT_STACK rs6000_supports_split_stack
3318dd4bdcdSmrg 
3328dd4bdcdSmrg struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
333