1 /* Common hooks for IBM RS/6000.
2    Copyright (C) 1991-2014 Free Software Foundation, Inc.
3 
4    This file is part of GCC.
5 
6    GCC is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published
8    by the Free Software Foundation; either version 3, or (at your
9    option) any later version.
10 
11    GCC is distributed in the hope that it will be useful, but WITHOUT
12    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14    License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with GCC; see the file COPYING3.  If not see
18    <http://www.gnu.org/licenses/>.  */
19 
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "diagnostic-core.h"
24 #include "tm.h"
25 #include "common/common-target.h"
26 #include "common/common-target-def.h"
27 #include "opts.h"
28 #include "flags.h"
29 #include "params.h"
30 
31 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE.  */
32 static const struct default_options rs6000_option_optimization_table[] =
33   {
34     { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
35     { OPT_LEVELS_NONE, 0, NULL, 0 }
36   };
37 
38 /* Implement TARGET_OPTION_INIT_STRUCT.  */
39 
40 static void
rs6000_option_init_struct(struct gcc_options * opts)41 rs6000_option_init_struct (struct gcc_options *opts)
42 {
43   if (DEFAULT_ABI == ABI_DARWIN)
44     /* The Darwin libraries never set errno, so we might as well
45        avoid calling them when that's the only reason we would.  */
46     opts->x_flag_errno_math = 0;
47 
48   /* Enable section anchors by default.  */
49   if (!TARGET_MACHO)
50     opts->x_flag_section_anchors = 1;
51 }
52 
53 /* Implement TARGET_OPTION_DEFAULT_PARAMS.  */
54 
55 static void
rs6000_option_default_params(void)56 rs6000_option_default_params (void)
57 {
58   /* Double growth factor to counter reduced min jump length.  */
59   set_default_param_value (PARAM_MAX_GROW_COPY_BB_INSNS, 16);
60 }
61 
62 /* If not otherwise specified by a target, make 'long double' equivalent to
63    'double'.  */
64 
65 #ifndef RS6000_DEFAULT_LONG_DOUBLE_SIZE
66 #define RS6000_DEFAULT_LONG_DOUBLE_SIZE 64
67 #endif
68 
69 /* Implement TARGET_HANDLE_OPTION.  */
70 
71 static bool
rs6000_handle_option(struct gcc_options * opts,struct gcc_options * opts_set,const struct cl_decoded_option * decoded,location_t loc)72 rs6000_handle_option (struct gcc_options *opts, struct gcc_options *opts_set,
73 		      const struct cl_decoded_option *decoded,
74 		      location_t loc)
75 {
76   enum fpu_type_t fpu_type = FPU_NONE;
77   char *p, *q;
78   size_t code = decoded->opt_index;
79   const char *arg = decoded->arg;
80   int value = decoded->value;
81 
82   switch (code)
83     {
84     case OPT_mfull_toc:
85       opts->x_rs6000_isa_flags &= ~OPTION_MASK_MINIMAL_TOC;
86       opts->x_TARGET_NO_FP_IN_TOC = 0;
87       opts->x_TARGET_NO_SUM_IN_TOC = 0;
88       opts_set->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC;
89 #ifdef TARGET_USES_SYSV4_OPT
90       /* Note, V.4 no longer uses a normal TOC, so make -mfull-toc, be
91 	 just the same as -mminimal-toc.  */
92       opts->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC;
93       opts_set->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC;
94 #endif
95       break;
96 
97 #ifdef TARGET_USES_SYSV4_OPT
98     case OPT_mtoc:
99       /* Make -mtoc behave like -mminimal-toc.  */
100       opts->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC;
101       opts_set->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC;
102       break;
103 #endif
104 
105 #ifdef TARGET_USES_AIX64_OPT
106     case OPT_maix64:
107 #else
108     case OPT_m64:
109 #endif
110       opts->x_rs6000_isa_flags |= OPTION_MASK_POWERPC64;
111       opts->x_rs6000_isa_flags |= (~opts_set->x_rs6000_isa_flags
112 				   & OPTION_MASK_PPC_GFXOPT);
113       opts_set->x_rs6000_isa_flags |= OPTION_MASK_POWERPC64;
114       break;
115 
116 #ifdef TARGET_USES_AIX64_OPT
117     case OPT_maix32:
118 #else
119     case OPT_m32:
120 #endif
121       opts->x_rs6000_isa_flags &= ~OPTION_MASK_POWERPC64;
122       opts_set->x_rs6000_isa_flags |= OPTION_MASK_POWERPC64;
123       break;
124 
125     case OPT_mminimal_toc:
126       if (value == 1)
127 	{
128 	  opts->x_TARGET_NO_FP_IN_TOC = 0;
129 	  opts->x_TARGET_NO_SUM_IN_TOC = 0;
130 	}
131       break;
132 
133     case OPT_mpowerpc_gpopt:
134     case OPT_mpowerpc_gfxopt:
135       break;
136 
137     case OPT_mdebug_:
138       p = ASTRDUP (arg);
139       opts->x_rs6000_debug = 0;
140 
141       while ((q = strtok (p, ",")) != NULL)
142 	{
143 	  unsigned mask = 0;
144 	  bool invert;
145 
146 	  p = NULL;
147 	  if (*q == '!')
148 	    {
149 	      invert = true;
150 	      q++;
151 	    }
152 	  else
153 	    invert = false;
154 
155 	  if (! strcmp (q, "all"))
156 	    mask = MASK_DEBUG_ALL;
157 	  else if (! strcmp (q, "stack"))
158 	    mask = MASK_DEBUG_STACK;
159 	  else if (! strcmp (q, "arg"))
160 	    mask = MASK_DEBUG_ARG;
161 	  else if (! strcmp (q, "reg"))
162 	    mask = MASK_DEBUG_REG;
163 	  else if (! strcmp (q, "addr"))
164 	    mask = MASK_DEBUG_ADDR;
165 	  else if (! strcmp (q, "cost"))
166 	    mask = MASK_DEBUG_COST;
167 	  else if (! strcmp (q, "target"))
168 	    mask = MASK_DEBUG_TARGET;
169 	  else if (! strcmp (q, "builtin"))
170 	    mask = MASK_DEBUG_BUILTIN;
171 	  else
172 	    error_at (loc, "unknown -mdebug-%s switch", q);
173 
174 	  if (invert)
175 	    opts->x_rs6000_debug &= ~mask;
176 	  else
177 	    opts->x_rs6000_debug |= mask;
178 	}
179       break;
180 
181 #ifdef TARGET_USES_SYSV4_OPT
182     case OPT_mrelocatable:
183       if (value == 1)
184 	{
185 	  opts->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC;
186 	  opts_set->x_rs6000_isa_flags |= OPTION_MASK_MINIMAL_TOC;
187 	  opts->x_TARGET_NO_FP_IN_TOC = 1;
188 	}
189       break;
190 
191     case OPT_mrelocatable_lib:
192       if (value == 1)
193 	{
194 	  opts->x_rs6000_isa_flags |= (OPTION_MASK_RELOCATABLE
195 				       | OPTION_MASK_MINIMAL_TOC);
196 	  opts_set->x_rs6000_isa_flags |= (OPTION_MASK_RELOCATABLE
197 					   | OPTION_MASK_MINIMAL_TOC);
198 	  opts->x_TARGET_NO_FP_IN_TOC = 1;
199 	}
200       else
201 	{
202 	  opts->x_rs6000_isa_flags &= ~OPTION_MASK_RELOCATABLE;
203 	  opts_set->x_rs6000_isa_flags |= OPTION_MASK_RELOCATABLE;
204 	}
205       break;
206 #endif
207 
208     case OPT_mabi_altivec:
209       /* Enabling the AltiVec ABI turns off the SPE ABI.  */
210       opts->x_rs6000_spe_abi = 0;
211       break;
212 
213     case OPT_mabi_spe:
214       opts->x_rs6000_altivec_abi = 0;
215       break;
216 
217     case OPT_mlong_double_:
218       if (value != 64 && value != 128)
219 	{
220 	  error_at (loc, "unknown switch -mlong-double-%s", arg);
221 	  opts->x_rs6000_long_double_type_size
222 	    = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
223 	  return false;
224 	}
225       break;
226 
227     case OPT_msingle_float:
228       if (!TARGET_SINGLE_FPU)
229 	warning_at (loc, 0,
230 		    "-msingle-float option equivalent to -mhard-float");
231       /* -msingle-float implies -mno-double-float and TARGET_HARD_FLOAT. */
232       opts->x_rs6000_double_float = 0;
233       opts->x_rs6000_isa_flags &= ~OPTION_MASK_SOFT_FLOAT;
234       opts_set->x_rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT;
235       break;
236 
237     case OPT_mdouble_float:
238       /* -mdouble-float implies -msingle-float and TARGET_HARD_FLOAT. */
239       opts->x_rs6000_single_float = 1;
240       opts->x_rs6000_isa_flags &= ~OPTION_MASK_SOFT_FLOAT;
241       opts_set->x_rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT;
242       break;
243 
244     case OPT_msimple_fpu:
245       if (!TARGET_SINGLE_FPU)
246 	warning_at (loc, 0, "-msimple-fpu option ignored");
247       break;
248 
249     case OPT_mhard_float:
250       /* -mhard_float implies -msingle-float and -mdouble-float. */
251       opts->x_rs6000_single_float = opts->x_rs6000_double_float = 1;
252       break;
253 
254     case OPT_msoft_float:
255       /* -msoft_float implies -mnosingle-float and -mnodouble-float. */
256       opts->x_rs6000_single_float = opts->x_rs6000_double_float = 0;
257       break;
258 
259     case OPT_mfpu_:
260       fpu_type = (enum fpu_type_t) value;
261       if (fpu_type != FPU_NONE)
262 	{
263 	  /* If -mfpu is not none, then turn off SOFT_FLOAT, turn on
264 	     HARD_FLOAT. */
265 	  opts->x_rs6000_isa_flags &= ~OPTION_MASK_SOFT_FLOAT;
266 	  opts_set->x_rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT;
267 	  opts->x_rs6000_xilinx_fpu = 1;
268 	  if (fpu_type == FPU_SF_LITE || fpu_type == FPU_SF_FULL)
269 	    opts->x_rs6000_single_float = 1;
270 	  if (fpu_type == FPU_DF_LITE || fpu_type == FPU_DF_FULL)
271 	    opts->x_rs6000_single_float = opts->x_rs6000_double_float = 1;
272 	  if (fpu_type == FPU_SF_LITE || fpu_type == FPU_DF_LITE)
273 	    opts->x_rs6000_simple_fpu = 1;
274 	}
275       else
276 	{
277 	  /* -mfpu=none is equivalent to -msoft-float.  */
278 	  opts->x_rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT;
279 	  opts_set->x_rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT;
280 	  opts->x_rs6000_single_float = opts->x_rs6000_double_float = 0;
281 	}
282       break;
283 
284     case OPT_mrecip:
285       opts->x_rs6000_recip_name = (value) ? "default" : "none";
286       break;
287     }
288   return true;
289 }
290 
291 #undef TARGET_HANDLE_OPTION
292 #define TARGET_HANDLE_OPTION rs6000_handle_option
293 
294 #undef TARGET_OPTION_INIT_STRUCT
295 #define TARGET_OPTION_INIT_STRUCT rs6000_option_init_struct
296 
297 #undef TARGET_OPTION_DEFAULT_PARAMS
298 #define TARGET_OPTION_DEFAULT_PARAMS rs6000_option_default_params
299 
300 #undef TARGET_OPTION_OPTIMIZATION_TABLE
301 #define TARGET_OPTION_OPTIMIZATION_TABLE rs6000_option_optimization_table
302 
303 struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
304