1 /* Definitions of target machine for GNU compiler.
2 AT&T UNIX PC version (pc7300, 3b1)
5 bug reports to alex@umbc3.umd.edu
7 Copyright (C) 1987 Free Software Foundation, Inc.
9 This file is part of GNU CC.
11 GNU CC is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
16 GNU CC is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with GNU CC; see the file COPYING. If not, write to
23 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
25 #define SGS_SWITCH_TABLES /* Different switch table handling */
27 #include "m68k/hp320.h"
29 /* See m68k.h. 0 means 680[01]0 with no 68881. */
32 #define TARGET_DEFAULT 0
34 /* Don't try using XFmode. */
35 #undef LONG_DOUBLE_TYPE_SIZE
36 #define LONG_DOUBLE_TYPE_SIZE 64
38 /* -m68020 requires special flags to the assembler. */
41 #define ASM_SPEC "%{m68020:-68020}%{!m68020:-68010} %{m68881:-68881}"
43 /* we use /lib/libp/lib* when profiling */
46 #define LIB_SPEC "%{!shlib:%{p:-L/lib/libp} %{pg:-L/lib/libp} -lc}"
48 /* shared libraries need to use crt0s.o */
51 #define STARTFILE_SPEC \
52 "%{!shlib:%{pg:mcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}\
53 %{shlib:crt0s.o%s shlib.ifile%s} "
55 /* cpp has to support a #sccs directive for the /usr/include files */
57 #define SCCS_DIRECTIVE
59 /* Make output for SDB. */
61 #define SDB_DEBUGGING_INFO
63 /* The .file command should always begin the output. */
66 #define ASM_FILE_START(FILE) \
67 output_file_directive ((FILE), main_input_filename)
69 /* Don't try to define `gcc_compiled.' since the assembler might not
70 accept symbols with periods and GDB doesn't run on this machine anyway. */
71 #define ASM_IDENTIFY_GCC(FILE)
73 /* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
74 This will control the use of inline 68881 insns in certain macros. */
77 #define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
79 /* Names to predefine in the preprocessor for this target machine. */
80 /* ihnp4!lmayk!lgm@eddie.mit.edu says mc68000 and m68k should not be here. */
83 #define CPP_PREDEFINES "-Dmc68k -Dunix -Dunixpc -D__motorola__"
86 #define REGISTER_NAMES \
87 {"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
88 "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp", \
89 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7"}
91 /* Specify how to pad function arguments.
92 Value should be `upward', `downward' or `none'.
93 Same as the default, except no padding for large or variable-size args. */
95 #define FUNCTION_ARG_PADDING(MODE, TYPE) \
97 ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
98 && int_size_in_bytes (TYPE) < PARM_BOUNDARY / BITS_PER_UNIT) \
99 : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY) \
102 /* Override part of the obstack macros. */
104 #define __PTR_TO_INT(P) ((int)(P))
105 #define __INT_TO_PTR(P) ((char *)(P))
107 /* The 3b1 does not have `atexit'. */
111 /* Override parts of m68k.h to fit the SGS-3b1 assembler. */
113 #undef TARGET_VERSION
114 #undef ASM_FORMAT_PRIVATE_NAME
115 #undef ASM_OUTPUT_DOUBLE
116 #undef ASM_OUTPUT_FLOAT
117 #undef ASM_OUTPUT_ALIGN
118 #undef ASM_OUTPUT_SOURCE_FILENAME
119 #undef ASM_OUTPUT_SOURCE_LINE
120 #undef PRINT_OPERAND_ADDRESS
121 #undef ASM_GENERATE_INTERNAL_LABEL
122 #undef FUNCTION_PROFILER
123 #undef ASM_OUTPUT_ADDR_VEC_ELT
124 #undef ASM_OUTPUT_ADDR_DIFF_ELT
125 #undef ASM_OUTPUT_INTERNAL_LABEL
126 #undef ASM_OUTPUT_OPCODE
127 #undef ASM_OUTPUT_LOCAL
128 #undef ASM_OUTPUT_LABELREF
129 #undef ASM_OUTPUT_ASCII
131 #define TARGET_VERSION fprintf (stderr, " (68k, SGS/AT&T unixpc syntax)");
133 /* Store in OUTPUT a string (made with alloca) containing
134 an assembler-name for a local static variable named NAME.
135 LABELNO is an integer which is different for each call. */
137 #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
138 ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 12), \
139 sprintf ((OUTPUT), "%s_%%%d", (NAME), (LABELNO)))
141 /* The unixpc doesn't know about double's and float's */
143 #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
145 REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
146 fprintf (FILE, "\tlong 0x%x,0x%x\n", l[0], l[1]); \
149 #undef ASM_OUTPUT_LONG_DOUBLE
150 #define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
152 REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
153 fprintf (FILE, "\tlong 0x%x,0x%x,0x%x\n", l[0], l[1], l[2]); \
156 /* This is how to output an assembler line defining a `float' constant. */
158 #define ASM_OUTPUT_FLOAT(FILE,VALUE) \
160 REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
161 fprintf ((FILE), "\tlong 0x%x\n", l); \
164 #define ASM_OUTPUT_ALIGN(FILE,LOG) \
166 fprintf (FILE, "\teven\n"); \
167 else if ((LOG) != 0) \
170 /* This is how to output an assembler line
171 that says to advance the location counter by SIZE bytes. */
173 #undef ASM_OUTPUT_SKIP
174 #define ASM_OUTPUT_SKIP(FILE,SIZE) \
175 fprintf (FILE, "\tspace %d\n", (SIZE))
177 /* Can't use ASM_OUTPUT_SKIP in text section; it doesn't leave 0s. */
179 #define ASM_NO_SKIP_IN_TEXT 1
181 /* The beginnings of sdb support... */
183 #define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
184 do { fprintf (FILE, "\tfile\t"); \
185 output_quoted_string (FILE, FILENAME); \
186 fprintf (FILE, "\n"); \
189 #define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \
190 fprintf (FILE, "\tln\t%d\n", \
191 (sdb_begin_function_line \
192 ? last_linenum - sdb_begin_function_line : 1))
194 /* Yet another null terminated string format. */
196 #define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
197 { register int sp = 0, lp = 0; \
198 fprintf ((FILE), "\tbyte\t"); \
200 if ((PTR)[sp] > ' ' && ! ((PTR)[sp] & 0x80) && (PTR)[sp] != '\\') \
202 fprintf ((FILE), "'%c", (PTR)[sp]); } \
205 fprintf ((FILE), "0x%x", (PTR)[sp]); } \
209 fprintf ((FILE), "\n\t%s ", ASCII_DATA_ASM_OP); } \
211 putc (',', (FILE)); \
213 putc ('\n', (FILE)); }
215 /* Note that in the case of the movhi which fetches an element of
216 an ADDR_DIFF_VEC the offset output is too large by 2.
217 This is because the 3b1 assembler refuses to subtract 2.
218 ASM_OUTPUT_CASE_LABEL, below, compensates for this. */
220 #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
221 { register rtx reg1, reg2, breg, ireg; \
222 register rtx addr = ADDR; \
224 switch (GET_CODE (addr)) \
227 fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
230 fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
233 fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
236 reg1 = 0; reg2 = 0; \
237 ireg = 0; breg = 0; \
239 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
241 offset = XEXP (addr, 0); \
242 addr = XEXP (addr, 1); \
244 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
246 offset = XEXP (addr, 1); \
247 addr = XEXP (addr, 0); \
249 if (GET_CODE (addr) != PLUS) ; \
250 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
252 reg1 = XEXP (addr, 0); \
253 addr = XEXP (addr, 1); \
255 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
257 reg1 = XEXP (addr, 1); \
258 addr = XEXP (addr, 0); \
260 else if (GET_CODE (XEXP (addr, 0)) == MULT) \
262 reg1 = XEXP (addr, 0); \
263 addr = XEXP (addr, 1); \
265 else if (GET_CODE (XEXP (addr, 1)) == MULT) \
267 reg1 = XEXP (addr, 1); \
268 addr = XEXP (addr, 0); \
270 else if (GET_CODE (XEXP (addr, 0)) == REG) \
272 reg1 = XEXP (addr, 0); \
273 addr = XEXP (addr, 1); \
275 else if (GET_CODE (XEXP (addr, 1)) == REG) \
277 reg1 = XEXP (addr, 1); \
278 addr = XEXP (addr, 0); \
280 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
281 || GET_CODE (addr) == SIGN_EXTEND) \
282 { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
283 /* for OLD_INDEXING \
284 else if (GET_CODE (addr) == PLUS) \
286 if (GET_CODE (XEXP (addr, 0)) == REG) \
288 reg2 = XEXP (addr, 0); \
289 addr = XEXP (addr, 1); \
291 else if (GET_CODE (XEXP (addr, 1)) == REG) \
293 reg2 = XEXP (addr, 1); \
294 addr = XEXP (addr, 0); \
298 if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
299 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
300 || GET_CODE (reg1) == MULT)) \
301 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
302 { breg = reg2; ireg = reg1; } \
303 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
304 { breg = reg1; ireg = reg2; } \
305 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
307 if (GET_CODE (ireg) == MULT) \
308 { scale = INTVAL (XEXP (ireg, 1)); \
309 ireg = XEXP (ireg, 0); } \
310 if (GET_CODE (ireg) == SIGN_EXTEND) \
311 fprintf (FILE, "LD%%%d(%%pc,%s.w", \
312 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
313 reg_names[REGNO (XEXP (ireg, 0))]); \
315 fprintf (FILE, "LD%%%d(%%pc,%s.l", \
316 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
317 reg_names[REGNO (ireg)]); \
318 if (scale != 1) fprintf (FILE, "*%d", scale); \
319 fprintf (FILE, ")"); \
321 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \
322 { fprintf (FILE, "LD%%%d(%%pc,%s.l", \
323 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
324 reg_names[REGNO (breg)]); \
327 if (ireg != 0 || breg != 0) \
332 output_addr_const (FILE, addr); \
333 fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
336 if (ireg != 0 && GET_CODE (ireg) == MULT) \
337 { scale = INTVAL (XEXP (ireg, 1)); \
338 ireg = XEXP (ireg, 0); } \
339 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
340 fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
341 else if (ireg != 0) \
342 fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
343 if (scale != 1) fprintf (FILE, "*%d", scale); \
347 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
348 { fprintf (FILE, "LD%%%d(%%pc,%s.w)", \
349 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
350 reg_names[REGNO (reg1)]); \
353 if (GET_CODE (addr) == CONST_INT \
354 && INTVAL (addr) < 0x8000 \
355 && INTVAL (addr) >= -0x8000) \
356 fprintf (FILE, "%d", INTVAL (addr)); \
358 output_addr_const (FILE, addr); \
361 #define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
362 sprintf ((LABEL), "%s%%%d", (PREFIX), (NUM))
364 #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
365 fprintf (FILE, "%s%%%d:\n", PREFIX, NUM)
367 /* Must put address in %a0 , not %d0 . -- LGM, 7/15/88 */
368 #define FUNCTION_PROFILER(FILE, LABEL_NO) \
369 fprintf (FILE, "\tmov.l &LP%%%d,%%a0\n\tjsr mcount\n", (LABEL_NO))
371 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
372 fprintf (FILE, "\tlong L%%%d\n", (VALUE))
374 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
375 fprintf (FILE, "\tshort L%%%d-L%%%d\n", (VALUE), (REL))
377 /* ihnp4!lmayk!lgm says that `short 0' triggers assembler bug;
378 `short L%nn-L%nn' supposedly works. */
379 #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
380 if (! RTX_INTEGRATED_P (TABLE)) \
381 fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n", \
382 XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM)); \
384 fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n\tshort %s%%%d-%s%%%d\n", \
385 XVECLEN (PATTERN (TABLE), 1) + 1, (PREFIX), (NUM), \
386 (PREFIX), (NUM), (PREFIX), (NUM))
388 /* At end of a switch table, define LDnnn iff the symbol LInnn was defined.
389 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
390 fails to assemble. Luckily "LDnnn(pc,d0.l*2)" produces the results
391 we want. This difference can be accommodated by making the assembler
392 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
393 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
396 #define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \
397 { if (switch_table_difference_label_flag) \
398 fprintf (FILE, "\tset LD%%%d,L%%%d-LI%%%d\n", (NUM), (NUM), (NUM)); \
399 switch_table_difference_label_flag = 0; }
401 int switch_table_difference_label_flag
;
403 #define ASM_OUTPUT_OPCODE(FILE, PTR) \
404 { if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
406 while (*(PTR) != ' ') \
407 { putc (*(PTR), (FILE)); ++(PTR); } \
408 fprintf ((FILE), ".w"); } \
409 else if ((PTR)[0] == 's') \
411 if (!strncmp ((PTR), "swap", 4)) \
412 { fprintf ((FILE), "swap.w"); (PTR) += 4; } \
414 else if ((PTR)[0] == 'f') \
416 if (!strncmp ((PTR), "fmove", 5)) \
417 { fprintf ((FILE), "fmov"); (PTR) += 5; } \
418 else if (!strncmp ((PTR), "fbne", 4)) \
419 { fprintf ((FILE), "fbneq"); (PTR) += 4; } \
421 /* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV */ \
422 else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
423 && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
424 { fprintf ((FILE), "mov"); (PTR) += 4; \
425 if ((PTR)[0] == 'q' || (PTR)[0] == 'a' \
426 || (PTR)[0] == 'c') (PTR)++; } \
427 /* SUB, SUBQ, SUBA, SUBI ==> SUB */ \
428 else if ((PTR)[0] == 's' && (PTR)[1] == 'u' \
429 && (PTR)[2] == 'b') \
430 { fprintf ((FILE), "sub"); (PTR) += 3; \
431 if ((PTR)[0] == 'q' || (PTR)[0] == 'i' \
432 || (PTR)[0] == 'a') (PTR)++; } \
433 /* CMP, CMPA, CMPI, CMPM ==> CMP */ \
434 else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \
435 && (PTR)[2] == 'p') \
436 { fprintf ((FILE), "cmp"); (PTR) += 3; \
437 if ((PTR)[0] == 'a' || (PTR)[0] == 'i' \
438 || (PTR)[0] == 'm') (PTR)++; } \
441 #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
442 ( fputs ("\tlcomm ", (FILE)), \
443 assemble_name ((FILE), (NAME)), \
444 fprintf ((FILE), ",%u\n", (ROUNDED)))
446 #define ASM_OUTPUT_LABELREF(FILE,NAME) \
447 fprintf (FILE, "%s", NAME)
449 /* Override usual definitions of SDB output macros.
450 These definitions differ only in the absence of the period
451 at the beginning of the name of the directive
452 and in the use of `~' as the symbol for the current location. */
454 #define PUT_SDB_SCL(a) fprintf(asm_out_file, "\tscl\t%d;", (a))
455 #define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\tval\t%d;", (a))
456 #define PUT_SDB_VAL(a) \
457 ( fputs ("\tval\t", asm_out_file), \
458 output_addr_const (asm_out_file, (a)), \
459 fputc (';', asm_out_file))
461 #define PUT_SDB_DEF(a) \
462 do { fprintf (asm_out_file, "\tdef\t"); \
463 ASM_OUTPUT_LABELREF (asm_out_file, a); \
464 fprintf (asm_out_file, ";"); } while (0)
466 #define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\tdef\t~%s;",a)
467 #define PUT_SDB_ENDEF fputs("\tendef\n", asm_out_file)
468 #define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\ttype\t0%o;", a)
469 #define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\tsize\t%d;", a)
470 #define PUT_SDB_START_DIM fprintf(asm_out_file, "\tdim\t")
472 #define PUT_SDB_TAG(a) \
473 do { fprintf (asm_out_file, "\ttag\t"); \
474 ASM_OUTPUT_LABELREF (asm_out_file, a); \
475 fprintf (asm_out_file, ";"); } while (0)
477 #define PUT_SDB_BLOCK_START(LINE) \
478 fprintf (asm_out_file, \
479 "\tdef\t~bb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
482 #define PUT_SDB_BLOCK_END(LINE) \
483 fprintf (asm_out_file, \
484 "\tdef\t~eb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
487 #define PUT_SDB_FUNCTION_START(LINE) \
488 fprintf (asm_out_file, \
489 "\tdef\t~bf;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
492 #define PUT_SDB_FUNCTION_END(LINE) \
493 fprintf (asm_out_file, \
494 "\tdef\t~ef;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
497 #define PUT_SDB_EPILOGUE_END(NAME) \
498 fprintf (asm_out_file, \
499 "\tdef\t%s;\tval\t~;\tscl\t-1;\tendef\n", \
502 #define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
503 sprintf ((BUFFER), "~%dfake", (NUMBER));
505 /* Define subroutines to call to handle multiply, divide, and remainder.
506 Use the subroutines that the 3b1's library provides.
507 The `*' prevents an underscore from being prepended by the compiler. */
509 #define DIVSI3_LIBCALL "*ldiv"
510 #define UDIVSI3_LIBCALL "*uldiv"
511 #define MODSI3_LIBCALL "*lrem"
512 #define UMODSI3_LIBCALL "*ulrem"
513 #define MULSI3_LIBCALL "*lmul"
514 #define UMULSI3_LIBCALL "*ulmul"
516 /* Definitions for collect2. */
518 #define OBJECT_FORMAT_COFF
519 #define NO_SYS_SIGLIST
520 #define MY_ISCOFF(magic) \
521 ((magic) == MC68KWRMAGIC || (magic) == MC68KROMAGIC || (magic) == MC68KPGMAGIC)