* target.h (asm_out.byte_op, asm_out.aligned_op, asm_out.unaligned_op,
[official-gcc.git] / gcc / config / m68k / dpx2.h
blobb23792930319e508e0a1e332db64b61faaf3ca6e
1 /* Definitions of target machine for GNU compiler.
2 Bull DPX/2 200 and 300 systems (m68k, SysVr3).
3 Copyright (C) 1987, 1993, 1994, 1995, 1996, 1999, 2000 Free Software Foundation, Inc.
4 Contributed by Frederic Pierresteguy (F.Pierresteguy@frcl.bull.fr).
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. */
24 #ifndef USE_GAS
25 #define MOTOROLA /* Use Motorola syntax rather than "MIT" */
26 #define SGS_NO_LI /* Suppress jump table label usage */
27 #define VERSADOS /* This is the name of the assembler we have */
28 #endif
30 #include "m68k/m68k.h"
31 #undef SELECT_RTX_SECTION
32 #include "svr3.h"
34 #undef INT_OP_GROUP
35 #define INT_OP_GROUP INT_OP_DC
37 /* We use collect2 instead of ctors_section constructors. */
38 #undef INIT_SECTION_ASM_OP
39 #undef FINI_SECTION_ASM_OP
40 #undef DTORS_SECTION_ASM_OP
41 #undef DO_GLOBAL_CTORS_BODY
43 /* Remove handling for a separate constant data section. We put
44 constant data in text_section, which is the default. */
45 #undef SELECT_SECTION
46 #undef SELECT_RTX_SECTION
47 #undef EXTRA_SECTIONS
48 #undef EXTRA_SECTION_FUNCTIONS
49 #undef CONST_SECTION_ASM_OP
50 #undef READONLY_DATA_SECTION
52 #define DPX2
54 /* See m68k.h. 7 means 68020 with 68881.
55 * We really have 68030 and 68882,
56 * but this will get us going.
58 #ifndef TARGET_DEFAULT
59 #define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
60 #endif
62 #define OBJECT_FORMAT_COFF
64 #ifdef CPP_PREDEFINES
65 #undef CPP_PREDEFINES
66 #endif
68 * define all the things the compiler should
70 #ifdef ncl_mr
71 # define CPP_PREDEFINES "-Dunix -Dbull -DDPX2 -DSVR3 -Dmc68000 -Dmc68020 -Dncl_mr=1 -D_BULL_SOURCE -D_POSIX_SOURCE -D_XOPEN_SOURCE -Asystem=unix -Asystem=svr3 -Acpu=m68k -Amachine=m68k"
72 #else
73 # ifdef ncl_el
74 # define CPP_PREDEFINES "-Dunix -Dbull -DDPX2 -DSVR3 -Dmc68000 -Dmc68020 -Dncl_el -D_BULL_SOURCE -D_POSIX_SOURCE -D_XOPEN_SOURCE -Asystem=unix -Asystem=svr3 -Acpu=m68k -Amachine=m68k"
75 # else
76 # define CPP_PREDEFINES "-Dunix -Dbull -DDPX2 -DSVR3 -Dmc68000 -Dmc68020 -D_BULL_SOURCE -D_POSIX_SOURCE -D_XOPEN_SOURCE -Asystem=unix -Asystem=svr3 -Acpu=m68k -Amachine=m68k"
77 # endif
78 #endif
80 #undef CPP_SPEC
82 * you can't get a DPX/2 without a 68882 but allow it
83 * to be ignored...
85 # define __HAVE_68881__ 1
86 # define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__ }"
88 #undef DO_GLOBAL_CTORS_BODY /* don't use svr3.h version */
89 #undef DO_GLOBAL_DTORS_BODY
91 #ifndef USE_GAS
93 * handle the native MOTOROLA VERSAdos assembler.
96 /* See m68k.h. 3 means 68020 with 68881 and no bitfield
97 * bitfield instructions do not seem to work a clean way.
99 #undef TARGET_DEFAULT
100 #define TARGET_DEFAULT (MASK_68881|MASK_68020)
102 /* The native assembler doesn't support fmovecr. */
103 #define NO_ASM_FMOVECR
105 #undef TEXT_SECTION_ASM_OP
106 #define TEXT_SECTION_ASM_OP "\tsection 10"
107 #undef DATA_SECTION_ASM_OP
108 #define DATA_SECTION_ASM_OP "\tsection 15"
109 #define BSS_SECTION_ASM_OP "\tsection 14"
112 /* Don't try using XFmode. */
113 #undef LONG_DOUBLE_TYPE_SIZE
114 #define LONG_DOUBLE_TYPE_SIZE 64
116 /* Define if you don't want extended real, but do want to use the
117 software floating point emulator for REAL_ARITHMETIC and
118 decimal <-> binary conversion. */
119 #define REAL_ARITHMETIC
121 #undef ASM_OUTPUT_SOURCE_FILENAME
122 #define ASM_OUTPUT_SOURCE_FILENAME(FILE, NA) \
123 do { fprintf ((FILE), "\t.file\t'%s'\n", (NA)); } while (0)
126 * we don't seem to support any of:
127 * .globl
128 * .even
129 * .align
130 * .ascii
132 #undef ASM_OUTPUT_SKIP
133 #define ASM_OUTPUT_SKIP(FILE,SIZE) \
134 fprintf (FILE, "\tdcb.b %u,0\n", (SIZE))
136 #undef GLOBAL_ASM_OP
137 #define GLOBAL_ASM_OP "\txdef\t"
139 #undef ASM_OUTPUT_ALIGN
140 #define ASM_OUTPUT_ALIGN(FILE,LOG) \
141 if ((LOG) >= 1) \
142 fprintf (FILE, "\tds.w 0\n");
145 #define STRING_LIMIT (0)
146 #undef ASM_APP_ON
147 #define ASM_APP_ON ""
148 #undef ASM_APP_OFF
149 #define ASM_APP_OFF ""
151 * dc.b 'hello, world!'
152 * dc.b 10,0
153 * is how we have to output "hello, world!\n"
155 #undef ASM_OUTPUT_ASCII
156 #define ASM_OUTPUT_ASCII(asm_out_file, p, thissize) \
157 do { register int i, c, f=0, len=0; \
158 for (i = 0; i < thissize; i++) { \
159 c = p[i]; \
160 if (c == '\'' || c < ' ' || c > 127) { \
161 switch(f) { \
162 case 0: /* need to output dc.b etc */ \
163 fprintf(asm_out_file, "\tdc.b %d", c); \
164 f=1; \
165 break; \
166 case 1: \
167 fprintf(asm_out_file, ",%d", c); \
168 break; \
169 default: \
170 /* close a string */ \
171 fprintf(asm_out_file, "'\n\tdc.b %d", c); \
172 f=1; \
173 break; \
175 } else { \
176 switch(f) { \
177 case 0: \
178 fprintf(asm_out_file, "\tdc.b '%c", c); \
179 f=2; \
180 break; \
181 case 2: \
182 if (len >= 79) { \
183 fprintf(asm_out_file, "'\n\tdc.b '%c", c); \
184 len = 0; } \
185 else \
186 fprintf(asm_out_file, "%c", c); \
187 break; \
188 default: \
189 len = 0; \
190 fprintf(asm_out_file, "\n\tdc.b '%c", c); \
191 f=2; \
192 break; \
195 len++; \
197 if (f==2) \
198 putc('\'', asm_out_file); \
199 putc('\n', asm_out_file); } while (0)
201 /* This is how to output an insn to push a register on the stack.
202 It need not be very fast code. */
204 #undef ASM_OUTPUT_REG_PUSH
205 #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
206 fprintf (FILE, "\tmove.l %s,-(sp)\n", reg_names[REGNO])
208 /* This is how to output an insn to pop a register from the stack.
209 It need not be very fast code. */
211 #undef ASM_OUTPUT_REG_POP
212 #define ASM_OUTPUT_REG_POP(FILE,REGNO) \
213 fprintf (FILE, "\tmove.l (sp)+,%s\n", reg_names[REGNO])
216 #define PUT_SDB_FUNCTION_START(LINE) \
217 fprintf (asm_out_file, \
218 "\t.def\t.bf%s\t.val\t*%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
219 SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
221 #define PUT_SDB_FUNCTION_END(LINE) \
222 fprintf (asm_out_file, \
223 "\t.def\t.ef%s\t.val\t*%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
224 SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
226 #define PUT_SDB_BLOCK_START(LINE) \
227 fprintf (asm_out_file, \
228 "\t.def\t.bb%s\t.val\t*%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \
229 SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
231 #define PUT_SDB_BLOCK_END(LINE) \
232 fprintf (asm_out_file, \
233 "\t.def\t.eb%s\t.val\t*%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \
234 SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
236 #define PUT_SDB_EPILOGUE_END(NAME)
238 /* Output type in decimal not in octal as done in sdbout.c */
239 #define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\t.type\t0%d%s", a, SDB_DELIM)
241 /* Translate Motorola opcodes such as `jbeq'
242 into VERSAdos opcodes such as `beq'.
243 Change `fbeq' to `fbseq', `fbne' to `fbsneq'.
246 #undef ASM_OUTPUT_OPCODE
247 #define ASM_OUTPUT_OPCODE(FILE, PTR) \
248 { if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
249 { ++(PTR); \
250 while (*(PTR) != ' ') \
251 { putc (*(PTR), (FILE)); ++(PTR); } \
253 else if ((PTR)[0] == 'f') \
255 if (!strncmp ((PTR), "fbeq", 4)) \
256 { fprintf ((FILE), "fbseq"); (PTR) += 4; } \
257 else if (!strncmp ((PTR), "fbne", 4)) \
258 { fprintf ((FILE), "fbsneq"); (PTR) += 4; } \
260 else if ((PTR)[0] == 'b' && (PTR)[1] == 'f') \
262 char *s; \
263 if ((s = (char*)strchr ((PTR), '{'))) \
264 while (*s != '}') { \
265 if (*s == 'b') \
266 /* hack, I replace it with R ie nothing */ \
267 *s = '0'; \
268 s++; } \
272 /* This is how to output a `long double' extended real constant. */
273 #undef ASM_OUTPUT_LONG_DOUBLE
274 #define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
275 do { long l[3]; \
276 REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
277 if (sizeof (int) == sizeof (long)) \
278 fprintf (FILE, "\tdc.l $%x,$%x,$%x\n", (int)l[0], (int)l[1], (int)l[2]); \
279 else \
280 fprintf (FILE, "\tdc.l $%lx,$%lx,$%lx\n", l[0], l[1], l[2]); \
281 } while (0)
283 #undef ASM_OUTPUT_DOUBLE
284 #if 0
285 #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
286 do { char dstr[30]; \
287 REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
288 fprintf (FILE, "\tdc.d %s\n", dstr); \
289 } while (0)
290 #endif
291 #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
292 do { long l[2]; \
293 REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
294 fprintf (FILE, "\tdc.l $%lx,$%lx\n", l[0], l[1]); \
295 } while (0)
298 /* This is how to output an assembler line defining a `float' constant. */
299 #undef ASM_OUTPUT_FLOAT
300 #define ASM_OUTPUT_FLOAT(FILE,VALUE) \
301 do { long l; \
302 REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
303 if (sizeof (int) == sizeof (long)) \
304 fprintf (FILE, "\tdc.l $%x\n", (int) l); \
305 else \
306 fprintf (FILE, "\tdc.l $%lx\n", l); \
307 } while (0)
309 /* This is how to output an element of a case-vector that is absolute.
310 (The 68000 does not use such vectors,
311 but we must define this macro anyway.) */
312 #undef ASM_OUTPUT_ADDR_VEC_ELT
313 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
314 asm_fprintf (FILE, "\tdc.l %LL%d\n", VALUE)
316 /* This is how to output an element of a case-vector that is relative. */
317 #undef ASM_OUTPUT_ADDR_DIFF_ELT
318 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
319 asm_fprintf (FILE, "\tdc.w %LL%d-%LL%d\n", VALUE, REL)
321 /* Currently, JUMP_TABLES_IN_TEXT_SECTION must be defined in order to
322 keep switch tables in the text section. */
323 #define JUMP_TABLES_IN_TEXT_SECTION 1
325 /* Output a float value (represented as a C double) as an immediate operand.
326 This macro is a 68k-specific macro. */
327 #undef ASM_OUTPUT_FLOAT_OPERAND
328 #define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
329 do { \
330 if (CODE == 'f') \
332 char dstr[30]; \
333 REAL_VALUE_TO_DECIMAL (VALUE, "%.9g", dstr); \
334 asm_fprintf ((FILE), "%I%s", dstr); \
336 else \
338 long l; \
339 REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
340 if (sizeof (int) == sizeof (long)) \
341 asm_fprintf ((FILE), "%I$%x", (int) l); \
342 else \
343 asm_fprintf ((FILE), "%I$%lx", l); \
345 } while (0)
347 /* Output a double value (represented as a C double) as an immediate operand.
348 This macro is a 68k-specific macro. */
349 #undef ASM_OUTPUT_DOUBLE_OPERAND
350 #define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
351 do { char dstr[30]; \
352 REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
353 asm_fprintf (FILE, "%I%s", dstr); \
354 } while (0)
356 /* Note, long double immediate operands are not actually
357 generated by m68k.md. */
358 #undef ASM_OUTPUT_LONG_DOUBLE_OPERAND
359 #define ASM_OUTPUT_LONG_DOUBLE_OPERAND(FILE,VALUE) \
360 do { char dstr[30]; \
361 REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
362 asm_fprintf (FILE, "%I%s", dstr); \
363 } while (0)
365 #undef ASM_OUTPUT_COMMON
366 #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
367 ( fputs ("\t.comm ", (FILE)), \
368 assemble_name ((FILE), (NAME)), \
369 fprintf ((FILE), ",%u\n", (ROUNDED)))
371 #undef ASM_OUTPUT_LOCAL
372 #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
373 do { \
374 int align = exact_log2 (ROUNDED); \
375 /*fprintf ((FILE), "\tsection 14\n"); */ \
376 data_section (); \
377 ASM_OUTPUT_ALIGN ((FILE), align) \
378 ASM_OUTPUT_LABEL ((FILE), (NAME)); \
379 fprintf ((FILE), "\tdcb.b %u,0\n", (ROUNDED)); \
380 /* fprintf ((FILE), "\tsection 10\n"); */ \
381 } while (0)
383 #undef PRINT_OPERAND_ADDRESS
384 #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
385 { register rtx reg1, reg2, breg, ireg; \
386 register rtx addr = ADDR; \
387 rtx offset; \
388 switch (GET_CODE (addr)) \
390 case REG: \
391 fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
392 break; \
393 case PRE_DEC: \
394 fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
395 break; \
396 case POST_INC: \
397 fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
398 break; \
399 case PLUS: \
400 reg1 = 0; reg2 = 0; \
401 ireg = 0; breg = 0; \
402 offset = 0; \
403 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
405 offset = XEXP (addr, 0); \
406 addr = XEXP (addr, 1); \
408 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
410 offset = XEXP (addr, 1); \
411 addr = XEXP (addr, 0); \
413 if (GET_CODE (addr) != PLUS) ; \
414 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
416 reg1 = XEXP (addr, 0); \
417 addr = XEXP (addr, 1); \
419 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
421 reg1 = XEXP (addr, 1); \
422 addr = XEXP (addr, 0); \
424 else if (GET_CODE (XEXP (addr, 0)) == MULT) \
426 reg1 = XEXP (addr, 0); \
427 addr = XEXP (addr, 1); \
429 else if (GET_CODE (XEXP (addr, 1)) == MULT) \
431 reg1 = XEXP (addr, 1); \
432 addr = XEXP (addr, 0); \
434 else if (GET_CODE (XEXP (addr, 0)) == REG) \
436 reg1 = XEXP (addr, 0); \
437 addr = XEXP (addr, 1); \
439 else if (GET_CODE (XEXP (addr, 1)) == REG) \
441 reg1 = XEXP (addr, 1); \
442 addr = XEXP (addr, 0); \
444 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
445 || GET_CODE (addr) == SIGN_EXTEND) \
446 { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
447 /* for OLD_INDEXING \
448 else if (GET_CODE (addr) == PLUS) \
450 if (GET_CODE (XEXP (addr, 0)) == REG) \
452 reg2 = XEXP (addr, 0); \
453 addr = XEXP (addr, 1); \
455 else if (GET_CODE (XEXP (addr, 1)) == REG) \
457 reg2 = XEXP (addr, 1); \
458 addr = XEXP (addr, 0); \
461 */ \
462 if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
463 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
464 || GET_CODE (reg1) == MULT)) \
465 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
466 { breg = reg2; ireg = reg1; } \
467 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
468 { breg = reg1; ireg = reg2; } \
469 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
470 { int scale = 1; \
471 if (GET_CODE (ireg) == MULT) \
472 { scale = INTVAL (XEXP (ireg, 1)); \
473 ireg = XEXP (ireg, 0); } \
474 if (GET_CODE (ireg) == SIGN_EXTEND) \
475 fprintf (FILE, "(.L%d,pc,%s.w", \
476 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
477 reg_names[REGNO (XEXP (ireg, 0))]); \
478 else \
479 fprintf (FILE, "(.L%d,pc,%s.l", \
480 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
481 reg_names[REGNO (ireg)]); \
482 if (scale != 1) fprintf (FILE, "*%d", scale); \
483 putc (')', FILE); \
484 break; } \
485 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF \
486 && ! (flag_pic && breg == pic_offset_table_rtx)) \
488 fprintf (FILE, "(.L%d,pc,%s.l", \
489 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
490 reg_names[REGNO (breg)]); \
491 putc (')', FILE); \
492 break; } \
493 if (ireg != 0 || breg != 0) \
494 { int scale = 1; \
495 if (breg == 0) \
496 abort (); \
497 putc ('(', FILE); \
498 if (addr != 0) \
500 output_addr_const (FILE, addr); \
501 putc (',', FILE); \
503 fprintf (FILE, "%s", reg_names[REGNO (breg)]); \
504 if (ireg != 0) \
505 putc (',', FILE); \
506 if (ireg != 0 && GET_CODE (ireg) == MULT) \
507 { scale = INTVAL (XEXP (ireg, 1)); \
508 ireg = XEXP (ireg, 0); } \
509 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
510 fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
511 else if (ireg != 0) \
512 fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
513 if (scale != 1) fprintf (FILE, "*%d", scale); \
514 putc (')', FILE); \
515 break; \
517 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
518 { fprintf (FILE, "(.L%d,pc,%s.w)", \
519 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
520 reg_names[REGNO (reg1)]); \
521 break; } \
522 default: \
523 if (GET_CODE (addr) == CONST_INT \
524 && INTVAL (addr) < 0x8000 \
525 && INTVAL (addr) >= -0x8000) \
526 fprintf (FILE, "%d.w", INTVAL (addr)); \
527 else \
528 output_addr_const (FILE, addr); \
532 #endif /* ! use gas */