[official-gcc.git] / gcc / config / m68k / crds.h
blob441b285b4eec99580a1c11ca3045ed919356b4fc
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)
6 This file is part of GNU CC.
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.
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.
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. */
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 */
29 #include "m68k/m68k.h"
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
38 /* See m68k.h. 0 means 680[01]0 with no 68881. */
40 #undef TARGET_DEFAULT
41 #define TARGET_DEFAULT 0
43 /* Don't try using XFmode. */
44 #undef LONG_DOUBLE_TYPE_SIZE
45 #define LONG_DOUBLE_TYPE_SIZE 64
47 /* special flags to the unos assembler. */
49 #undef ASM_SPEC
50 #define ASM_SPEC "-g"
52 #undef LIB_SPEC
53 #define LIB_SPEC "%{!p:%{!pg:-lunos}}%{p:-lc_p}%{pg:-lc_p}"
55 #undef STARTFILE_SPEC
56 #define STARTFILE_SPEC \
57 "%{pg:gcrt0.o%s}%{!pg:%{p:mc68rt0.o%s}%{!p:c68rt0.o%s}}"
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
66 /* -O2 for MAX optimization */
67 #undef CC1_SPEC
68 #define CC1_SPEC "%{O2:-fstrength-reduce}"
70 /* cpp has to support a #sccs directive for the /usr/include files */
72 #define SCCS_DIRECTIVE
74 /* Make output for SDB. */
76 /* #define SDB_DEBUGGING_INFO UNOS casm has no debugging :-( */
78 /* UNOS need stack probe :-( */
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
88 /* use memcpy, memset instead of bcopy, etc. */
90 #define TARGET_MEM_FUNCTIONS
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)
96 /* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
97 This will control the use of inline 68881 insns in certain macros. */
99 #undef CPP_SPEC
100 #define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
102 /* Names to predefine in the preprocessor for this target machine. */
104 #undef CPP_PREDEFINES
105 #define CPP_PREDEFINES "-Dmc68k -DM68000 -Dmc68000 -Dunos -Dunix -D__motorola__ -Asystem(unix) -Acpu(m68k) -Amachine(m68k)"
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( , , ) )
115 #define BSS_SECTION_ASM_OP ".bss"
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. */
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)
128 /* Override parts of m68k.h to fit the CRuDS assembler. */
130 #undef TARGET_VERSION
131 #define TARGET_VERSION fprintf (stderr, " (68k, CRDS/UNOS)");
133 /* Specify extra dir to search for include files. */
134 #define SYSTEM_INCLUDE_DIR "/include"
136 /* Control the assembler format that we output. */
138 /* Output at beginning of assembler file. */
140 #undef ASM_FILE_START
141 #define ASM_FILE_START(FILE) \
142 fprintf (FILE, ";#NO_APP\n");
144 /* Output to assembler file text saying following lines
145 may contain character constants, extra white space, comments, etc. */
147 #undef ASM_APP_ON
148 #define ASM_APP_ON ";#APP\n"
150 /* Output to assembler file text saying following lines
151 no longer contain unusual constructs. */
153 #undef ASM_APP_OFF
154 #define ASM_APP_OFF ";#NO_APP\n"
156 /* The prefix for immediate operands. */
158 #undef IMMEDIATE_PREFIX
159 #define IMMEDIATE_PREFIX "$"
161 /* This is how to output an assembler line defining a `double' constant. */
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)
170 /*unos has no .skip :-( */
171 #undef ASM_OUTPUT_SKIP
172 #define ASM_OUTPUT_SKIP(FILE,SIZE) \
173 fprintf (FILE, "\t. = . + %u\n", (SIZE));
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 ? */
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));}
186 /* This is how to output an insn to push a register on the stack.
187 It need not be very fast code. */
189 #undef ASM_OUTPUT_REG_PUSH
190 #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
191 fprintf (FILE, "\tmovel %s,-(sp)\n", reg_names[REGNO])
193 /* This is how to output an insn to pop a register from the stack.
194 It need not be very fast code. */
196 #undef ASM_OUTPUT_REG_POP
197 #define ASM_OUTPUT_REG_POP(FILE,REGNO) \
198 fprintf (FILE, "\tmovel (sp)+,%s\n", reg_names[REGNO])
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++) \
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; \
215 /* brain dead asm doesn't understand char escapes */ \
216 fprintf ((FILE), "\"\n\t.byte\t%d\n\t.ascii \"", c); \
218 fprintf ((FILE), "\"\n"); \
219 } while (0)
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. */
225 #define ASM_OUTPUT_OPCODE(FILE, PTR) \
226 { if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
227 { ++(PTR); } \
228 else if ((PTR)[0] == 'd') \
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; } \
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.
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).
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. */
266 #undef PRINT_OPERAND_PUNCT_VALID_P
267 #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
268 ((CODE) == '.' || (CODE) == '#' || (CODE) == '-' \
269 || (CODE) == '+' || (CODE) == '@' || (CODE) == '!')
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 == '/') \
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)]); \
288 else if (GET_CODE (X) == MEM) \
290 output_address (XEXP (X, 0)); \
291 if (CODE == 'd' && ! TARGET_68020 \
292 && CONSTANT_ADDRESS_P (XEXP (X, 0))) \
293 /* fprintf (FILE, ".l") */; \
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
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)) \
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))) \
344 offset = XEXP (addr, 0); \
345 addr = XEXP (addr, 1); \
347 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
349 offset = XEXP (addr, 1); \
350 addr = XEXP (addr, 0); \
352 if (GET_CODE (addr) != PLUS) ; \
353 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
355 reg1 = XEXP (addr, 0); \
356 addr = XEXP (addr, 1); \
358 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
360 reg1 = XEXP (addr, 1); \
361 addr = XEXP (addr, 0); \
363 else if (GET_CODE (XEXP (addr, 0)) == MULT) \
365 reg1 = XEXP (addr, 0); \
366 addr = XEXP (addr, 1); \
368 else if (GET_CODE (XEXP (addr, 1)) == MULT) \
370 reg1 = XEXP (addr, 1); \
371 addr = XEXP (addr, 0); \
373 else if (GET_CODE (XEXP (addr, 0)) == REG) \
375 reg1 = XEXP (addr, 0); \
376 addr = XEXP (addr, 1); \
378 else if (GET_CODE (XEXP (addr, 1)) == REG) \
380 reg1 = XEXP (addr, 1); \
381 addr = XEXP (addr, 0); \
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; \
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); \
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)
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))
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. */
473 /* Note that the order of the bit mask for fmovem is the opposite
474 of the order for movem! */
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); \
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) \
497 /* Adding negative number is faster on the 68040. */ \
498 if (fsize + 4 < 0x8000) \
500 fprintf (FILE, "\tadd.w #%d,sp\n", - (fsize + 4)); \
502 else \
504 fprintf (FILE, "\tadd.l #%d,sp\n", - (fsize + 4)); \
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); }
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))
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.
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. */
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; \
605 if (frame_pointer_needed) \
606 fprintf (FILE, "\tunlk a6\n"); \
607 else if (fsize) \
609 if (fsize + 4 < 0x8000) \
611 fprintf (FILE, "\tadd.w #%d,sp\n", fsize + 4); \
613 else \
615 fprintf (FILE, "\tadd.l #%d,sp\n", fsize + 4); \
618 if (current_function_pops_args) \
619 fprintf (FILE, "\trtd $%d\n", current_function_pops_args); \
620 else fprintf (FILE, "\trts\n"); }