OSDN Git Service

Change FSF address.
[pf3gnuchains/gcc-fork.git] / gcc / config / m68k / tower-as.h
1 /* Definitions of target machine for GNU compiler.
2    For NCR Tower 32/4x0 and 32/6x0 running System V Release 3.
3    Copyright (C) 1990, 1993, 1994 Free Software Foundation, Inc.
4    Written by Robert Andersson (ra@intsys.no), International Systems,
5    Oslo, Norway.
6
7    This file outputs assembler source suitable for the native Tower as
8    and with sdb debugging symbols.  See tower.h for more comments.
9
10    This file was based on m68k.h, hp320.h and 3b1.h as of the 1.37.1 version.
11
12 This file is part of GNU CC.
13
14 GNU CC is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2, or (at your option)
17 any later version.
18
19 GNU CC is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with GNU CC; see the file COPYING.  If not, write to
26 the Free Software Foundation, 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA.  */
28
29
30 #include "m68k/tower.h"
31 #undef SELECT_RTX_SECTION
32
33 /* Use default settings for system V.3.  */
34
35 #include "svr3.h"
36
37 /* Names to predefine in the preprocessor for this target machine.  */
38
39 #define CPP_PREDEFINES "-Dunix -Dtower32 -Dtower32_600 -D__motorola__ -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
40
41 /* Define __HAVE_68881 in preprocessor only if -m68881 is specified.
42    This will control the use of inline 68881 insns in certain macros.
43    Also, define special define used to identify the Tower assembler.  */
44
45 #define CPP_SPEC "-D__TOWER_ASM__ %{m68881:-D__HAVE_68881__}"
46
47 /* We don't want local labels to start with period.
48    See ASM_OUTPUT_INTERNAL_LABEL.  */
49 #undef LOCAL_LABEL_PREFIX
50 #define LOCAL_LABEL_PREFIX ""
51
52 /* These four macros control how m68k.md is expanded.  */
53
54 #define MOTOROLA                /* Use Motorola syntax rather than "MIT" */
55 #define SGS                     /* Uses SGS assembler */
56 #define SGS_CMP_ORDER           /* Takes cmp operands in reverse order */
57 #define SGS_NO_LI               /* Suppress jump table label usage */
58
59 /* Turn on SDB debugging info.  */
60
61 #define SDB_DEBUGGING_INFO
62
63 /* This is only useful if gdb is changed, but doesn't harm anyway.  */
64
65 #define ASM_IDENTIFY_GCC(FILE) \
66   fprintf (FILE, "gcc2_compiled%%:\n")
67
68 /* All the ASM_OUTPUT macros need to conform to the Tower as syntax.  */
69
70 #define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
71   do {                                             \
72     fprintf (FILE, "\tfile\t");                    \
73     output_quoted_string (FILE, FILENAME);         \
74     fprintf (FILE, "\n");                          \
75     fprintf (FILE, "section ~init,\"x\"\n");       \
76     fprintf (FILE, "section ~fini,\"x\"\n");       \
77     fprintf (FILE, "section ~rodata,\"x\"\n");   \
78     fprintf (FILE, "text\n");                      \
79   } while (0)
80
81 #define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO)    \
82   fprintf (FILE, "\tln\t%d\n",                  \
83            (sdb_begin_function_line             \
84             ? last_linenum - sdb_begin_function_line : 1))
85
86 #undef ASM_OUTPUT_IDENT
87 #define ASM_OUTPUT_IDENT(FILE, NAME) \
88   fprintf (FILE, "\tident\t\"%s\" \n", NAME)
89
90 #define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
91   do { register int sp = 0, lp = 0; \
92     fprintf ((FILE), "\tbyte\t"); \
93   loop: \
94     if ((PTR)[sp] > ' ' && ! ((PTR)[sp] & 0x80) && (PTR)[sp] != '\\') \
95       { lp += 3; \
96         fprintf ((FILE), "'%c", (PTR)[sp]); } \
97     else \
98       { lp += 5; \
99         fprintf ((FILE), "0x%x", (PTR)[sp]); } \
100     if (++sp < (LEN)) \
101       { if (lp > 60) \
102           { lp = 0; \
103             fprintf ((FILE), "\n\tbyte\t"); }   \
104         else \
105           putc (',', (FILE)); \
106         goto loop; } \
107     putc ('\n', (FILE)); } while (0)
108
109 /* Translate Motorola opcodes such as `jbeq'
110    into SGS/Tower opcodes such as `beq.w'.
111    Change `move' to `mov'.
112    Change `cmpm' to `cmp'.
113    Change `divsl' to `tdivs'.
114    Change `divul' to `tdivu'.
115    Change `ftst' to `ftest'.
116    Change `fmove' to `fmov'.  */
117
118 #define ASM_OUTPUT_OPCODE(FILE, PTR)                    \
119 { if ((PTR)[0] == 'j' && (PTR)[1] == 'b')               \
120     { ++(PTR);                                          \
121       while (*(PTR) != ' ')                             \
122         { putc (*(PTR), (FILE)); ++(PTR); }             \
123       fprintf ((FILE), ".w"); }                         \
124   else if ((PTR)[0] == 'm' && (PTR)[1] == 'o'           \
125            && (PTR)[2] == 'v' && (PTR)[3] == 'e')       \
126     { fprintf ((FILE), "mov"); (PTR) += 4; }            \
127   else if ((PTR)[0] == 'c' && (PTR)[1] == 'm'           \
128            && (PTR)[2] == 'p' && (PTR)[3] == 'm')       \
129     { fprintf ((FILE), "cmp"); (PTR) += 4; }            \
130   else if ((PTR)[0] == 'd' && (PTR)[1] == 'i'           \
131            && (PTR)[2] == 'v' && (PTR)[3] == 's'        \
132            && (PTR)[4] == 'l')                          \
133     { fprintf ((FILE), "tdivs"); (PTR) += 5; }          \
134   else if ((PTR)[0] == 'd' && (PTR)[1] == 'i'           \
135            && (PTR)[2] == 'v' && (PTR)[3] == 'u'        \
136            && (PTR)[4] == 'l')                          \
137     { fprintf ((FILE), "tdivu"); (PTR) += 5; }          \
138   else if ((PTR)[0] == 'f' && (PTR)[1] == 't'           \
139            && (PTR)[2] == 's' && (PTR)[3] == 't')       \
140     { fprintf ((FILE), "ftest"); (PTR) += 4; }          \
141   else if ((PTR)[0] == 'f' && (PTR)[1] == 'm'           \
142            && (PTR)[2] == 'o' && (PTR)[3] == 'v'        \
143            && (PTR)[4] == 'e')                          \
144     { fprintf ((FILE), "fmov"); (PTR) += 5; }           \
145 }
146
147
148 \f
149 /* Override parts of m68k.h to fit the Tower assembler.
150    This section needs to track changes done to m68k.h in the future.  */
151
152 #undef TARGET_VERSION
153 #define TARGET_VERSION fprintf (stderr, " (68k, Motorola/SGS/Tower32 syntax)");
154
155 #undef FUNCTION_BLOCK_PROFILER
156 #define FUNCTION_BLOCK_PROFILER(FILE, LABELNO)                          \
157   do {                                                                  \
158     char label1[20], label2[20];                                        \
159     ASM_GENERATE_INTERNAL_LABEL (label1, "LPBX", 0);                    \
160     ASM_GENERATE_INTERNAL_LABEL (label2, "LPI", LABELNO);               \
161     fprintf (FILE, "\ttst.l %s\n\tbne %s\n\tpea %s\n\tjsr __bb_init_func\n\taddq.l &4,%%sp\n",  \
162              label1, label2, label1);                                   \
163     ASM_OUTPUT_INTERNAL_LABEL (FILE, "LPI", LABELNO);                   \
164     putc ('\n', FILE);                                          \
165     } while (0)
166
167 #undef BLOCK_PROFILER
168 #define BLOCK_PROFILER(FILE, BLOCKNO)                           \
169   do {                                                          \
170     char label[20];                                             \
171     ASM_GENERATE_INTERNAL_LABEL (label, "LPBX", 2);             \
172     fprintf (FILE, "\taddq.l &1,%s+%d\n", label, 4 * BLOCKNO);  \
173     } while (0)
174
175 #undef FUNCTION_PROFILER
176 #define FUNCTION_PROFILER(FILE, LABEL_NO)       \
177     fprintf (FILE, "\tmov.l &LP%%%d,%%a0\n\tjsr mcount%%\n", (LABEL_NO))
178
179 #undef FUNCTION_EXTRA_EPILOGUE
180 #define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE)                             \
181   { extern int current_function_returns_pointer;                        \
182     if ((current_function_returns_pointer) &&                           \
183       ! find_equiv_reg (0, get_last_insn (), 0, 0, 0, 8, Pmode))        \
184       asm_fprintf (FILE, "\tmov.l %Rd0,%Ra0\n"); } 
185
186 /* This is how to output an insn to push a register on the stack.
187    It need not be very fast code.  */
188
189 #undef ASM_OUTPUT_REG_PUSH
190 #define ASM_OUTPUT_REG_PUSH(FILE,REGNO)  \
191   fprintf (FILE, "\tmov.l %s,-(%%sp)\n", reg_names[REGNO])
192
193 /* This is how to output an insn to pop a register from the stack.
194    It need not be very fast code.  */
195
196 #undef ASM_OUTPUT_REG_POP
197 #define ASM_OUTPUT_REG_POP(FILE,REGNO)  \
198   fprintf (FILE, "\tmov.l (%%sp)+,%s\n", reg_names[REGNO])
199
200 #undef ASM_FILE_START
201 #define ASM_FILE_START(FILE) \
202 ( fprintf (FILE, "#NO_APP\n"), \
203   output_file_directive ((FILE), main_input_filename))
204
205 #undef TEXT_SECTION_ASM_OP
206 #define TEXT_SECTION_ASM_OP "text"
207
208 #undef DATA_SECTION_ASM_OP
209 #define DATA_SECTION_ASM_OP "data"
210
211 /* This says how to output an assembler line to define a global common symbol.
212    We use SIZE rather than ROUNDED, as this is what the native cc does.  */
213
214 #undef ASM_OUTPUT_COMMON
215 #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED)  \
216 ( fputs ("\tcomm ", (FILE)),                    \
217   assemble_name ((FILE), (NAME)),               \
218   fprintf ((FILE), ",%d\n", ((SIZE) == 0) ? (ROUNDED) : (SIZE)))
219
220 /* This says how to output an assembler line to define a local common symbol.
221    We use SIZE rather than ROUNDED, as this is what the native cc does.  */
222
223 #undef ASM_OUTPUT_LOCAL
224 #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)  \
225 ( fputs ("\tlcomm ", (FILE)),                   \
226   assemble_name ((FILE), (NAME)),               \
227   fprintf ((FILE), ",%d\n", ((SIZE) == 0) ? (ROUNDED) : (SIZE)))
228
229 /* Store in OUTPUT a string (made with alloca) containing
230    an assembler-name for a local static variable named NAME.
231    LABELNO is an integer which is different for each call.  */
232
233 #undef ASM_FORMAT_PRIVATE_NAME
234 #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO)  \
235 ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 11),    \
236   sprintf ((OUTPUT), "%s%%%%%d", (NAME), (LABELNO)))
237  
238 /* This is the command to make the user-level label named NAME
239    defined for reference from other files.  */
240
241 #undef GLOBAL_ASM_OP
242 #define GLOBAL_ASM_OP "global"
243
244 #undef ASM_GENERATE_INTERNAL_LABEL
245 #define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
246   sprintf ((LABEL), "%s%%%d", (PREFIX), (NUM))
247
248 #undef ASM_OUTPUT_INTERNAL_LABEL
249 #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM)      \
250   fprintf ((FILE), "%s%%%d:\n", (PREFIX), (NUM))
251
252 #undef ASM_OUTPUT_CASE_LABEL
253 #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE)                    \
254   fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n",                              \
255            XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM));              \
256
257 #undef ASM_OUTPUT_DOUBLE
258 #define ASM_OUTPUT_DOUBLE(FILE,VALUE)  \
259 do { long l[2];                                         \
260      REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l);            \
261      fprintf (FILE, "\tlong 0x%x,0x%x\n", l[0], l[1]); \
262    } while (0)
263
264 #undef ASM_OUTPUT_LONG_DOUBLE
265 #define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE)                              \
266 do { long l[3];                                                         \
267      REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l);                       \
268      fprintf (FILE, "\tlong 0x%x,0x%x,0x%x\n", l[0], l[1], l[2]);       \
269    } while (0)
270
271 #undef ASM_OUTPUT_FLOAT
272 #define ASM_OUTPUT_FLOAT(FILE,VALUE)  \
273 do { long l;                                    \
274      REAL_VALUE_TO_TARGET_SINGLE (VALUE, l);    \
275      fprintf ((FILE), "\tlong 0x%x\n", l);      \
276    } while (0)
277
278 /* This is how to output an assembler line defining an `int' constant.  */
279
280 #undef ASM_OUTPUT_INT
281 #define ASM_OUTPUT_INT(FILE,VALUE)  \
282 ( fprintf (FILE, "\tlong "),                    \
283   output_addr_const (FILE, (VALUE)),            \
284   fprintf (FILE, "\n"))
285
286 /* Likewise for `char' and `short' constants.  */
287
288 #undef ASM_OUTPUT_SHORT
289 #define ASM_OUTPUT_SHORT(FILE,VALUE)  \
290 ( fprintf (FILE, "\tshort "),                   \
291   output_addr_const (FILE, (VALUE)),            \
292   fprintf (FILE, "\n"))
293
294 #undef ASM_OUTPUT_CHAR
295 #define ASM_OUTPUT_CHAR(FILE,VALUE)  \
296 ( fprintf (FILE, "\tbyte "),                    \
297   output_addr_const (FILE, (VALUE)),            \
298   fprintf (FILE, "\n"))
299
300 /* This is how to output an assembler line for a numeric constant byte.  */
301
302 #undef ASM_OUTPUT_BYTE
303 #define ASM_OUTPUT_BYTE(FILE,VALUE)  \
304   fprintf (FILE, "\tbyte 0x%x\n", (VALUE))
305
306 #undef ASM_OUTPUT_ADDR_VEC_ELT
307 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)  \
308   fprintf (FILE, "\tlong L%%%d\n", (VALUE))
309
310 #undef ASM_OUTPUT_ADDR_DIFF_ELT
311 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  \
312   fprintf (FILE, "\tshort L%%%d-L%%%d\n", (VALUE), (REL))
313
314 #undef ASM_OUTPUT_ALIGN
315 #define ASM_OUTPUT_ALIGN(FILE,LOG)      \
316   if ((LOG) == 1)                       \
317     fprintf (FILE, "\teven\n");         \
318   else if ((LOG) != 0)                  \
319     abort ();
320
321 #undef ASM_OUTPUT_SKIP
322 #define ASM_OUTPUT_SKIP(FILE,SIZE)  \
323   fprintf (FILE, "\tspace %d\n", (SIZE))
324
325 #undef PRINT_OPERAND
326 #define PRINT_OPERAND(FILE, X, CODE)  \
327 { if (CODE == '.') fprintf (FILE, ".");                                 \
328   else if (CODE == '#') fprintf (FILE, "&");                            \
329   else if (CODE == '-') fprintf (FILE, "-(%%sp)");                      \
330   else if (CODE == '+') fprintf (FILE, "(%%sp)+");                      \
331   else if (CODE == '@') fprintf (FILE, "(%%sp)");                       \
332   else if (CODE == '!') fprintf (FILE, "%%fpcr");                       \
333   else if (CODE == '/')                                                 \
334     fprintf (FILE, "%%");                                               \
335   else if (CODE == '$') { if (TARGET_68040_ONLY) fprintf (FILE, "s"); } \
336   else if (CODE == '&') { if (TARGET_68040_ONLY) fprintf (FILE, "d"); } \
337   else if (GET_CODE (X) == REG)                                         \
338     fprintf (FILE, "%s", reg_names[REGNO (X)]);                         \
339   else if (GET_CODE (X) == MEM)                                         \
340     output_address (XEXP (X, 0));                                       \
341   else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode)      \
342     { REAL_VALUE_TYPE r; long l;                                        \
343       REAL_VALUE_FROM_CONST_DOUBLE (r, X);                              \
344       REAL_VALUE_TO_TARGET_SINGLE (r, l);                               \
345       fprintf (FILE, "&0x%x", l); }                                     \
346   else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode)      \
347     { REAL_VALUE_TYPE r; int i[2];                                      \
348       REAL_VALUE_FROM_CONST_DOUBLE (r, X);                              \
349       REAL_VALUE_TO_TARGET_DOUBLE (r, i);                               \
350       fprintf (FILE, "&0x%x%08x", i[0], i[1]); }                        \
351   else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == XFmode)      \
352     { REAL_VALUE_TYPE r;                                                \
353       REAL_VALUE_FROM_CONST_DOUBLE (r, X);                              \
354       ASM_OUTPUT_LONG_DOUBLE_OPERAND (FILE, r); }                       \
355   else { putc ('&', FILE); output_addr_const (FILE, X); }}
356
357 /* Note that this contains a kludge that knows that the only reason
358    we have an address (plus (label_ref...) (reg...))
359    is in the insn before a tablejump, and we know that the table is
360    exactly 10 bytes away.  */
361
362 #undef PRINT_OPERAND_ADDRESS
363 #define PRINT_OPERAND_ADDRESS(FILE, ADDR)  \
364 { register rtx reg1, reg2, breg, ireg;                                  \
365   register rtx addr = ADDR;                                             \
366   rtx offset;                                                           \
367   switch (GET_CODE (addr))                                              \
368     {                                                                   \
369     case REG:                                                           \
370       fprintf (FILE, "(%s)", reg_names[REGNO (addr)]);                  \
371       break;                                                            \
372     case PRE_DEC:                                                       \
373       fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);       \
374       break;                                                            \
375     case POST_INC:                                                      \
376       fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);       \
377       break;                                                            \
378     case PLUS:                                                          \
379       reg1 = 0; reg2 = 0;                                               \
380       ireg = 0; breg = 0;                                               \
381       offset = 0;                                                       \
382       if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))                          \
383         {                                                               \
384           offset = XEXP (addr, 0);                                      \
385           addr = XEXP (addr, 1);                                        \
386         }                                                               \
387       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))                     \
388         {                                                               \
389           offset = XEXP (addr, 1);                                      \
390           addr = XEXP (addr, 0);                                        \
391         }                                                               \
392       if (GET_CODE (addr) != PLUS) ;                                    \
393       else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)                \
394         {                                                               \
395           reg1 = XEXP (addr, 0);                                        \
396           addr = XEXP (addr, 1);                                        \
397         }                                                               \
398       else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)                \
399         {                                                               \
400           reg1 = XEXP (addr, 1);                                        \
401           addr = XEXP (addr, 0);                                        \
402         }                                                               \
403       else if (GET_CODE (XEXP (addr, 0)) == MULT)                       \
404         {                                                               \
405           reg1 = XEXP (addr, 0);                                        \
406           addr = XEXP (addr, 1);                                        \
407         }                                                               \
408       else if (GET_CODE (XEXP (addr, 1)) == MULT)                       \
409         {                                                               \
410           reg1 = XEXP (addr, 1);                                        \
411           addr = XEXP (addr, 0);                                        \
412         }                                                               \
413       else if (GET_CODE (XEXP (addr, 0)) == REG)                        \
414         {                                                               \
415           reg1 = XEXP (addr, 0);                                        \
416           addr = XEXP (addr, 1);                                        \
417         }                                                               \
418       else if (GET_CODE (XEXP (addr, 1)) == REG)                        \
419         {                                                               \
420           reg1 = XEXP (addr, 1);                                        \
421           addr = XEXP (addr, 0);                                        \
422         }                                                               \
423       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT             \
424           || GET_CODE (addr) == SIGN_EXTEND)                            \
425         { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; }     \
426 /*  for OLD_INDEXING                                                    \
427       else if (GET_CODE (addr) == PLUS)                                 \
428         {                                                               \
429           if (GET_CODE (XEXP (addr, 0)) == REG)                         \
430             {                                                           \
431               reg2 = XEXP (addr, 0);                                    \
432               addr = XEXP (addr, 1);                                    \
433             }                                                           \
434           else if (GET_CODE (XEXP (addr, 1)) == REG)                    \
435             {                                                           \
436               reg2 = XEXP (addr, 1);                                    \
437               addr = XEXP (addr, 0);                                    \
438             }                                                           \
439         }                                                               \
440   */                                                                    \
441       if (offset != 0) { if (addr != 0) abort (); addr = offset; }      \
442       if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND                      \
443                     || GET_CODE (reg1) == MULT))                        \
444           || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))         \
445         { breg = reg2; ireg = reg1; }                                   \
446       else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))         \
447         { breg = reg1; ireg = reg2; }                                   \
448       if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF)       \
449         { int scale = 1;                                                \
450           if (GET_CODE (ireg) == MULT)                                  \
451             { scale = INTVAL (XEXP (ireg, 1));                          \
452               ireg = XEXP (ireg, 0); }                                  \
453           if (GET_CODE (ireg) == SIGN_EXTEND)                           \
454             fprintf (FILE, "10(%%pc,%s.w",                              \
455                      reg_names[REGNO (XEXP (ireg, 0))]);                \
456           else                                                          \
457             fprintf (FILE, "10(%%pc,%s.l",                              \
458                      reg_names[REGNO (ireg)]);                          \
459           if (scale != 1) fprintf (FILE, "*%d", scale);                 \
460           putc (')', FILE);                                             \
461           break; }                                                      \
462       if (ireg != 0 || breg != 0)                                       \
463         { int scale = 1;                                                \
464           if (breg == 0)                                                \
465             abort ();                                                   \
466           if (addr != 0)                                                \
467             output_addr_const (FILE, addr);                             \
468           fprintf (FILE, "(%s", reg_names[REGNO (breg)]);               \
469           if (ireg != 0)                                                \
470             putc (',', FILE);                                           \
471           if (ireg != 0 && GET_CODE (ireg) == MULT)                     \
472             { scale = INTVAL (XEXP (ireg, 1));                          \
473               ireg = XEXP (ireg, 0); }                                  \
474           if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)              \
475             fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);  \
476           else if (ireg != 0)                                           \
477             fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]);            \
478           if (scale != 1) fprintf (FILE, "*%d", scale);                 \
479           putc (')', FILE);                                             \
480           break;                                                        \
481         }                                                               \
482       else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF)               \
483         { fprintf (FILE, "10(%%pc,%s.w)",                               \
484                    reg_names[REGNO (reg1)]);                            \
485           break; }                                                      \
486     default:                                                            \
487         output_addr_const (FILE, addr);                                 \
488     }}
489
490
491 \f
492 /* Override usual definitions of SDB output macros.
493    These definitions differ only in the absence of the period
494    at the beginning of the name of the directive
495    and in the use of `~' as the symbol for the current location.  */
496
497 #define PUT_SDB_SCL(a) fprintf(asm_out_file, "\tscl\t%d;", (a))
498 #define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\tval\t%d;", (a))
499 #define PUT_SDB_VAL(a)                          \
500 ( fputs ("\tval\t", asm_out_file),              \
501   output_addr_const (asm_out_file, (a)),        \
502   fputc (';', asm_out_file))
503
504 #define PUT_SDB_DEF(a)                          \
505 do { fprintf (asm_out_file, "\tdef\t"); \
506      ASM_OUTPUT_LABELREF (asm_out_file, a);     \
507      fprintf (asm_out_file, ";"); } while (0)
508
509 #define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\tdef\t~%s;",a)
510 #define PUT_SDB_ENDEF fputs("\tendef\n", asm_out_file)
511 #define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\ttype\t0%o;", a)
512 #define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\tsize\t%d;", a)
513 #define PUT_SDB_START_DIM fprintf(asm_out_file, "\tdim\t")
514 #define PUT_SDB_NEXT_DIM(a) fprintf(asm_out_file, "%d,", a)
515 #define PUT_SDB_LAST_DIM(a) fprintf(asm_out_file, "%d;", a)
516
517 #define PUT_SDB_TAG(a)                          \
518 do { fprintf (asm_out_file, "\ttag\t"); \
519      ASM_OUTPUT_LABELREF (asm_out_file, a);     \
520      fprintf (asm_out_file, ";"); } while (0)
521
522 #define PUT_SDB_BLOCK_START(LINE)               \
523   fprintf (asm_out_file,                        \
524            "\tdef\t~bb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n",       \
525            (LINE))
526
527 #define PUT_SDB_BLOCK_END(LINE)                 \
528   fprintf (asm_out_file,                        \
529            "\tdef\t~eb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n",       \
530            (LINE))
531
532 #define PUT_SDB_FUNCTION_START(LINE)            \
533   fprintf (asm_out_file,                        \
534            "\tdef\t~bf;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n",       \
535            (LINE))
536
537 #define PUT_SDB_FUNCTION_END(LINE)              \
538   fprintf (asm_out_file,                        \
539            "\tdef\t~ef;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n",       \
540            (LINE))
541
542 #define PUT_SDB_EPILOGUE_END(NAME)              \
543   fprintf (asm_out_file,                        \
544            "\tdef\t%s;\tval\t~;\tscl\t-1;\tendef\n",    \
545            (NAME))
546
547 #define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
548   sprintf ((BUFFER), "~%dfake", (NUMBER));
549
550 #define NO_DOLLAR_IN_LABEL
551 #define NO_DOT_IN_LABEL
552
553 /* The usual definitions don't work because neither $ nor . is allowed.  */
554 #define CONSTRUCTOR_NAME_FORMAT "_GLOBAL_%%I\%%%s"
555
556 /* Define a few machine-specific details
557    of the implementation of constructors.
558
559    The __CTORS_LIST__ goes in the .init section.  Define CTOR_LIST_BEGIN
560    and CTOR_LIST_END to contribute to the .init section an instruction to
561    push a word containing 0 (or some equivalent of that).
562
563    ASM_OUTPUT_CONSTRUCTOR should be defined
564    to push the address of the constructor.  */
565
566 #define ASM_LONG        "\tlong"
567 #undef INIT_SECTION_ASM_OP
568 #define INIT_SECTION_ASM_OP     "section\t~init"
569 #undef FINI_SECTION_ASM_OP
570 #define FINI_SECTION_ASM_OP     "section\t~fini"
571 #undef CONST_SECTION_ASM_OP
572 #define CONST_SECTION_ASM_OP    "section\t~rodata"
573
574 #define CTOR_LIST_BEGIN                         \
575   asm (INIT_SECTION_ASM_OP);                    \
576   asm ("clr.l -(%sp)")
577 #define CTOR_LIST_END CTOR_LIST_BEGIN
578
579 #define BSS_SECTION_ASM_OP      "section\t~bss"
580
581 #define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME)       \
582   do {                                          \
583     init_section ();                            \
584     fprintf (FILE, "\tmov.l &");                \
585     assemble_name (FILE, NAME);                 \
586     fprintf (FILE, ",-(%%sp)\n");               \
587   } while (0)
588
589 /* We do not want leading underscores.  */
590
591 #undef ASM_OUTPUT_LABELREF
592 #define ASM_OUTPUT_LABELREF(FILE,NAME)  \
593   fprintf (FILE, "%s", NAME)