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