1 /* Definitions of target machine for GNU compiler;
2 Charles River Data Systems UNiverse/32.
3 Copyright (C) 1987, 1993, 1994, 1996, 1997, 1998, 1999, 2000
4 Free Software Foundation, Inc.
5 Contributed by Gary E. Miller (Gary_Edmunds_Miller@cup.portal.com)
7 This file is part of GNU CC.
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)
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.
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. */
24 #define MOTOROLA /* Use Motorola syntax rather than "MIT" */
25 #define SGS /* Uses SGS assembler */
26 #define SGS_SWITCH_TABLES /* Different switch table handling */
27 #define SGS_NO_LI /* Suppress jump table label usage */
28 #define CRDS /* Charles River Data Systems assembler */
30 #include "m68k/m68k.h"
32 /* Without STRUCTURE_SIZE_BOUNDARY, we can't ensure that structures are
33 aligned such that we can correctly extract bitfields from them.
34 Someone should check whether the usual compiler on the crds machine
35 provides the equivalent behavior of STRUCTURE_SIZE_BOUNDARY. */
36 /* Set to 16 because all other m68k targets have it so */
37 #define STRUCTURE_SIZE_BOUNDARY 16
39 /* See m68k.h. 0 means 680[01]0 with no 68881. */
42 #define TARGET_DEFAULT 0
44 /* Don't try using XFmode. */
45 #undef LONG_DOUBLE_TYPE_SIZE
46 #define LONG_DOUBLE_TYPE_SIZE 64
48 /* special flags to the unos assembler. */
54 #define LIB_SPEC "%{!p:%{!pg:-lunos}}%{p:-lc_p}%{pg:-lc_p}"
57 #define STARTFILE_SPEC \
58 "%{pg:gcrt0.o%s}%{!pg:%{p:mc68rt0.o%s}%{!p:c68rt0.o%s}}"
62 /* c.sac only used in _s_call_r() in libunos.a and malloc() in libmalloc.a */
63 /* so we do not need to bother ! */
64 #define CC1_SPEC "-fpcc-struct-return"
67 /* -O2 for MAX optimization */
69 #define CC1_SPEC "%{O2:-fstrength-reduce}"
71 /* cpp has to support a #sccs directive for the /usr/include files */
73 #define SCCS_DIRECTIVE
75 /* Make output for SDB. */
77 /* #define SDB_DEBUGGING_INFO UNOS casm has no debugging :-( */
79 /* UNOS need stack probe :-( */
83 #define gen_probe() gen_rtx_ASM_INPUT (VOIDmode, "tstb -2048(sp)\t;probe\n")
86 #define NEED_PROBE (-2048)
89 /* use memcpy, memset instead of bcopy, etc. */
91 #define TARGET_MEM_FUNCTIONS
93 /* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
94 This will control the use of inline 68881 insns in certain macros. */
97 #define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
99 /* Names to predefine in the preprocessor for this target machine. */
101 #undef CPP_PREDEFINES
102 #define CPP_PREDEFINES "-Dmc68k -DM68000 -Dmc68000 -Dunos -Dunix -D__motorola__ -Asystem=unix -Acpu=m68k -Amachine=m68k"
104 /* Register in which address to store a structure value
105 is passed to a function. */
106 /* unos uses ".comm c.sac" returns &c.sac in d0 */
107 /* make pointer to c.sac ?
108 #undef STRUCT_VALUE_REGNUM
109 #define STRUCT_VALUE gen_rtx_MEM (Pmode, gen_rtx( , , ) )
112 #define BSS_SECTION_ASM_OP "\t.bss"
114 /* Specify how to pad function arguments.
115 Value should be `upward', `downward' or `none'.
116 Same as the default, except no padding for large or variable-size args. */
118 #define FUNCTION_ARG_PADDING(MODE, TYPE) \
119 (((MODE) == BLKmode \
120 ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
121 && int_size_in_bytes (TYPE) < PARM_BOUNDARY / BITS_PER_UNIT) \
122 : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY) \
125 /* Override parts of m68k.h to fit the CRuDS assembler. */
127 #undef TARGET_VERSION
128 #define TARGET_VERSION fprintf (stderr, " (68k, CRDS/UNOS)");
130 /* Specify extra dir to search for include files. */
131 #define SYSTEM_INCLUDE_DIR "/include"
133 /* Control the assembler format that we output. */
135 /* Output at beginning of assembler file. */
137 #undef ASM_FILE_START
138 #define ASM_FILE_START(FILE) \
139 fprintf (FILE, ";#NO_APP\n");
141 /* Output to assembler file text saying following lines
142 may contain character constants, extra white space, comments, etc. */
145 #define ASM_APP_ON ";#APP\n"
147 /* Output to assembler file text saying following lines
148 no longer contain unusual constructs. */
151 #define ASM_APP_OFF ";#NO_APP\n"
153 /* The prefix for immediate operands. */
155 #undef IMMEDIATE_PREFIX
156 #define IMMEDIATE_PREFIX "$"
158 /* This is how to output an assembler line defining a `double' constant. */
160 #undef ASM_OUTPUT_DOUBLE
161 #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
163 REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
164 fprintf (FILE, "\t.long 0x%x, 0x%x\n", l[0], l[1]); \
167 /*unos has no .skip :-( */
168 #undef ASM_OUTPUT_SKIP
169 #define ASM_OUTPUT_SKIP(FILE,SIZE) \
170 fprintf (FILE, "\t. = . + %u\n", (SIZE));
172 /* This says how to output an assembler line
173 to define a local common symbol. */
174 /* should use bss_section instead of data_section but this makes casm die ? */
176 #undef ASM_OUTPUT_LOCAL
177 #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
179 if ((SIZE) > 1) fprintf (FILE, "\t.even\n"); \
180 assemble_name ((FILE), (NAME)); \
181 fprintf ((FILE), ":\t. = . + %u\n", (ROUNDED));}
183 /* This is how to output an insn to push a register on the stack.
184 It need not be very fast code. */
186 #undef ASM_OUTPUT_REG_PUSH
187 #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
188 fprintf (FILE, "\tmovel %s,-(sp)\n", reg_names[REGNO])
190 /* This is how to output an insn to pop a register from the stack.
191 It need not be very fast code. */
193 #undef ASM_OUTPUT_REG_POP
194 #define ASM_OUTPUT_REG_POP(FILE,REGNO) \
195 fprintf (FILE, "\tmovel (sp)+,%s\n", reg_names[REGNO])
197 #undef ASM_OUTPUT_ASCII
198 #define ASM_OUTPUT_ASCII(FILE, P , SIZE) \
200 fprintf ((FILE), "\t.ascii \""); \
201 for (i = 0; i < (SIZE); i++) \
203 register int c = (P)[i]; \
204 if (i != 0 && (i / 200) * 200 == i) \
205 fprintf ((FILE), "\"\n\t.ascii \""); \
206 if (c >= ' ' && c < 0177) { \
207 if (c != '\"' && c != '\\') { \
212 /* brain dead asm doesn't understand char escapes */ \
213 fprintf ((FILE), "\"\n\t.byte\t%d\n\t.ascii \"", c); \
215 fprintf ((FILE), "\"\n"); \
219 /* Change all JBxx to Bxx. Also change all DBRA to DBF.
220 Also change divs.l, etc., to divs, etc. But don't change divsl.l. */
222 #define ASM_OUTPUT_OPCODE(FILE, PTR) \
223 { if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
225 else if ((PTR)[0] == 'd') \
227 if (!strncmp ((PTR), "dbra", 4)) \
228 { fprintf ((FILE), "dbf"); (PTR) += 4; } \
229 else if (!strncmp ((PTR), "div", 3) && (PTR)[5] == ' ') \
230 { fprintf ((FILE), "div%c", (PTR)[3]); (PTR) += 6; } \
236 /* Print operand X (an rtx) in assembler syntax to file FILE.
237 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
238 For `%' followed by punctuation, CODE is the punctuation and X is null.
240 On the 68000, we use several CODE characters:
241 '.' for dot needed in Motorola-style opcode names.
242 '-' for an operand pushing on the stack:
243 sp@-, -(sp) or -(%sp) depending on the style of syntax.
244 '+' for an operand pushing on the stack:
245 sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
246 '@' for a reference to the top word on the stack:
247 sp@, (sp) or (%sp) depending on the style of syntax.
248 '#' for an immediate operand prefix (# in MIT and Motorola syntax
249 but & in SGS syntax, $ in unos syntax).
250 '!' for the fpcr register (used in some float-to-fixed conversions).
252 'b' for byte insn (no effect, on the Sun; this is for the ISI).
253 'd' to force memory addressing to be absolute, not relative.
254 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
255 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
256 than directly). Second part of 'y' below.
257 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
258 or print pair of registers as rx:ry.
259 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
260 CONST_DOUBLE's as SunFPA constant RAM registers if
261 possible, so it should not be used except for the SunFPA. */
263 #undef PRINT_OPERAND_PUNCT_VALID_P
264 #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
265 ((CODE) == '.' || (CODE) == '#' || (CODE) == '-' \
266 || (CODE) == '+' || (CODE) == '@' || (CODE) == '!')
269 #define PRINT_OPERAND(FILE, X, CODE) \
272 else if (CODE == '#') fprintf (FILE, "$"); \
273 else if (CODE == '-') fprintf (FILE, "-(sp)"); \
274 else if (CODE == '+') fprintf (FILE, "(sp)+"); \
275 else if (CODE == '@') fprintf (FILE, "(sp)"); \
276 else if (CODE == '!') fprintf (FILE, "fpcr"); \
277 else if (CODE == '/') \
279 else if (GET_CODE (X) == REG) \
280 { if (REGNO (X) < 16 && (CODE == 'y' || CODE == 'x') && GET_MODE (X) == DFmode) \
281 fprintf (FILE, "%s:%s", reg_names[REGNO (X)], reg_names[REGNO (X)+1]); \
283 fprintf (FILE, "%s", reg_names[REGNO (X)]); \
285 else if (GET_CODE (X) == MEM) \
287 output_address (XEXP (X, 0)); \
288 if (CODE == 'd' && ! TARGET_68020 \
289 && CONSTANT_ADDRESS_P (XEXP (X, 0))) \
290 /* fprintf (FILE, ".l") */; \
292 else if ((CODE == 'y' || CODE == 'w') \
293 && GET_CODE(X) == CONST_DOUBLE \
294 && (i = standard_sun_fpa_constant_p (X))) \
295 fprintf (FILE, "%%%d", i & 0x1ff); \
296 else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
297 { REAL_VALUE_TYPE r; long l; \
298 REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
300 ASM_OUTPUT_FLOAT_OPERAND (CODE, FILE, r); \
302 { REAL_VALUE_TO_TARGET_SINGLE (r, l); \
303 fprintf (FILE, "$0x%x", l); } } \
304 else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode) \
305 { REAL_VALUE_TYPE r; \
306 REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
307 ASM_OUTPUT_DOUBLE_OPERAND (FILE, r); } \
308 else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == XFmode) \
309 { REAL_VALUE_TYPE r; \
310 REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
311 ASM_OUTPUT_LONG_DOUBLE_OPERAND (FILE, r); } \
312 else { putc ('$', FILE); output_addr_const (FILE, X); }}
315 /* Note that this contains a kludge that knows that the only reason
316 we have an address (plus (label_ref...) (reg...))
317 is in the insn before a tablejump, and we know that m68k.md
318 generates a label LInnn: on such an insn. */
319 #undef PRINT_OPERAND_ADDRESS
320 #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
321 { register rtx reg1, reg2, breg, ireg; \
322 register rtx addr = ADDR; \
324 switch (GET_CODE (addr)) \
327 fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
330 fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
333 fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
336 reg1 = 0; reg2 = 0; \
337 ireg = 0; breg = 0; \
339 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
341 offset = XEXP (addr, 0); \
342 addr = XEXP (addr, 1); \
344 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
346 offset = XEXP (addr, 1); \
347 addr = XEXP (addr, 0); \
349 if (GET_CODE (addr) != PLUS) ; \
350 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
352 reg1 = XEXP (addr, 0); \
353 addr = XEXP (addr, 1); \
355 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
357 reg1 = XEXP (addr, 1); \
358 addr = XEXP (addr, 0); \
360 else if (GET_CODE (XEXP (addr, 0)) == MULT) \
362 reg1 = XEXP (addr, 0); \
363 addr = XEXP (addr, 1); \
365 else if (GET_CODE (XEXP (addr, 1)) == MULT) \
367 reg1 = XEXP (addr, 1); \
368 addr = XEXP (addr, 0); \
370 else if (GET_CODE (XEXP (addr, 0)) == REG) \
372 reg1 = XEXP (addr, 0); \
373 addr = XEXP (addr, 1); \
375 else if (GET_CODE (XEXP (addr, 1)) == REG) \
377 reg1 = XEXP (addr, 1); \
378 addr = XEXP (addr, 0); \
380 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
381 || GET_CODE (addr) == SIGN_EXTEND) \
382 { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
383 if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
384 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
385 || GET_CODE (reg1) == MULT)) \
386 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
387 { breg = reg2; ireg = reg1; } \
388 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
389 { breg = reg1; ireg = reg2; } \
390 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
392 if (GET_CODE (ireg) == MULT) \
393 { scale = INTVAL (XEXP (ireg, 1)); \
394 ireg = XEXP (ireg, 0); } \
395 if (GET_CODE (ireg) == SIGN_EXTEND) \
396 fprintf (FILE, "L%d-LI%d-2(pc,%s.w", \
397 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
398 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
399 reg_names[REGNO (XEXP (ireg, 0))]); \
401 fprintf (FILE, "L%d-LI%d-2(pc,%s.l", \
402 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
403 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
404 reg_names[REGNO (ireg)]); \
405 if (scale != 1) fprintf (FILE, ":%d", scale); \
408 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \
409 { fprintf (FILE, "L%d-LI%d-2(pc,%s.l", \
410 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
411 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
412 reg_names[REGNO (breg)]); \
415 if (ireg != 0 || breg != 0) \
419 if (addr && GET_CODE (addr) == LABEL_REF) abort (); \
421 output_addr_const (FILE, addr); \
422 fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
423 if (breg != 0 && ireg != 0) \
425 if (ireg != 0 && GET_CODE (ireg) == MULT) \
426 { scale = INTVAL (XEXP (ireg, 1)); \
427 ireg = XEXP (ireg, 0); } \
428 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
429 fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
430 else if (ireg != 0) \
431 fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
432 if (scale != 1) fprintf (FILE, ":%d", scale); \
436 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
437 { fprintf (FILE, "L%d-LI%d-2(pc,%s.l)", \
438 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
439 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
440 reg_names[REGNO (reg1)]); \
443 if (GET_CODE (addr) == CONST_INT \
444 && INTVAL (addr) < 0x8000 \
445 && INTVAL (addr) >= -0x8000) \
446 fprintf (FILE, "%d", INTVAL (addr)); \
448 output_addr_const (FILE, addr); \
451 #define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
452 do { fprintf (FILE, "\t; file\t"); \
453 output_quoted_string (FILE, FILENAME); \
454 fprintf (FILE, "\n"); \
457 #define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \
458 fprintf (FILE, "\t; ln\t%d\n", \
459 (sdb_begin_function_line \
460 ? last_linenum - sdb_begin_function_line : 1))
462 /* This macro generates the assembly code for function entry.
463 FILE is a stdio stream to output the code to.
464 SIZE is an int: how many units of temporary storage to allocate.
465 Refer to the array `regs_ever_live' to determine which registers
466 to save; `regs_ever_live[I]' is nonzero if register number I
467 is ever used in the function. This macro is responsible for
468 knowing which registers should not be saved even if used. */
470 /* Note that the order of the bit mask for fmovem is the opposite
471 of the order for movem! */
473 #undef FUNCTION_PROLOGUE
474 #define FUNCTION_PROLOGUE(FILE, SIZE) \
475 { register int regno; \
476 register int mask = 0; \
477 extern char call_used_regs[]; \
478 int fsize = ((SIZE) + 3) & -4; \
479 /* unos stack probe */ \
480 if ( fsize > 30000 ) { \
481 fprintf (FILE, "\tmovel sp,a0\n"); \
482 fprintf (FILE, "\taddl $-%d,a0\n", 2048 + fsize); \
483 fprintf (FILE, "\ttstb (a0)\n"); \
485 fprintf (FILE, "\ttstb -%d(sp)\n", 2048 + fsize); \
487 if (frame_pointer_needed) \
488 { if (TARGET_68020 || fsize < 0x8000) \
489 fprintf (FILE, "\tlink a6,$%d\n", -fsize); \
491 fprintf (FILE, "\tlink a6,$0\n\tsubl $%d,sp\n", fsize); } \
494 /* Adding negative number is faster on the 68040. */ \
495 if (fsize + 4 < 0x8000) \
497 fprintf (FILE, "\tadd.w #%d,sp\n", - (fsize + 4)); \
501 fprintf (FILE, "\tadd.l #%d,sp\n", - (fsize + 4)); \
504 for (regno = 16; regno < 24; regno++) \
505 if (regs_ever_live[regno] && ! call_used_regs[regno]) \
506 mask |= 1 << (regno - 16); \
507 if ((mask & 0xff) != 0) \
508 fprintf (FILE, "\tfmovem $0x%x,-(sp)\n", mask & 0xff); \
510 for (regno = 0; regno < 16; regno++) \
511 if (regs_ever_live[regno] && ! call_used_regs[regno]) \
512 mask |= 1 << (15 - regno); \
513 if (frame_pointer_needed) \
514 mask &= ~ (1 << (15-FRAME_POINTER_REGNUM)); \
515 if (exact_log2 (mask) >= 0) \
516 fprintf (FILE, "\tmovel %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]); \
517 else if (mask) fprintf (FILE, "\tmovem $0x%x,-(sp)\n", mask); }
519 /* Must put address in %a0 , not %d0 . -- LGM, 7/15/88 */
521 #undef FUNCTION_PROFILER
522 #define FUNCTION_PROFILER(FILE, LABEL_NO) \
523 fprintf (FILE, "\tmovl &LP%%%d,%%a0\n\tjsr mcount\n", (LABEL_NO))
525 /* This macro generates the assembly code for function exit,
526 on machines that need it. If FUNCTION_EPILOGUE is not defined
527 then individual return instructions are generated for each
528 return statement. Args are same as for FUNCTION_PROLOGUE.
530 The function epilogue should not depend on the current stack pointer!
531 It should use the frame pointer only. This is mandatory because
532 of alloca; we also take advantage of it to omit stack adjustments
535 #undef FUNCTION_EPILOGUE
536 #define FUNCTION_EPILOGUE(FILE, SIZE) \
537 { register int regno; \
538 register int mask, fmask; \
539 register int nregs; \
540 int offset, foffset, fpoffset; \
541 extern char call_used_regs[]; \
542 int fsize = ((SIZE) + 3) & -4; \
544 nregs = 0; fmask = 0; fpoffset = 0; \
545 for (regno = 16; regno < 24; regno++) \
546 if (regs_ever_live[regno] && ! call_used_regs[regno]) \
547 { nregs++; fmask |= 1 << (23 - regno); } \
548 foffset = fpoffset + nregs * 12; \
549 nregs = 0; mask = 0; \
550 if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
551 for (regno = 0; regno < 16; regno++) \
552 if (regs_ever_live[regno] && ! call_used_regs[regno]) \
553 { nregs++; mask |= 1 << regno; } \
554 offset = foffset + nregs * 4; \
555 if (offset + fsize >= 0x8000 \
556 && frame_pointer_needed \
557 && (mask || fmask || fpoffset)) \
558 { fprintf (FILE, "\tmovel $%d,a0\n", -fsize); \
559 fsize = 0, big = 1; } \
560 if (exact_log2 (mask) >= 0) { \
562 fprintf (FILE, "\tmovel -%d(a6,a0.l),%s\n", \
563 offset + fsize, reg_names[exact_log2 (mask)]); \
564 else if (! frame_pointer_needed) \
565 fprintf (FILE, "\tmovel (sp)+,%s\n", \
566 reg_names[exact_log2 (mask)]); \
568 fprintf (FILE, "\tmovel -%d(a6),%s\n", \
569 offset + fsize, reg_names[exact_log2 (mask)]); } \
572 fprintf (FILE, "\tmovem -%d(a6,a0.l),$0x%x\n", \
573 offset + fsize, mask); \
574 else if (! frame_pointer_needed) \
575 fprintf (FILE, "\tmovem (sp)+,$0x%x\n", mask); \
577 fprintf (FILE, "\tmovem -%d(a6),$0x%x\n", \
578 offset + fsize, mask); } \
581 fprintf (FILE, "\tfmovem -%d(a6,a0.l),$0x%x\n", \
582 foffset + fsize, fmask); \
583 else if (! frame_pointer_needed) \
584 fprintf (FILE, "\tfmovem (sp)+,$0x%x\n", fmask); \
586 fprintf (FILE, "\tfmovem -%d(a6),$0x%x\n", \
587 foffset + fsize, fmask); } \
589 for (regno = 55; regno >= 24; regno--) \
590 if (regs_ever_live[regno] && ! call_used_regs[regno]) { \
592 fprintf(FILE, "\tfpmoved -%d(a6,a0.l), %s\n", \
593 fpoffset + fsize, reg_names[regno]); \
594 else if (! frame_pointer_needed) \
595 fprintf(FILE, "\tfpmoved (sp)+, %s\n", \
598 fprintf(FILE, "\tfpmoved -%d(a6), %s\n", \
599 fpoffset + fsize, reg_names[regno]); \
602 if (frame_pointer_needed) \
603 fprintf (FILE, "\tunlk a6\n"); \
606 if (fsize + 4 < 0x8000) \
608 fprintf (FILE, "\tadd.w #%d,sp\n", fsize + 4); \
612 fprintf (FILE, "\tadd.l #%d,sp\n", fsize + 4); \
615 if (current_function_pops_args) \
616 fprintf (FILE, "\trtd $%d\n", current_function_pops_args); \
617 else fprintf (FILE, "\trts\n"); }