xref: /openbsd/gnu/usr.bin/gcc/gcc/config/m68k/mot3300.h (revision c87b03e5)
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 
11 This file is part of GNU CC.
12 
13 GNU CC is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2, or (at your option)
16 any later version.
17 
18 GNU CC is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 GNU General Public License for more details.
22 
23 You should have received a copy of the GNU General Public License
24 along with GNU CC; see the file COPYING.  If not, write to
25 the Free Software Foundation, 59 Temple Place - Suite 330,
26 Boston, 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)				\
571 do { 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)				\
584 do { 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 
629 struct 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)	\
640 do {(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