OSDN Git Service

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