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)
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. */
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. */
39 #define ASM_SPEC "%{m68020:-68020}%{!m68020:-68010} %{m68881:-68881}"
41 /* we use /lib/libp/lib* when profiling */
44 #define LIB_SPEC "%{!shlib:%{p:-L/lib/libp} %{pg:-L/lib/libp} -lc}"
46 /* shared libraries need to use crt0s.o */
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. */
64 #define ASM_FILE_START(FILE) \
65 output_file_directive ((FILE), main_input_filename)
67 /* Don't try to define `gcc_compiled.' since the assembler might not
68 accept symbols with periods and GDB doesn't run on this machine anyway. */
69 #define ASM_IDENTIFY_GCC(FILE)
71 /* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
72 This will control the use of inline 68881 insns in certain macros. */
75 #define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
77 /* Names to predefine in the preprocessor for this target machine. */
78 /* ihnp4!lmayk!lgm@eddie.mit.edu says mc68000 and m68k should not be here. */
81 #define CPP_PREDEFINES "-Dmc68k -Dunix -Dunixpc -D__motorola__ -Asystem=unix -Asystem=svr3 -Acpu=m68k -Amachine=m68k"
84 #define REGISTER_NAMES \
85 {"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
86 "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp", \
87 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7"}
89 /* Specify how to pad function arguments.
90 Value should be `upward', `downward' or `none'.
91 Same as the default, except no padding for large or variable-size args. */
93 #define FUNCTION_ARG_PADDING(MODE, TYPE) \
95 ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
96 && int_size_in_bytes (TYPE) < PARM_BOUNDARY / BITS_PER_UNIT) \
97 : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY) \
100 /* The 3b1 does not have `atexit'. */
104 /* Override parts of m68k.h to fit the SGS-3b1 assembler. */
106 #undef TARGET_VERSION
107 #undef ASM_FORMAT_PRIVATE_NAME
108 #undef ASM_OUTPUT_DOUBLE
109 #undef ASM_OUTPUT_FLOAT
110 #undef ASM_OUTPUT_ALIGN
111 #undef ASM_OUTPUT_SOURCE_FILENAME
112 #undef ASM_OUTPUT_SOURCE_LINE
113 #undef PRINT_OPERAND_ADDRESS
114 #undef ASM_GENERATE_INTERNAL_LABEL
115 #undef FUNCTION_PROFILER
116 #undef ASM_OUTPUT_ADDR_VEC_ELT
117 #undef ASM_OUTPUT_ADDR_DIFF_ELT
118 #undef ASM_OUTPUT_INTERNAL_LABEL
119 #undef ASM_OUTPUT_OPCODE
120 #undef ASM_OUTPUT_LOCAL
121 #undef USER_LABEL_PREFIX
122 #undef ASM_OUTPUT_ASCII
124 #define TARGET_VERSION fprintf (stderr, " (68k, SGS/AT&T unixpc syntax)");
126 /* Store in OUTPUT a string (made with alloca) containing
127 an assembler-name for a local static variable named NAME.
128 LABELNO is an integer which is different for each call. */
130 #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
131 ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 12), \
132 sprintf ((OUTPUT), "%s_%%%d", (NAME), (LABELNO)))
134 /* The unixpc doesn't know about double's and float's */
136 #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
138 REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
139 fprintf (FILE, "\tlong 0x%x,0x%x\n", l[0], l[1]); \
142 #undef ASM_OUTPUT_LONG_DOUBLE
143 #define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
145 REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
146 fprintf (FILE, "\tlong 0x%x,0x%x,0x%x\n", l[0], l[1], l[2]); \
149 /* This is how to output an assembler line defining a `float' constant. */
151 #define ASM_OUTPUT_FLOAT(FILE,VALUE) \
153 REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
154 fprintf ((FILE), "\tlong 0x%x\n", l); \
157 #define ASM_OUTPUT_ALIGN(FILE,LOG) \
159 fprintf (FILE, "\teven\n"); \
160 else if ((LOG) != 0) \
163 /* This is how to output an assembler line
164 that says to advance the location counter by SIZE bytes. */
166 #undef ASM_OUTPUT_SKIP
167 #define ASM_OUTPUT_SKIP(FILE,SIZE) \
168 fprintf (FILE, "\tspace %d\n", (SIZE))
170 /* Can't use ASM_OUTPUT_SKIP in text section; it doesn't leave 0s. */
172 #define ASM_NO_SKIP_IN_TEXT 1
174 /* The beginnings of sdb support... */
176 #define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
177 do { fprintf (FILE, "\tfile\t"); \
178 output_quoted_string (FILE, FILENAME); \
179 fprintf (FILE, "\n"); \
182 #define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \
183 fprintf (FILE, "\tln\t%d\n", \
184 (sdb_begin_function_line \
185 ? last_linenum - sdb_begin_function_line : 1))
187 /* Yet another null terminated string format. */
189 #define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
190 do { register int sp = 0, lp = 0; \
191 fprintf ((FILE), "\tbyte\t"); \
193 if ((PTR)[sp] > ' ' && ! ((PTR)[sp] & 0x80) && (PTR)[sp] != '\\') \
195 fprintf ((FILE), "'%c", (PTR)[sp]); } \
198 fprintf ((FILE), "0x%x", (PTR)[sp]); } \
202 fprintf ((FILE), "\n%s", ASCII_DATA_ASM_OP); } \
204 putc (',', (FILE)); \
206 putc ('\n', (FILE)); } while (0)
208 /* Note that in the case of the movhi which fetches an element of
209 an ADDR_DIFF_VEC the offset output is too large by 2.
210 This is because the 3b1 assembler refuses to subtract 2.
211 ASM_OUTPUT_CASE_LABEL, below, compensates for this. */
213 #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
214 { register rtx reg1, reg2, breg, ireg; \
215 register rtx addr = ADDR; \
217 switch (GET_CODE (addr)) \
220 fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
223 fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
226 fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
229 reg1 = 0; reg2 = 0; \
230 ireg = 0; breg = 0; \
232 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
234 offset = XEXP (addr, 0); \
235 addr = XEXP (addr, 1); \
237 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
239 offset = XEXP (addr, 1); \
240 addr = XEXP (addr, 0); \
242 if (GET_CODE (addr) != PLUS) ; \
243 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
245 reg1 = XEXP (addr, 0); \
246 addr = XEXP (addr, 1); \
248 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
250 reg1 = XEXP (addr, 1); \
251 addr = XEXP (addr, 0); \
253 else if (GET_CODE (XEXP (addr, 0)) == MULT) \
255 reg1 = XEXP (addr, 0); \
256 addr = XEXP (addr, 1); \
258 else if (GET_CODE (XEXP (addr, 1)) == MULT) \
260 reg1 = XEXP (addr, 1); \
261 addr = XEXP (addr, 0); \
263 else if (GET_CODE (XEXP (addr, 0)) == REG) \
265 reg1 = XEXP (addr, 0); \
266 addr = XEXP (addr, 1); \
268 else if (GET_CODE (XEXP (addr, 1)) == REG) \
270 reg1 = XEXP (addr, 1); \
271 addr = XEXP (addr, 0); \
273 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
274 || GET_CODE (addr) == SIGN_EXTEND) \
275 { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
276 /* for OLD_INDEXING \
277 else if (GET_CODE (addr) == PLUS) \
279 if (GET_CODE (XEXP (addr, 0)) == REG) \
281 reg2 = XEXP (addr, 0); \
282 addr = XEXP (addr, 1); \
284 else if (GET_CODE (XEXP (addr, 1)) == REG) \
286 reg2 = XEXP (addr, 1); \
287 addr = XEXP (addr, 0); \
291 if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
292 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
293 || GET_CODE (reg1) == MULT)) \
294 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
295 { breg = reg2; ireg = reg1; } \
296 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
297 { breg = reg1; ireg = reg2; } \
298 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
300 if (GET_CODE (ireg) == MULT) \
301 { scale = INTVAL (XEXP (ireg, 1)); \
302 ireg = XEXP (ireg, 0); } \
303 if (GET_CODE (ireg) == SIGN_EXTEND) \
304 fprintf (FILE, "LD%%%d(%%pc,%s.w", \
305 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
306 reg_names[REGNO (XEXP (ireg, 0))]); \
308 fprintf (FILE, "LD%%%d(%%pc,%s.l", \
309 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
310 reg_names[REGNO (ireg)]); \
311 if (scale != 1) fprintf (FILE, "*%d", scale); \
312 fprintf (FILE, ")"); \
314 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \
315 { fprintf (FILE, "LD%%%d(%%pc,%s.l", \
316 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
317 reg_names[REGNO (breg)]); \
320 if (ireg != 0 || breg != 0) \
325 output_addr_const (FILE, addr); \
326 fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
329 if (ireg != 0 && GET_CODE (ireg) == MULT) \
330 { scale = INTVAL (XEXP (ireg, 1)); \
331 ireg = XEXP (ireg, 0); } \
332 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
333 fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
334 else if (ireg != 0) \
335 fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
336 if (scale != 1) fprintf (FILE, "*%d", scale); \
340 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
341 { fprintf (FILE, "LD%%%d(%%pc,%s.w)", \
342 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
343 reg_names[REGNO (reg1)]); \
346 if (GET_CODE (addr) == CONST_INT \
347 && INTVAL (addr) < 0x8000 \
348 && INTVAL (addr) >= -0x8000) \
349 fprintf (FILE, "%d", INTVAL (addr)); \
351 output_addr_const (FILE, addr); \
354 #define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
355 sprintf ((LABEL), "%s%%%d", (PREFIX), (NUM))
357 #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
358 fprintf (FILE, "%s%%%d:\n", PREFIX, NUM)
360 /* Must put address in %a0 , not %d0 . -- LGM, 7/15/88 */
361 #define FUNCTION_PROFILER(FILE, LABEL_NO) \
362 fprintf (FILE, "\tmov.l &LP%%%d,%%a0\n\tjsr mcount\n", (LABEL_NO))
364 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
365 fprintf (FILE, "\tlong L%%%d\n", (VALUE))
367 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
368 fprintf (FILE, "\tshort L%%%d-L%%%d\n", (VALUE), (REL))
370 /* ihnp4!lmayk!lgm says that `short 0' triggers assembler bug;
371 `short L%nn-L%nn' supposedly works. */
372 #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
373 if (! RTX_INTEGRATED_P (TABLE)) \
374 fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n", \
375 XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM)); \
377 fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n\tshort %s%%%d-%s%%%d\n", \
378 XVECLEN (PATTERN (TABLE), 1) + 1, (PREFIX), (NUM), \
379 (PREFIX), (NUM), (PREFIX), (NUM))
381 /* At end of a switch table, define LDnnn iff the symbol LInnn was defined.
382 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
383 fails to assemble. Luckily "LDnnn(pc,d0.l*2)" produces the results
384 we want. This difference can be accommodated by making the assembler
385 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
386 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
389 #define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \
390 { if (switch_table_difference_label_flag) \
391 fprintf (FILE, "\tset LD%%%d,L%%%d-LI%%%d\n", (NUM), (NUM), (NUM)); \
392 switch_table_difference_label_flag = 0; }
394 int switch_table_difference_label_flag;
396 #define ASM_OUTPUT_OPCODE(FILE, PTR) \
397 { if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
399 while (*(PTR) != ' ') \
400 { putc (*(PTR), (FILE)); ++(PTR); } \
401 fprintf ((FILE), ".w"); } \
402 else if ((PTR)[0] == 's') \
404 if (!strncmp ((PTR), "swap", 4)) \
405 { fprintf ((FILE), "swap.w"); (PTR) += 4; } \
407 else if ((PTR)[0] == 'f') \
409 if (!strncmp ((PTR), "fmove", 5)) \
410 { fprintf ((FILE), "fmov"); (PTR) += 5; } \
411 else if (!strncmp ((PTR), "fbne", 4)) \
412 { fprintf ((FILE), "fbneq"); (PTR) += 4; } \
414 /* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV */ \
415 else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
416 && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
417 { fprintf ((FILE), "mov"); (PTR) += 4; \
418 if ((PTR)[0] == 'q' || (PTR)[0] == 'a' \
419 || (PTR)[0] == 'c') (PTR)++; } \
420 /* SUB, SUBQ, SUBA, SUBI ==> SUB */ \
421 else if ((PTR)[0] == 's' && (PTR)[1] == 'u' \
422 && (PTR)[2] == 'b') \
423 { fprintf ((FILE), "sub"); (PTR) += 3; \
424 if ((PTR)[0] == 'q' || (PTR)[0] == 'i' \
425 || (PTR)[0] == 'a') (PTR)++; } \
426 /* CMP, CMPA, CMPI, CMPM ==> CMP */ \
427 else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \
428 && (PTR)[2] == 'p') \
429 { fprintf ((FILE), "cmp"); (PTR) += 3; \
430 if ((PTR)[0] == 'a' || (PTR)[0] == 'i' \
431 || (PTR)[0] == 'm') (PTR)++; } \
434 #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
435 ( fputs ("\tlcomm ", (FILE)), \
436 assemble_name ((FILE), (NAME)), \
437 fprintf ((FILE), ",%u\n", (ROUNDED)))
439 #define USER_LABEL_PREFIX ""
441 /* Override usual definitions of SDB output macros.
442 These definitions differ only in the absence of the period
443 at the beginning of the name of the directive
444 and in the use of `~' as the symbol for the current location. */
446 #define PUT_SDB_SCL(a) fprintf(asm_out_file, "\tscl\t%d;", (a))
447 #define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\tval\t%d;", (a))
448 #define PUT_SDB_VAL(a) \
449 ( fputs ("\tval\t", asm_out_file), \
450 output_addr_const (asm_out_file, (a)), \
451 fputc (';', asm_out_file))
453 #define PUT_SDB_DEF(a) \
454 do { fprintf (asm_out_file, "\tdef\t"); \
455 ASM_OUTPUT_LABELREF (asm_out_file, a); \
456 fprintf (asm_out_file, ";"); } while (0)
458 #define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\tdef\t~%s;",a)
459 #define PUT_SDB_ENDEF fputs("\tendef\n", asm_out_file)
460 #define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\ttype\t0%o;", a)
461 #define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\tsize\t%d;", a)
462 #define PUT_SDB_START_DIM fprintf(asm_out_file, "\tdim\t")
464 #define PUT_SDB_TAG(a) \
465 do { fprintf (asm_out_file, "\ttag\t"); \
466 ASM_OUTPUT_LABELREF (asm_out_file, a); \
467 fprintf (asm_out_file, ";"); } while (0)
469 #define PUT_SDB_BLOCK_START(LINE) \
470 fprintf (asm_out_file, \
471 "\tdef\t~bb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
474 #define PUT_SDB_BLOCK_END(LINE) \
475 fprintf (asm_out_file, \
476 "\tdef\t~eb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
479 #define PUT_SDB_FUNCTION_START(LINE) \
480 fprintf (asm_out_file, \
481 "\tdef\t~bf;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
484 #define PUT_SDB_FUNCTION_END(LINE) \
485 fprintf (asm_out_file, \
486 "\tdef\t~ef;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
489 #define PUT_SDB_EPILOGUE_END(NAME) \
490 fprintf (asm_out_file, \
491 "\tdef\t%s;\tval\t~;\tscl\t-1;\tendef\n", \
494 #define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
495 sprintf ((BUFFER), "~%dfake", (NUMBER));
497 /* Define subroutines to call to handle multiply, divide, and remainder.
498 Use the subroutines that the 3b1's library provides.
499 The `*' prevents an underscore from being prepended by the compiler. */
501 #define DIVSI3_LIBCALL "*ldiv"
502 #define UDIVSI3_LIBCALL "*uldiv"
503 #define MODSI3_LIBCALL "*lrem"
504 #define UMODSI3_LIBCALL "*ulrem"
505 #define MULSI3_LIBCALL "*lmul"
506 #define UMULSI3_LIBCALL "*ulmul"
508 /* Definitions for collect2. */
510 #define OBJECT_FORMAT_COFF
511 #define MY_ISCOFF(magic) \
512 ((magic) == MC68KWRMAGIC || (magic) == MC68KROMAGIC || (magic) == MC68KPGMAGIC)