OSDN Git Service

* rtl.h (addr_diff_vec_flags): New typedef.
[pf3gnuchains/gcc-fork.git] / gcc / config / m68k / crds.h
1 /* Definitions of target machine for GNU compiler;
2    Charles River Data Systems UNiverse/32.
3    Copyright (C) 1987, 1993, 1994, 1996, 1997 Free Software Foundation, Inc.
4    Contributed by Gary E. Miller (Gary_Edmunds_Miller@cup.portal.com)
5
6 This file is part of GNU CC.
7
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING.  If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 #define MOTOROLA                /* Use Motorola syntax rather than "MIT" */
24 #define SGS                     /* Uses SGS assembler */
25 #define SGS_SWITCH_TABLES       /* Different switch table handling */
26 #define SGS_NO_LI               /* Suppress jump table label usage */
27 #define CRDS                    /* Charles River Data Systems assembler */
28
29 #include "m68k/m68k.h"
30
31 /* Without STRUCTURE_SIZE_BOUNDARY, we can't ensure that structures are
32    aligned such that we can correctly extract bitfields from them.
33    Someone should check whether the usual compiler on the crds machine
34    provides the equivalent behavior of STRUCTURE_SIZE_BOUNDARY.  */
35 /* Set to 16 because all other m68k targets have it so */
36 #define STRUCTURE_SIZE_BOUNDARY 16
37
38 /* See m68k.h.  0 means 680[01]0 with no 68881.  */
39
40 #undef TARGET_DEFAULT
41 #define TARGET_DEFAULT 0
42
43 /* Don't try using XFmode.  */
44 #undef LONG_DOUBLE_TYPE_SIZE
45 #define LONG_DOUBLE_TYPE_SIZE 64
46
47 /* special flags to the unos assembler.  */
48
49 #undef ASM_SPEC
50 #define ASM_SPEC "-g"
51
52 #undef LIB_SPEC
53 #define LIB_SPEC "%{!p:%{!pg:-lunos}}%{p:-lc_p}%{pg:-lc_p}"
54
55 #undef STARTFILE_SPEC
56 #define STARTFILE_SPEC  \
57   "%{pg:gcrt0.o%s}%{!pg:%{p:mc68rt0.o%s}%{!p:c68rt0.o%s}}"
58
59 /* CC1 spec */
60 #if 0
61 /* c.sac only used in _s_call_r() in libunos.a and malloc() in libmalloc.a */
62 /* so we do not need to bother ! */
63 #define CC1_SPEC "-fpcc-struct-return"
64 #endif
65
66 /* -O2 for MAX optimization */
67 #undef CC1_SPEC
68 #define CC1_SPEC "%{O2:-fstrength-reduce}"
69
70 /* cpp has to support a #sccs directive for the /usr/include files */
71
72 #define SCCS_DIRECTIVE
73
74 /* Make output for SDB.  */
75
76 /* #define SDB_DEBUGGING_INFO UNOS casm has no debugging :-( */
77
78 /* UNOS need stack probe :-( */
79
80 #if 0
81 #define HAVE_probe 1
82 #define gen_probe()  gen_rtx(ASM_INPUT, VOIDmode, "tstb -2048(sp)\t;probe\n")
83 #else
84 #undef NEED_PROBE
85 #define NEED_PROBE (-2048)
86 #endif
87
88 /* use memcpy, memset instead of bcopy, etc. */
89
90 #define TARGET_MEM_FUNCTIONS
91
92 /* Don't try to define `gcc_compiled.' since the assembler might not
93    accept symbols with periods and GDB doesn't run on this machine anyway.  */
94 #define ASM_IDENTIFY_GCC(FILE)
95
96 /* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
97    This will control the use of inline 68881 insns in certain macros.  */
98
99 #undef CPP_SPEC
100 #define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
101
102 /* Names to predefine in the preprocessor for this target machine.  */
103
104 #undef CPP_PREDEFINES
105 #define CPP_PREDEFINES "-Dmc68k -DM68000 -Dmc68000 -Dunos -Dunix -D__motorola__ -Asystem(unix)  -Acpu(m68k) -Amachine(m68k)"
106
107 /* Register in which address to store a structure value
108    is passed to a function.  */
109 /* unos uses ".comm c.sac" returns &c.sac in d0 */
110 /* make pointer to c.sac ?
111 #undef STRUCT_VALUE_REGNUM
112 #define STRUCT_VALUE gen_rtx(MEM, Pmode, gen_rtx( , , ) )
113 */
114
115 #define BSS_SECTION_ASM_OP ".bss"
116
117 /* Specify how to pad function arguments.
118    Value should be `upward', `downward' or `none'.
119    Same as the default, except no padding for large or variable-size args.  */
120
121 #define FUNCTION_ARG_PADDING(MODE, TYPE)                                \
122   (((MODE) == BLKmode                                                   \
123     ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE))   == INTEGER_CST          \
124        && int_size_in_bytes (TYPE) < PARM_BOUNDARY / BITS_PER_UNIT)     \
125     : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY)                          \
126    ? downward : none)
127
128 /* Override parts of m68k.h to fit the CRuDS assembler.  */
129
130 #undef TARGET_VERSION 
131 #define TARGET_VERSION fprintf (stderr, " (68k, CRDS/UNOS)");
132
133 /* Specify extra dir to search for include files.  */
134 #define SYSTEM_INCLUDE_DIR "/include"
135
136 /* Control the assembler format that we output.  */
137
138 /* Output at beginning of assembler file.  */
139
140 #undef ASM_FILE_START
141 #define ASM_FILE_START(FILE)    \
142   fprintf (FILE, ";#NO_APP\n");
143
144 /* Output to assembler file text saying following lines
145    may contain character constants, extra white space, comments, etc.  */
146
147 #undef ASM_APP_ON
148 #define ASM_APP_ON ";#APP\n"
149
150 /* Output to assembler file text saying following lines
151    no longer contain unusual constructs.  */
152
153 #undef ASM_APP_OFF 
154 #define ASM_APP_OFF ";#NO_APP\n"
155
156 /* The prefix for immediate operands.  */
157
158 #undef IMMEDIATE_PREFIX
159 #define IMMEDIATE_PREFIX "$"
160
161 /* This is how to output an assembler line defining a `double' constant.  */
162
163 #undef ASM_OUTPUT_DOUBLE
164 #define ASM_OUTPUT_DOUBLE(FILE,VALUE)  \
165 do { long l[2];                                         \
166      REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l);            \
167      fprintf (FILE, "\t.long 0x%x, 0x%x\n", l[0], l[1]);        \
168    } while (0)
169
170 /*unos has no .skip :-( */
171 #undef ASM_OUTPUT_SKIP
172 #define ASM_OUTPUT_SKIP(FILE,SIZE)              \
173     fprintf (FILE, "\t. = . + %u\n", (SIZE));   
174
175 /* This says how to output an assembler line
176    to define a local common symbol.  */
177 /* should use bss_section instead of data_section but this makes casm die ? */
178
179 #undef ASM_OUTPUT_LOCAL
180 #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)  \
181 { data_section ();                              \
182   if ((SIZE) > 1) fprintf (FILE, "\t.even\n");  \
183   assemble_name ((FILE), (NAME));               \
184   fprintf ((FILE), ":\t. = . + %u\n", (ROUNDED));}
185
186 /* This is how to output an insn to push a register on the stack.
187    It need not be very fast code.  */
188
189 #undef ASM_OUTPUT_REG_PUSH
190 #define ASM_OUTPUT_REG_PUSH(FILE,REGNO)  \
191   fprintf (FILE, "\tmovel %s,-(sp)\n", reg_names[REGNO])
192
193 /* This is how to output an insn to pop a register from the stack.
194    It need not be very fast code.  */
195
196 #undef ASM_OUTPUT_REG_POP
197 #define ASM_OUTPUT_REG_POP(FILE,REGNO)  \
198   fprintf (FILE, "\tmovel (sp)+,%s\n", reg_names[REGNO])
199
200 #undef  ASM_OUTPUT_ASCII
201 #define  ASM_OUTPUT_ASCII(FILE, P , SIZE)                               \
202 do {  int i;                                                            \
203           fprintf ((FILE), "\t.ascii \"");                              \
204           for (i = 0; i < (SIZE); i++)                                  \
205             {                                                           \
206               register int c = (P)[i];                                  \
207               if (i != 0 && (i / 200) * 200 == i)                       \
208                 fprintf ((FILE), "\"\n\t.ascii \"");                    \
209               if (c >= ' ' && c < 0177) {                               \
210                 if (c != '\"' && c != '\\') {                           \
211                   putc (c, (FILE));                                     \
212                   continue;                                             \
213                 }                                                       \
214                }                                                        \
215                /* brain dead asm doesn't understand char escapes */     \
216                fprintf ((FILE), "\"\n\t.byte\t%d\n\t.ascii \"", c);     \
217             }                                                           \
218           fprintf ((FILE), "\"\n");                                     \
219  } while (0)
220
221
222 /* Change all JBxx to Bxx.  Also change all DBRA to DBF.
223    Also change divs.l, etc., to divs, etc.  But don't change divsl.l.  */
224
225 #define ASM_OUTPUT_OPCODE(FILE, PTR)                    \
226 { if ((PTR)[0] == 'j' && (PTR)[1] == 'b')               \
227     { ++(PTR); }                                        \
228   else if ((PTR)[0] == 'd')                             \
229     {                                                   \
230       if (!strncmp ((PTR), "dbra", 4))                  \
231         { fprintf ((FILE), "dbf"); (PTR) += 4; }        \
232       else if (!strncmp ((PTR), "div", 3) && (PTR)[5] == ' ')  \
233         { fprintf ((FILE), "div%c", (PTR)[3]); (PTR) += 6; }   \
234     }                                                   \
235 }
236
237
238 #if 0
239 /* Print operand X (an rtx) in assembler syntax to file FILE.
240    CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
241    For `%' followed by punctuation, CODE is the punctuation and X is null.
242
243    On the 68000, we use several CODE characters:
244    '.' for dot needed in Motorola-style opcode names.
245    '-' for an operand pushing on the stack:
246        sp@-, -(sp) or -(%sp) depending on the style of syntax.
247    '+' for an operand pushing on the stack:
248        sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
249    '@' for a reference to the top word on the stack:
250        sp@, (sp) or (%sp) depending on the style of syntax.
251    '#' for an immediate operand prefix (# in MIT and Motorola syntax
252        but & in SGS syntax, $ in unos syntax).
253    '!' for the fpcr register (used in some float-to-fixed conversions).
254
255    'b' for byte insn (no effect, on the Sun; this is for the ISI).
256    'd' to force memory addressing to be absolute, not relative.
257    'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
258    'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
259        than directly).  Second part of 'y' below.
260    'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
261        or print pair of registers as rx:ry.
262    'y' for a FPA insn (print pair of registers as rx:ry).  This also outputs
263        CONST_DOUBLE's as SunFPA constant RAM registers if
264        possible, so it should not be used except for the SunFPA. */
265
266 #undef PRINT_OPERAND_PUNCT_VALID_P
267 #define PRINT_OPERAND_PUNCT_VALID_P(CODE)                               \
268   ((CODE) == '.' || (CODE) == '#' || (CODE) == '-'                      \
269    || (CODE) == '+' || (CODE) == '@' || (CODE) == '!')
270
271 #undef PRINT_OPERAND
272 #define PRINT_OPERAND(FILE, X, CODE)  \
273 { int i;                                                                \
274   if (CODE == '.') ;                                                    \
275   else if (CODE == '#') fprintf (FILE, "$");                            \
276   else if (CODE == '-') fprintf (FILE, "-(sp)");                        \
277   else if (CODE == '+') fprintf (FILE, "(sp)+");                        \
278   else if (CODE == '@') fprintf (FILE, "(sp)");                         \
279   else if (CODE == '!') fprintf (FILE, "fpcr");                         \
280   else if (CODE == '/')                                                 \
281     ;                                                                   \
282   else if (GET_CODE (X) == REG)                                         \
283     { if (REGNO (X) < 16 && (CODE == 'y' || CODE == 'x') && GET_MODE (X) == DFmode)     \
284         fprintf (FILE, "%s:%s", reg_names[REGNO (X)], reg_names[REGNO (X)+1]); \
285       else                                                              \
286         fprintf (FILE, "%s", reg_names[REGNO (X)]);                     \
287     }                                                                   \
288   else if (GET_CODE (X) == MEM)                                         \
289     {                                                                   \
290       output_address (XEXP (X, 0));                                     \
291       if (CODE == 'd' && ! TARGET_68020                                 \
292           && CONSTANT_ADDRESS_P (XEXP (X, 0)))                          \
293         /* fprintf (FILE, ".l") */;                                     \
294     }                                                                   \
295   else if ((CODE == 'y' || CODE == 'w')                                 \
296            && GET_CODE(X) == CONST_DOUBLE                               \
297            && (i = standard_sun_fpa_constant_p (X)))                    \
298     fprintf (FILE, "%%%d", i & 0x1ff);                                  \
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       if (CODE == 'f')                                                  \
303         ASM_OUTPUT_FLOAT_OPERAND (CODE, FILE, r);                       \
304       else                                                              \
305         { REAL_VALUE_TO_TARGET_SINGLE (r, l);                           \
306           fprintf (FILE, "$0x%x", l); } }                               \
307   else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode)      \
308     { REAL_VALUE_TYPE r;                                                \
309       REAL_VALUE_FROM_CONST_DOUBLE (r, X);                              \
310       ASM_OUTPUT_DOUBLE_OPERAND (FILE, r); }                            \
311   else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == XFmode)      \
312     { REAL_VALUE_TYPE r;                                                \
313       REAL_VALUE_FROM_CONST_DOUBLE (r, X);                              \
314       ASM_OUTPUT_LONG_DOUBLE_OPERAND (FILE, r); }                       \
315   else { putc ('$', FILE); output_addr_const (FILE, X); }}
316 #endif
317 \f
318 /* Note that this contains a kludge that knows that the only reason
319    we have an address (plus (label_ref...) (reg...))
320    is in the insn before a tablejump, and we know that m68k.md
321    generates a label LInnn: on such an insn.  */
322 #undef PRINT_OPERAND_ADDRESS
323 #define PRINT_OPERAND_ADDRESS(FILE, ADDR)  \
324 { register rtx reg1, reg2, breg, ireg;                                  \
325   register rtx addr = ADDR;                                             \
326   rtx offset;                                                           \
327   switch (GET_CODE (addr))                                              \
328     {                                                                   \
329     case REG:                                                           \
330       fprintf (FILE, "(%s)", reg_names[REGNO (addr)]);                  \
331       break;                                                            \
332     case PRE_DEC:                                                       \
333       fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);       \
334       break;                                                            \
335     case POST_INC:                                                      \
336       fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);       \
337       break;                                                            \
338     case PLUS:                                                          \
339       reg1 = 0; reg2 = 0;                                               \
340       ireg = 0; breg = 0;                                               \
341       offset = 0;                                                       \
342       if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))                          \
343         {                                                               \
344           offset = XEXP (addr, 0);                                      \
345           addr = XEXP (addr, 1);                                        \
346         }                                                               \
347       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))                     \
348         {                                                               \
349           offset = XEXP (addr, 1);                                      \
350           addr = XEXP (addr, 0);                                        \
351         }                                                               \
352       if (GET_CODE (addr) != PLUS) ;                                    \
353       else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)                \
354         {                                                               \
355           reg1 = XEXP (addr, 0);                                        \
356           addr = XEXP (addr, 1);                                        \
357         }                                                               \
358       else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)                \
359         {                                                               \
360           reg1 = XEXP (addr, 1);                                        \
361           addr = XEXP (addr, 0);                                        \
362         }                                                               \
363       else if (GET_CODE (XEXP (addr, 0)) == MULT)                       \
364         {                                                               \
365           reg1 = XEXP (addr, 0);                                        \
366           addr = XEXP (addr, 1);                                        \
367         }                                                               \
368       else if (GET_CODE (XEXP (addr, 1)) == MULT)                       \
369         {                                                               \
370           reg1 = XEXP (addr, 1);                                        \
371           addr = XEXP (addr, 0);                                        \
372         }                                                               \
373       else if (GET_CODE (XEXP (addr, 0)) == REG)                        \
374         {                                                               \
375           reg1 = XEXP (addr, 0);                                        \
376           addr = XEXP (addr, 1);                                        \
377         }                                                               \
378       else if (GET_CODE (XEXP (addr, 1)) == REG)                        \
379         {                                                               \
380           reg1 = XEXP (addr, 1);                                        \
381           addr = XEXP (addr, 0);                                        \
382         }                                                               \
383       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT             \
384           || GET_CODE (addr) == SIGN_EXTEND)                            \
385         { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; }     \
386       if (offset != 0) { if (addr != 0) abort (); addr = offset; }      \
387       if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND                      \
388                     || GET_CODE (reg1) == MULT))                        \
389           || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))         \
390         { breg = reg2; ireg = reg1; }                                   \
391       else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))         \
392         { breg = reg1; ireg = reg2; }                                   \
393       if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF)       \
394         { int scale = 1;                                                \
395           if (GET_CODE (ireg) == MULT)                                  \
396             { scale = INTVAL (XEXP (ireg, 1));                          \
397               ireg = XEXP (ireg, 0); }                                  \
398           if (GET_CODE (ireg) == SIGN_EXTEND)                           \
399             fprintf (FILE, "L%d-LI%d-2(pc,%s.w",                        \
400                      CODE_LABEL_NUMBER (XEXP (addr, 0)),                \
401                      CODE_LABEL_NUMBER (XEXP (addr, 0)),                \
402                      reg_names[REGNO (XEXP (ireg, 0))]);                \
403           else                                                          \
404             fprintf (FILE, "L%d-LI%d-2(pc,%s.l",                        \
405                      CODE_LABEL_NUMBER (XEXP (addr, 0)),                \
406                      CODE_LABEL_NUMBER (XEXP (addr, 0)),                \
407                      reg_names[REGNO (ireg)]);                          \
408           if (scale != 1) fprintf (FILE, ":%d", scale);                 \
409           putc (')', FILE);                                             \
410           break; }                                                      \
411       if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF)       \
412         { fprintf (FILE, "L%d-LI%d-2(pc,%s.l",                          \
413                    CODE_LABEL_NUMBER (XEXP (addr, 0)),                  \
414                    CODE_LABEL_NUMBER (XEXP (addr, 0)),                  \
415                    reg_names[REGNO (breg)]);                            \
416           putc (')', FILE);                                             \
417           break; }                                                      \
418       if (ireg != 0 || breg != 0)                                       \
419         { int scale = 1;                                                \
420           if (breg == 0)                                                \
421             abort ();                                                   \
422           if (addr && GET_CODE (addr) == LABEL_REF) abort ();           \
423           if (addr != 0)                                                \
424             output_addr_const (FILE, addr);                             \
425           fprintf (FILE, "(%s", reg_names[REGNO (breg)]);               \
426           if (breg != 0 && ireg != 0)                                   \
427             putc (',', FILE);                                           \
428           if (ireg != 0 && GET_CODE (ireg) == MULT)                     \
429             { scale = INTVAL (XEXP (ireg, 1));                          \
430               ireg = XEXP (ireg, 0); }                                  \
431           if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)              \
432             fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);  \
433           else if (ireg != 0)                                           \
434             fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]);            \
435           if (scale != 1) fprintf (FILE, ":%d", scale);                 \
436           putc (')', FILE);                                             \
437           break;                                                        \
438         }                                                               \
439       else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF)               \
440         { fprintf (FILE, "L%d-LI%d-2(pc,%s.l)",                         \
441                    CODE_LABEL_NUMBER (XEXP (addr, 0)),                  \
442                    CODE_LABEL_NUMBER (XEXP (addr, 0)),                  \
443                    reg_names[REGNO (reg1)]);                            \
444           break; }                                                      \
445     default:                                                            \
446       if (GET_CODE (addr) == CONST_INT                                  \
447           && INTVAL (addr) < 0x8000                                     \
448           && INTVAL (addr) >= -0x8000)                                  \
449         fprintf (FILE, "%d", INTVAL (addr));                            \
450       else                                                              \
451         output_addr_const (FILE, addr);                                 \
452     }}
453 \f
454 #define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
455   do {  fprintf (FILE, "\t; file\t");                   \
456         output_quoted_string (FILE, FILENAME);          \
457         fprintf (FILE, "\n");                           \
458   } while (0)
459
460 #define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO)    \
461   fprintf (FILE, "\t; ln\t%d\n",                        \
462            (sdb_begin_function_line             \
463             ? last_linenum - sdb_begin_function_line : 1))
464
465 /* This macro generates the assembly code for function entry.
466    FILE is a stdio stream to output the code to.
467    SIZE is an int: how many units of temporary storage to allocate.
468    Refer to the array `regs_ever_live' to determine which registers
469    to save; `regs_ever_live[I]' is nonzero if register number I
470    is ever used in the function.  This macro is responsible for
471    knowing which registers should not be saved even if used.  */
472
473 /* Note that the order of the bit mask for fmovem is the opposite
474    of the order for movem!  */
475
476 #undef FUNCTION_PROLOGUE
477 #define FUNCTION_PROLOGUE(FILE, SIZE)     \
478 { register int regno;                                           \
479   register int mask = 0;                                        \
480   extern char call_used_regs[];                                 \
481   int fsize = ((SIZE) + 3) & -4;                                \
482   /* unos stack probe */                                        \
483   if ( fsize > 30000 ) {                                        \
484     fprintf (FILE, "\tmovel sp,a0\n");                          \
485     fprintf (FILE, "\taddl $-%d,a0\n", 2048 + fsize);           \
486     fprintf (FILE, "\ttstb (a0)\n");                            \
487   } else {                                                      \
488     fprintf (FILE, "\ttstb -%d(sp)\n", 2048 + fsize);           \
489   }                                                             \
490   if (frame_pointer_needed)                                     \
491     { if (TARGET_68020 || fsize < 0x8000)                       \
492         fprintf (FILE, "\tlink a6,$%d\n", -fsize);              \
493       else                                                      \
494         fprintf (FILE, "\tlink a6,$0\n\tsubl $%d,sp\n", fsize); }  \
495   else if (fsize)                                                     \
496     {                                                                 \
497       /* Adding negative number is faster on the 68040.  */           \
498       if (fsize + 4 < 0x8000)                                         \
499         {                                                             \
500           fprintf (FILE, "\tadd.w #%d,sp\n", - (fsize + 4));          \
501         }                                                             \
502       else                                                            \
503         {                                                             \
504           fprintf (FILE, "\tadd.l #%d,sp\n", - (fsize + 4));          \
505         }                                                             \
506     }                                                                 \
507   for (regno = 16; regno < 24; regno++)                         \
508     if (regs_ever_live[regno] && ! call_used_regs[regno])       \
509        mask |= 1 << (regno - 16);                               \
510   if ((mask & 0xff) != 0)                                       \
511     fprintf (FILE, "\tfmovem $0x%x,-(sp)\n", mask & 0xff);       \
512   mask = 0;                                                     \
513   for (regno = 0; regno < 16; regno++)                          \
514     if (regs_ever_live[regno] && ! call_used_regs[regno])       \
515        mask |= 1 << (15 - regno);                               \
516   if (frame_pointer_needed)                                     \
517     mask &= ~ (1 << (15-FRAME_POINTER_REGNUM));                 \
518   if (exact_log2 (mask) >= 0)                                   \
519     fprintf (FILE, "\tmovel %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]);  \
520   else if (mask) fprintf (FILE, "\tmovem $0x%x,-(sp)\n", mask); }
521
522 /* Must put address in  %a0 , not  %d0 . -- LGM, 7/15/88 */
523 /* UNOS ?? */
524 #undef FUNCTION_PROFILER
525 #define FUNCTION_PROFILER(FILE, LABEL_NO)       \
526     fprintf (FILE, "\tmovl &LP%%%d,%%a0\n\tjsr mcount\n", (LABEL_NO))
527
528 /* This macro generates the assembly code for function exit,
529    on machines that need it.  If FUNCTION_EPILOGUE is not defined
530    then individual return instructions are generated for each
531    return statement.  Args are same as for FUNCTION_PROLOGUE.
532
533    The function epilogue should not depend on the current stack pointer!
534    It should use the frame pointer only.  This is mandatory because
535    of alloca; we also take advantage of it to omit stack adjustments
536    before returning.  */
537
538 #undef FUNCTION_EPILOGUE
539 #define FUNCTION_EPILOGUE(FILE, SIZE) \
540 { register int regno;                                           \
541   register int mask, fmask;                                     \
542   register int nregs;                                           \
543   int offset, foffset, fpoffset;                                \
544   extern char call_used_regs[];                                 \
545   int fsize = ((SIZE) + 3) & -4;                                \
546   int big = 0;                                                  \
547   nregs = 0;  fmask = 0; fpoffset = 0;                          \
548   for (regno = 16; regno < 24; regno++)                         \
549     if (regs_ever_live[regno] && ! call_used_regs[regno])       \
550       { nregs++; fmask |= 1 << (23 - regno); }                  \
551   foffset = fpoffset + nregs * 12;                              \
552   nregs = 0;  mask = 0;                                         \
553   if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
554   for (regno = 0; regno < 16; regno++)                          \
555     if (regs_ever_live[regno] && ! call_used_regs[regno])       \
556       { nregs++; mask |= 1 << regno; }                          \
557   offset = foffset + nregs * 4;                                 \
558   if (offset + fsize >= 0x8000                                  \
559       && frame_pointer_needed                                   \
560       && (mask || fmask || fpoffset))                           \
561     { fprintf (FILE, "\tmovel $%d,a0\n", -fsize);               \
562       fsize = 0, big = 1; }                                     \
563   if (exact_log2 (mask) >= 0) {                                 \
564     if (big)                                                    \
565       fprintf (FILE, "\tmovel -%d(a6,a0.l),%s\n",               \
566                offset + fsize, reg_names[exact_log2 (mask)]);   \
567     else if (! frame_pointer_needed)                            \
568       fprintf (FILE, "\tmovel (sp)+,%s\n",                      \
569                reg_names[exact_log2 (mask)]);                   \
570     else                                                        \
571       fprintf (FILE, "\tmovel -%d(a6),%s\n",                    \
572                offset + fsize, reg_names[exact_log2 (mask)]); } \
573   else if (mask) {                                              \
574     if (big)                                                    \
575       fprintf (FILE, "\tmovem -%d(a6,a0.l),$0x%x\n",            \
576                offset + fsize, mask);                           \
577     else if (! frame_pointer_needed)                            \
578       fprintf (FILE, "\tmovem (sp)+,$0x%x\n", mask);            \
579     else                                                        \
580       fprintf (FILE, "\tmovem -%d(a6),$0x%x\n",         \
581                offset + fsize, mask); }                         \
582   if (fmask) {                                                  \
583     if (big)                                                    \
584       fprintf (FILE, "\tfmovem -%d(a6,a0.l),$0x%x\n",           \
585                foffset + fsize, fmask);                         \
586     else if (! frame_pointer_needed)                            \
587       fprintf (FILE, "\tfmovem (sp)+,$0x%x\n", fmask);          \
588     else                                                        \
589       fprintf (FILE, "\tfmovem -%d(a6),$0x%x\n",                \
590                foffset + fsize, fmask); }                       \
591   if (fpoffset != 0)                                            \
592     for (regno = 55; regno >= 24; regno--)                      \
593       if (regs_ever_live[regno] && ! call_used_regs[regno]) {   \
594         if (big)                                                \
595           fprintf(FILE, "\tfpmoved -%d(a6,a0.l), %s\n", \
596                   fpoffset + fsize, reg_names[regno]);          \
597         else if (! frame_pointer_needed)                        \
598           fprintf(FILE, "\tfpmoved (sp)+, %s\n",                        \
599                   reg_names[regno]);                            \
600         else                                                    \
601           fprintf(FILE, "\tfpmoved -%d(a6), %s\n",              \
602                   fpoffset + fsize, reg_names[regno]);          \
603         fpoffset -= 8;                                          \
604       }                                                         \
605   if (frame_pointer_needed)                                     \
606     fprintf (FILE, "\tunlk a6\n");                              \
607   else if (fsize)                                                     \
608     {                                                                 \
609       if (fsize + 4 < 0x8000)                                         \
610         {                                                             \
611           fprintf (FILE, "\tadd.w #%d,sp\n", fsize + 4);              \
612         }                                                             \
613       else                                                            \
614         {                                                             \
615           fprintf (FILE, "\tadd.l #%d,sp\n", fsize + 4);              \
616         }                                                             \
617     }                                                                 \
618   if (current_function_pops_args)                               \
619     fprintf (FILE, "\trtd $%d\n", current_function_pops_args);  \
620   else fprintf (FILE, "\trts\n"); }
621