1/* Target definitions for GNU compiler for Alliant FX/2800
2   running Concentrix 2.2
3   Copyright (C) 1991, 1996, 1998, 1999 Free Software Foundation, Inc.
4   Contributed by Howard Chu (hyc@hanauma.jpl.nasa.gov).
5
6This file is part of GNU CC.
7
8GNU CC is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2, or (at your option)
11any later version.
12
13GNU CC is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU CC; see the file COPYING.  If not, write to
20the Free Software Foundation, 59 Temple Place - Suite 330,
21Boston, MA 02111-1307, USA.  */
22
23/* The Alliant fx2800 running Concentrix 2.x is weird.  This is basically
24   a BSD 4.3 based operating system, but it uses svr4 ELF format object
25   files and it somehow puts BSD stabs records into the ELF files for
26   symbolic debug information.  The assembler is "mostly an SVR4 assembler
27   with some Alliant additions. We based it on the `Intel 80860 Assembly
28   Language Specification' from AT&T." */
29
30/* This file consists of three sections. The first section establishes
31   definitions unique to the Alliant FX/2800. The next section reconciles
32   differences between Alliant and i860v4.h, and the last overrides the
33   remaining differences with svr4.h */
34
35#undef TARGET_VERSION
36#define TARGET_VERSION fprintf (stderr, " (i860 Alliant)");
37
38/* atexit is not present prior to Concentrix 2.2. Uncomment the following
39   if you're on 2.1 or older. */
40
41/* #undef HAVE_ATEXIT */
42
43#define I860_STRICT_ABI_PROLOGUES
44
45/* There is no avoiding this; -L does not exist at all (in Concentrix 2.2).  */
46#define LINK_LIBGCC_SPECIAL 1
47
48/* Most of the Alliant-specific definitions here are to get stab info that
49   Alliant's dbx can understand. */
50
51#define DBX_DEBUGGING_INFO
52#define DEFAULT_GDB_EXTENSIONS 0
53#define DBX_NO_XREFS
54#define DBX_NO_EXTRA_TAGS
55
56/* Alliant dbx also needs to see the function stab before anything
57   else in the function. */
58
59#define DBX_FUNCTION_FIRST
60#define DBX_LBRAC_FIRST
61
62/* Alliant dbx also needs to see the end of a function somewhere. */
63
64#define DBX_OUTPUT_FUNCTION_END(file,decl)	\
65	fprintf (file, ".stab \"\",.,0x%x,0,0\n", N_EFUN)
66
67/* Alliant dbx has predefined types, so they must be emitted with the
68   proper type numbers. The defined types are:
69
70     Type #	C, Fortran, Pascal Types
71	--	------------------------
72	 1	char, integer*1
73	 2	short, 	integer*2
74	 3	int, long, integer*4, integer
75	 4	logical*1, byte
76	 5	logical*2
77	 6	logical*4, logical
78	 7	float, real*4, 	real
79	 8	double, real*8,	double
80	 9	single complex, complex*8, complex
81	10	double complex, doublecomplex
82	11	character
83	12	void
84	13	nil
85	14	boolean
86	15	unsigned char, ubyte
87	16	unsigned short, uword
88	17	unsigned, unsigned int, unsigned long, ulong
89	18	quad, logical*8
90	19	long long, integer*8
91	20	unsigned long long, uquad*8
92    21-100	reserved for future predefined types
93	100	long redefine same as 3
94	101	unsigned long same as 17
95	--	--------------------
96	102	First user program type
97
98   Since long and unsigned long are int references, they must be handled
99   as special cases. The Alliant compiler doesn't use types 18-20, so it
100   sets long & unsigned long in 18 & 19, not in 100 & 101 as shown above. */
101
102#define DBX_OUTPUT_STANDARD_TYPES(syms)	\
103{ char *dtyps[]={"", "char", "short int", "int", "logical*1",		\
104	"logical*2", "logical*4", "float", "double", "complex",		\
105	"doublecomplex", "character", "void", "nil", "boolean",		\
106	"unsigned char", "short unsigned int", "unsigned int",		\
107	"logical*8", "long long int", "long long unsigned int",""};	\
108									\
109  tree decl;								\
110  int i;								\
111									\
112  for (i=1;*dtyps[i];i++)						\
113    for (decl = syms; decl; decl = TREE_CHAIN(decl))			\
114	if ((TREE_CODE (decl) == TYPE_DECL) && DECL_NAME(decl) &&	\
115	    !strcmp(IDENTIFIER_POINTER(DECL_NAME(decl)), dtyps[i])) {	\
116		TYPE_SYMTAB_ADDRESS (TREE_TYPE (decl)) = i;		\
117		typevec[i] = TYPE_DEFINED;				\
118		dbxout_symbol (decl, 0);				\
119		break;							\
120	}								\
121									\
122  for (decl = syms; decl; decl = TREE_CHAIN(decl))			\
123    if ((TREE_CODE (decl) == TYPE_DECL) && DECL_NAME(decl) &&		\
124	!strcmp(IDENTIFIER_POINTER(DECL_NAME(decl)),"long int")) {	\
125      TYPE_SYMTAB_ADDRESS (TREE_TYPE (decl)) = i;			\
126      typevec[i] = TYPE_DEFINED;					\
127      fprintf(asmfile,".stab \"long int:t%d=3\",0,0x%x,0,0\n",		\
128		i++,N_LSYM);						\
129      TREE_ASM_WRITTEN (decl) = 1;					\
130      break;								\
131    }									\
132									\
133  for (decl = syms; decl; decl = TREE_CHAIN(decl))			\
134    if ((TREE_CODE (decl) == TYPE_DECL) && DECL_NAME(decl) && !strcmp(	\
135	IDENTIFIER_POINTER(DECL_NAME(decl)),"long unsigned int")) {	\
136      TYPE_SYMTAB_ADDRESS (TREE_TYPE (decl)) = i;			\
137      typevec[i] = TYPE_DEFINED;					\
138      fprintf(asmfile,".stab \"long unsigned int:t%d=17\",0,0x%x,0,0\n",\
139		i++,N_LSYM);						\
140      TREE_ASM_WRITTEN (decl) = 1;					\
141      break;								\
142    }									\
143  next_type_number = i; };
144
145/* Alliant dbx doesn't understand split names... */
146
147#define DBX_CONTIN_LENGTH 0
148
149/* The syntax for stabs records is also different; there is only a single
150   ".stab" directive instead of the 3 directives in BSD, and the order of
151   arguments is slightly changed. */
152
153#define ASM_STABS_OP	".stab"
154#define ASM_STABN_OP	".stab"
155#define ASM_STABD_OP	".stab"
156
157#define DBX_MEMPARM_STABS_LETTER 'k'
158#define DBX_REGPARM_STABS_LETTER 'r'
159
160#define ASM_OUTPUT_SOURCE_LINE(file,num)		\
161	fprintf (file, "\t.stab \"\",.,0x%x,0,%d\n",	\
162		N_SLINE,num)
163
164#if 0	/* Alliant dbx only reads first N_SO, so it
165	   ignores the filename if dir is present. */
166#define DBX_OUTPUT_MAIN_SOURCE_DIRECTORY(file,name)		\
167	fprintf (file, ".stab \"%s/\",.Ltext0,0x%x,0,0\n",	\
168		name, N_SO)
169#else
170#define DBX_OUTPUT_MAIN_SOURCE_DIRECTORY(file,name)
171#endif
172
173#define DBX_OUTPUT_MAIN_SOURCE_FILENAME(file,name)		\
174	fprintf (file, ".stab ");				\
175	output_quoted_string (file, name);			\
176	fprintf (file, ",.Ltext0,0x%x,0,0\n", N_SO);		\
177	text_section ();					\
178	ASM_OUTPUT_INTERNAL_LABEL (file, "Ltext", 0)
179
180#define DBX_OUTPUT_SOURCE_FILENAME(file,name)			\
181  do {	fprintf (file, ".stab ");				\
182	output_quoted_string (file, name);			\
183	fprintf (file, ",.Ltext0,0x%x,0,0\n", N_SOL);		\
184  } while (0)
185
186#define DBX_OUTPUT_CONSTANT_SYMBOL(file,name,ival)		\
187	fprintf (file, ".stab \"%s:c=i%d\",0,0x%x,0,0\n",	\
188		name, ival, N_LSYM)
189
190#define DBX_FINISH_SYMBOL(decl)	\
191	int line = 0;						\
192	fprintf (asmfile, "\",");				\
193	if (current_sym_addr)					\
194	  output_addr_const (asmfile, current_sym_addr);	\
195	else							\
196	  fprintf (asmfile, "%d", current_sym_value);		\
197	if (decl != 0 && TREE_CODE(decl) == FUNCTION_DECL)	\
198	  line=DECL_SOURCE_LINE (decl);				\
199	fprintf (asmfile, ",0x%x,%d,%d\n", current_sym_code,	\
200	  line!=0?64:0,line)
201
202#define DBX_OUTPUT_CATCH(file,decl,name)		\
203  fprintf (file, ".stab \"%s:C1\",",			\
204	   IDENTIFIER_POINTER (DECL_NAME (decl)));	\
205  assemble_name (file, name);				\
206  fprintf (file, ",0x%x,0,0\n", N_CATCH)
207
208#define DBX_OUTPUT_LBRAC(file,name)	\
209  if (depth > 1) {			\
210    fprintf (file, ".stab \"\",");	\
211    assemble_name (file, name);		\
212    fprintf (file, ",0x%x,0,%d\n", N_LBRAC, depth); }
213
214#define DBX_OUTPUT_RBRAC(file,name)	\
215  if (depth > 1) {			\
216    fprintf (file, ".stab \"\",");	\
217    assemble_name (file, name);		\
218    fprintf (file, ",0x%x,0,%d\n", N_RBRAC, depth); }
219
220#define DBX_OUTPUT_ENUM(file,type)				\
221  fprintf (file, "e3");						\
222  CHARS(2);							\
223  for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem))	\
224    {								\
225      fprintf (asmfile, "%s:%d,",				\
226	       IDENTIFIER_POINTER (TREE_PURPOSE (tem)),		\
227	       TREE_INT_CST_LOW (TREE_VALUE (tem)));		\
228      CHARS (11 + IDENTIFIER_LENGTH (TREE_PURPOSE (tem)));	\
229      if (TREE_CHAIN (tem) != 0)				\
230	CONTIN;							\
231    }								\
232  putc (';', asmfile);						\
233  CHARS (1);
234
235/* Undefine some things defined in i860.h because the native C compiler
236   on the FX/2800 emits code to do these operations inline.  For GCC,
237   we will use the default implementation of these things... i.e.
238   generating calls to libgcc1 routines.  */
239
240#undef DIVSI3_LIBCALL
241#undef UDIVSI3_LIBCALL
242#undef REMSI3_LIBCALL
243#undef UREMSI3_LIBCALL
244
245/* The Alliant compiler's mod function gives the wrong result after a
246   shift operation. This bug typically hits in hash functions. */
247
248#define perform_umodsi3(a, b)	a %= b; if (a == b) a=0; return a
249#define perform_modsi3(a, b)	a %= b; if (a == b) a=0; return a
250
251/* Global pointer needs to be 8 byte aligned? Link error if not... */
252
253#define DATA_ALIGNMENT(dummy,align)	\
254	((TREE_PUBLIC (decl) &&	\
255	 (POINTER_TYPE_P (TREE_TYPE (decl)))) ? 64: align)
256
257#undef FUNCTION_PROFILER
258#define FUNCTION_PROFILER(FILE, LABELNO)	\
259	fprintf (FILE, "\tcall __mcount_\n\tnop\n")
260
261/* Overrides for i860v4.h begin here */
262
263/* Provide a set of pre-definitions and pre-assertions appropriate for
264   the i860 running Concentrix 2.x.  */
265
266#undef CPP_PREDEFINES
267#define CPP_PREDEFINES "-Di860 -Dunix -DBSD4_3 -Dalliant -Asystem(unix) -Asystem(bsd) -Acpu(i860) -Amachine(i860)"
268
269#undef I860_REG_PREFIX
270#undef ASM_COMMENT_START
271#define ASM_COMMENT_START "//"
272
273/* Use definitions of ASM_OUTPUT_{DOUBLE,FLOAT} as given in i860.h */
274
275#undef ASM_OUTPUT_DOUBLE
276#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
277  fprintf(FILE, "\t.double %.20e\n", (VALUE))
278#undef ASM_OUTPUT_FLOAT
279#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
280  fprintf(FILE, "\t.float %.12e\n", (VALUE))
281
282#undef ASM_FILE_START
283#define ASM_FILE_START(FILE)
284#undef ASM_OUTPUT_FUNCTION_PREFIX
285#define ASM_OUTPUT_FUNCTION_PREFIX(FILE,NAME) \
286  fputs("\tnop\n", (FILE));			\
287  current_function_original_name = (NAME)
288#undef ASM_OUTPUT_PROLOGUE_SUFFIX
289
290/* Overrides for svr4.h begin here */
291
292#undef SVR4
293
294#undef SWITCH_TAKES_ARG
295#undef WORD_SWITCH_TAKES_ARG
296
297#undef ASM_SPEC
298#undef ASM_FINAL_SPEC
299#undef MD_STARTFILE_PREFIX
300#undef MD_EXEC_PREFIX
301
302/* Generate an error message if -p option is selected. Concentrix 2.x
303   does not support prof format profiling, only gprof is supported. */
304
305#define CPP_SPEC	"%{p:%e-p option not supported: use -pg instead}"
306
307/* Provide an appropriate LIB_SPEC. The crtend.o file provides part of the
308   support for getting C++ file-scope static objects constructed before
309   entering `main'. */
310
311#undef LIB_SPEC
312#define LIB_SPEC \
313	"%{g*:-lg} %{!pg:-lc}%{pg:-lc_p} crtend.o%s"
314
315/* Tell linker to strip local symbols, since assembler may not. */
316
317#undef LINK_SPEC
318#define LINK_SPEC	"-X"
319
320/* Get the correct startup file for regular or profiled code. Also
321   use the crtbegin.o file for C++ ... */
322
323#undef STARTFILE_SPEC
324#define STARTFILE_SPEC \
325	"%{!pg:crt0.o%s}%{pg:gcrt0.o%s} crtbegin.o%s"
326
327#undef SCCS_DIRECTIVE
328#undef NO_DOLLAR_IN_LABEL
329#undef TARGET_MEM_FUNCTIONS
330
331#undef DWARF_DEBUGGING_INFO
332
333/* The prefix to add to user-visible assembler symbols. */
334
335#undef USER_LABEL_PREFIX
336#define USER_LABEL_PREFIX "_"
337
338#undef ASM_OUTPUT_EXTERNAL_LIBCALL
339
340/* ??? Is this used anywhere?  */
341#undef BSS_ASM_OP
342#define BSS_ASM_OP	"\t.lcomm"
343
344#undef ASM_FILE_END
345#define ASM_FILE_END(FILE)					\
346do {				 				\
347     if (current_function_original_name != NULL) {		\
348       tdesc_section();						\
349       fprintf ((FILE), "%s __ETEXT\n", ASM_LONG);		\
350       fprintf ((FILE), "%s 0\n", ASM_LONG);			\
351       text_section();						\
352       fputs("__ETEXT:\n", (FILE));				\
353     }								\
354     if (!flag_no_ident)					\
355	fprintf ((FILE), "\t.ident\t\"GCC: (GNU) %s\"\n",	\
356		 version_string);				\
357   } while (0)
358