1/* Definitions of target machine for GNU compiler,
2   SysV68 Motorola 3300 Delta Series.
3   Copyright (C) 1987, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002
4   Free Software Foundation, Inc.
5   Contributed by Abramo and Roberto Bagnara (bagnara@dipisa.di.unipi.it)
6   based on Alex Crain's 3B1 definitions.
7   Maintained by Philippe De Muyter (phdm@info.ucl.ac.be).
8   Support for GAS added by merging mot3300g.h into this file by
9   Manfred Hollstein (manfred@lts.sel.alcatel.de).
10
11This file is part of GNU CC.
12
13GNU CC is free software; you can redistribute it and/or modify
14it under the terms of the GNU General Public License as published by
15the Free Software Foundation; either version 2, or (at your option)
16any later version.
17
18GNU CC is distributed in the hope that it will be useful,
19but WITHOUT ANY WARRANTY; without even the implied warranty of
20MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21GNU General Public License for more details.
22
23You should have received a copy of the GNU General Public License
24along with GNU CC; see the file COPYING.  If not, write to
25the Free Software Foundation, 59 Temple Place - Suite 330,
26Boston, MA 02111-1307, USA.  */
27
28#ifndef USE_GAS
29#define MOTOROLA		/* Use Motorola syntax rather than "MIT" */
30#define MOTOROLA_BSR		/* Use Span-dependent optimized bsr */
31#define SGS			/* Uses SGS assembler */
32#define SGS_CMP_ORDER		/* Takes cmp operands in reverse order */
33#define SGS_SWAP_W		/* Use swap.w rather than just plain swap */
34#endif /* USE_GAS */
35
36#define NO_DOLLAR_IN_LABEL
37#define NO_DOT_IN_LABEL
38
39#include "m68k/m68k.h"
40
41/* GDB expects a slightly different marker on this target.  */
42#define STABS_GCC_MARKER "gcc2_compiled%"
43
44/* See m68k.h.  0407 means 68020-68040.  */
45
46#ifndef TARGET_DEFAULT
47#define TARGET_DEFAULT (MASK_68040|MASK_BITFIELD|MASK_68881|MASK_68020)
48#endif
49
50/* -m[c]6800 requires special flag to the assembler.  */
51
52#undef ASM_SPEC
53#ifndef USE_GAS
54#define ASM_SPEC "%{m68000:-p 000}%{mc68000:-p 000}"
55#else /* USE_GAS */
56#define ASM_SPEC \
57  "%{v:-v} %{m68000:-mc68000}%{mc68000:-mc68000}%{!mc68000:%{!m68000:-mc68020}}"
58#endif /* USE_GAS */
59
60/* NYI: FP= is equivalent to -msoft-float  */
61
62/* We use /lib/libp/lib* when profiling.  */
63
64/* NYI: if FP=M68881U library is -lc881u  */
65/* NYI: if FP= library is -lc.  */
66/* Default for us: FP=M68881 library is -lc881  */
67#undef LIB_SPEC
68#define LIB_SPEC "%{!shlib:%{!msoft-float:-lc881}%{msoft-float:-lc}}"
69#ifdef CROSS_COMPILE
70#ifndef USE_GLD
71#define DEFAULT_A_OUT_NAME "m68ka.out"
72#endif
73#endif
74
75#ifdef USE_GLD
76#undef LINK_SPEC
77#define LINK_SPEC "%{v:-v}"
78#endif /* defined (USE_GLD) */
79
80#define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__}\
81%{!mc68000:%{!m68000: -D__mc68020__}}"
82
83/* Shared libraries need to use crt0s.o  */
84
85#undef STARTFILE_SPEC
86#ifdef CROSS_COMPILE
87#define STARTFILE_SPEC \
88  "%{!shlib:%{pg:mcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}\
89   %{shlib:crt0s.o%s shlib.ifile%s} %{p:-L"TOOLDIR_BASE_PREFIX DEFAULT_TARGET_MACHINE"/lib/libp} %{pg:-L"TOOLDIR_BASE_PREFIX DEFAULT_TARGET_MACHINE"/lib/libp} "
90#else /* CROSS_COMPILE */
91#define STARTFILE_SPEC \
92  "%{!shlib:%{pg:mcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}\
93   %{shlib:crt0s.o%s shlib.ifile%s} %{p:-L/usr/lib/libp} %{pg:-L/usr/lib/libp} "
94#endif /* CROSS_COMPILE */
95
96/* Generate calls to memcpy, memcmp and memset.  */
97
98#define TARGET_MEM_FUNCTIONS
99
100/* size_t is unsigned int.  */
101
102#define SIZE_TYPE "unsigned int"
103
104/* We need POSIX/XOPEN symbols; otherwise building libio will fail.  */
105#define ADD_MISSING_POSIX 1
106#define ADD_MISSING_XOPEN 1
107
108/* Every structure or union's size must be a multiple of 2 bytes.  */
109
110#define STRUCTURE_SIZE_BOUNDARY 16
111
112/* Follow sysV68 cc regarding alignment imposed by char:0; */
113
114#define PCC_BITFIELD_TYPE_MATTERS 1
115
116/* Allocation boundary (in *bits*) for storing arguments in argument list.  */
117/* Be compatible with native compiler.  */
118#undef PARM_BOUNDARY
119#define PARM_BOUNDARY 16
120
121/* Make output for SDB.  */
122
123#define SDB_DEBUGGING_INFO 1
124
125#undef REGISTER_PREFIX
126#define REGISTER_PREFIX "%"
127
128#undef LOCAL_LABEL_PREFIX
129#ifdef USE_GAS
130#define LOCAL_LABEL_PREFIX ".L"
131#else
132#define LOCAL_LABEL_PREFIX "L%"
133#endif
134
135#undef USER_LABEL_PREFIX
136
137#undef IMMEDIATE_PREFIX
138#define IMMEDIATE_PREFIX "&"
139
140#undef REGISTER_NAMES
141#define REGISTER_NAMES \
142{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",	\
143 "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp",	\
144 "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7"}
145
146#undef FUNCTION_EXTRA_EPILOGUE
147#define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE)				\
148{ if (current_function_returns_pointer					\
149      && ! find_equiv_reg (0, get_last_insn (), 0, 0, 0, 8, Pmode))	\
150    asm_fprintf (FILE, "\tmov.l %Ra0,%Rd0\n"); }
151
152#undef FUNCTION_PROFILER
153#define FUNCTION_PROFILER(FILE, LABEL_NO)	\
154    asm_fprintf (FILE, "\tmov.l %I%LLP%d,%Ra0\n\tjsr mcount%%\n", (LABEL_NO))
155
156/* This is how to output an insn to push a register on the stack.
157   It need not be very fast code.  */
158
159#undef ASM_OUTPUT_REG_PUSH
160#define ASM_OUTPUT_REG_PUSH(FILE,REGNO)  \
161  fprintf (FILE, "\tmov.l %s,-(%%sp)\n", reg_names[REGNO])
162
163/* This is how to output an insn to pop a register from the stack.
164   It need not be very fast code.  */
165
166#undef ASM_OUTPUT_REG_POP
167#define ASM_OUTPUT_REG_POP(FILE,REGNO)  \
168  fprintf (FILE, "\tmov.l (%%sp)+,%s\n", reg_names[REGNO])
169
170#ifndef USE_GAS
171
172#undef ASM_APP_ON
173#define ASM_APP_ON ""
174
175#undef ASM_APP_OFF
176#define ASM_APP_OFF ""
177
178#undef TEXT_SECTION_ASM_OP
179#define TEXT_SECTION_ASM_OP "\ttext"
180#undef DATA_SECTION_ASM_OP
181#define DATA_SECTION_ASM_OP "\tdata"
182#undef ASCII_DATA_ASM_OP
183#define	ASCII_DATA_ASM_OP "\tbyte\t"
184
185#undef SET_ASM_OP
186#define SET_ASM_OP "\tset\t"
187
188#endif /* USE_GAS */
189
190#ifdef USE_GLD
191/* Support the ctors and dtors sections for g++.  */
192
193#define CTORS_SECTION_ASM_OP	"\t.section\t.ctors,\"x\""
194#define DTORS_SECTION_ASM_OP	"\t.section\t.dtors,\"x\""
195#endif /* defined (USE_GLD) */
196
197/* The file command should always begin the output.  */
198
199#undef ASM_FILE_START
200#ifndef USE_GAS
201#define ASM_FILE_START(FILE) \
202  output_file_directive ((FILE), main_input_filename)
203#else /* USE_GAS */
204#define ASM_FILE_START(FILE) \
205    { \
206       fprintf (FILE, "%s", ASM_APP_OFF); \
207       output_file_directive ((FILE), main_input_filename); \
208    }
209#endif /* USE_GAS */
210
211/* Names to predefine in the preprocessor for this target machine.  */
212/* ihnp4!lmayk!lgm@eddie.mit.edu says mc68000 and m68k should not be here,
213   on the other hand I don't care what he says.  */
214
215#undef CPP_PREDEFINES
216#define CPP_PREDEFINES "-Dm68k -Dunix -DsysV68 -D__motorola__ -Asystem=unix -Asystem=svr3 -Acpu=m68k -Amachine=m68k"
217
218#undef TARGET_VERSION
219#ifndef USE_GAS
220#define TARGET_VERSION fprintf (stderr, " (68k, SGS/AT&T sysV68 syntax)");
221#endif /* USE_GAS */
222
223/* This will return small structs in d0.  */
224#define RETURN_IN_MEMORY(type) \
225  ((TYPE_MODE (type) == BLKmode) \
226   || (AGGREGATE_TYPE_P (type) \
227       && GET_MODE_SIZE (TYPE_MODE (type)) > UNITS_PER_WORD))
228
229/* Don't default to pcc-struct-return, because we have already specified
230   exactly how to return structures in the RETURN_IN_MEMORY macro.  */
231#define DEFAULT_PCC_STRUCT_RETURN 0
232
233/* If TARGET_68881, return SF and DF values in fp0 instead of d0.  */
234/* NYI: If FP=M68881U return SF and DF values in d0.  */
235/* NYI: If -mold return pointer in a0 and d0 */
236
237#undef FUNCTION_VALUE
238/* sysV68 (brain damaged) cc convention support.  */
239#define FUNCTION_VALUE(VALTYPE,FUNC) \
240  (TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_68881 	\
241   ? gen_rtx_REG (TYPE_MODE (VALTYPE), 16)		\
242   : (POINTER_TYPE_P (VALTYPE)				\
243      ? gen_rtx_REG (TYPE_MODE (VALTYPE), 8)		\
244      : gen_rtx_REG (TYPE_MODE (VALTYPE), 0)))
245
246/* If TARGET_68881, SF and DF values are returned in fp0 instead of d0.  */
247
248/* Is LIBCALL_VALUE never called with a pointer ? */
249#undef LIBCALL_VALUE
250#define LIBCALL_VALUE(MODE)					\
251 gen_rtx_REG ((MODE),						\
252	      ((TARGET_68881					\
253		&& ((MODE) == SFmode || (MODE) == DFmode	\
254		    || (MODE) == XFmode))			\
255	       ? 16 : 0))
256
257/* 1 if N is a possible register number for a function value.
258   d0 may be used, and fp0 as well if -msoft-float is not specified.  */
259
260#undef FUNCTION_VALUE_REGNO_P
261/* sysV68 (brain damaged) cc convention support.  */
262#define FUNCTION_VALUE_REGNO_P(N) \
263 ((N) == 0 || (N) == 8 || (TARGET_68881 && (N) == 16))
264
265/* Define this to be true when FUNCTION_VALUE_REGNO_P is true for
266   more than one register.  */
267
268#undef NEEDS_UNTYPED_CALL
269#define NEEDS_UNTYPED_CALL 1
270
271#ifndef USE_GAS
272/* This is the command to make the user-level label named NAME
273   defined for reference from other files.  */
274
275#undef GLOBAL_ASM_OP
276#define GLOBAL_ASM_OP "\tglobal\t"
277#endif /* USE_GAS */
278
279/* Store in OUTPUT a string (made with alloca) containing
280   an assembler-name for a local static variable named NAME.
281   LABELNO is an integer which is different for each call.  */
282
283#undef ASM_FORMAT_PRIVATE_NAME
284#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO)	\
285( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 12),	\
286  sprintf ((OUTPUT), "%s_%%%d", (NAME), (LABELNO)))
287
288#undef INT_OP_GROUP
289#ifdef USE_GAS
290#define INT_OP_GROUP INT_OP_STANDARD
291#else
292#define INT_OP_GROUP INT_OP_NO_DOT
293#endif
294
295/* This is how to output an assembler line
296   that says to advance the location counter
297   to a multiple of 2**LOG bytes.  */
298
299#ifndef USE_GAS
300#define ALIGN_ASM_OP	"\teven"
301#else /* USE_GAS */
302#define ALIGN_ASM_OP	"\t.even"
303#endif /* USE_GAS */
304
305#undef ASM_OUTPUT_ALIGN
306#define ASM_OUTPUT_ALIGN(FILE,LOG)	\
307  if ((LOG) >= 1)			\
308    fprintf (FILE, "%s\n", ALIGN_ASM_OP);
309
310#ifndef USE_GAS
311#define SKIP_ASM_OP	"\tspace\t"
312#else /* USE_GAS */
313#define SKIP_ASM_OP	"\t.skip\t"
314#endif /* USE_GAS */
315
316#undef ASM_OUTPUT_SKIP
317#define ASM_OUTPUT_SKIP(FILE,SIZE)  \
318  fprintf (FILE, "%s%u\n", SKIP_ASM_OP, (SIZE))
319
320/* Can't use ASM_OUTPUT_SKIP in text section.  */
321
322#define ASM_NO_SKIP_IN_TEXT 1
323
324/* The beginnings of sdb support...  */
325
326/* Undefining these will allow `output_file_directive' (in toplev.c)
327   to default to the right thing.  */
328#undef ASM_OUTPUT_MAIN_SOURCE_FILENAME
329#ifndef USE_GAS
330#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
331  do {	fprintf (FILE, "\tfile\t");		\
332	output_quoted_string (FILE, FILENAME);	\
333	fprintf (FILE, "\n");			\
334  } while (0)
335
336#undef ASM_OUTPUT_SOURCE_LINE
337#define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO)	\
338  fprintf (FILE, "\tln\t%d\n",			\
339	   (sdb_begin_function_line		\
340	    ? (LINENO) - sdb_begin_function_line : 1))
341
342/* Yet another null terminated string format.  */
343
344#undef ASM_OUTPUT_ASCII
345#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
346  do { register size_t sp = 0, lp = 0, limit = (LEN);		\
347    fputs (integer_asm_op (1, TRUE), (FILE));			\
348  loop:								\
349    if ((PTR)[sp] > ' ' && ! ((PTR)[sp] & 0x80) && (PTR)[sp] != '\\')	\
350      { lp += 3;						\
351	fprintf ((FILE), "'%c", (PTR)[sp]); }			\
352    else							\
353      { lp += 5;						\
354	fprintf ((FILE), "0x%x", (PTR)[sp]); }			\
355    if (++sp < limit)						\
356      {	if (lp > 60)						\
357	  { lp = 0;						\
358	    fprintf ((FILE), "\n%s", ASCII_DATA_ASM_OP); }	\
359	else							\
360	  putc (',', (FILE));					\
361	goto loop; }						\
362    putc ('\n', (FILE)); } while (0)
363#endif /* USE_GAS */
364
365#ifndef USE_GAS
366/* Output a float value (represented as a C double) as an immediate operand.
367   This macro is a 68k-specific macro.  */
368
369#undef ASM_OUTPUT_FLOAT_OPERAND
370#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE)			\
371 do { long l;								\
372      REAL_VALUE_TO_TARGET_SINGLE (r, l);				\
373      /* Use hex representation even if CODE is f.  as needs it.  */	\
374      fprintf ((FILE), "&0x%lx", l);					\
375    } while (0)
376
377/* Output a double value (represented as a C double) as an immediate operand.
378   This macro is a 68k-specific macro.  */
379#undef ASM_OUTPUT_DOUBLE_OPERAND
380#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE)				\
381 do { long l[2];							\
382      REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l);				\
383      fprintf ((FILE), "&0x%lx%08lx", l[0], l[1]);			\
384    } while (0)
385#endif /* USE_GAS */
386
387/* This is how to store into the string LABEL
388   the symbol_ref name of an internal numbered label where
389   PREFIX is the class of label and NUM is the number within the class.
390   This is suitable for output with `assemble_name'.  */
391
392#undef ASM_GENERATE_INTERNAL_LABEL
393#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM)	\
394  sprintf ((LABEL), "%s%s%ld", LOCAL_LABEL_PREFIX, (PREFIX), (long)(NUM))
395
396/* This is how to output an internal numbered label where
397   PREFIX is the class of label and NUM is the number within the class.  */
398
399#undef ASM_OUTPUT_INTERNAL_LABEL
400#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM)	\
401    asm_fprintf (FILE, "%L%s%d:\n", PREFIX, NUM)
402
403/* The prefix to add to user-visible assembler symbols.  */
404
405#undef USER_LABEL_PREFIX
406#define USER_LABEL_PREFIX ""
407
408/* This is how to output an element of a case-vector that is absolute.
409   (The 68000 does not use such vectors,
410   but we must define this macro anyway.)  */
411/* The L after the local prefix is the "L" prefix for the normal labels
412   generated by gcc; why are ASM_OUTPUT_ADDR_VEC_ELT and
413   ASM_OUTPUT_ADDR_DIFF_ELT not called with a PREFIX parameter, like
414   ASM_OUTPUT_INTERNAL_LABEL ? */
415
416#undef ASM_OUTPUT_ADDR_VEC_ELT
417#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)	\
418    asm_fprintf (FILE, "%s%LL%d\n", integer_asm_op (4, TRUE), (VALUE))
419
420/* This is how to output an element of a case-vector that is relative.  */
421
422#undef ASM_OUTPUT_ADDR_DIFF_ELT
423#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)	\
424    asm_fprintf (FILE, "\t%s %LL%d-%LL%d\n",			\
425		 integer_asm_op (2, TRUE), (VALUE), (REL))
426
427#ifndef USE_GAS
428
429#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE)			\
430    asm_fprintf (FILE, "\tswbeg &%d\n%L%s%d:\n",			\
431	     XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM))
432
433/* sysV68 as cannot handle LD%n(%pc,%reg) */
434#define SGS_NO_LI
435
436/* labelno is not used here */
437#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
438	asm_fprintf (file, "12(%Rpc,%s.", regname)
439
440#define ASM_RETURN_CASE_JUMP				\
441  do {							\
442    if (TARGET_5200)					\
443      {							\
444	if (ADDRESS_REG_P (operands[0]))		\
445	  return "jmp 8(%%pc,%0.l)";			\
446	else						\
447	  return "ext%.l %0\n\tjmp 8(%%pc,%0.l)";	\
448      }							\
449    else						\
450      return "jmp 8(%%pc,%0.w)";			\
451  } while (0)
452
453#else /* USE_GAS */
454
455/* labelno is not used here */
456#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
457	asm_fprintf (file, "%Rpc@(6,%s:", regname)
458
459#define ASM_RETURN_CASE_JUMP return "jmp %%pc@(2,%0:w)"
460
461#endif /* USE_GAS */
462
463#ifndef USE_GAS
464
465/* Translate some opcodes to fit the sysV68 assembler syntax.  */
466/* The opcodes fdmov and fsmov are guesses.  */
467
468/* cliffm@netcom.com says no need for .w suffix on jumps.  */
469#undef ASM_OUTPUT_OPCODE
470#define ASM_OUTPUT_OPCODE(FILE, PTR)			\
471{ if ((PTR)[0] == 'j' && (PTR)[1] == 'b')		\
472    { ++(PTR);						\
473      while (*(PTR) != ' ')				\
474	{ putc (*(PTR), (FILE)); ++(PTR); }		\
475    }							\
476  else if ((PTR)[0] == 's')				\
477    {							\
478      if (!strncmp ((PTR), "swap", 4))			\
479	{ fprintf ((FILE), "swap.w"); (PTR) += 4; }	\
480    }							\
481  else if ((PTR)[0] == 'f')				\
482    {							\
483      if (!strncmp ((PTR), "fmove", 5))			\
484	{ fprintf ((FILE), "fmov"); (PTR) += 5; }	\
485      else if (!strncmp ((PTR), "f%$move", 7))		\
486	{ if (TARGET_68040_ONLY)			\
487	    { fprintf ((FILE), "fsmov"); (PTR) += 7; }	\
488	  else						\
489	    { fprintf ((FILE), "fmov"); (PTR) += 7; } }	\
490      else if (!strncmp ((PTR), "f%&move", 7))		\
491	{ if (TARGET_68040_ONLY)			\
492	    { fprintf ((FILE), "fdmov"); (PTR) += 7; }	\
493	  else						\
494	    { fprintf ((FILE), "fmov"); (PTR) += 7; } }	\
495      else if (!strncmp ((PTR), "ftst", 4))		\
496	{ fprintf ((FILE), "ftest"); (PTR) += 4; }	\
497      else if (!strncmp ((PTR), "fbne", 4))		\
498	{ fprintf ((FILE), "fbneq"); (PTR) += 4; }	\
499      else if (!strncmp ((PTR), "fsne", 4))		\
500	{ fprintf ((FILE), "fsneq"); (PTR) += 4; }	\
501    }							\
502/* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV	*/		\
503  else if ((PTR)[0] == 'm' && (PTR)[1] == 'o'		\
504	   && (PTR)[2] == 'v' && (PTR)[3] == 'e')	\
505    { fprintf ((FILE), "mov"); (PTR) += 4;		\
506       if ((PTR)[0] == 'q' || (PTR)[0] == 'a'		\
507	   || (PTR)[0] == 'c') (PTR)++; }		\
508/* SUB, SUBQ, SUBA, SUBI ==> SUB */			\
509  else if ((PTR)[0] == 's' && (PTR)[1] == 'u' 		\
510	   && (PTR)[2] == 'b')				\
511    { fprintf ((FILE), "sub"); (PTR) += 3;		\
512       if ((PTR)[0] == 'q' || (PTR)[0] == 'i'	 	\
513	   || (PTR)[0] == 'a') (PTR)++; }		\
514/* CMP, CMPA, CMPI, CMPM ==> CMP	*/		\
515  else if ((PTR)[0] == 'c' && (PTR)[1] == 'm'		\
516	   && (PTR)[2] == 'p')				\
517    { fprintf ((FILE), "cmp"); (PTR) += 3;		\
518       if ((PTR)[0] == 'a' || (PTR)[0] == 'i'	 	\
519	   || (PTR)[0] == 'm') (PTR)++; }		\
520}
521#endif /* USE_GAS */
522
523/* phdm@info.ucl.ac.be says to pass SIZE, not ROUNDED.  */
524
525/* This says how to output an assembler line
526   to define a global common symbol.  */
527
528#undef ASM_OUTPUT_COMMON
529#ifndef USE_GAS
530#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED)  \
531( fputs ("\tcomm ", (FILE)),			\
532  assemble_name ((FILE), (NAME)),		\
533  fprintf ((FILE), ",%u\n", (SIZE)))
534#else /* USE_GAS */
535#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED)  \
536( fputs ("\t.comm ", (FILE)),			\
537  assemble_name ((FILE), (NAME)),		\
538  fprintf ((FILE), ",%u\n", (SIZE)))
539#endif /* USE_GAS */
540
541/* This says how to output an assembler line
542   to define a local common symbol.  */
543
544#undef ASM_OUTPUT_LOCAL
545#ifndef USE_GAS
546#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)  \
547( fputs ("\tlcomm ", (FILE)),			\
548  assemble_name ((FILE), (NAME)),		\
549  fprintf ((FILE), ",%u\n", (SIZE)))
550#else /* USE_GAS */
551#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)  \
552( fputs ("\t.lcomm ", (FILE)),			\
553  assemble_name ((FILE), (NAME)),		\
554  fprintf ((FILE), ",%u\n", (SIZE)))
555#endif /* USE_GAS */
556
557#ifndef USE_GAS
558/* Override usual definitions of SDB output macros.
559   These definitions differ only in the absence of the period
560   at the beginning of the name of the directive
561   and in the use of `~' as the symbol for the current location.  */
562
563#define PUT_SDB_SCL(a) fprintf(asm_out_file, "\tscl\t%d;", (a))
564#define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\tval\t%d;", (a))
565#define PUT_SDB_VAL(a)				\
566( fputs ("\tval\t", asm_out_file),		\
567  output_addr_const (asm_out_file, (a)),	\
568  fputc (';', asm_out_file))
569
570#define PUT_SDB_DEF(a)				\
571do { fprintf (asm_out_file, "\tdef\t");	\
572     ASM_OUTPUT_LABELREF (asm_out_file, a); 	\
573     fprintf (asm_out_file, ";"); } while (0)
574
575#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\tdef\t~%s;",a)
576#define PUT_SDB_ENDEF fputs("\tendef\n", asm_out_file)
577#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\ttype\t0%o;", a)
578#define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\tsize\t%d;", a)
579#define PUT_SDB_START_DIM fprintf(asm_out_file, "\tdim\t")
580#define PUT_SDB_NEXT_DIM(a) fprintf(asm_out_file, "%d,", a)
581#define PUT_SDB_LAST_DIM(a) fprintf(asm_out_file, "%d;", a)
582
583#define PUT_SDB_TAG(a)				\
584do { fprintf (asm_out_file, "\ttag\t");	\
585     ASM_OUTPUT_LABELREF (asm_out_file, a);	\
586     fprintf (asm_out_file, ";"); } while (0)
587
588#define PUT_SDB_BLOCK_START(LINE)		\
589  fprintf (asm_out_file,			\
590	   "\tdef\t~bb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n",	\
591	   (LINE))
592
593#define PUT_SDB_BLOCK_END(LINE)			\
594  fprintf (asm_out_file,			\
595	   "\tdef\t~eb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n",	\
596	   (LINE))
597
598#define PUT_SDB_FUNCTION_START(LINE)		\
599  fprintf (asm_out_file,			\
600	   "\tdef\t~bf;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n",	\
601	   (LINE))
602
603#define PUT_SDB_FUNCTION_END(LINE)		\
604  fprintf (asm_out_file,			\
605	   "\tdef\t~ef;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n",	\
606	   (LINE))
607
608#define PUT_SDB_EPILOGUE_END(NAME)		\
609  fprintf (asm_out_file,			\
610	   "\tdef\t%s;\tval\t~;\tscl\t-1;\tendef\n",	\
611	   (NAME))
612
613#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
614  sprintf ((BUFFER), "~%dfake", (NUMBER));
615
616#endif /* USE_GAS */
617
618/* Define subroutines to call to handle multiply, divide, and remainder.
619   Use the subroutines that the sysV68's library provides.
620   The `*' prevents an underscore from being prepended by the compiler.  */
621/* The '*' is also used by INIT_CUMULATIVE_ARGS */
622
623#define DIVSI3_LIBCALL "*ldiv%%"
624#define UDIVSI3_LIBCALL "*uldiv%%"
625#define MODSI3_LIBCALL "*lrem%%"
626#define UMODSI3_LIBCALL "*ulrem%%"
627#define MULSI3_LIBCALL "*lmul%%"
628
629struct sysV68_cumulative_args
630	{
631	int	offset;
632	int	libcall;
633	};
634
635#undef CUMULATIVE_ARGS
636#define CUMULATIVE_ARGS struct sysV68_cumulative_args
637
638#undef INIT_CUMULATIVE_ARGS
639#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT)	\
640do {(CUM).offset = 0;\
641(CUM).libcall = (LIBNAME) && (*XSTR((LIBNAME), 0) == '*');} while(0)
642
643#undef FUNCTION_ARG_ADVANCE
644#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)	\
645 ((CUM).offset += ((MODE) != BLKmode			\
646	    ? (GET_MODE_SIZE (MODE) + 3) & ~3	\
647	    : (int_size_in_bytes (TYPE) + 3) & ~3))
648
649#undef FUNCTION_ARG
650#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
651(((CUM).libcall && (CUM).offset == 0) ? gen_rtx_REG ((MODE), 0)\
652: (TARGET_REGPARM && (CUM).offset < 8) ? gen_rtx_REG ((MODE), (CUM).offset / 4) : 0)
653
654#undef FUNCTION_ARG_PARTIAL_NREGS
655#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
656((TARGET_REGPARM && (CUM).offset < 8				\
657  && 8 < ((CUM).offset + ((MODE) == BLKmode			\
658		      ? int_size_in_bytes (TYPE)		\
659		      : GET_MODE_SIZE (MODE))))  		\
660 ? 2 - (CUM).offset / 4 : 0)
661
662#undef FUNCTION_ARG_REGNO_P
663#define FUNCTION_ARG_REGNO_P(N) (TARGET_68020 ? 0 : (N) == 0)
664
665/* manfred@lts.sel.alcatel.de: I believe that most delta machines are configured to have
666   a 6888[12] FPU for which we need to link -lm881 instead of -lm; define ALT_LIBM to
667   tell g++.c about that.  */
668#define ALT_LIBM	"-lm881"
669
670#if (TARGET_DEFAULT & MASK_68881)      /* The default configuration has a 6888[12] FPU.  */
671#define MATH_LIBRARY	"-lm881"
672#endif
673
674/* Currently we do not have the atexit() function,
675   so take that from libgcc2.c */
676
677#define NEED_ATEXIT 1
678
679#define EXIT_BODY	\
680  do								\
681    { 								\
682      __stop_monitor ();					\
683      _cleanup ();						\
684    } while (0)
685
686/* FINALIZE_TRAMPOLINE clears the instruction cache.  */
687
688#undef FINALIZE_TRAMPOLINE
689#define FINALIZE_TRAMPOLINE(TRAMP)	\
690  if (!TARGET_68040)			\
691    ;					\
692  else					\
693    emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_insn_cache"), \
694		       0, VOIDmode, 0)
695