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 /* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
68 This will control the use of inline 68881 insns in certain macros. */
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. */
77 #define CPP_PREDEFINES "-Dmc68k -Dunix -Dunixpc -D__motorola__ -Asystem=unix -Asystem=svr3 -Acpu=m68k -Amachine=m68k"
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) \
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) \
96 /* The 3b1 does not have `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_DOUBLE
105 #undef ASM_OUTPUT_FLOAT
106 #undef ASM_OUTPUT_ALIGN
107 #undef ASM_OUTPUT_SOURCE_FILENAME
108 #undef ASM_OUTPUT_SOURCE_LINE
109 #undef PRINT_OPERAND_ADDRESS
110 #undef ASM_GENERATE_INTERNAL_LABEL
111 #undef FUNCTION_PROFILER
112 #undef ASM_OUTPUT_ADDR_VEC_ELT
113 #undef ASM_OUTPUT_ADDR_DIFF_ELT
114 #undef ASM_OUTPUT_INTERNAL_LABEL
115 #undef ASM_OUTPUT_OPCODE
116 #undef ASM_OUTPUT_LOCAL
117 #undef USER_LABEL_PREFIX
118 #undef ASM_OUTPUT_ASCII
120 #define TARGET_VERSION fprintf (stderr, " (68k, SGS/AT&T unixpc syntax)");
122 /* Store in OUTPUT a string (made with alloca) containing
123 an assembler-name for a local static variable named NAME.
124 LABELNO is an integer which is different for each call. */
126 #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
127 ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 12), \
128 sprintf ((OUTPUT), "%s_%%%d", (NAME), (LABELNO)))
130 /* The unixpc doesn't know about double's and float's */
132 #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
134 REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
135 fprintf (FILE, "\tlong 0x%lx,0x%lx\n", l[0], l[1]); \
138 #undef ASM_OUTPUT_LONG_DOUBLE
139 #define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
141 REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
142 fprintf (FILE, "\tlong 0x%lx,0x%lx,0x%lx\n", l[0], l[1], l[2]); \
145 /* This is how to output an assembler line defining a `float' constant. */
147 #define ASM_OUTPUT_FLOAT(FILE,VALUE) \
149 REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
150 fprintf ((FILE), "\tlong 0x%lx\n", l); \
153 #define ASM_OUTPUT_ALIGN(FILE,LOG) \
155 fprintf (FILE, "\teven\n"); \
156 else if ((LOG) != 0) \
159 /* This is how to output an assembler line
160 that says to advance the location counter by SIZE bytes. */
162 #undef ASM_OUTPUT_SKIP
163 #define ASM_OUTPUT_SKIP(FILE,SIZE) \
164 fprintf (FILE, "\tspace %d\n", (SIZE))
166 /* Can't use ASM_OUTPUT_SKIP in text section; it doesn't leave 0s. */
168 #define ASM_NO_SKIP_IN_TEXT 1
170 /* The beginnings of sdb support... */
172 #define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
173 do { fprintf (FILE, "\tfile\t"); \
174 output_quoted_string (FILE, FILENAME); \
175 fprintf (FILE, "\n"); \
178 #define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \
179 fprintf (FILE, "\tln\t%d\n", \
180 (sdb_begin_function_line \
181 ? (LINENO) - sdb_begin_function_line : 1))
183 /* Yet another null terminated string format. */
185 #define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
186 do { register int sp = 0, lp = 0; \
187 fprintf ((FILE), "\tbyte\t"); \
189 if ((PTR)[sp] > ' ' && ! ((PTR)[sp] & 0x80) && (PTR)[sp] != '\\') \
191 fprintf ((FILE), "'%c", (PTR)[sp]); } \
194 fprintf ((FILE), "0x%x", (PTR)[sp]); } \
198 fprintf ((FILE), "\n%s", ASCII_DATA_ASM_OP); } \
200 putc (',', (FILE)); \
202 putc ('\n', (FILE)); } while (0)
204 /* Note that in the case of the movhi which fetches an element of
205 an ADDR_DIFF_VEC the offset output is too large by 2.
206 This is because the 3b1 assembler refuses to subtract 2.
207 ASM_OUTPUT_CASE_LABEL, below, compensates for this. */
209 #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
210 { register rtx reg1, reg2, breg, ireg; \
211 register rtx addr = ADDR; \
213 switch (GET_CODE (addr)) \
216 fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
219 fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
222 fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
225 reg1 = 0; reg2 = 0; \
226 ireg = 0; breg = 0; \
228 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
230 offset = XEXP (addr, 0); \
231 addr = XEXP (addr, 1); \
233 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
235 offset = XEXP (addr, 1); \
236 addr = XEXP (addr, 0); \
238 if (GET_CODE (addr) != PLUS) ; \
239 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
241 reg1 = XEXP (addr, 0); \
242 addr = XEXP (addr, 1); \
244 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
246 reg1 = XEXP (addr, 1); \
247 addr = XEXP (addr, 0); \
249 else if (GET_CODE (XEXP (addr, 0)) == MULT) \
251 reg1 = XEXP (addr, 0); \
252 addr = XEXP (addr, 1); \
254 else if (GET_CODE (XEXP (addr, 1)) == MULT) \
256 reg1 = XEXP (addr, 1); \
257 addr = XEXP (addr, 0); \
259 else if (GET_CODE (XEXP (addr, 0)) == REG) \
261 reg1 = XEXP (addr, 0); \
262 addr = XEXP (addr, 1); \
264 else if (GET_CODE (XEXP (addr, 1)) == REG) \
266 reg1 = XEXP (addr, 1); \
267 addr = XEXP (addr, 0); \
269 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
270 || GET_CODE (addr) == SIGN_EXTEND) \
271 { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
272 /* for OLD_INDEXING \
273 else if (GET_CODE (addr) == PLUS) \
275 if (GET_CODE (XEXP (addr, 0)) == REG) \
277 reg2 = XEXP (addr, 0); \
278 addr = XEXP (addr, 1); \
280 else if (GET_CODE (XEXP (addr, 1)) == REG) \
282 reg2 = XEXP (addr, 1); \
283 addr = XEXP (addr, 0); \
287 if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
288 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
289 || GET_CODE (reg1) == MULT)) \
290 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
291 { breg = reg2; ireg = reg1; } \
292 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
293 { breg = reg1; ireg = reg2; } \
294 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
296 if (GET_CODE (ireg) == MULT) \
297 { scale = INTVAL (XEXP (ireg, 1)); \
298 ireg = XEXP (ireg, 0); } \
299 if (GET_CODE (ireg) == SIGN_EXTEND) \
300 fprintf (FILE, "LD%%%d(%%pc,%s.w", \
301 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
302 reg_names[REGNO (XEXP (ireg, 0))]); \
304 fprintf (FILE, "LD%%%d(%%pc,%s.l", \
305 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
306 reg_names[REGNO (ireg)]); \
307 if (scale != 1) fprintf (FILE, "*%d", scale); \
308 fprintf (FILE, ")"); \
310 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \
311 { fprintf (FILE, "LD%%%d(%%pc,%s.l", \
312 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
313 reg_names[REGNO (breg)]); \
316 if (ireg != 0 || breg != 0) \
321 output_addr_const (FILE, addr); \
322 fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
325 if (ireg != 0 && GET_CODE (ireg) == MULT) \
326 { scale = INTVAL (XEXP (ireg, 1)); \
327 ireg = XEXP (ireg, 0); } \
328 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
329 fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
330 else if (ireg != 0) \
331 fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
332 if (scale != 1) fprintf (FILE, "*%d", scale); \
336 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
337 { fprintf (FILE, "LD%%%d(%%pc,%s.w)", \
338 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
339 reg_names[REGNO (reg1)]); \
342 if (GET_CODE (addr) == CONST_INT \
343 && INTVAL (addr) < 0x8000 \
344 && INTVAL (addr) >= -0x8000) \
345 fprintf (FILE, "%d", INTVAL (addr)); \
347 output_addr_const (FILE, addr); \
350 #define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
351 sprintf ((LABEL), "%s%%%ld", (PREFIX), (long)(NUM))
353 #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
354 fprintf (FILE, "%s%%%d:\n", PREFIX, NUM)
356 /* Must put address in %a0 , not %d0 . -- LGM, 7/15/88 */
357 #define FUNCTION_PROFILER(FILE, LABEL_NO) \
358 fprintf (FILE, "\tmov.l &LP%%%d,%%a0\n\tjsr mcount\n", (LABEL_NO))
360 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
361 fprintf (FILE, "\tlong L%%%d\n", (VALUE))
363 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
364 fprintf (FILE, "\tshort L%%%d-L%%%d\n", (VALUE), (REL))
366 /* ihnp4!lmayk!lgm says that `short 0' triggers assembler bug;
367 `short L%nn-L%nn' supposedly works. */
368 #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
369 if (! RTX_INTEGRATED_P (TABLE)) \
370 fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n", \
371 XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM)); \
373 fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n\tshort %s%%%d-%s%%%d\n", \
374 XVECLEN (PATTERN (TABLE), 1) + 1, (PREFIX), (NUM), \
375 (PREFIX), (NUM), (PREFIX), (NUM))
377 /* At end of a switch table, define LDnnn iff the symbol LInnn was defined.
378 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
379 fails to assemble. Luckily "LDnnn(pc,d0.l*2)" produces the results
380 we want. This difference can be accommodated by making the assembler
381 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
382 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
385 #define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \
386 { if (switch_table_difference_label_flag) \
387 fprintf (FILE, "\tset LD%%%d,L%%%d-LI%%%d\n", (NUM), (NUM), (NUM)); \
388 switch_table_difference_label_flag = 0; }
390 int switch_table_difference_label_flag;
392 #define ASM_OUTPUT_OPCODE(FILE, PTR) \
393 { if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
395 while (*(PTR) != ' ') \
396 { putc (*(PTR), (FILE)); ++(PTR); } \
397 fprintf ((FILE), ".w"); } \
398 else if ((PTR)[0] == 's') \
400 if (!strncmp ((PTR), "swap", 4)) \
401 { fprintf ((FILE), "swap.w"); (PTR) += 4; } \
403 else if ((PTR)[0] == 'f') \
405 if (!strncmp ((PTR), "fmove", 5)) \
406 { fprintf ((FILE), "fmov"); (PTR) += 5; } \
407 else if (!strncmp ((PTR), "fbne", 4)) \
408 { fprintf ((FILE), "fbneq"); (PTR) += 4; } \
410 /* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV */ \
411 else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
412 && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
413 { fprintf ((FILE), "mov"); (PTR) += 4; \
414 if ((PTR)[0] == 'q' || (PTR)[0] == 'a' \
415 || (PTR)[0] == 'c') (PTR)++; } \
416 /* SUB, SUBQ, SUBA, SUBI ==> SUB */ \
417 else if ((PTR)[0] == 's' && (PTR)[1] == 'u' \
418 && (PTR)[2] == 'b') \
419 { fprintf ((FILE), "sub"); (PTR) += 3; \
420 if ((PTR)[0] == 'q' || (PTR)[0] == 'i' \
421 || (PTR)[0] == 'a') (PTR)++; } \
422 /* CMP, CMPA, CMPI, CMPM ==> CMP */ \
423 else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \
424 && (PTR)[2] == 'p') \
425 { fprintf ((FILE), "cmp"); (PTR) += 3; \
426 if ((PTR)[0] == 'a' || (PTR)[0] == 'i' \
427 || (PTR)[0] == 'm') (PTR)++; } \
430 #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
431 ( fputs ("\tlcomm ", (FILE)), \
432 assemble_name ((FILE), (NAME)), \
433 fprintf ((FILE), ",%u\n", (ROUNDED)))
435 #define USER_LABEL_PREFIX ""
437 /* Override usual definitions of SDB output macros.
438 These definitions differ only in the absence of the period
439 at the beginning of the name of the directive
440 and in the use of `~' as the symbol for the current location. */
442 #define PUT_SDB_SCL(a) fprintf(asm_out_file, "\tscl\t%d;", (a))
443 #define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\tval\t%d;", (a))
444 #define PUT_SDB_VAL(a) \
445 ( fputs ("\tval\t", asm_out_file), \
446 output_addr_const (asm_out_file, (a)), \
447 fputc (';', asm_out_file))
449 #define PUT_SDB_DEF(a) \
450 do { fprintf (asm_out_file, "\tdef\t"); \
451 ASM_OUTPUT_LABELREF (asm_out_file, a); \
452 fprintf (asm_out_file, ";"); } while (0)
454 #define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\tdef\t~%s;",a)
455 #define PUT_SDB_ENDEF fputs("\tendef\n", asm_out_file)
456 #define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\ttype\t0%o;", a)
457 #define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\tsize\t%d;", a)
458 #define PUT_SDB_START_DIM fprintf(asm_out_file, "\tdim\t")
460 #define PUT_SDB_TAG(a) \
461 do { fprintf (asm_out_file, "\ttag\t"); \
462 ASM_OUTPUT_LABELREF (asm_out_file, a); \
463 fprintf (asm_out_file, ";"); } while (0)
465 #define PUT_SDB_BLOCK_START(LINE) \
466 fprintf (asm_out_file, \
467 "\tdef\t~bb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
470 #define PUT_SDB_BLOCK_END(LINE) \
471 fprintf (asm_out_file, \
472 "\tdef\t~eb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
475 #define PUT_SDB_FUNCTION_START(LINE) \
476 fprintf (asm_out_file, \
477 "\tdef\t~bf;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
480 #define PUT_SDB_FUNCTION_END(LINE) \
481 fprintf (asm_out_file, \
482 "\tdef\t~ef;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
485 #define PUT_SDB_EPILOGUE_END(NAME) \
486 fprintf (asm_out_file, \
487 "\tdef\t%s;\tval\t~;\tscl\t-1;\tendef\n", \
490 #define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
491 sprintf ((BUFFER), "~%dfake", (NUMBER));
493 /* Define subroutines to call to handle multiply, divide, and remainder.
494 Use the subroutines that the 3b1's library provides.
495 The `*' prevents an underscore from being prepended by the compiler. */
497 #define DIVSI3_LIBCALL "*ldiv"
498 #define UDIVSI3_LIBCALL "*uldiv"
499 #define MODSI3_LIBCALL "*lrem"
500 #define UMODSI3_LIBCALL "*ulrem"
501 #define MULSI3_LIBCALL "*lmul"
502 #define UMULSI3_LIBCALL "*ulmul"
504 /* Definitions for collect2. */
506 #define OBJECT_FORMAT_COFF
507 #define MY_ISCOFF(magic) \
508 ((magic) == MC68KWRMAGIC || (magic) == MC68KROMAGIC || (magic) == MC68KPGMAGIC)