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)
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. */
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. */
53 #define LIB_SPEC "%{!p:%{!pg:-lunos}}%{p:-lc_p}%{pg:-lc_p}"
56 #define STARTFILE_SPEC \
57 "%{pg:gcrt0.o%s}%{!pg:%{p:mc68rt0.o%s}%{!p:c68rt0.o%s}}"
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"
66 /* -O2 for MAX optimization */
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 :-( */
82 #define gen_probe() gen_rtx(ASM_INPUT, VOIDmode, "tstb -2048(sp)\t;probe\n")
85 #define NEED_PROBE (-2048)
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. */
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) \
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. */
148 #define ASM_APP_ON ";#APP\n"
150 /* Output to assembler file text saying following lines
151 no longer contain unusual constructs. */
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) \
166 REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
167 fprintf (FILE, "\t.long 0x%x, 0x%x\n", l[0], l[1]); \
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) \
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) \
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 != '\\') { \
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"); \
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') \
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; } \
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) == '!')
272 #define PRINT_OPERAND(FILE, X, 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]); \
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); \
303 ASM_OUTPUT_FLOAT_OPERAND (CODE, FILE, r); \
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); }}
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; \
327 switch (GET_CODE (addr)) \
330 fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
333 fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
336 fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
339 reg1 = 0; reg2 = 0; \
340 ireg = 0; breg = 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) \
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))]); \
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); \
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)]); \
418 if (ireg != 0 || breg != 0) \
422 if (addr && GET_CODE (addr) == LABEL_REF) abort (); \
424 output_addr_const (FILE, addr); \
425 fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
426 if (breg != 0 && ireg != 0) \
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); \
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)]); \
446 if (GET_CODE (addr) == CONST_INT \
447 && INTVAL (addr) < 0x8000 \
448 && INTVAL (addr) >= -0x8000) \
449 fprintf (FILE, "%d", INTVAL (addr)); \
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"); \
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"); \
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); \
494 fprintf (FILE, "\tlink a6,$0\n\tsubl $%d,sp\n", 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)); \
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); \
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 */
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
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; \
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) { \
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)]); \
571 fprintf (FILE, "\tmovel -%d(a6),%s\n", \
572 offset + fsize, reg_names[exact_log2 (mask)]); } \
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); \
580 fprintf (FILE, "\tmovem -%d(a6),$0x%x\n", \
581 offset + fsize, mask); } \
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); \
589 fprintf (FILE, "\tfmovem -%d(a6),$0x%x\n", \
590 foffset + fsize, fmask); } \
592 for (regno = 55; regno >= 24; regno--) \
593 if (regs_ever_live[regno] && ! call_used_regs[regno]) { \
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", \
601 fprintf(FILE, "\tfpmoved -%d(a6), %s\n", \
602 fpoffset + fsize, reg_names[regno]); \
605 if (frame_pointer_needed) \
606 fprintf (FILE, "\tunlk a6\n"); \
609 if (fsize + 4 < 0x8000) \
611 fprintf (FILE, "\tadd.w #%d,sp\n", fsize + 4); \
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"); }