update copyrights in config dir.
[official-gcc.git] / gcc / config / m68k / dpx2.h
blobdde95bb0d032eb59f895a5e95cfb8acd0192e925
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 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 /* See m68k.h. 7 means 68020 with 68881.
35 * We really have 68030 and 68882,
36 * but this will get us going.
38 #ifndef TARGET_DEFAULT
39 #define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
40 #endif
42 #define OBJECT_FORMAT_COFF
44 #ifdef CPP_PREDEFINES
45 #undef CPP_PREDEFINES
46 #endif
48 * define all the things the compiler should
50 #ifdef ncl_mr
51 # 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)"
52 #else
53 # ifdef ncl_el
54 # 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)"
55 # else
56 # 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)"
57 # endif
58 #endif
60 #undef CPP_SPEC
62 * you can't get a DPX/2 without a 68882 but allow it
63 * to be ignored...
65 # define __HAVE_68881__ 1
66 # define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__ }"
68 #undef DO_GLOBAL_CTORS_BODY /* don't use svr3.h version */
69 #undef DO_GLOBAL_DTORS_BODY
71 #ifndef USE_GAS
73 * handle the native MOTOROLA VERSAdos assembler.
76 /* See m68k.h. 3 means 68020 with 68881 and no bitfield
77 * bitfield instructions do not seem to work a clean way.
79 #undef TARGET_DEFAULT
80 #define TARGET_DEFAULT (MASK_68881|MASK_68020)
82 /* The native assembler doesn't support fmovecr. */
83 #define NO_ASM_FMOVECR
85 #undef EXTRA_SECTIONS
86 #undef EXTRA_SECTION_FUNCTIONS
87 #undef READONLY_DATA_SECTION
88 #define READONLY_DATA_SECTION data_section
89 #undef SELECT_SECTION
90 #undef SELECT_RTX_SECTION
91 #define fini_section() while (0)
93 #undef CTORS_SECTION_ASM_OP
94 #define CTORS_SECTION_ASM_OP "\tsection 15"
95 #undef DTORS_SECTION_ASM_OP
96 #define DTORS_SECTION_ASM_OP "\tsection 15"
97 #undef INIT_SECTION_ASM_OP
98 #define BSS_SECTION_ASM_OP "\tsection 14"
99 #undef TEXT_SECTION_ASM_OP
100 #define TEXT_SECTION_ASM_OP "\tsection 10"
101 #undef DATA_SECTION_ASM_OP
102 #define DATA_SECTION_ASM_OP "\tsection 15"
105 /* Don't try using XFmode. */
106 #undef LONG_DOUBLE_TYPE_SIZE
107 #define LONG_DOUBLE_TYPE_SIZE 64
109 /* Define if you don't want extended real, but do want to use the
110 software floating point emulator for REAL_ARITHMETIC and
111 decimal <-> binary conversion. */
112 #define REAL_ARITHMETIC
114 #undef ASM_OUTPUT_SOURCE_FILENAME
115 #define ASM_OUTPUT_SOURCE_FILENAME(FILE, NA) \
116 do { fprintf ((FILE), "\t.file\t'%s'\n", (NA)); } while (0)
118 /* Assembler pseudos to introduce constants of various size. */
120 #undef ASM_BYTE_OP
121 #define ASM_BYTE_OP "\tdc.b"
122 #undef ASM_LONG
123 #define ASM_LONG "\tdc.l"
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"
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 #undef FUNCTION_PROLOGUE
242 #define FUNCTION_PROLOGUE(FILE, SIZE) \
244 register int regno; \
245 register int mask = 0; \
246 int num_saved_regs = 0, first = 1; \
247 extern char call_used_regs[]; \
248 int fsize = ((SIZE) + 3) & -4; \
251 if (frame_pointer_needed) \
253 /* Adding negative number is faster on the 68040. */ \
254 if (fsize < 0x8000 && !TARGET_68040) \
256 fprintf (FILE, "\tlink %s,#%d\n", \
257 reg_names[FRAME_POINTER_REGNUM], -fsize); \
259 else if (TARGET_68020) \
261 fprintf (FILE, "\tlink %s,#%d\n", \
262 reg_names[FRAME_POINTER_REGNUM], -fsize); \
264 else \
266 fprintf (FILE, "\tlink %s,#0\n\tadd.l #%d,sp\n", \
267 reg_names[FRAME_POINTER_REGNUM], -fsize); \
270 else if (fsize) \
272 /* Adding negative number is faster on the 68040. */ \
273 if (fsize + 4 < 0x8000) \
275 fprintf (FILE, "\tadd.w #%d,sp\n", - (fsize + 4)); \
277 else \
279 fprintf (FILE, "\tadd.l #%d,sp\n", - (fsize + 4)); \
282 for (regno = 23; regno >= 16; regno--) \
283 if (regs_ever_live[regno] && ! call_used_regs[regno]) \
284 if (first) { \
285 fprintf (FILE, "\tfmovem.x %s", reg_names[regno]); \
286 first = 0; \
288 else fprintf (FILE, "/%s", reg_names[regno]); \
289 if (!first) fprintf (FILE, ",-(sp)\n"); \
291 mask = 0; \
292 for (regno = 0; regno < 16; regno++) \
293 if (regs_ever_live[regno] && ! call_used_regs[regno]) \
295 mask |= 1 << (15 - regno); \
296 num_saved_regs++; \
298 if (frame_pointer_needed) \
300 mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM)); \
301 num_saved_regs--; \
305 if (num_saved_regs <= 2) \
307 /* Store each separately in the same order moveml uses. \
308 Using two movel instructions instead of a single moveml \
309 is about 15% faster for the 68020 and 68030 at no expense \
310 in code size */ \
312 int i; \
314 /* Undo the work from above. */ \
315 for (i = 0; i< 16; i++) \
316 if (mask & (1 << i)) \
317 fprintf (FILE, "\tmove.l %s,-(sp)\n", reg_names[15 - i]); \
319 else if (mask) \
321 first = 1; \
322 for (regno = 0; regno < 16; regno++) \
323 if (mask & (1 << regno)) \
324 if (first) { \
325 fprintf (FILE, "\tmovem.l %s", reg_names[15 - regno]); \
326 first = 0; \
328 else fprintf (FILE, "/%s", reg_names[15 - regno]); \
329 fprintf (FILE, ",-(sp)\n"); \
331 if (flag_pic && current_function_uses_pic_offset_table) \
333 fprintf (FILE, "\tmove.l #__GLOBAL_OFFSET_TABLE_, %s\n", \
334 reg_names[PIC_OFFSET_TABLE_REGNUM]); \
335 fprintf (FILE, "\tlea.l (pc,%s.l),%s\n", \
336 reg_names[PIC_OFFSET_TABLE_REGNUM], \
337 reg_names[PIC_OFFSET_TABLE_REGNUM]); \
342 #undef FUNCTION_EPILOGUE
343 #define FUNCTION_EPILOGUE(FILE, SIZE) \
345 register int regno; \
346 register int mask, fmask; \
347 register int nregs; \
348 int offset, foffset, fpoffset, first = 1; \
349 extern char call_used_regs[]; \
350 int fsize = ((SIZE) + 3) & -4; \
351 int big = 0; \
352 rtx insn = get_last_insn (); \
354 /* If the last insn was a BARRIER, we don't have to write any code. */ \
355 if (GET_CODE (insn) == NOTE) \
356 insn = prev_nonnote_insn (insn); \
357 if (insn && GET_CODE (insn) == BARRIER) \
359 /* Output just a no-op so that debuggers don't get confused \
360 about which function the pc is in at this address. */ \
361 fprintf (FILE, "\tnop\n"); \
362 return; \
365 nregs = 0; fmask = 0; fpoffset = 0; \
366 for (regno = 16; regno < 24; regno++) \
367 if (regs_ever_live[regno] && ! call_used_regs[regno]) \
369 nregs++; \
370 fmask |= 1 << (23 - regno); \
372 foffset = fpoffset + nregs * 12; \
373 nregs = 0; mask = 0; \
374 if (frame_pointer_needed) \
375 regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
376 for (regno = 0; regno < 16; regno++) \
377 if (regs_ever_live[regno] && ! call_used_regs[regno]) \
379 nregs++; \
380 mask |= 1 << regno; \
382 offset = foffset + nregs * 4; \
383 if (offset + fsize >= 0x8000 \
384 && frame_pointer_needed \
385 && (mask || fmask || fpoffset)) \
387 fprintf (FILE, "\tmove.l #%d,a0\n", -fsize); \
388 fsize = 0, big = 1; \
390 if (nregs <= 2) \
392 /* Restore each separately in the same order moveml does. \
393 Using two movel instructions instead of a single moveml \
394 is about 15% faster for the 68020 and 68030 at no expense \
395 in code size. */ \
397 int i; \
399 /* Undo the work from above. */ \
400 for (i = 0; i< 16; i++) \
401 if (mask & (1 << i)) \
403 if (big) \
405 fprintf (FILE, "\tmove.l -%d(%s,a0.l),%s\n", \
406 offset + fsize, \
407 reg_names[FRAME_POINTER_REGNUM], \
408 reg_names[i]); \
410 else if (! frame_pointer_needed) \
412 fprintf (FILE, "\tmove.l (sp)+,%s\n", \
413 reg_names[i]); \
415 else \
417 fprintf (FILE, "\tmove.l -%d(%s),%s\n", \
418 offset + fsize, \
419 reg_names[FRAME_POINTER_REGNUM], \
420 reg_names[i]); \
422 offset = offset - 4; \
425 else if (mask) \
427 first = 1; \
428 for (regno = 0; regno < 16; regno++) \
429 if (mask & (1 << regno)) \
430 if (first && big) { \
431 fprintf (FILE, "\tmovem.l -%d(%s,a0.l),%s", \
432 offset + fsize, \
433 reg_names[FRAME_POINTER_REGNUM], \
434 reg_names[regno]); \
435 first = 0; \
437 else if (first && ! frame_pointer_needed) { \
438 fprintf (FILE, "\tmovem.l (sp)+,%s", \
439 offset + fsize, \
440 reg_names[FRAME_POINTER_REGNUM], \
441 reg_names[regno]); \
442 first = 0; \
444 else if (first) { \
445 fprintf (FILE, "\tmovem.l -%d(%s),%s", \
446 offset + fsize, \
447 reg_names[FRAME_POINTER_REGNUM], \
448 reg_names[regno]); \
449 first = 0; \
451 else \
452 fprintf (FILE, "/%s", reg_names[regno]); \
453 fprintf (FILE, "\n"); \
455 if (fmask) \
457 first = 1; \
458 for (regno = 16; regno < 24; regno++) \
459 if (fmask & (1 << (23 - regno))) \
460 if (first && big) { \
461 fprintf (FILE, "\tfmovem.x -%d(%s,a0.l),%s", \
462 foffset + fsize, \
463 reg_names[FRAME_POINTER_REGNUM], \
464 reg_names[regno]); \
465 first = 0; \
467 else if (first && ! frame_pointer_needed) { \
468 fprintf (FILE, "\tfmovem.x (sp)+,%s", \
469 foffset + fsize, \
470 reg_names[FRAME_POINTER_REGNUM], \
471 reg_names[regno]); \
472 first = 0; \
474 else if (first) { \
475 fprintf (FILE, "\tfmovem.x -%d(%s),%s", \
476 foffset + fsize, \
477 reg_names[FRAME_POINTER_REGNUM], \
478 reg_names[regno]); \
479 first = 0; \
481 else fprintf (FILE, "/%s", reg_names[regno]); \
482 fprintf (FILE, "\n"); \
484 if (frame_pointer_needed) \
485 fprintf (FILE, "\tunlk %s\n", \
486 reg_names[FRAME_POINTER_REGNUM]); \
487 else if (fsize) \
489 if (fsize + 4 < 0x8000) \
491 fprintf (FILE, "\tadd.w #%d,sp\n", fsize + 4); \
493 else \
495 fprintf (FILE, "\tadd.l #%d,sp\n", fsize + 4); \
498 if (current_function_pops_args) \
499 fprintf (FILE, "\trtd #%d\n", current_function_pops_args); \
500 else \
501 fprintf (FILE, "\trts\n"); \
504 /* Translate Motorola opcodes such as `jbeq'
505 into VERSAdos opcodes such as `beq'.
506 Change `fbeq' to `fbseq', `fbne' to `fbsneq'.
509 #undef ASM_OUTPUT_OPCODE
510 #define ASM_OUTPUT_OPCODE(FILE, PTR) \
511 { if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
512 { ++(PTR); \
513 while (*(PTR) != ' ') \
514 { putc (*(PTR), (FILE)); ++(PTR); } \
516 else if ((PTR)[0] == 'f') \
518 if (!strncmp ((PTR), "fbeq", 4)) \
519 { fprintf ((FILE), "fbseq"); (PTR) += 4; } \
520 else if (!strncmp ((PTR), "fbne", 4)) \
521 { fprintf ((FILE), "fbsneq"); (PTR) += 4; } \
523 else if ((PTR)[0] == 'b' && (PTR)[1] == 'f') \
525 char *s; \
526 if ((s = (char*)strchr ((PTR), '{'))) \
527 while (*s != '}') { \
528 if (*s == 'b') \
529 /* hack, I replace it with R ie nothing */ \
530 *s = '0'; \
531 s++; } \
535 /* This is how to output a `long double' extended real constant. */
536 #undef ASM_OUTPUT_LONG_DOUBLE
537 #define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
538 do { long l[3]; \
539 REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
540 if (sizeof (int) == sizeof (long)) \
541 fprintf (FILE, "\tdc.l $%x,$%x,$%x\n", l[0], l[1], l[2]); \
542 else \
543 fprintf (FILE, "\tdc.l $%lx,$%lx,$%lx\n", l[0], l[1], l[2]); \
544 } while (0)
546 #undef ASM_OUTPUT_DOUBLE
547 #if 0
548 #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
549 do { char dstr[30]; \
550 REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
551 fprintf (FILE, "\tdc.d %s\n", dstr); \
552 } while (0)
553 #endif
554 #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
555 do { long l[2]; \
556 REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
557 fprintf (FILE, "\tdc.l $%x,$%x\n", l[0], l[1]); \
558 } while (0)
561 /* This is how to output an assembler line defining a `float' constant. */
562 #undef ASM_OUTPUT_FLOAT
563 #define ASM_OUTPUT_FLOAT(FILE,VALUE) \
564 do { long l; \
565 REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
566 if (sizeof (int) == sizeof (long)) \
567 fprintf (FILE, "\tdc.l $%x\n", l); \
568 else \
569 fprintf (FILE, "\tdc.l $%lx\n", l); \
570 } while (0)
572 /* This is how to output an assembler line defining an `int' constant. */
573 #undef ASM_OUTPUT_INT
574 #define ASM_OUTPUT_INT(FILE,VALUE) \
575 ( fprintf (FILE, "\tdc.l "), \
576 output_addr_const (FILE, (VALUE)), \
577 fprintf (FILE, "\n"))
579 /* Likewise for `char' and `short' constants. */
580 #undef ASM_OUTPUT_SHORT
581 #define ASM_OUTPUT_SHORT(FILE,VALUE) \
582 ( fprintf (FILE, "\tdc.w "), \
583 output_addr_const (FILE, (VALUE)), \
584 fprintf (FILE, "\n"))
586 #undef ASM_OUTPUT_CHAR
587 #define ASM_OUTPUT_CHAR(FILE,VALUE) \
588 ( fprintf (FILE, "\tdc.b "), \
589 output_addr_const (FILE, (VALUE)), \
590 fprintf (FILE, "\n"))
592 /* This is how to output an assembler line for a numeric constant byte. */
593 #undef ASM_OUTPUT_BYTE
594 #define ASM_OUTPUT_BYTE(FILE,VALUE) \
595 fprintf (FILE, "\tdc.b $%x\n", (VALUE))
597 /* This is how to output an element of a case-vector that is absolute.
598 (The 68000 does not use such vectors,
599 but we must define this macro anyway.) */
600 #undef ASM_OUTPUT_ADDR_VEC_ELT
601 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
602 asm_fprintf (FILE, "\tdc.l %LL%d\n", VALUE)
604 /* This is how to output an element of a case-vector that is relative. */
605 #undef ASM_OUTPUT_ADDR_DIFF_ELT
606 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
607 asm_fprintf (FILE, "\tdc.w %LL%d-%LL%d\n", VALUE, REL)
609 /* Currently, JUMP_TABLES_IN_TEXT_SECTION must be defined in order to
610 keep switch tables in the text section. */
611 #define JUMP_TABLES_IN_TEXT_SECTION 1
613 /* Output a float value (represented as a C double) as an immediate operand.
614 This macro is a 68k-specific macro. */
615 #undef ASM_OUTPUT_FLOAT_OPERAND
616 #define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
617 do { \
618 if (CODE == 'f') \
620 char dstr[30]; \
621 REAL_VALUE_TO_DECIMAL (VALUE, "%.9g", dstr); \
622 asm_fprintf ((FILE), "%I%s", dstr); \
624 else \
626 long l; \
627 REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
628 if (sizeof (int) == sizeof (long)) \
629 asm_fprintf ((FILE), "%I$%x", l); \
630 else \
631 asm_fprintf ((FILE), "%I$%lx", l); \
633 } while (0)
635 /* Output a double value (represented as a C double) as an immediate operand.
636 This macro is a 68k-specific macro. */
637 #undef ASM_OUTPUT_DOUBLE_OPERAND
638 #define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
639 do { char dstr[30]; \
640 REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
641 asm_fprintf (FILE, "%I%s", dstr); \
642 } while (0)
644 /* Note, long double immediate operands are not actually
645 generated by m68k.md. */
646 #undef ASM_OUTPUT_LONG_DOUBLE_OPERAND
647 #define ASM_OUTPUT_LONG_DOUBLE_OPERAND(FILE,VALUE) \
648 do { char dstr[30]; \
649 REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
650 asm_fprintf (FILE, "%I%s", dstr); \
651 } while (0)
653 #undef ASM_OUTPUT_COMMON
654 #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
655 ( fputs ("\t.comm ", (FILE)), \
656 assemble_name ((FILE), (NAME)), \
657 fprintf ((FILE), ",%u\n", (ROUNDED)))
659 #undef ASM_OUTPUT_LOCAL
660 #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
661 do { \
662 int align = exact_log2 (ROUNDED); \
663 /*fprintf ((FILE), "\tsection 14\n"); */ \
664 data_section (); \
665 ASM_OUTPUT_ALIGN ((FILE), align) \
666 ASM_OUTPUT_LABEL ((FILE), (NAME)); \
667 fprintf ((FILE), "\tdcb.b %u,0\n", (ROUNDED)); \
668 /* fprintf ((FILE), "\tsection 10\n"); */ \
669 } while (0)
671 #undef PRINT_OPERAND_ADDRESS
672 #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
673 { register rtx reg1, reg2, breg, ireg; \
674 register rtx addr = ADDR; \
675 rtx offset; \
676 switch (GET_CODE (addr)) \
678 case REG: \
679 fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
680 break; \
681 case PRE_DEC: \
682 fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
683 break; \
684 case POST_INC: \
685 fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
686 break; \
687 case PLUS: \
688 reg1 = 0; reg2 = 0; \
689 ireg = 0; breg = 0; \
690 offset = 0; \
691 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
693 offset = XEXP (addr, 0); \
694 addr = XEXP (addr, 1); \
696 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
698 offset = XEXP (addr, 1); \
699 addr = XEXP (addr, 0); \
701 if (GET_CODE (addr) != PLUS) ; \
702 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
704 reg1 = XEXP (addr, 0); \
705 addr = XEXP (addr, 1); \
707 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
709 reg1 = XEXP (addr, 1); \
710 addr = XEXP (addr, 0); \
712 else if (GET_CODE (XEXP (addr, 0)) == MULT) \
714 reg1 = XEXP (addr, 0); \
715 addr = XEXP (addr, 1); \
717 else if (GET_CODE (XEXP (addr, 1)) == MULT) \
719 reg1 = XEXP (addr, 1); \
720 addr = XEXP (addr, 0); \
722 else if (GET_CODE (XEXP (addr, 0)) == REG) \
724 reg1 = XEXP (addr, 0); \
725 addr = XEXP (addr, 1); \
727 else if (GET_CODE (XEXP (addr, 1)) == REG) \
729 reg1 = XEXP (addr, 1); \
730 addr = XEXP (addr, 0); \
732 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
733 || GET_CODE (addr) == SIGN_EXTEND) \
734 { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
735 /* for OLD_INDEXING \
736 else if (GET_CODE (addr) == PLUS) \
738 if (GET_CODE (XEXP (addr, 0)) == REG) \
740 reg2 = XEXP (addr, 0); \
741 addr = XEXP (addr, 1); \
743 else if (GET_CODE (XEXP (addr, 1)) == REG) \
745 reg2 = XEXP (addr, 1); \
746 addr = XEXP (addr, 0); \
749 */ \
750 if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
751 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
752 || GET_CODE (reg1) == MULT)) \
753 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
754 { breg = reg2; ireg = reg1; } \
755 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
756 { breg = reg1; ireg = reg2; } \
757 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
758 { int scale = 1; \
759 if (GET_CODE (ireg) == MULT) \
760 { scale = INTVAL (XEXP (ireg, 1)); \
761 ireg = XEXP (ireg, 0); } \
762 if (GET_CODE (ireg) == SIGN_EXTEND) \
763 fprintf (FILE, "(.L%d,pc,%s.w", \
764 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
765 reg_names[REGNO (XEXP (ireg, 0))]); \
766 else \
767 fprintf (FILE, "(.L%d,pc,%s.l", \
768 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
769 reg_names[REGNO (ireg)]); \
770 if (scale != 1) fprintf (FILE, "*%d", scale); \
771 putc (')', FILE); \
772 break; } \
773 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF \
774 && ! (flag_pic && breg == pic_offset_table_rtx)) \
776 fprintf (FILE, "(.L%d,pc,%s.l", \
777 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
778 reg_names[REGNO (breg)]); \
779 putc (')', FILE); \
780 break; } \
781 if (ireg != 0 || breg != 0) \
782 { int scale = 1; \
783 if (breg == 0) \
784 abort (); \
785 putc ('(', FILE); \
786 if (addr != 0) \
788 output_addr_const (FILE, addr); \
789 putc (',', FILE); \
791 fprintf (FILE, "%s", reg_names[REGNO (breg)]); \
792 if (ireg != 0) \
793 putc (',', FILE); \
794 if (ireg != 0 && GET_CODE (ireg) == MULT) \
795 { scale = INTVAL (XEXP (ireg, 1)); \
796 ireg = XEXP (ireg, 0); } \
797 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
798 fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
799 else if (ireg != 0) \
800 fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
801 if (scale != 1) fprintf (FILE, "*%d", scale); \
802 putc (')', FILE); \
803 break; \
805 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
806 { fprintf (FILE, "(.L%d,pc,%s.w)", \
807 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
808 reg_names[REGNO (reg1)]); \
809 break; } \
810 default: \
811 if (GET_CODE (addr) == CONST_INT \
812 && INTVAL (addr) < 0x8000 \
813 && INTVAL (addr) >= -0x8000) \
814 fprintf (FILE, "%d.w", INTVAL (addr)); \
815 else \
816 output_addr_const (FILE, addr); \
820 #endif /* ! use gas */