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