1/* Definitions for 64-bit PowerPC running FreeBSD using the ELF format
2   Copyright (C) 2012-2020 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/* Undef gnu-user.h macros we don't want.  */
21#undef CPLUSPLUS_CPP_SPEC
22#undef LINK_GCC_C_SEQUENCE_SPEC
23
24/* Override the defaults, which exist to force the proper definition.  */
25
26#ifdef IN_LIBGCC2
27#undef TARGET_64BIT
28#ifdef __powerpc64__
29#define TARGET_64BIT 1
30#else
31#define TARGET_64BIT 0
32#endif
33#endif
34
35#undef	TARGET_AIX
36#define	TARGET_AIX TARGET_64BIT
37
38#ifdef HAVE_LD_NO_DOT_SYMS
39/* New ABI uses a local sym for the function entry point.  */
40extern int dot_symbols;
41#undef DOT_SYMBOLS
42#define DOT_SYMBOLS dot_symbols
43#endif
44
45#define TARGET_USES_LINUX64_OPT 1
46#ifdef HAVE_LD_LARGE_TOC
47#undef TARGET_CMODEL
48#define TARGET_CMODEL rs6000_current_cmodel
49#define SET_CMODEL(opt) rs6000_current_cmodel = opt
50#else
51#define SET_CMODEL(opt) do {} while (0)
52#endif
53
54#undef  PROCESSOR_DEFAULT
55#define PROCESSOR_DEFAULT PROCESSOR_PPC7450
56#undef  PROCESSOR_DEFAULT64
57#define PROCESSOR_DEFAULT64 PROCESSOR_POWER8
58
59/* We don't need to generate entries in .fixup, except when
60   -mrelocatable or -mrelocatable-lib is given.  */
61#undef RELOCATABLE_NEEDS_FIXUP
62#define RELOCATABLE_NEEDS_FIXUP \
63  (rs6000_isa_flags & rs6000_isa_flags_explicit & OPTION_MASK_RELOCATABLE)
64
65#undef  RS6000_ABI_NAME
66#define RS6000_ABI_NAME "freebsd"
67
68#define INVALID_64BIT "-m%s not supported in this configuration"
69#define INVALID_32BIT INVALID_64BIT
70
71/* Use LINUX64 instead of FREEBSD64 for compat with e.g. sysv4le.h */
72#ifdef LINUX64_DEFAULT_ABI_ELFv2
73#define ELFv2_ABI_CHECK (rs6000_elf_abi != 1)
74#else
75#define ELFv2_ABI_CHECK (rs6000_elf_abi == 2)
76#endif
77
78#undef  SUBSUBTARGET_OVERRIDE_OPTIONS
79#define SUBSUBTARGET_OVERRIDE_OPTIONS				\
80  do								\
81    {								\
82      if (!global_options_set.x_rs6000_alignment_flags)		\
83	rs6000_alignment_flags = MASK_ALIGN_NATURAL;		\
84      if (TARGET_64BIT)						\
85	{							\
86	  if (DEFAULT_ABI != ABI_AIX)				\
87	    {							\
88	      rs6000_current_abi = ABI_AIX;			\
89	      error (INVALID_64BIT, "call");			\
90	    }							\
91	  dot_symbols = !strcmp (rs6000_abi_name, "aixdesc");	\
92	  if (rs6000_isa_flags & OPTION_MASK_RELOCATABLE)	\
93	    {							\
94	      rs6000_isa_flags &= ~OPTION_MASK_RELOCATABLE;	\
95	      error (INVALID_64BIT, "relocatable");		\
96	    }							\
97	  if (ELFv2_ABI_CHECK)					\
98	    {							\
99	      rs6000_current_abi = ABI_ELFv2;			\
100	      if (dot_symbols)					\
101		error ("%<-mcall-aixdesc%> incompatible with %<-mabi=elfv2%>"); \
102	    }							\
103	  if (rs6000_isa_flags & OPTION_MASK_EABI)		\
104	    {							\
105	      rs6000_isa_flags &= ~OPTION_MASK_EABI;		\
106	      error (INVALID_64BIT, "eabi");			\
107	    }							\
108	  if (TARGET_PROTOTYPE)					\
109	    {							\
110	      target_prototype = 0;				\
111	      error (INVALID_64BIT, "prototype");		\
112	    }							\
113	  if ((rs6000_isa_flags & OPTION_MASK_POWERPC64) == 0)	\
114	    {							\
115	      rs6000_isa_flags |= OPTION_MASK_POWERPC64;	\
116	      error ("%<-m64%> requires a PowerPC64 cpu");		\
117	    }							\
118	   if ((rs6000_isa_flags_explicit			\
119		& OPTION_MASK_MINIMAL_TOC) != 0)		\
120	    {							\
121	      if (global_options_set.x_rs6000_current_cmodel	\
122		  && rs6000_current_cmodel != CMODEL_SMALL)	\
123		error ("%<-mcmodel%> incompatible with other toc options"); \
124	      SET_CMODEL (CMODEL_SMALL);			\
125	    }							\
126	  else							\
127	    {							\
128	      if (!global_options_set.x_rs6000_current_cmodel)	\
129		SET_CMODEL (CMODEL_MEDIUM);			\
130	      if (rs6000_current_cmodel != CMODEL_SMALL)	\
131		{						\
132		  TARGET_NO_FP_IN_TOC = 0;			\
133		  TARGET_NO_SUM_IN_TOC = 0;			\
134		}						\
135	    }							\
136	}							\
137    }								\
138  while (0)
139
140#undef	ASM_SPEC
141#undef	LINK_OS_FREEBSD_SPEC
142
143#define	ASM_SPEC	 "%{m32:%(asm_spec32)}%{!m32:%(asm_spec64)} %(asm_spec_common)"
144#define	LINK_OS_FREEBSD_SPEC "%{m32:%(link_os_freebsd_spec32)}%{!m32:%(link_os_freebsd_spec64)}"
145
146#define ASM_SPEC32 "-a32 \
147%{mrelocatable} %{mrelocatable-lib} %{" FPIE_OR_FPIC_SPEC ":-K PIC} \
148%{memb} %{!memb: %{msdata=eabi: -memb}} \
149%{!mlittle: %{!mlittle-endian: %{!mbig: %{!mbig-endian: \
150    %{mcall-freebsd: -mbig} \
151    %{mcall-i960-old: -mlittle} \
152    %{mcall-linux: -mbig} \
153    %{mcall-gnu: -mbig} \
154    %{mcall-netbsd: -mbig} \
155}}}}"
156
157#define ASM_SPEC64 "-a64"
158
159#define ASM_SPEC_COMMON "%(asm_cpu) \
160%{,assembler|,assembler-with-cpp: %{mregnames} %{mno-regnames}}" \
161  ENDIAN_SELECT(" -mbig", " -mlittle", DEFAULT_ASM_ENDIAN)
162
163#undef	SUBSUBTARGET_EXTRA_SPECS
164#define SUBSUBTARGET_EXTRA_SPECS					\
165  { "asm_spec_common",		ASM_SPEC_COMMON },			\
166  { "asm_spec32",		ASM_SPEC32 },				\
167  { "asm_spec64",		ASM_SPEC64 },				\
168  { "link_os_freebsd_spec32",	LINK_OS_FREEBSD_SPEC32 },     		\
169  { "link_os_freebsd_spec64",	LINK_OS_FREEBSD_SPEC64 },
170
171#define LINK_OS_FREEBSD_SPEC_DEF "\
172  %{p:%nconsider using `-pg' instead of `-p' with gprof(1)} \
173  %{v:-V} \
174  %{assert*} %{R*} %{rpath*} %{defsym*} \
175  %{shared:-Bshareable %{h*} %{soname*}} \
176  %{!shared: \
177    %{!static: \
178      %{rdynamic: -export-dynamic} \
179      %{!dynamic-linker:-dynamic-linker " FBSD_DYNAMIC_LINKER "}} \
180    %{static:-Bstatic}} \
181  %{symbolic:-Bsymbolic}"
182
183#undef  DEFAULT_ASM_ENDIAN
184#define LINK_OS_FREEBSD_SPEC32 "-melf32ppc_fbsd " LINK_OS_FREEBSD_SPEC_DEF
185#if (TARGET_DEFAULT & MASK_LITTLE_ENDIAN)
186#define DEFAULT_ASM_ENDIAN " -mlittle"
187#define LINK_OS_FREEBSD_SPEC64 "-melf64lppc_fbsd " LINK_OS_FREEBSD_SPEC_DEF
188#else
189#define DEFAULT_ASM_ENDIAN " -mbig"
190#define LINK_OS_FREEBSD_SPEC64 "-melf64ppc_fbsd " LINK_OS_FREEBSD_SPEC_DEF
191#endif
192
193#undef	MULTILIB_DEFAULTS
194#define MULTILIB_DEFAULTS { "m64" }
195
196/* PowerPC-64 FreeBSD increases natural record alignment to doubleword if
197   the first field is an FP double, only if in power alignment mode.  */
198#undef  ROUND_TYPE_ALIGN
199#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED)			\
200  ((TARGET_64BIT							\
201    && (TREE_CODE (STRUCT) == RECORD_TYPE				\
202	|| TREE_CODE (STRUCT) == UNION_TYPE				\
203	|| TREE_CODE (STRUCT) == QUAL_UNION_TYPE)			\
204    && TARGET_ALIGN_NATURAL == 0)					\
205   ? rs6000_special_round_type_align (STRUCT, COMPUTED, SPECIFIED)	\
206   : MAX ((COMPUTED), (SPECIFIED)))
207
208/* Use the default for compiling target libs.  */
209#ifdef IN_TARGET_LIBS
210#undef TARGET_ALIGN_NATURAL
211#define TARGET_ALIGN_NATURAL 1
212#endif
213
214/* Indicate that jump tables go in the text section.  */
215#undef  JUMP_TABLES_IN_TEXT_SECTION
216#define JUMP_TABLES_IN_TEXT_SECTION TARGET_64BIT
217
218/* The linux ppc64 ABI isn't explicit on whether aggregates smaller
219   than a doubleword should be padded upward or downward.  You could
220   reasonably assume that they follow the normal rules for structure
221   layout treating the parameter area as any other block of memory,
222   then map the reg param area to registers.  i.e. pad upward.
223   Setting both of the following defines results in this behavior.
224   Setting just the first one will result in aggregates that fit in a
225   doubleword being padded downward, and others being padded upward.
226   Not a bad idea as this results in struct { int x; } being passed
227   the same way as an int.  */
228#define AGGREGATE_PADDING_FIXED TARGET_64BIT
229#define AGGREGATES_PAD_UPWARD_ALWAYS 0
230
231/* Specify padding for the last element of a block move between
232   registers and memory.  FIRST is nonzero if this is the only
233   element.  */
234#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
235  (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
236
237/* FreeBSD doesn't support saving and restoring 64-bit regs with a 32-bit
238   kernel. This is supported when running on a 64-bit kernel with
239   COMPAT_FREEBSD32, but tell GCC it isn't so that our 32-bit binaries
240   are compatible. */
241#define OS_MISSING_POWERPC64 !TARGET_64BIT
242
243#undef  FBSD_TARGET_CPU_CPP_BUILTINS
244#define FBSD_TARGET_CPU_CPP_BUILTINS()			\
245  do							\
246    {							\
247      builtin_define ("__PPC__");			\
248      builtin_define ("__ppc__");			\
249      builtin_define ("__powerpc__");			\
250      if (TARGET_64BIT)					\
251	{						\
252	  builtin_define ("__arch64__");		\
253	  builtin_define ("__LP64__");			\
254	  builtin_define ("__PPC64__");			\
255	  builtin_define ("__powerpc64__");		\
256	  builtin_assert ("cpu=powerpc64");		\
257	  builtin_assert ("machine=powerpc64");		\
258	}						\
259      else						\
260	{						\
261	  builtin_define_std ("PPC");			\
262	  builtin_define_std ("powerpc");		\
263	  builtin_assert ("cpu=powerpc");		\
264	  builtin_assert ("machine=powerpc");		\
265	  TARGET_OS_SYSV_CPP_BUILTINS ();		\
266	}						\
267    }							\
268  while (0)
269
270#undef	CPP_OS_DEFAULT_SPEC
271#define CPP_OS_DEFAULT_SPEC "%(cpp_os_freebsd)"
272
273#undef CPP_OS_FREEBSD_SPEC
274#define CPP_OS_FREEBSD_SPEC ""
275
276#undef	STARTFILE_DEFAULT_SPEC
277#define STARTFILE_DEFAULT_SPEC "%(startfile_freebsd)"
278
279#undef	ENDFILE_DEFAULT_SPEC
280#define ENDFILE_DEFAULT_SPEC "%(endfile_freebsd)"
281
282#undef	LIB_DEFAULT_SPEC
283#define LIB_DEFAULT_SPEC "%(lib_freebsd)"
284
285#undef	LINK_START_DEFAULT_SPEC
286#define LINK_START_DEFAULT_SPEC "%(link_start_freebsd)"
287
288#undef	LINK_OS_DEFAULT_SPEC
289#define	LINK_OS_DEFAULT_SPEC "%(link_os_freebsd)"
290
291/* XXX: This is wrong for many platforms in sysv4.h.
292   We should work on getting that definition fixed.  */
293#undef  LINK_SHLIB_SPEC
294#define LINK_SHLIB_SPEC "%{shared:-shared} %{!shared: %{static:-static}}"
295
296
297/************************[  Target stuff  ]***********************************/
298
299/* Define the actual types of some ANSI-mandated types.
300   Needs to agree with <machine/ansi.h>.  GCC defaults come from c-decl.c,
301   c-common.c, and config/<arch>/<arch>.h.  */
302
303
304#undef  SIZE_TYPE
305#define SIZE_TYPE (TARGET_64BIT ? "long unsigned int" : "unsigned int")
306
307#undef  PTRDIFF_TYPE
308#define PTRDIFF_TYPE	(TARGET_64BIT ? "long int" : "int")
309
310/* rs6000.h gets this wrong for FreeBSD.  We use the GCC defaults instead.  */
311#undef WCHAR_TYPE
312
313#undef  WCHAR_TYPE_SIZE
314#define WCHAR_TYPE_SIZE 32
315
316/* Function profiling bits */
317#undef  RS6000_MCOUNT
318#define RS6000_MCOUNT "_mcount"
319
320#define PROFILE_HOOK(LABEL) \
321  do { if (TARGET_64BIT) output_profile_hook (LABEL); } while (0)
322
323/* _init and _fini functions are built from bits spread across many
324   object files, each potentially with a different TOC pointer.  For
325   that reason, place a nop after the call so that the linker can
326   restore the TOC pointer if a TOC adjusting call stub is needed.  */
327#ifdef __powerpc64__
328#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC)	\
329  asm (SECTION_OP "\n"					\
330"	bl " #FUNC "\n"					\
331"	nop\n"						\
332"	.previous");
333#endif
334
335/* FP save and restore routines.  */
336#undef  SAVE_FP_PREFIX
337#define SAVE_FP_PREFIX (TARGET_64BIT ? "._savef" : "_savefpr_")
338#undef  SAVE_FP_SUFFIX
339#define SAVE_FP_SUFFIX ""
340#undef  RESTORE_FP_PREFIX
341#define RESTORE_FP_PREFIX (TARGET_64BIT ? "._restf" : "_restfpr_")
342#undef  RESTORE_FP_SUFFIX
343#define RESTORE_FP_SUFFIX ""
344
345/* Select a format to encode pointers in exception handling data.  CODE
346   is 0 for data, 1 for code labels, 2 for function pointers.  GLOBAL is
347   true if the symbol may be affected by dynamic relocations.  */
348#undef	ASM_PREFERRED_EH_DATA_FORMAT
349#define	ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
350  (TARGET_64BIT || flag_pic						\
351   ? (((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel		\
352      | (TARGET_64BIT ? DW_EH_PE_udata8 : DW_EH_PE_sdata4))		\
353   : DW_EH_PE_absptr)
354
355/* Static stack checking is supported by means of probes.  */
356#define STACK_CHECK_STATIC_BUILTIN 1
357
358/* The default value isn't sufficient in 64-bit mode.  */
359#define STACK_CHECK_PROTECT (TARGET_64BIT ? 16 * 1024 : 12 * 1024)
360
361/* Use standard DWARF numbering for DWARF debugging information.  */
362#define RS6000_USE_DWARF_NUMBERING
363
364/* PowerPC64 Linux word-aligns FP doubles when -malign-power is given.  */
365#undef  ADJUST_FIELD_ALIGN
366#define ADJUST_FIELD_ALIGN(FIELD, TYPE, COMPUTED) \
367  (rs6000_special_adjust_field_align_p ((TYPE), (COMPUTED))		\
368   ? 128                                                                \
369   : (TARGET_64BIT                                                      \
370      && TARGET_ALIGN_NATURAL == 0                                      \
371      && TYPE_MODE (strip_array_types (TYPE)) == DFmode)   		\
372   ? MIN ((COMPUTED), 32)                                               \
373   : (COMPUTED))
374
375#undef  TOC_SECTION_ASM_OP
376#define TOC_SECTION_ASM_OP \
377  (TARGET_64BIT                                         \
378   ? "\t.section\t\".toc\",\"aw\""                      \
379   : "\t.section\t\".got\",\"aw\"")
380
381#undef  MINIMAL_TOC_SECTION_ASM_OP
382#define MINIMAL_TOC_SECTION_ASM_OP \
383  (TARGET_64BIT                                         \
384   ? "\t.section\t\".toc1\",\"aw\""                     \
385   : (flag_pic						\
386      ? "\t.section\t\".got2\",\"aw\""                  \
387      : "\t.section\t\".got1\",\"aw\""))
388
389/* This is how to declare the size of a function.  */
390#undef  ASM_DECLARE_FUNCTION_SIZE
391#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL)                    \
392  do                                                                    \
393    {                                                                   \
394      if (!flag_inhibit_size_directive)                                 \
395        {                                                               \
396          fputs ("\t.size\t", (FILE));                                  \
397          if (TARGET_64BIT && DOT_SYMBOLS)                              \
398            putc ('.', (FILE));                                         \
399          assemble_name ((FILE), (FNAME));                              \
400          fputs (",.-", (FILE));                                        \
401          rs6000_output_function_entry (FILE, FNAME);                   \
402          putc ('\n', (FILE));                                          \
403        }                                                               \
404    }                                                                   \
405  while (0)
406
407#undef  ASM_OUTPUT_SPECIAL_POOL_ENTRY_P
408#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE)                        \
409  (TARGET_TOC                                                           \
410   && (SYMBOL_REF_P (X)							\
411       || (GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS      \
412           && SYMBOL_REF_P (XEXP (XEXP (X, 0), 0)))			\
413       || GET_CODE (X) == LABEL_REF                                     \
414       || (CONST_INT_P (X)						\
415           && GET_MODE_BITSIZE (MODE) <= GET_MODE_BITSIZE (Pmode))      \
416       || (CONST_DOUBLE_P (X)						\
417           && ((TARGET_64BIT                                            \
418                && (TARGET_MINIMAL_TOC                                  \
419                    || (SCALAR_FLOAT_MODE_P (GET_MODE (X))              \
420                        && ! TARGET_NO_FP_IN_TOC)))                     \
421               || (!TARGET_64BIT                                        \
422                   && !TARGET_NO_FP_IN_TOC                              \
423                   && SCALAR_FLOAT_MODE_P (GET_MODE (X))                \
424                   && BITS_PER_WORD == HOST_BITS_PER_INT)))))
425
426/* Use --as-needed -lgcc_s for eh support.  */
427#ifdef HAVE_LD_AS_NEEDED
428#define USE_LD_AS_NEEDED 1
429#endif
430
431#define POWERPC_FREEBSD
432