OSDN Git Service

* config/m68k/3b1.h: Fix comment formatting.
[pf3gnuchains/gcc-fork.git] / gcc / config / m68k / sgs.h
1 /* Definitions of target machine for GNU compiler for m68k targets using
2    assemblers derived from AT&T "SGS" releases.
3    Copyright (C) 1991, 1993, 1996, 2000 Free Software Foundation, Inc.
4    Written by Fred Fish (fnf@cygnus.com)
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 /* Control assembler-syntax conditionals in m68k.md and conditionals in
24    m68k.h.  Note that some systems may also require SGS_SWAP_W and/or
25    SGS_SWITCH_TABLES to be defined as well.  */
26
27 #define MOTOROLA                /* Use Motorola syntax rather than "MIT" */
28 #define SGS                     /* Uses SGS assembler */
29 #define SGS_CMP_ORDER           /* Takes cmp operands in reverse order */
30
31 #include "m68k/m68k.h"
32
33 /* SGS specific assembler pseudo ops.  */
34
35 #define BYTE_ASM_OP             "\t.byte "
36 #define WORD_ASM_OP             "\t.short "
37 #define LONG_ASM_OP             "\t.long "
38 #define SPACE_ASM_OP            "\t.space "
39 #define ALIGN_ASM_OP            "\t.align "
40 #undef GLOBAL_ASM_OP
41 #define GLOBAL_ASM_OP           "\t.global "
42 #define SWBEG_ASM_OP            "\t.swbeg "
43 #define SET_ASM_OP              "\t.set "
44
45 #define UNALIGNED_SHORT_ASM_OP  "\t.short "     /* Used in dwarfout.c */
46 #define UNALIGNED_INT_ASM_OP    "\t.long "              /* Used in dwarfout.c */
47
48 #define ASM_PN_FORMAT           "%s_%d"         /* Format for private names */
49
50 /* Here are four prefixes that are used by asm_fprintf to
51    facilitate customization for alternate assembler syntaxes.
52    Machines with no likelihood of an alternate syntax need not
53    define these and need not use asm_fprintf.  */
54
55 /* The prefix for register names.  Note that REGISTER_NAMES
56    is supposed to include this prefix. Also note that this is NOT an
57    fprintf format string, it is a literal string */
58
59 #undef REGISTER_PREFIX
60 #define REGISTER_PREFIX "%"
61
62 /* The prefix for local (compiler generated) labels.
63    These labels will not appear in the symbol table.  */
64
65 #undef LOCAL_LABEL_PREFIX
66 #define LOCAL_LABEL_PREFIX "."
67
68 /* The prefix to add to user-visible assembler symbols.  */
69
70 #undef USER_LABEL_PREFIX
71 #define USER_LABEL_PREFIX ""
72
73 /* The prefix for immediate operands.  */
74
75 #undef IMMEDIATE_PREFIX
76 #define IMMEDIATE_PREFIX "&"
77
78 /* How to refer to registers in assembler output.
79    This sequence is indexed by compiler's hard-register-number.
80    Motorola format uses different register names than defined in m68k.h.
81    We also take this chance to convert 'a6' to 'fp' */
82
83 #undef REGISTER_NAMES
84
85 #ifndef SUPPORT_SUN_FPA
86
87 #define REGISTER_NAMES \
88 {"%d0",   "%d1",   "%d2",   "%d3",   "%d4",   "%d5",   "%d6",   "%d7",       \
89  "%a0",   "%a1",   "%a2",   "%a3",   "%a4",   "%a5",   "%fp",   "%sp",       \
90  "%fp0",  "%fp1",  "%fp2",  "%fp3",  "%fp4",  "%fp5",  "%fp6",  "%fp7" }
91
92 #else /* SUPPORTED_SUN_FPA */
93
94 #define REGISTER_NAMES \
95 {"%d0",   "%d1",   "%d2",   "%d3",   "%d4",   "%d5",   "%d6",   "%d7",       \
96  "%a0",   "%a1",   "%a2",   "%a3",   "%a4",   "%a5",   "%fp",   "%sp",       \
97  "%fp0",  "%fp1",  "%fp2",  "%fp3",  "%fp4",  "%fp5",  "%fp6",  "%fp7",      \
98  "%fpa0", "%fpa1", "%fpa2", "%fpa3", "%fpa4", "%fpa5", "%fpa6","%fpa7",      \
99  "%fpa8", "%fpa9", "%fpa10","%fpa11","%fpa12","%fpa13","%fpa14","%fpa15",    \
100  "%fpa16","%fpa17","%fpa18","%fpa19","%fpa20","%fpa21","%fpa22","%fpa23",    \
101  "%fpa24","%fpa25","%fpa26","%fpa27","%fpa28","%fpa29","%fpa30","%fpa31" }
102
103 #endif /* defined SUPPORT_SUN_FPA */
104
105 /* This is how to output an assembler line defining an `int' constant.  */
106 /* The SGS assembler doesn't understand ".word".  */
107
108 #undef ASM_OUTPUT_SHORT
109 #define ASM_OUTPUT_SHORT(FILE,VALUE)                    \
110 ( fprintf ((FILE), "%s", WORD_ASM_OP),                  \
111   output_addr_const ((FILE), (VALUE)),                  \
112   fprintf ((FILE), "\n"))
113
114 #undef ASM_OUTPUT_LONG_DOUBLE
115 #define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE)                      \
116 do { long l[3];                                                 \
117      REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l);               \
118      fprintf ((FILE), "%s0x%x,0x%x,0x%x\n", LONG_ASM_OP,        \
119              l[0], l[1], l[2]);                                 \
120    } while (0)
121
122 /* This is how to output an assembler line defining a `double' constant.  */
123
124 #undef ASM_OUTPUT_DOUBLE
125 #define ASM_OUTPUT_DOUBLE(FILE,VALUE)                   \
126 do { long l[2];                                         \
127      REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l);            \
128      fprintf ((FILE), "%s0x%x,0x%x\n", LONG_ASM_OP,     \
129               l[0], l[1]);                              \
130    } while (0)
131
132 /* This is how to output an assembler line defining a `float' constant.  */
133
134 #undef ASM_OUTPUT_FLOAT
135 #define ASM_OUTPUT_FLOAT(FILE,VALUE)                    \
136 do { long l;                                            \
137      REAL_VALUE_TO_TARGET_SINGLE (VALUE, l);            \
138      fprintf ((FILE), "%s0x%x\n", LONG_ASM_OP, l);      \
139    } while (0)
140
141 /* This is how to output an assembler line that says to advance the
142    location counter to a multiple of 2**LOG bytes.  */
143
144 #undef ASM_OUTPUT_ALIGN
145 #define ASM_OUTPUT_ALIGN(FILE,LOG)                              \
146   if ((LOG) > 0)                                                \
147     fprintf ((FILE), "%s%u\n", ALIGN_ASM_OP, 1 << (LOG));       \
148   else if ((LOG) > 31)                                          \
149     abort ();
150
151 /* The routine used to output null terminated string literals.  We cannot
152    use the ".string" pseudo op, because it silently truncates strings to
153    1023 bytes.  There is no "partial string op" which works like ".string"
154    but doesn't append a null byte, so we can't chop the input string up
155    into small pieces and use that.  Our only remaining alternative is to
156    output the string one byte at a time.  */
157
158 #define ASM_OUTPUT_ASCII(FILE,PTR,LEN)                          \
159 do {                                                            \
160   register int sp = 0, lp = 0, ch;                              \
161   fprintf ((FILE), "%s", BYTE_ASM_OP);                          \
162   do {                                                          \
163     ch = (PTR)[sp];                                             \
164     if (ch > ' ' && ! (ch & 0x80) && ch != '\\')                \
165       {                                                         \
166         fprintf ((FILE), "'%c", ch);                            \
167       }                                                         \
168     else                                                        \
169       {                                                         \
170         fprintf ((FILE), "0x%x", ch);                           \
171       }                                                         \
172     if (++sp < (LEN))                                           \
173       {                                                         \
174         if ((sp % 10) == 0)                                     \
175           {                                                     \
176             fprintf ((FILE), "\n%s", BYTE_ASM_OP);              \
177           }                                                     \
178         else                                                    \
179           {                                                     \
180             putc (',', (FILE));                                 \
181           }                                                     \
182       }                                                         \
183   } while (sp < (LEN));                                         \
184   putc ('\n', (FILE));                                          \
185 } while (0)
186
187
188 /* SGS based assemblers don't understand #NO_APP and #APP, so just don't
189    bother emitting them.  */
190
191 #undef ASM_APP_ON
192 #define ASM_APP_ON ""
193
194 #undef ASM_APP_OFF
195 #define ASM_APP_OFF ""
196
197 /* When using SGS derived assemblers, change the "MIT" or "MOTOROLA"
198    to "SGS/AT&T"  */
199
200 #undef TARGET_VERSION
201 #define TARGET_VERSION fprintf (stderr, " (68k, SGS/AT&T syntax)");
202
203 /* Use proper assembler syntax for these macros.  */
204 #undef ASM_OUTPUT_REG_PUSH
205 #define ASM_OUTPUT_REG_PUSH(FILE,REGNO)  \
206   asm_fprintf (FILE, "\t%Omove.l %s,-(%Rsp)\n", reg_names[REGNO])
207
208 #undef ASM_OUTPUT_REG_POP
209 #define ASM_OUTPUT_REG_POP(FILE,REGNO)  \
210   asm_fprintf (FILE, "\t%Omove.l (%Rsp)+,%s\n", reg_names[REGNO])
211
212 #undef ASM_OUTPUT_FLOAT_OPERAND
213 #define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE)       \
214   do { long l;                                          \
215        REAL_VALUE_TO_TARGET_SINGLE (VALUE, l);          \
216        asm_fprintf ((FILE), "%I0x%x", l);               \
217      } while (0)
218   
219 #undef ASM_OUTPUT_DOUBLE_OPERAND
220 #define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE)           \
221   do { long l[2];                                       \
222        REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l);          \
223        asm_fprintf ((FILE), "%I0x%x%08x", l[0], l[1]);  \
224      } while (0)
225
226 /* How to output a block of SIZE zero bytes.  Note that the `space' pseudo,
227    when used in the text segment, causes SGS assemblers to output nop insns
228    rather than 0s, so we set ASM_NO_SKIP_IN_TEXT to prevent this.  */
229
230 #define ASM_NO_SKIP_IN_TEXT 1
231
232 #undef ASM_OUTPUT_SKIP
233 #define ASM_OUTPUT_SKIP(FILE,SIZE)  \
234   fprintf (FILE, "%s%u\n", SPACE_ASM_OP, (SIZE))
235 \f
236 /* Translate Motorola opcodes such as `jbeq' into SGS opcodes such
237    as `beq.w'.
238    Delete the `e' in `move...' and `fmove'.
239    Change `ftst' to `ftest'.
240    Change `fbne' to `fbneq'
241    Change `fsne' to `fsneq'
242    Change `divsl' to `tdivs' (32/32 -> 32r:32q)
243    Change `divul' to `tdivu' (32/32 -> 32r:32q)
244    Optionally change swap to swap.w.
245    */
246
247 #ifdef SGS_SWAP_W
248 #define ASM_OUTPUT_OPCODE(FILE, PTR)                    \
249 {                                                       \
250   extern int flag_pic;                                  \
251   if (!strncmp ((PTR), "jbsr", 4))                      \
252     { if (flag_pic)                                     \
253         fprintf ((FILE), "bsr");                        \
254       else                                              \
255         fprintf ((FILE), "jsr");                        \
256     (PTR) += 4; }                                       \
257   else if ((PTR)[0] == 'j' && (PTR)[1] == 'b')          \
258     { ++(PTR);                                          \
259       while (*(PTR) != ' ')                             \
260         { putc (*(PTR), (FILE)); ++(PTR); }             \
261       fprintf ((FILE), ".w"); }                         \
262   else if ((PTR)[0] == 's')                             \
263     {                                                   \
264       if (!strncmp ((PTR), "swap", 4))                  \
265         { fprintf ((FILE), "swap.w"); (PTR) += 4; }     \
266     }                                                   \
267 /* FMOVE ==> FMOV, (and F%& F%$ translations) */        \
268   else if ((PTR)[0] == 'f')                             \
269     {                                                   \
270       if (!strncmp ((PTR), "fmove", 5))                 \
271         { fprintf ((FILE), "fmov"); (PTR) += 5; }       \
272       else if (!strncmp ((PTR), "ftst", 4))             \
273         { fprintf ((FILE), "ftest"); (PTR) += 4; }      \
274       else if (!strncmp ((PTR), "fbne", 4))             \
275         { fprintf ((FILE), "fbneq"); (PTR) += 4; }      \
276       else if (!strncmp ((PTR), "fsne", 4))             \
277         { fprintf ((FILE), "fsneq"); (PTR) += 4; }      \
278       else if (!strncmp ((PTR), "f%$move", 7))          \
279         { (PTR) += 7;                                   \
280           if (TARGET_68040_ONLY)                        \
281             fprintf ((FILE), "fsmov");                  \
282           else fprintf ((FILE), "fmov"); }              \
283       else if (!strncmp ((PTR), "f%&move", 7))          \
284         { (PTR) += 7;                                   \
285           if (TARGET_68040_ONLY)                        \
286             fprintf ((FILE), "fdmov");                  \
287           else fprintf ((FILE), "fmov"); }              \
288     }                                                   \
289 /* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV    */              \
290   else if ((PTR)[0] == 'm' && (PTR)[1] == 'o'           \
291            && (PTR)[2] == 'v' && (PTR)[3] == 'e')       \
292     { fprintf ((FILE), "mov"); (PTR) += 4;              \
293        if ((PTR)[0] == 'q' || (PTR)[0] == 'a'           \
294            || (PTR)[0] == 'c') (PTR)++; }               \
295 /* SUB, SUBQ, SUBA, SUBI ==> SUB */                     \
296   else if ((PTR)[0] == 's' && (PTR)[1] == 'u'           \
297            && (PTR)[2] == 'b')                          \
298     { fprintf ((FILE), "sub"); (PTR) += 3;              \
299        if ((PTR)[0] == 'q' || (PTR)[0] == 'i'           \
300            || (PTR)[0] == 'a') (PTR)++; }               \
301 /* CMP, CMPA, CMPI, CMPM ==> CMP        */              \
302   else if ((PTR)[0] == 'c' && (PTR)[1] == 'm'           \
303            && (PTR)[2] == 'p')                          \
304     { fprintf ((FILE), "cmp"); (PTR) += 3;              \
305        if ((PTR)[0] == 'a' || (PTR)[0] == 'i'           \
306            || (PTR)[0] == 'm') (PTR)++; }               \
307 /* DIVSL ==> TDIVS */                                   \
308   else if ((PTR)[0] == 'd' && (PTR)[1] == 'i'           \
309            && (PTR)[2] == 'v' && (PTR)[3] == 's'        \
310            && (PTR)[4] == 'l')                          \
311     { fprintf ((FILE), "tdivs"); (PTR) += 5; }          \
312 /* DIVUL ==> TDIVU */                                   \
313   else if ((PTR)[0] == 'd' && (PTR)[1] == 'i'           \
314            && (PTR)[2] == 'v' && (PTR)[3] == 'u'        \
315            && (PTR)[4] == 'l')                          \
316     { fprintf ((FILE), "tdivu"); (PTR) += 5; }          \
317 }
318
319 #else /* not SGS_SWAP_W */
320
321 #define ASM_OUTPUT_OPCODE(FILE, PTR)                    \
322 {                                                       \
323   extern int flag_pic;                                  \
324   if (!strncmp ((PTR), "jbsr", 4))                      \
325     { if (flag_pic)                                     \
326         fprintf ((FILE), "bsr");                        \
327       else                                              \
328         fprintf ((FILE), "jsr");                        \
329     (PTR) += 4; }                                       \
330   else if ((PTR)[0] == 'j' && (PTR)[1] == 'b')          \
331     { ++(PTR);                                          \
332       while (*(PTR) != ' ')                             \
333         { putc (*(PTR), (FILE)); ++(PTR); }             \
334       fprintf ((FILE), ".w"); }                         \
335 /* FMOVE ==> FMOV, (and F%& F%$ translations) */        \
336   else if ((PTR)[0] == 'f')                             \
337     {                                                   \
338       if (!strncmp ((PTR), "fmove", 5))                 \
339         { fprintf ((FILE), "fmov"); (PTR) += 5; }       \
340       else if (!strncmp ((PTR), "ftst", 4))             \
341         { fprintf ((FILE), "ftest"); (PTR) += 4; }      \
342       else if (!strncmp ((PTR), "fbne", 4))             \
343         { fprintf ((FILE), "fbneq"); (PTR) += 4; }      \
344       else if (!strncmp ((PTR), "fsne", 4))             \
345         { fprintf ((FILE), "fsneq"); (PTR) += 4; }      \
346       else if (!strncmp ((PTR), "f%$move", 7))          \
347         { (PTR) += 7;                                   \
348           if (TARGET_68040_ONLY)                        \
349             fprintf ((FILE), "fsmov");                  \
350           else fprintf ((FILE), "fmov"); }              \
351       else if (!strncmp ((PTR), "f%&move", 7))          \
352         { (PTR) += 7;                                   \
353           if (TARGET_68040_ONLY)                        \
354             fprintf ((FILE), "fdmov");                  \
355           else fprintf ((FILE), "fmov"); }              \
356     }                                                   \
357 /* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV    */              \
358   else if ((PTR)[0] == 'm' && (PTR)[1] == 'o'           \
359            && (PTR)[2] == 'v' && (PTR)[3] == 'e')       \
360     { fprintf ((FILE), "mov"); (PTR) += 4;              \
361        if ((PTR)[0] == 'q' || (PTR)[0] == 'a'           \
362            || (PTR)[0] == 'c') (PTR)++; }               \
363 /* SUB, SUBQ, SUBA, SUBI ==> SUB */                     \
364   else if ((PTR)[0] == 's' && (PTR)[1] == 'u'           \
365            && (PTR)[2] == 'b')                          \
366     { fprintf ((FILE), "sub"); (PTR) += 3;              \
367        if ((PTR)[0] == 'q' || (PTR)[0] == 'i'           \
368            || (PTR)[0] == 'a') (PTR)++; }               \
369 /* CMP, CMPA, CMPI, CMPM ==> CMP        */              \
370   else if ((PTR)[0] == 'c' && (PTR)[1] == 'm'           \
371            && (PTR)[2] == 'p')                          \
372     { fprintf ((FILE), "cmp"); (PTR) += 3;              \
373        if ((PTR)[0] == 'a' || (PTR)[0] == 'i'           \
374            || (PTR)[0] == 'm') (PTR)++; }               \
375 /* DIVSL ==> TDIVS */                                   \
376   else if ((PTR)[0] == 'd' && (PTR)[1] == 'i'           \
377            && (PTR)[2] == 'v' && (PTR)[3] == 's'        \
378            && (PTR)[4] == 'l')                          \
379     { fprintf ((FILE), "tdivs"); (PTR) += 5; }          \
380 /* DIVUL ==> TDIVU */                                   \
381   else if ((PTR)[0] == 'd' && (PTR)[1] == 'i'           \
382            && (PTR)[2] == 'v' && (PTR)[3] == 'u'        \
383            && (PTR)[4] == 'l')                          \
384     { fprintf ((FILE), "tdivu"); (PTR) += 5; }          \
385 }
386
387 #endif /* not SGS_SWAP_W */
388 \f
389 /* This macro outputs the label at the start of a switch table.  The
390    ".swbeg <N>" is an assembler directive that causes the switch table
391    size to be inserted into the object code so that disassemblers, for
392    example, can identify that it is the start of a switch table.  */
393
394 #define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE)             \
395   fprintf ((FILE), "%s&%d\n", SWBEG_ASM_OP, XVECLEN (PATTERN (TABLE), 1));
396
397 #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE)                    \
398   do {                                                                  \
399     ASM_OUTPUT_BEFORE_CASE_LABEL((FILE),(PREFIX),(NUM),(TABLE));        \
400     ASM_OUTPUT_INTERNAL_LABEL((FILE),(PREFIX),(NUM));                   \
401   } while (0)
402
403 /* At end of a switch table, define LDnnn iff the symbol LInnn was defined.
404    Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
405    fails to assemble.  Luckily "LDnnn(pc,d0.l*2)" produces the results
406    we want.  This difference can be accommodated by making the assembler
407    define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
408    string, as necessary.  This is accomplished via the ASM_OUTPUT_CASE_END
409    macro.  */
410
411 #undef ASM_OUTPUT_CASE_END
412 #define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE)             \
413 { if (switch_table_difference_label_flag)               \
414     asm_fprintf (FILE, "%s%LLD%d,%LL%d-%LLI%d-2.b\n",\
415                  SET_ASM_OP, (NUM), (NUM), (NUM));      \
416   switch_table_difference_label_flag = 0; }
417
418 extern int switch_table_difference_label_flag;
419
420 /* This is how to output an element of a case-vector that is relative.  */
421
422 #undef ASM_OUTPUT_ADDR_DIFF_ELT
423 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)        \
424   asm_fprintf (FILE, "%s%LL%d-%LL%d\n", WORD_ASM_OP, VALUE, REL)
425
426 /* Currently, JUMP_TABLES_IN_TEXT_SECTION must be defined in order to
427    keep switch tables in the text section.  */
428    
429 #define JUMP_TABLES_IN_TEXT_SECTION 1
430
431 /* Store in OUTPUT a string (made with alloca) containing
432    an assembler-name for a local static variable named NAME.
433    LABELNO is an integer which is different for each call.  */
434
435 #undef ASM_FORMAT_PRIVATE_NAME
436 #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO)  \
437 ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10),    \
438   sprintf ((OUTPUT), ASM_PN_FORMAT, (NAME), (LABELNO)))
439