OSDN Git Service

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