1/* Definitions of target machine for GNU compiler, for DEC Alpha on Cray
2   T3E running Unicos/Mk.
3   Copyright (C) 2001, 2002, 2004, 2005
4   Free Software Foundation, Inc.
5   Contributed by Roman Lechtchinsky (rl@cs.tu-berlin.de)
6
7This file is part of GCC.
8
9GCC is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2, or (at your option)
12any later version.
13
14GCC is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with GCC; see the file COPYING.  If not, write to
21the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22Boston, MA 02110-1301, USA.  */
23
24#undef TARGET_ABI_UNICOSMK
25#define TARGET_ABI_UNICOSMK 1
26
27/* CAM requires a slash before floating-pointing instruction suffixes.  */
28
29#undef TARGET_AS_SLASH_BEFORE_SUFFIX
30#define TARGET_AS_SLASH_BEFORE_SUFFIX 1
31
32/* The following defines are necessary for the standard headers to work
33   correctly.  */
34
35#define TARGET_OS_CPP_BUILTINS()				\
36    do {							\
37	builtin_define ("__unix");				\
38	builtin_define ("_UNICOS=205");				\
39	builtin_define ("_CRAY");				\
40	builtin_define ("_CRAYT3E");				\
41	builtin_define ("_CRAYMPP");				\
42	builtin_define ("_CRAYIEEE");				\
43	builtin_define ("_ADDR64");				\
44	builtin_define ("_LD64");				\
45	builtin_define ("__UNICOSMK__");			\
46    } while (0)
47
48#define SHORT_TYPE_SIZE 32
49
50#undef INT_TYPE_SIZE
51#define INT_TYPE_SIZE 64
52
53/* This is consistent with the definition Cray CC uses.  */
54#undef WCHAR_TYPE
55#define WCHAR_TYPE "int"
56#undef WCHAR_TYPE_SIZE
57#define WCHAR_TYPE_SIZE 64
58
59/*
60#define SIZE_TYPE "unsigned int"
61#define PTRDIFF_TYPE "int"
62*/
63
64/* Alphas are operated in big endian mode on the Cray T3E.  */
65
66#undef BITS_BIG_ENDIAN
67#undef BYTES_BIG_ENDIAN
68#undef WORDS_BIG_ENDIAN
69#define BITS_BIG_ENDIAN 0
70#define BYTES_BIG_ENDIAN 1
71#define WORDS_BIG_ENDIAN 1
72
73
74/* Every structure's size must be a multiple of this.  */
75
76#undef STRUCTURE_SIZE_BOUNDARY
77#define STRUCTURE_SIZE_BOUNDARY 64
78
79/* No data type wants to be aligned rounder than this.  */
80
81#undef BIGGEST_ALIGNMENT
82#define BIGGEST_ALIGNMENT 256
83
84/* Include the frame pointer in fixed_regs and call_used_regs as it can't be
85   used as a general-purpose register even in frameless functions.
86   ??? The global_regs hack is needed for now because -O2 sometimes tries to
87   eliminate $15 increments/decrements in frameless functions.  */
88
89#undef CONDITIONAL_REGISTER_USAGE
90#define CONDITIONAL_REGISTER_USAGE	\
91  do {					\
92    fixed_regs[15] = 1;			\
93    call_used_regs[15] = 1;		\
94    global_regs[15] = 1;		\
95  } while(0)
96
97/* The stack frame grows downward.  */
98
99#define FRAME_GROWS_DOWNWARD 1
100
101/* Define the offset between two registers, one to be eliminated, and the
102   other its replacement, at the start of a routine. This is somewhat
103   complicated on the T3E which is why we use a function.  */
104
105#undef INITIAL_ELIMINATION_OFFSET
106#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)			\
107  do {									\
108    (OFFSET) = unicosmk_initial_elimination_offset ((FROM), (TO));	\
109  } while (0)
110
111
112/* Define this if stack space is still allocated for a parameter passed
113   in a register. On the T3E, stack space is preallocated for all outgoing
114   arguments, including those passed in registers. To avoid problems, we
115   assume that at least 48 bytes (i.e. enough space for all arguments passed
116   in registers) are allocated.  */
117
118#define REG_PARM_STACK_SPACE(DECL) 48
119#define OUTGOING_REG_PARM_STACK_SPACE
120
121/* If an argument can't be passed in registers even though not all argument
122   registers have been used yet, it is passed on the stack in the space
123   preallocated for these registers.  */
124
125#define STACK_PARMS_IN_REG_PARM_AREA
126
127/* Define a data type for recording info about an argument list
128   during the scan of that argument list.  This data type should
129   hold all necessary information about the function itself
130   and about the args processed so far, enough to enable macros
131   such as FUNCTION_ARG to determine where the next arg should go.
132
133   On Unicos/Mk, this is a structure that contains various information for
134   the static subroutine information block (SSIB) and the call information
135   word (CIW).  */
136
137typedef struct {
138
139  /* The overall number of arguments.  */
140  int num_args;
141
142  /* The overall size of the arguments in words.  */
143  int num_arg_words;
144
145  /* The number of words passed in registers.  */
146  int num_reg_words;
147
148  /* If an argument must be passed in the stack, all subsequent arguments
149     must be passed there, too. This flag indicates whether this is the
150     case.  */
151  int force_stack;
152
153  /* This array indicates whether a word is passed in an integer register or
154     a floating point one.  */
155
156  /* For each of the 6 register arguments, the corresponding flag in this
157     array indicates whether the argument is passed in an integer or a
158     floating point register.  */
159  int reg_args_type[6];
160
161} unicosmk_arg_info;
162
163#undef CUMULATIVE_ARGS
164#define CUMULATIVE_ARGS unicosmk_arg_info
165
166/* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a
167   function whose data type is FNTYPE.  For a library call, FNTYPE is 0.  */
168
169#undef INIT_CUMULATIVE_ARGS
170#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
171  do { (CUM).num_args = 0;					\
172       (CUM).num_arg_words = 0;					\
173       (CUM).num_reg_words = 0;					\
174       (CUM).force_stack = 0;					\
175  } while(0)
176
177/* Update the data in CUM to advance over an argument of mode MODE and data
178   type TYPE. (TYPE is null for libcalls where that information may not be
179   available.)
180
181   On Unicos/Mk, at most 6 words can be passed in registers. Structures
182   which fit in two words are passed in registers, larger structures are
183   passed on stack.  */
184
185#undef FUNCTION_ARG_ADVANCE
186#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)		\
187do {								\
188  int size;							\
189								\
190  size = ALPHA_ARG_SIZE (MODE, TYPE, NAMED);			\
191                                                                \
192  if (size > 2							\
193      || (CUM).num_reg_words + size > 6				\
194      || targetm.calls.must_pass_in_stack (MODE, TYPE))		\
195    (CUM).force_stack = 1;					\
196                                                                \
197  if (! (CUM).force_stack)					\
198    {								\
199      int i;							\
200      int isfloat;						\
201      isfloat = (GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT	\
202              || GET_MODE_CLASS (MODE) == MODE_FLOAT);		\
203      for (i = 0; i < size; i++)				\
204        {							\
205          (CUM).reg_args_type[(CUM).num_reg_words] = isfloat;	\
206          ++(CUM).num_reg_words;				\
207        }							\
208    }								\
209  (CUM).num_arg_words += size;					\
210  ++(CUM).num_args;						\
211} while(0)
212
213/* This ensures that $15 increments/decrements in leaf functions won't get
214   eliminated.  */
215
216#undef EPILOGUE_USES
217#define EPILOGUE_USES(REGNO)  ((REGNO) == 26 || (REGNO) == 15)
218
219/* Would have worked, only the stack doesn't seem to be executable
220#undef TRAMPOLINE_TEMPLATE
221#define TRAMPOLINE_TEMPLATE(FILE)			\
222do { fprintf (FILE, "\tbr $1,0\n");			\
223     fprintf (FILE, "\tldq $0,12($1)\n");		\
224     fprintf (FILE, "\tldq $1,20($1)\n");		\
225     fprintf (FILE, "\tjmp $31,(r0)\n");		\
226     fprintf (FILE, "\tbis $31,$31,$31\n");		\
227     fprintf (FILE, "\tbis $31,$31,$31\n");		\
228} while (0) */
229
230/* We don't support nested functions (yet).  */
231
232#undef TRAMPOLINE_TEMPLATE
233#define TRAMPOLINE_TEMPLATE(FILE) gcc_unreachable ()
234
235/* Specify the machine mode that this machine uses for the index in the
236   tablejump instruction. On Unicos/Mk, we don't support relative case
237   vectors yet, thus the entries should be absolute addresses.  */
238
239#undef CASE_VECTOR_MODE
240#define CASE_VECTOR_MODE DImode
241
242#undef CASE_VECTOR_PC_RELATIVE
243
244/* Define this as 1 if `char' should by default be signed; else as 0.  */
245/* #define DEFAULT_SIGNED_CHAR 1 */
246
247/* The Cray assembler is really weird with respect to sections. It has only
248   named sections and you can't reopen a section once it has been closed.
249   This means that we have to generate unique names whenever we want to
250   reenter the text or the data section. The following is a rather bad hack
251   as TEXT_SECTION_ASM_OP and DATA_SECTION_ASM_OP are supposed to be
252   constants.  */
253
254#undef TEXT_SECTION_ASM_OP
255#define TEXT_SECTION_ASM_OP unicosmk_text_section ()
256
257#undef DATA_SECTION_ASM_OP
258#define DATA_SECTION_ASM_OP unicosmk_data_section ()
259
260/* There are no read-only sections on Unicos/Mk.  */
261
262#undef READONLY_DATA_SECTION_ASM_OP
263#define READONLY_DATA_SECTION data_section
264
265/* Define extra sections for common data and SSIBs (static subroutine
266   information blocks). The actual section header is output by the callers
267   of these functions.  */
268
269#undef EXTRA_SECTIONS
270#undef EXTRA_SECTION_FUNCTIONS
271
272#define EXTRA_SECTIONS in_common, in_ssib
273#define EXTRA_SECTION_FUNCTIONS	\
274COMMON_SECTION			\
275SSIB_SECTION
276
277extern void common_section (void);
278#define COMMON_SECTION		\
279void				\
280common_section (void)		\
281{				\
282  in_section = in_common;	\
283}
284
285extern void ssib_section (void);
286#define SSIB_SECTION		\
287void				\
288ssib_section (void)		\
289{				\
290  in_section = in_ssib;		\
291}
292
293/* We take care of this in unicosmk_file_start.  */
294
295#undef ASM_OUTPUT_SOURCE_FILENAME
296
297/* This is how to output a label for a jump table.  Arguments are the same as
298   for (*targetm.asm_out.internal_label), except the insn for the jump table is
299   passed.  */
300
301#undef ASM_OUTPUT_CASE_LABEL
302#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLEINSN)	\
303  (*targetm.asm_out.internal_label) (FILE, PREFIX, NUM)
304
305/* CAM has some restrictions with respect to string literals. It won't
306   accept lines with more that 256 characters which means that we have
307   to split long strings. Moreover, it only accepts escape sequences of
308   the form \nnn in the range 0 to 127. We generate .byte directives for
309   escapes characters greater than 127. And finally, ` must be escaped.  */
310
311#undef ASM_OUTPUT_ASCII
312#define ASM_OUTPUT_ASCII(MYFILE, MYSTRING, MYLENGTH) \
313  do {									      \
314    FILE *_hide_asm_out_file = (MYFILE);				      \
315    const unsigned char *_hide_p = (const unsigned char *) (MYSTRING);	      \
316    int _hide_thissize = (MYLENGTH);					      \
317    int _size_so_far = 0;						      \
318    {									      \
319      FILE *asm_out_file = _hide_asm_out_file;				      \
320      const unsigned char *p = _hide_p;					      \
321      int thissize = _hide_thissize;					      \
322      int in_ascii = 0;							      \
323      int i;								      \
324									      \
325      for (i = 0; i < thissize; i++)					      \
326	{								      \
327	  register int c = p[i];					      \
328									      \
329	  if (c > 127)							      \
330	    {								      \
331	      if (in_ascii)						      \
332		{							      \
333		  fprintf (asm_out_file, "\"\n");			      \
334		  in_ascii = 0;						      \
335		}							      \
336									      \
337	      fprintf (asm_out_file, "\t.byte\t%d\n", c);		      \
338	    }								      \
339	  else								      \
340	    {								      \
341	      if (! in_ascii)						      \
342		{							      \
343		  fprintf (asm_out_file, "\t.ascii\t\"");		      \
344		  in_ascii = 1;						      \
345		  _size_so_far = 0;					      \
346		}							      \
347	      else if (_size_so_far >= 64)				      \
348		{							      \
349		  fprintf (asm_out_file, "\"\n\t.ascii\t\"");		      \
350		  _size_so_far = 0;					      \
351		}							      \
352									      \
353	      if (c == '\"' || c == '\\' || c == '`')			      \
354		putc ('\\', asm_out_file);				      \
355	      if (c >= ' ')						      \
356		putc (c, asm_out_file);					      \
357	      else							      \
358		fprintf (asm_out_file, "\\%.3o", c);			      \
359	      ++ _size_so_far;						      \
360	    }								      \
361	}								      \
362      if (in_ascii)							      \
363	fprintf (asm_out_file, "\"\n");					      \
364    }									      \
365  } while(0)
366
367/* This is how to output an element of a case-vector that is absolute.  */
368
369#undef ASM_OUTPUT_ADDR_VEC_ELT
370#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)	\
371  fprintf (FILE, "\t.quad $L%d\n", (VALUE))
372
373/* This is how to output an element of a case-vector that is relative.
374   (Unicos/Mk does not use such vectors yet).  */
375
376#undef ASM_OUTPUT_ADDR_DIFF_ELT
377#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) gcc_unreachable ()
378
379/* We can't output case vectors in the same section as the function code
380   because CAM doesn't allow data definitions in code sections. Thus, we
381   simply record the case vectors and put them in a separate section after
382   the function.  */
383
384#define ASM_OUTPUT_ADDR_VEC(LAB,VEC) \
385  unicosmk_defer_case_vector ((LAB),(VEC))
386
387#define ASM_OUTPUT_ADDR_DIFF_VEC(LAB,VEC) gcc_unreachable ()
388
389/* This is how to output an assembler line that says to advance the location
390   counter to a multiple of 2**LOG bytes. Annoyingly, CAM always uses zeroes
391   to fill the unused space which does not work in code sections. We have to
392   be careful not to use the .align directive in code sections.  */
393
394#undef ASM_OUTPUT_ALIGN
395#define ASM_OUTPUT_ALIGN(STREAM,LOG) unicosmk_output_align (STREAM, LOG)
396
397/* This is how to advance the location counter by SIZE bytes.  */
398
399#undef ASM_OUTPUT_SKIP
400#define ASM_OUTPUT_SKIP(STREAM,SIZE)			\
401  fprintf ((STREAM), "\t.byte\t0:"HOST_WIDE_INT_PRINT_UNSIGNED"\n",\
402	   (SIZE));
403
404/* This says how to output an assembler line to define a global common
405   symbol. We need the alignment information because it has to be supplied
406   in the section header.  */
407
408#undef ASM_OUTPUT_COMMON
409#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN)	\
410  unicosmk_output_common ((FILE), (NAME), (SIZE), (ALIGN))
411
412/* This says how to output an assembler line to define a local symbol.  */
413
414#undef ASM_OUTPUT_LOCAL
415#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
416  do { data_section ();					\
417       fprintf (FILE, "\t.align\t%d\n", floor_log2 ((ALIGN) / BITS_PER_UNIT));\
418       ASM_OUTPUT_LABEL ((FILE), (NAME));		\
419       fprintf (FILE, "\t.byte 0:"HOST_WIDE_INT_PRINT_UNSIGNED"\n",(SIZE));\
420  } while (0)
421
422/* CAM does not allow us to declare a symbol as external first and then
423   define it in the same file later. Thus, we keep a list of all external
424   references, remove all symbols defined locally from it and output it at
425   the end of the asm file.  */
426
427#define ASM_OUTPUT_EXTERNAL(FILE,DECL,NAME) \
428  unicosmk_add_extern ((NAME))
429
430#define ASM_OUTPUT_EXTERNAL_LIBCALL(STREAM,SYMREF)	\
431  unicosmk_add_extern (XSTR ((SYMREF), 0))
432
433/* This is how to declare an object. We don't have to output anything if
434   it is a global variable because those go into unique `common' sections
435   and the section name is globally visible. For local variables, we simply
436   output the label. In any case, we have to record that no extern
437   declaration should be generated for the symbol.  */
438
439#define ASM_DECLARE_OBJECT_NAME(STREAM,NAME,DECL) 	\
440  do { tree name_tree;					\
441       name_tree = get_identifier ((NAME));		\
442       TREE_ASM_WRITTEN (name_tree) = 1;		\
443       if (!TREE_PUBLIC (DECL))				\
444	 {						\
445	   assemble_name (STREAM, NAME);		\
446	   fputs (":\n", STREAM);			\
447         }						\
448  } while(0)
449
450/* Switch into a generic section.  */
451#define TARGET_ASM_NAMED_SECTION unicosmk_asm_named_section
452
453#undef ASM_OUTPUT_MAX_SKIP_ALIGN
454#define ASM_OUTPUT_MAX_SKIP_ALIGN(STREAM,POWER,MAXSKIP)
455
456#undef NM_FLAGS
457
458#undef OBJECT_FORMAT_COFF
459
460/* We cannot generate debugging information on Unicos/Mk.  */
461
462#undef SDB_DEBUGGING_INFO
463#undef MIPS_DEBUGGING_INFO
464#undef DBX_DEBUGGING_INFO
465#undef DWARF2_DEBUGGING_INFO
466#undef DWARF2_UNWIND_INFO
467#undef INCOMING_RETURN_ADDR_RTX
468#undef PREFERRED_DEBUGGING_TYPE
469
470/* We don't need a start file.  */
471
472#undef STARTFILE_SPEC
473#define STARTFILE_SPEC ""
474
475/* These are the libraries we have to link with.
476   ??? The Craylibs directory should be autoconfed.  */
477#undef LIB_SPEC
478#define LIB_SPEC "-L/opt/ctl/craylibs/craylibs -lu -lm -lc -lsma"
479
480#undef EXPAND_BUILTIN_VA_START
481
482#define EH_FRAME_IN_DATA_SECTION 1
483