OSDN Git Service

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