* config/xtensa/xtensa.c (xtensa_va_arg): Handle variable-sized types.
[official-gcc.git] / gcc / config / m68k / 3b1.h
blob74aec112bf63238b9627fae898a31cbfd0e8ec81
1 /* Definitions of target machine for GNU compiler.
2 AT&T UNIX PC version (pc7300, 3b1)
3 Copyright (C) 1987, 1993, 1996, 1999, 2000 Free Software Foundation, Inc.
4 Contributed by Alex Crain (alex@umbc3.umd.edu).
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 #define SGS_SWITCH_TABLES /* Different switch table handling */
25 #include "m68k/hp320.h"
27 /* See m68k.h. 0 means 680[01]0 with no 68881. */
29 #undef TARGET_DEFAULT
30 #define TARGET_DEFAULT 0
32 /* Don't try using XFmode. */
33 #undef LONG_DOUBLE_TYPE_SIZE
34 #define LONG_DOUBLE_TYPE_SIZE 64
36 /* -m68020 requires special flags to the assembler. */
38 #undef ASM_SPEC
39 #define ASM_SPEC "%{m68020:-68020}%{!m68020:-68010} %{m68881:-68881}"
41 /* we use /lib/libp/lib* when profiling */
43 #undef LIB_SPEC
44 #define LIB_SPEC "%{!shlib:%{p:-L/lib/libp} %{pg:-L/lib/libp} -lc}"
46 /* shared libraries need to use crt0s.o */
48 #undef STARTFILE_SPEC
49 #define STARTFILE_SPEC \
50 "%{!shlib:%{pg:mcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}\
51 %{shlib:crt0s.o%s shlib.ifile%s} "
53 /* cpp has to support a #sccs directive for the /usr/include files */
55 #define SCCS_DIRECTIVE
57 /* Make output for SDB. */
59 #define SDB_DEBUGGING_INFO
61 /* The .file command should always begin the output. */
63 #undef ASM_FILE_START
64 #define ASM_FILE_START(FILE) \
65 output_file_directive ((FILE), main_input_filename)
67 /* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
68 This will control the use of inline 68881 insns in certain macros. */
70 #undef CPP_SPEC
71 #define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
73 /* Names to predefine in the preprocessor for this target machine. */
74 /* ihnp4!lmayk!lgm@eddie.mit.edu says mc68000 and m68k should not be here. */
76 #undef CPP_PREDEFINES
77 #define CPP_PREDEFINES "-Dmc68k -Dunix -Dunixpc -D__motorola__ -Asystem=unix -Asystem=svr3 -Acpu=m68k -Amachine=m68k"
79 #undef REGISTER_NAMES
80 #define REGISTER_NAMES \
81 {"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
82 "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp", \
83 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7"}
85 /* Specify how to pad function arguments.
86 Value should be `upward', `downward' or `none'.
87 Same as the default, except no padding for large or variable-size args. */
89 #define FUNCTION_ARG_PADDING(MODE, TYPE) \
90 (((MODE) == BLKmode \
91 ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
92 && int_size_in_bytes (TYPE) < PARM_BOUNDARY / BITS_PER_UNIT) \
93 : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY) \
94 ? downward : none)
96 /* The 3b1 does not have `atexit'. */
98 #define NEED_ATEXIT
100 /* Override parts of m68k.h to fit the SGS-3b1 assembler. */
102 #undef TARGET_VERSION
103 #undef ASM_FORMAT_PRIVATE_NAME
104 #undef ASM_OUTPUT_ALIGN
105 #undef ASM_OUTPUT_SOURCE_FILENAME
106 #undef ASM_OUTPUT_SOURCE_LINE
107 #undef PRINT_OPERAND_ADDRESS
108 #undef ASM_GENERATE_INTERNAL_LABEL
109 #undef FUNCTION_PROFILER
110 #undef ASM_OUTPUT_ADDR_VEC_ELT
111 #undef ASM_OUTPUT_ADDR_DIFF_ELT
112 #undef ASM_OUTPUT_INTERNAL_LABEL
113 #undef ASM_OUTPUT_OPCODE
114 #undef ASM_OUTPUT_LOCAL
115 #undef USER_LABEL_PREFIX
116 #undef ASM_OUTPUT_ASCII
118 #define TARGET_VERSION fprintf (stderr, " (68k, SGS/AT&T unixpc syntax)");
120 /* Store in OUTPUT a string (made with alloca) containing
121 an assembler-name for a local static variable named NAME.
122 LABELNO is an integer which is different for each call. */
124 #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
125 ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 12), \
126 sprintf ((OUTPUT), "%s_%%%d", (NAME), (LABELNO)))
128 #define ASM_OUTPUT_ALIGN(FILE,LOG) \
129 do { \
130 if ((LOG) == 1) \
131 fprintf (FILE, "\teven\n"); \
132 else if ((LOG) != 0) \
133 abort (); \
134 } while (0)
136 /* This is how to output an assembler line
137 that says to advance the location counter by SIZE bytes. */
139 #undef ASM_OUTPUT_SKIP
140 #define ASM_OUTPUT_SKIP(FILE,SIZE) \
141 fprintf (FILE, "\tspace %d\n", (SIZE))
143 /* Can't use ASM_OUTPUT_SKIP in text section; it doesn't leave 0s. */
145 #define ASM_NO_SKIP_IN_TEXT 1
147 /* The beginnings of sdb support... */
149 #define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
150 do { fprintf (FILE, "\tfile\t"); \
151 output_quoted_string (FILE, FILENAME); \
152 fprintf (FILE, "\n"); \
153 } while (0)
155 #define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \
156 fprintf (FILE, "\tln\t%d\n", \
157 (sdb_begin_function_line \
158 ? (LINENO) - sdb_begin_function_line : 1))
160 /* Yet another null terminated string format. */
162 #define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
163 do { register size_t sp = 0, lp = 0, limit = (LEN); \
164 fprintf ((FILE), "\tbyte\t"); \
165 loop: \
166 if ((PTR)[sp] > ' ' && ! ((PTR)[sp] & 0x80) && (PTR)[sp] != '\\') \
167 { lp += 3; \
168 fprintf ((FILE), "'%c", (PTR)[sp]); } \
169 else \
170 { lp += 5; \
171 fprintf ((FILE), "0x%x", (PTR)[sp]); } \
172 if (++sp < limit) \
173 { if (lp > 60) \
174 { lp = 0; \
175 fprintf ((FILE), "\n%s", ASCII_DATA_ASM_OP); } \
176 else \
177 putc (',', (FILE)); \
178 goto loop; } \
179 putc ('\n', (FILE)); } while (0)
181 /* Note that in the case of the movhi which fetches an element of
182 an ADDR_DIFF_VEC the offset output is too large by 2.
183 This is because the 3b1 assembler refuses to subtract 2.
184 ASM_OUTPUT_CASE_LABEL, below, compensates for this. */
186 #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
187 { register rtx reg1, reg2, breg, ireg; \
188 register rtx addr = ADDR; \
189 rtx offset; \
190 switch (GET_CODE (addr)) \
192 case REG: \
193 fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
194 break; \
195 case PRE_DEC: \
196 fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
197 break; \
198 case POST_INC: \
199 fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
200 break; \
201 case PLUS: \
202 reg1 = 0; reg2 = 0; \
203 ireg = 0; breg = 0; \
204 offset = 0; \
205 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
207 offset = XEXP (addr, 0); \
208 addr = XEXP (addr, 1); \
210 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
212 offset = XEXP (addr, 1); \
213 addr = XEXP (addr, 0); \
215 if (GET_CODE (addr) != PLUS) ; \
216 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
218 reg1 = XEXP (addr, 0); \
219 addr = XEXP (addr, 1); \
221 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
223 reg1 = XEXP (addr, 1); \
224 addr = XEXP (addr, 0); \
226 else if (GET_CODE (XEXP (addr, 0)) == MULT) \
228 reg1 = XEXP (addr, 0); \
229 addr = XEXP (addr, 1); \
231 else if (GET_CODE (XEXP (addr, 1)) == MULT) \
233 reg1 = XEXP (addr, 1); \
234 addr = XEXP (addr, 0); \
236 else if (GET_CODE (XEXP (addr, 0)) == REG) \
238 reg1 = XEXP (addr, 0); \
239 addr = XEXP (addr, 1); \
241 else if (GET_CODE (XEXP (addr, 1)) == REG) \
243 reg1 = XEXP (addr, 1); \
244 addr = XEXP (addr, 0); \
246 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
247 || GET_CODE (addr) == SIGN_EXTEND) \
248 { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
249 /* for OLD_INDEXING \
250 else if (GET_CODE (addr) == PLUS) \
252 if (GET_CODE (XEXP (addr, 0)) == REG) \
254 reg2 = XEXP (addr, 0); \
255 addr = XEXP (addr, 1); \
257 else if (GET_CODE (XEXP (addr, 1)) == REG) \
259 reg2 = XEXP (addr, 1); \
260 addr = XEXP (addr, 0); \
263 */ \
264 if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
265 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
266 || GET_CODE (reg1) == MULT)) \
267 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
268 { breg = reg2; ireg = reg1; } \
269 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
270 { breg = reg1; ireg = reg2; } \
271 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
272 { int scale = 1; \
273 if (GET_CODE (ireg) == MULT) \
274 { scale = INTVAL (XEXP (ireg, 1)); \
275 ireg = XEXP (ireg, 0); } \
276 if (GET_CODE (ireg) == SIGN_EXTEND) \
277 fprintf (FILE, "LD%%%d(%%pc,%s.w", \
278 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
279 reg_names[REGNO (XEXP (ireg, 0))]); \
280 else \
281 fprintf (FILE, "LD%%%d(%%pc,%s.l", \
282 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
283 reg_names[REGNO (ireg)]); \
284 if (scale != 1) fprintf (FILE, "*%d", scale); \
285 fprintf (FILE, ")"); \
286 break; } \
287 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \
288 { fprintf (FILE, "LD%%%d(%%pc,%s.l", \
289 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
290 reg_names[REGNO (breg)]); \
291 putc (')', FILE); \
292 break; } \
293 if (ireg != 0 || breg != 0) \
294 { int scale = 1; \
295 if (breg == 0) \
296 abort (); \
297 if (addr != 0) \
298 output_addr_const (FILE, addr); \
299 fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
300 if (ireg != 0) \
301 putc (',', FILE); \
302 if (ireg != 0 && GET_CODE (ireg) == MULT) \
303 { scale = INTVAL (XEXP (ireg, 1)); \
304 ireg = XEXP (ireg, 0); } \
305 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
306 fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
307 else if (ireg != 0) \
308 fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
309 if (scale != 1) fprintf (FILE, "*%d", scale); \
310 putc (')', FILE); \
311 break; \
313 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
314 { fprintf (FILE, "LD%%%d(%%pc,%s.w)", \
315 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
316 reg_names[REGNO (reg1)]); \
317 break; } \
318 default: \
319 if (GET_CODE (addr) == CONST_INT \
320 && INTVAL (addr) < 0x8000 \
321 && INTVAL (addr) >= -0x8000) \
322 fprintf (FILE, "%d", INTVAL (addr)); \
323 else \
324 output_addr_const (FILE, addr); \
327 #define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
328 sprintf ((LABEL), "%s%%%ld", (PREFIX), (long)(NUM))
330 #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
331 fprintf (FILE, "%s%%%d:\n", PREFIX, NUM)
333 /* Must put address in %a0 , not %d0 . -- LGM, 7/15/88 */
334 #define FUNCTION_PROFILER(FILE, LABEL_NO) \
335 fprintf (FILE, "\tmov.l &LP%%%d,%%a0\n\tjsr mcount\n", (LABEL_NO))
337 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
338 fprintf (FILE, "\tlong L%%%d\n", (VALUE))
340 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
341 fprintf (FILE, "\tshort L%%%d-L%%%d\n", (VALUE), (REL))
343 /* ihnp4!lmayk!lgm says that `short 0' triggers assembler bug;
344 `short L%nn-L%nn' supposedly works. */
345 #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
346 if (! RTX_INTEGRATED_P (TABLE)) \
347 fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n", \
348 XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM)); \
349 else \
350 fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n\tshort %s%%%d-%s%%%d\n", \
351 XVECLEN (PATTERN (TABLE), 1) + 1, (PREFIX), (NUM), \
352 (PREFIX), (NUM), (PREFIX), (NUM))
354 /* At end of a switch table, define LDnnn iff the symbol LInnn was defined.
355 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
356 fails to assemble. Luckily "LDnnn(pc,d0.l*2)" produces the results
357 we want. This difference can be accommodated by making the assembler
358 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
359 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
360 macro. */
362 #define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \
363 { if (switch_table_difference_label_flag) \
364 fprintf (FILE, "\tset LD%%%d,L%%%d-LI%%%d\n", (NUM), (NUM), (NUM)); \
365 switch_table_difference_label_flag = 0; }
367 int switch_table_difference_label_flag;
369 #define ASM_OUTPUT_OPCODE(FILE, PTR) \
370 { if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
371 { ++(PTR); \
372 while (*(PTR) != ' ') \
373 { putc (*(PTR), (FILE)); ++(PTR); } \
374 fprintf ((FILE), ".w"); } \
375 else if ((PTR)[0] == 's') \
377 if (!strncmp ((PTR), "swap", 4)) \
378 { fprintf ((FILE), "swap.w"); (PTR) += 4; } \
380 else if ((PTR)[0] == 'f') \
382 if (!strncmp ((PTR), "fmove", 5)) \
383 { fprintf ((FILE), "fmov"); (PTR) += 5; } \
384 else if (!strncmp ((PTR), "fbne", 4)) \
385 { fprintf ((FILE), "fbneq"); (PTR) += 4; } \
387 /* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV */ \
388 else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
389 && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
390 { fprintf ((FILE), "mov"); (PTR) += 4; \
391 if ((PTR)[0] == 'q' || (PTR)[0] == 'a' \
392 || (PTR)[0] == 'c') (PTR)++; } \
393 /* SUB, SUBQ, SUBA, SUBI ==> SUB */ \
394 else if ((PTR)[0] == 's' && (PTR)[1] == 'u' \
395 && (PTR)[2] == 'b') \
396 { fprintf ((FILE), "sub"); (PTR) += 3; \
397 if ((PTR)[0] == 'q' || (PTR)[0] == 'i' \
398 || (PTR)[0] == 'a') (PTR)++; } \
399 /* CMP, CMPA, CMPI, CMPM ==> CMP */ \
400 else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \
401 && (PTR)[2] == 'p') \
402 { fprintf ((FILE), "cmp"); (PTR) += 3; \
403 if ((PTR)[0] == 'a' || (PTR)[0] == 'i' \
404 || (PTR)[0] == 'm') (PTR)++; } \
407 #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
408 ( fputs ("\tlcomm ", (FILE)), \
409 assemble_name ((FILE), (NAME)), \
410 fprintf ((FILE), ",%u\n", (ROUNDED)))
412 #define USER_LABEL_PREFIX ""
414 /* Override usual definitions of SDB output macros.
415 These definitions differ only in the absence of the period
416 at the beginning of the name of the directive
417 and in the use of `~' as the symbol for the current location. */
419 #define PUT_SDB_SCL(a) fprintf(asm_out_file, "\tscl\t%d;", (a))
420 #define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\tval\t%d;", (a))
421 #define PUT_SDB_VAL(a) \
422 ( fputs ("\tval\t", asm_out_file), \
423 output_addr_const (asm_out_file, (a)), \
424 fputc (';', asm_out_file))
426 #define PUT_SDB_DEF(a) \
427 do { fprintf (asm_out_file, "\tdef\t"); \
428 ASM_OUTPUT_LABELREF (asm_out_file, a); \
429 fprintf (asm_out_file, ";"); } while (0)
431 #define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\tdef\t~%s;",a)
432 #define PUT_SDB_ENDEF fputs("\tendef\n", asm_out_file)
433 #define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\ttype\t0%o;", a)
434 #define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\tsize\t%d;", a)
435 #define PUT_SDB_START_DIM fprintf(asm_out_file, "\tdim\t")
437 #define PUT_SDB_TAG(a) \
438 do { fprintf (asm_out_file, "\ttag\t"); \
439 ASM_OUTPUT_LABELREF (asm_out_file, a); \
440 fprintf (asm_out_file, ";"); } while (0)
442 #define PUT_SDB_BLOCK_START(LINE) \
443 fprintf (asm_out_file, \
444 "\tdef\t~bb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
445 (LINE))
447 #define PUT_SDB_BLOCK_END(LINE) \
448 fprintf (asm_out_file, \
449 "\tdef\t~eb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
450 (LINE))
452 #define PUT_SDB_FUNCTION_START(LINE) \
453 fprintf (asm_out_file, \
454 "\tdef\t~bf;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
455 (LINE))
457 #define PUT_SDB_FUNCTION_END(LINE) \
458 fprintf (asm_out_file, \
459 "\tdef\t~ef;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
460 (LINE))
462 #define PUT_SDB_EPILOGUE_END(NAME) \
463 fprintf (asm_out_file, \
464 "\tdef\t%s;\tval\t~;\tscl\t-1;\tendef\n", \
465 (NAME))
467 #define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
468 sprintf ((BUFFER), "~%dfake", (NUMBER));
470 /* Define subroutines to call to handle multiply, divide, and remainder.
471 Use the subroutines that the 3b1's library provides.
472 The `*' prevents an underscore from being prepended by the compiler. */
474 #define DIVSI3_LIBCALL "*ldiv"
475 #define UDIVSI3_LIBCALL "*uldiv"
476 #define MODSI3_LIBCALL "*lrem"
477 #define UMODSI3_LIBCALL "*ulrem"
478 #define MULSI3_LIBCALL "*lmul"
479 #define UMULSI3_LIBCALL "*ulmul"
481 /* Definitions for collect2. */
483 #define OBJECT_FORMAT_COFF
484 #define MY_ISCOFF(magic) \
485 ((magic) == MC68KWRMAGIC || (magic) == MC68KROMAGIC || (magic) == MC68KPGMAGIC)