Restore definition of STRUCT_VALUE_REGNUM,
[official-gcc.git] / gcc / config / m68k / m68k.c
blobf8932037775a3afc2cc334725ab8300a8d72835c
1 /* Subroutines for insn-output.c for Motorola 68000 family.
2 Copyright (C) 1987, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include "config.h"
23 #include "system.h"
24 #include "tree.h"
25 #include "rtl.h"
26 #include "function.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "real.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "output.h"
33 #include "insn-attr.h"
34 #include "recog.h"
35 #include "toplev.h"
36 #include "expr.h"
37 #include "reload.h"
38 #include "tm_p.h"
39 #include "target.h"
40 #include "target-def.h"
41 #include "debug.h"
43 /* Needed for use_return_insn. */
44 #include "flags.h"
46 #ifdef SUPPORT_SUN_FPA
48 /* Index into this array by (register number >> 3) to find the
49 smallest class which contains that register. */
50 enum reg_class regno_reg_class[]
51 = { DATA_REGS, ADDR_REGS, FP_REGS,
52 LO_FPA_REGS, LO_FPA_REGS, FPA_REGS, FPA_REGS };
54 #endif /* defined SUPPORT_SUN_FPA */
56 /* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
57 if SGS_SWITCH_TABLE. */
58 int switch_table_difference_label_flag;
60 static rtx find_addr_reg PARAMS ((rtx));
61 static const char *singlemove_string PARAMS ((rtx *));
62 static void m68k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
63 static void m68k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
64 static void m68k_coff_asm_named_section PARAMS ((const char *, unsigned int));
65 #ifdef CTOR_LIST_BEGIN
66 static void m68k_svr3_asm_out_constructor PARAMS ((rtx, int));
67 #endif
70 /* Alignment to use for loops and jumps */
71 /* Specify power of two alignment used for loops. */
72 const char *m68k_align_loops_string;
73 /* Specify power of two alignment used for non-loop jumps. */
74 const char *m68k_align_jumps_string;
75 /* Specify power of two alignment used for functions. */
76 const char *m68k_align_funcs_string;
78 /* Specify power of two alignment used for loops. */
79 int m68k_align_loops;
80 /* Specify power of two alignment used for non-loop jumps. */
81 int m68k_align_jumps;
82 /* Specify power of two alignment used for functions. */
83 int m68k_align_funcs;
85 /* Nonzero if the last compare/test insn had FP operands. The
86 sCC expanders peek at this to determine what to do for the
87 68060, which has no fsCC instructions. */
88 int m68k_last_compare_had_fp_operands;
90 /* Initialize the GCC target structure. */
91 #undef TARGET_ASM_FUNCTION_PROLOGUE
92 #define TARGET_ASM_FUNCTION_PROLOGUE m68k_output_function_prologue
93 #undef TARGET_ASM_FUNCTION_EPILOGUE
94 #define TARGET_ASM_FUNCTION_EPILOGUE m68k_output_function_epilogue
96 struct gcc_target targetm = TARGET_INITIALIZER;
98 /* Sometimes certain combinations of command options do not make
99 sense on a particular target machine. You can define a macro
100 `OVERRIDE_OPTIONS' to take account of this. This macro, if
101 defined, is executed once just after all the command options have
102 been parsed.
104 Don't use this macro to turn on various extra optimizations for
105 `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
107 void
108 override_options ()
110 int def_align;
111 int i;
113 def_align = 1;
115 /* Validate -malign-loops= value, or provide default */
116 m68k_align_loops = def_align;
117 if (m68k_align_loops_string)
119 i = atoi (m68k_align_loops_string);
120 if (i < 1 || i > MAX_CODE_ALIGN)
121 error ("-malign-loops=%d is not between 1 and %d", i, MAX_CODE_ALIGN);
122 else
123 m68k_align_loops = i;
126 /* Validate -malign-jumps= value, or provide default */
127 m68k_align_jumps = def_align;
128 if (m68k_align_jumps_string)
130 i = atoi (m68k_align_jumps_string);
131 if (i < 1 || i > MAX_CODE_ALIGN)
132 error ("-malign-jumps=%d is not between 1 and %d", i, MAX_CODE_ALIGN);
133 else
134 m68k_align_jumps = i;
137 /* Validate -malign-functions= value, or provide default */
138 m68k_align_funcs = def_align;
139 if (m68k_align_funcs_string)
141 i = atoi (m68k_align_funcs_string);
142 if (i < 1 || i > MAX_CODE_ALIGN)
143 error ("-malign-functions=%d is not between 1 and %d",
144 i, MAX_CODE_ALIGN);
145 else
146 m68k_align_funcs = i;
150 /* This function generates the assembly code for function entry.
151 STREAM is a stdio stream to output the code to.
152 SIZE is an int: how many units of temporary storage to allocate.
153 Refer to the array `regs_ever_live' to determine which registers
154 to save; `regs_ever_live[I]' is nonzero if register number I
155 is ever used in the function. This function is responsible for
156 knowing which registers should not be saved even if used. */
159 /* Note that the order of the bit mask for fmovem is the opposite
160 of the order for movem! */
162 #ifdef CRDS
164 static void
165 m68k_output_function_prologue (stream, size)
166 FILE *stream;
167 HOST_WIDE_INT size;
169 register int regno;
170 register int mask = 0;
171 extern char call_used_regs[];
172 HOST_WIDE_INT fsize = ((size) + 3) & -4;
174 /* unos stack probe */
175 if (fsize > 30000)
177 fprintf (stream, "\tmovel sp,a0\n");
178 fprintf (stream, "\taddl $-%d,a0\n", 2048 + fsize);
179 fprintf (stream, "\ttstb (a0)\n");
181 else
182 fprintf (stream, "\ttstb -%d(sp)\n", 2048 + fsize);
184 if (frame_pointer_needed)
186 if (TARGET_68020 || fsize < 0x8000)
187 fprintf (stream, "\tlink a6,$%d\n", -fsize);
188 else
189 fprintf (stream, "\tlink a6,$0\n\tsubl $%d,sp\n", fsize);
191 else if (fsize)
193 /* Adding negative number is faster on the 68040. */
194 if (fsize + 4 < 0x8000)
195 fprintf (stream, "\tadd.w #%d,sp\n", - (fsize + 4));
196 else
197 fprintf (stream, "\tadd.l #%d,sp\n", - (fsize + 4));
200 for (regno = 16; regno < 24; regno++)
201 if (regs_ever_live[regno] && ! call_used_regs[regno])
202 mask |= 1 << (regno - 16);
204 if ((mask & 0xff) != 0)
205 fprintf (stream, "\tfmovem $0x%x,-(sp)\n", mask & 0xff);
207 mask = 0;
208 for (regno = 0; regno < 16; regno++)
209 if (regs_ever_live[regno] && ! call_used_regs[regno])
210 mask |= 1 << (15 - regno);
211 if (frame_pointer_needed)
212 mask &= ~ (1 << (15-FRAME_POINTER_REGNUM));
214 if (exact_log2 (mask) >= 0)
215 fprintf (stream, "\tmovel %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]);
216 else if (mask)
217 fprintf (stream, "\tmovem $0x%x,-(sp)\n", mask);
220 #else
221 #if defined (DPX2) && defined (MOTOROLA)
223 static void
224 m68k_output_function_prologue (stream, size)
225 FILE *stream;
226 HOST_WIDE_INT size;
228 register int regno;
229 register int mask = 0;
230 int num_saved_regs = 0, first = 1;
231 extern char call_used_regs[];
232 HOST_WIDE_INT fsize = ((size) + 3) & -4;
234 if (frame_pointer_needed)
236 /* Adding negative number is faster on the 68040. */
237 if (fsize < 0x8000 && !TARGET_68040)
238 fprintf (stream, "\tlink %s,#%d\n",
239 reg_names[FRAME_POINTER_REGNUM], -fsize);
240 else if (TARGET_68020)
241 fprintf (stream, "\tlink %s,#%d\n",
242 reg_names[FRAME_POINTER_REGNUM], -fsize);
243 else
244 fprintf (stream, "\tlink %s,#0\n\tadd.l #%d,sp\n",
245 reg_names[FRAME_POINTER_REGNUM], -fsize);
247 else if (fsize)
249 /* Adding negative number is faster on the 68040. */
250 if (fsize + 4 < 0x8000)
251 fprintf (stream, "\tadd.w #%d,sp\n", - (fsize + 4));
252 else
253 fprintf (stream, "\tadd.l #%d,sp\n", - (fsize + 4));
256 for (regno = 23; regno >= 16; regno--)
257 if (regs_ever_live[regno] && ! call_used_regs[regno])
259 if (first)
261 fprintf (stream, "\tfmovem.x %s", reg_names[regno]);
262 first = 0;
264 else
265 fprintf (stream, "/%s", reg_names[regno]);
267 if (!first)
268 fprintf (stream, ",-(sp)\n");
270 mask = 0;
271 for (regno = 0; regno < 16; regno++)
272 if (regs_ever_live[regno] && ! call_used_regs[regno])
274 mask |= 1 << (15 - regno);
275 num_saved_regs++;
278 if (frame_pointer_needed)
280 mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));
281 num_saved_regs--;
284 if (num_saved_regs <= 2)
286 /* Store each separately in the same order moveml uses.
287 Using two movel instructions instead of a single moveml
288 is about 15% faster for the 68020 and 68030 at no expense
289 in code size */
291 int i;
293 /* Undo the work from above. */
294 for (i = 0; i< 16; i++)
295 if (mask & (1 << i))
296 fprintf (stream, "\tmove.l %s,-(sp)\n", reg_names[15 - i]);
298 else if (mask)
300 first = 1;
301 for (regno = 0; regno < 16; regno++)
302 if (mask & (1 << regno))
304 if (first)
306 fprintf (stream, "\tmovem.l %s", reg_names[15 - regno]);
307 first = 0;
309 else
310 fprintf (stream, "/%s", reg_names[15 - regno]);
312 fprintf (stream, ",-(sp)\n");
315 if (flag_pic && current_function_uses_pic_offset_table)
317 fprintf (stream, "\tmove.l #__GLOBAL_OFFSET_TABLE_, %s\n",
318 reg_names[PIC_OFFSET_TABLE_REGNUM]);
319 fprintf (stream, "\tlea.l (pc,%s.l),%s\n",
320 reg_names[PIC_OFFSET_TABLE_REGNUM],
321 reg_names[PIC_OFFSET_TABLE_REGNUM]);
325 #else
326 #if defined (NEWS) && defined (MOTOROLA)
328 static void
329 m68k_output_function_prologue (stream, size)
330 FILE *stream;
331 HOST_WIDE_INT size;
333 register int regno;
334 register int mask = 0;
335 extern char call_used_regs[];
336 HOST_WIDE_INT fsize = ((size) + 3) & -4;
338 if (frame_pointer_needed)
340 if (fsize < 0x8000)
341 fprintf (stream, "\tlink fp,#%d\n", -fsize);
342 else if (TARGET_68020)
343 fprintf (stream, "\tlink.l fp,#%d\n", -fsize);
344 else
345 fprintf (stream, "\tlink fp,#0\n\tsub.l #%d,sp\n", fsize);
347 else if (fsize)
349 int amt = fsize + 4;
350 /* Adding negative number is faster on the 68040. */
351 if (fsize + 4 < 0x8000)
352 asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - amt);
353 else
354 asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", - amt);
357 for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++)
358 if (regs_ever_live[regno] && ! call_used_regs[regno])
359 mask |= 1 << (regno - 16);
361 if (mask != 0)
362 fprintf (stream, "\tfmovem.x #0x%x,-(sp)\n", mask & 0xff);
364 mask = 0;
365 for (regno = 0; regno < 16; regno++)
366 if (regs_ever_live[regno] && ! call_used_regs[regno])
367 mask |= 1 << (15 - regno);
369 if (frame_pointer_needed)
370 mask &= ~ (1 << (15-FRAME_POINTER_REGNUM));
372 if (exact_log2 (mask) >= 0)
373 fprintf (stream, "\tmove.l %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]);
374 else
375 if (mask) fprintf (stream, "\tmovem.l #0x%x,-(sp)\n", mask);
378 #else /* !CRDS && ! (NEWS && MOTOROLA) && ! (DPX2 && MOTOROLA) */
380 static void
381 m68k_output_function_prologue (stream, size)
382 FILE *stream;
383 HOST_WIDE_INT size;
385 register int regno;
386 register int mask = 0;
387 int num_saved_regs = 0;
388 extern char call_used_regs[];
389 HOST_WIDE_INT fsize = (size + 3) & -4;
390 HOST_WIDE_INT cfa_offset = INCOMING_FRAME_SP_OFFSET;
391 HOST_WIDE_INT cfa_store_offset = cfa_offset;
393 /* If the stack limit is a symbol, we can check it here,
394 before actually allocating the space. */
395 if (current_function_limit_stack
396 && GET_CODE (stack_limit_rtx) == SYMBOL_REF)
398 #if defined (MOTOROLA)
399 asm_fprintf (stream, "\tcmp.l %0I%s+%d,%Rsp\n\ttrapcs\n",
400 XSTR (stack_limit_rtx, 0), fsize + 4);
401 #else
402 asm_fprintf (stream, "\tcmpl %0I%s+%d,%Rsp\n\ttrapcs\n",
403 XSTR (stack_limit_rtx, 0), fsize + 4);
404 #endif
407 if (frame_pointer_needed)
409 if (fsize == 0 && TARGET_68040)
411 /* on the 68040, pea + move is faster than link.w 0 */
412 #ifdef MOTOROLA
413 asm_fprintf (stream, "\tpea (%s)\n\tmove.l %s,%s\n",
414 reg_names[FRAME_POINTER_REGNUM], reg_names[STACK_POINTER_REGNUM],
415 reg_names[FRAME_POINTER_REGNUM]);
416 #else
417 asm_fprintf (stream, "\tpea %s@\n\tmovel %s,%s\n",
418 reg_names[FRAME_POINTER_REGNUM], reg_names[STACK_POINTER_REGNUM],
419 reg_names[FRAME_POINTER_REGNUM]);
420 #endif
422 else if (fsize < 0x8000)
424 #ifdef MOTOROLA
425 asm_fprintf (stream, "\tlink.w %s,%0I%d\n",
426 reg_names[FRAME_POINTER_REGNUM], -fsize);
427 #else
428 asm_fprintf (stream, "\tlink %s,%0I%d\n",
429 reg_names[FRAME_POINTER_REGNUM], -fsize);
430 #endif
432 else if (TARGET_68020)
434 #ifdef MOTOROLA
435 asm_fprintf (stream, "\tlink.l %s,%0I%d\n",
436 reg_names[FRAME_POINTER_REGNUM], -fsize);
437 #else
438 asm_fprintf (stream, "\tlink %s,%0I%d\n",
439 reg_names[FRAME_POINTER_REGNUM], -fsize);
440 #endif
442 else
444 /* Adding negative number is faster on the 68040. */
445 #ifdef MOTOROLA
446 asm_fprintf (stream, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
447 reg_names[FRAME_POINTER_REGNUM], -fsize);
448 #else
449 asm_fprintf (stream, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
450 reg_names[FRAME_POINTER_REGNUM], -fsize);
451 #endif
453 if (dwarf2out_do_frame ())
455 char *l;
456 l = (char *) dwarf2out_cfi_label ();
457 cfa_store_offset += 4;
458 cfa_offset = cfa_store_offset;
459 dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, -cfa_store_offset);
460 dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, cfa_offset);
461 cfa_store_offset += fsize;
464 else if (fsize)
466 if (fsize + 4 < 0x8000)
468 #ifndef NO_ADDSUB_Q
469 if (fsize + 4 <= 8)
471 if (!TARGET_5200)
473 /* asm_fprintf() cannot handle %. */
474 #ifdef MOTOROLA
475 asm_fprintf (stream, "\tsubq.w %0I%d,%Rsp\n", fsize + 4);
476 #else
477 asm_fprintf (stream, "\tsubqw %0I%d,%Rsp\n", fsize + 4);
478 #endif
480 else
482 /* asm_fprintf() cannot handle %. */
483 #ifdef MOTOROLA
484 asm_fprintf (stream, "\tsubq.l %0I%d,%Rsp\n", fsize + 4);
485 #else
486 asm_fprintf (stream, "\tsubql %0I%d,%Rsp\n", fsize + 4);
487 #endif
490 else if (fsize + 4 <= 16 && TARGET_CPU32)
492 /* On the CPU32 it is faster to use two subqw instructions to
493 subtract a small integer (8 < N <= 16) to a register. */
494 /* asm_fprintf() cannot handle %. */
495 #ifdef MOTOROLA
496 asm_fprintf (stream, "\tsubq.w %0I8,%Rsp\n\tsubq.w %0I%d,%Rsp\n",
497 fsize + 4 - 8);
498 #else
499 asm_fprintf (stream, "\tsubqw %0I8,%Rsp\n\tsubqw %0I%d,%Rsp\n",
500 fsize + 4 - 8);
501 #endif
503 else
504 #endif /* not NO_ADDSUB_Q */
505 if (TARGET_68040)
507 /* Adding negative number is faster on the 68040. */
508 /* asm_fprintf() cannot handle %. */
509 #ifdef MOTOROLA
510 asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - (fsize + 4));
511 #else
512 asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", - (fsize + 4));
513 #endif
515 else
517 #ifdef MOTOROLA
518 asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", - (fsize + 4));
519 #else
520 asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", - (fsize + 4));
521 #endif
524 else
526 /* asm_fprintf() cannot handle %. */
527 #ifdef MOTOROLA
528 asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", - (fsize + 4));
529 #else
530 asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", - (fsize + 4));
531 #endif
533 if (dwarf2out_do_frame ())
535 cfa_store_offset += fsize;
536 cfa_offset = cfa_store_offset;
537 dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset);
540 #ifdef SUPPORT_SUN_FPA
541 for (regno = 24; regno < 56; regno++)
542 if (regs_ever_live[regno] && ! call_used_regs[regno])
544 #ifdef MOTOROLA
545 asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n",
546 reg_names[regno]);
547 #else
548 asm_fprintf (stream, "\tfpmoved %s,%Rsp@-\n",
549 reg_names[regno]);
550 #endif
551 if (dwarf2out_do_frame ())
553 char *l = dwarf2out_cfi_label ();
555 cfa_store_offset += 8;
556 if (! frame_pointer_needed)
558 cfa_offset = cfa_store_offset;
559 dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
561 dwarf2out_reg_save (l, regno, -cfa_store_offset);
564 #endif
565 if (TARGET_68881)
567 for (regno = 16; regno < 24; regno++)
568 if (regs_ever_live[regno] && ! call_used_regs[regno])
570 mask |= 1 << (regno - 16);
571 num_saved_regs++;
573 if ((mask & 0xff) != 0)
575 #ifdef MOTOROLA
576 asm_fprintf (stream, "\tfmovm %0I0x%x,-(%Rsp)\n", mask & 0xff);
577 #else
578 asm_fprintf (stream, "\tfmovem %0I0x%x,%Rsp@-\n", mask & 0xff);
579 #endif
580 if (dwarf2out_do_frame ())
582 char *l = (char *) dwarf2out_cfi_label ();
583 int n_regs;
585 cfa_store_offset += num_saved_regs * 12;
586 if (! frame_pointer_needed)
588 cfa_offset = cfa_store_offset;
589 dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
591 for (regno = 16, n_regs = 0; regno < 24; regno++)
592 if (mask & (1 << (regno - 16)))
593 dwarf2out_reg_save (l, regno,
594 -cfa_store_offset + n_regs++ * 12);
597 mask = 0;
598 num_saved_regs = 0;
600 for (regno = 0; regno < 16; regno++)
601 if (regs_ever_live[regno] && ! call_used_regs[regno])
603 mask |= 1 << (15 - regno);
604 num_saved_regs++;
606 if (frame_pointer_needed)
608 mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));
609 num_saved_regs--;
611 if (flag_pic && current_function_uses_pic_offset_table)
613 mask |= 1 << (15 - PIC_OFFSET_TABLE_REGNUM);
614 num_saved_regs++;
617 #if NEED_PROBE
618 #ifdef MOTOROLA
619 asm_fprintf (stream, "\ttst.l %d(%Rsp)\n", NEED_PROBE - num_saved_regs * 4);
620 #else
621 asm_fprintf (stream, "\ttstl %Rsp@(%d)\n", NEED_PROBE - num_saved_regs * 4);
622 #endif
623 #endif
625 /* If the stack limit is not a symbol, check it here.
626 This has the disadvantage that it may be too late... */
627 if (current_function_limit_stack)
629 if (REG_P (stack_limit_rtx))
631 #if defined (MOTOROLA)
632 asm_fprintf (stream, "\tcmp.l %s,%Rsp\n\ttrapcs\n",
633 reg_names[REGNO (stack_limit_rtx)]);
634 #else
635 asm_fprintf (stream, "\tcmpl %s,%Rsp\n\ttrapcs\n",
636 reg_names[REGNO (stack_limit_rtx)]);
637 #endif
639 else if (GET_CODE (stack_limit_rtx) != SYMBOL_REF)
640 warning ("stack limit expression is not supported");
643 if (num_saved_regs <= 2)
645 /* Store each separately in the same order moveml uses.
646 Using two movel instructions instead of a single moveml
647 is about 15% faster for the 68020 and 68030 at no expense
648 in code size */
650 int i;
652 /* Undo the work from above. */
653 for (i = 0; i< 16; i++)
654 if (mask & (1 << i))
656 asm_fprintf (stream,
657 #ifdef MOTOROLA
658 "\t%Omove.l %s,-(%Rsp)\n",
659 #else
660 "\tmovel %s,%Rsp@-\n",
661 #endif
662 reg_names[15 - i]);
663 if (dwarf2out_do_frame ())
665 char *l = (char *) dwarf2out_cfi_label ();
667 cfa_store_offset += 4;
668 if (! frame_pointer_needed)
670 cfa_offset = cfa_store_offset;
671 dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
673 dwarf2out_reg_save (l, 15 - i, -cfa_store_offset);
677 else if (mask)
679 if (TARGET_5200)
681 /* The coldfire does not support the predecrement form of the
682 movml instruction, so we must adjust the stack pointer and
683 then use the plain address register indirect mode. We also
684 have to invert the register save mask to use the new mode.
686 FIXME: if num_saved_regs was calculated earlier, we could
687 combine the stack pointer adjustment with any adjustment
688 done when the initial stack frame is created. This would
689 save an instruction */
691 int newmask = 0;
692 int i;
694 for (i = 0; i < 16; i++)
695 if (mask & (1 << i))
696 newmask |= (1 << (15-i));
698 #ifdef MOTOROLA
699 asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", -num_saved_regs*4);
700 asm_fprintf (stream, "\tmovm.l %0I0x%x,(%Rsp)\n", newmask);
701 #else
702 asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", -num_saved_regs*4);
703 asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@\n", newmask);
704 #endif
706 else
708 #ifdef MOTOROLA
709 asm_fprintf (stream, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask);
710 #else
711 asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@-\n", mask);
712 #endif
714 if (dwarf2out_do_frame ())
716 char *l = (char *) dwarf2out_cfi_label ();
717 int n_regs;
719 cfa_store_offset += num_saved_regs * 4;
720 if (! frame_pointer_needed)
722 cfa_offset = cfa_store_offset;
723 dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
725 for (regno = 0, n_regs = 0; regno < 16; regno++)
726 if (mask & (1 << (15 - regno)))
727 dwarf2out_reg_save (l, regno,
728 -cfa_store_offset + n_regs++ * 4);
731 if (flag_pic && current_function_uses_pic_offset_table)
733 #ifdef MOTOROLA
734 asm_fprintf (stream, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
735 reg_names[PIC_OFFSET_TABLE_REGNUM]);
736 #else
737 asm_fprintf (stream, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
738 reg_names[PIC_OFFSET_TABLE_REGNUM]);
739 asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n",
740 reg_names[PIC_OFFSET_TABLE_REGNUM],
741 reg_names[PIC_OFFSET_TABLE_REGNUM]);
742 #endif
745 #endif /* ! (DPX2 && MOTOROLA) */
746 #endif /* ! (NEWS && MOTOROLA) */
747 #endif /* !CRDS */
749 /* Return true if this function's epilogue can be output as RTL. */
752 use_return_insn ()
754 int regno;
756 if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)
757 return 0;
759 /* Copied from output_function_epilogue (). We should probably create a
760 separate layout routine to perform the common work. */
762 for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++)
763 if (regs_ever_live[regno] && ! call_used_regs[regno])
764 return 0;
766 if (flag_pic && current_function_uses_pic_offset_table)
767 return 0;
769 return 1;
772 /* This function generates the assembly code for function exit,
773 on machines that need it.
775 The function epilogue should not depend on the current stack pointer!
776 It should use the frame pointer only, if there is a frame pointer.
777 This is mandatory because of alloca; we also take advantage of it to
778 omit stack adjustments before returning. */
780 #ifdef CRDS
782 static void
783 m68k_output_function_epilogue (stream, size)
784 FILE *stream;
785 HOST_WIDE_INT size;
787 register int regno;
788 register int mask, fmask;
789 register int nregs;
790 HOST_WIDE_INT offset, foffset, fpoffset;
791 extern char call_used_regs[];
792 HOST_WIDE_INT fsize = ((size) + 3) & -4;
793 int big = 0;
795 nregs = 0; fmask = 0; fpoffset = 0;
796 for (regno = 16; regno < 24; regno++)
797 if (regs_ever_live[regno] && ! call_used_regs[regno])
799 nregs++;
800 fmask |= 1 << (23 - regno);
803 foffset = fpoffset + nregs * 12;
804 nregs = 0; mask = 0;
805 if (frame_pointer_needed)
806 regs_ever_live[FRAME_POINTER_REGNUM] = 0;
808 for (regno = 0; regno < 16; regno++)
809 if (regs_ever_live[regno] && ! call_used_regs[regno])
811 nregs++;
812 mask |= 1 << regno;
815 offset = foffset + nregs * 4;
816 if (offset + fsize >= 0x8000
817 && frame_pointer_needed
818 && (mask || fmask || fpoffset))
820 fprintf (stream, "\tmovel $%d,a0\n", -fsize);
821 fsize = 0, big = 1;
824 if (exact_log2 (mask) >= 0)
826 if (big)
827 fprintf (stream, "\tmovel -%d(a6,a0.l),%s\n",
828 offset + fsize, reg_names[exact_log2 (mask)]);
829 else if (! frame_pointer_needed)
830 fprintf (stream, "\tmovel (sp)+,%s\n",
831 reg_names[exact_log2 (mask)]);
832 else
833 fprintf (stream, "\tmovel -%d(a6),%s\n",
834 offset + fsize, reg_names[exact_log2 (mask)]);
836 else if (mask)
838 if (big)
839 fprintf (stream, "\tmovem -%d(a6,a0.l),$0x%x\n",
840 offset + fsize, mask);
841 else if (! frame_pointer_needed)
842 fprintf (stream, "\tmovem (sp)+,$0x%x\n", mask);
843 else
844 fprintf (stream, "\tmovem -%d(a6),$0x%x\n",
845 offset + fsize, mask);
848 if (fmask)
850 if (big)
851 fprintf (stream, "\tfmovem -%d(a6,a0.l),$0x%x\n",
852 foffset + fsize, fmask);
853 else if (! frame_pointer_needed)
854 fprintf (stream, "\tfmovem (sp)+,$0x%x\n", fmask);
855 else
856 fprintf (stream, "\tfmovem -%d(a6),$0x%x\n",
857 foffset + fsize, fmask);
860 if (fpoffset != 0)
861 for (regno = 55; regno >= 24; regno--)
862 if (regs_ever_live[regno] && ! call_used_regs[regno])
864 if (big)
865 fprintf(stream, "\tfpmoved -%d(a6,a0.l), %s\n",
866 fpoffset + fsize, reg_names[regno]);
867 else if (! frame_pointer_needed)
868 fprintf(stream, "\tfpmoved (sp)+, %s\n",
869 reg_names[regno]);
870 else
871 fprintf(stream, "\tfpmoved -%d(a6), %s\n",
872 fpoffset + fsize, reg_names[regno]);
873 fpoffset -= 8;
876 if (frame_pointer_needed)
877 fprintf (stream, "\tunlk a6\n");
878 else if (fsize)
880 if (fsize + 4 < 0x8000)
881 fprintf (stream, "\tadd.w #%d,sp\n", fsize + 4);
882 else
883 fprintf (stream, "\tadd.l #%d,sp\n", fsize + 4);
886 if (current_function_pops_args)
887 fprintf (stream, "\trtd $%d\n", current_function_pops_args);
888 else
889 fprintf (stream, "\trts\n");
892 #else
893 #if defined (DPX2) && defined (MOTOROLA)
895 static void
896 m68k_output_function_epilogue (stream, size)
897 FILE *stream;
898 HOST_WIDE_INT size;
900 register int regno;
901 register int mask, fmask;
902 register int nregs;
903 HOST_WIDE_INT offset, foffset, fpoffset, first = 1;
904 extern char call_used_regs[];
905 HOST_WIDE_INT fsize = ((size) + 3) & -4;
906 int big = 0;
907 rtx insn = get_last_insn ();
909 /* If the last insn was a BARRIER, we don't have to write any code. */
910 if (GET_CODE (insn) == NOTE)
911 insn = prev_nonnote_insn (insn);
912 if (insn && GET_CODE (insn) == BARRIER)
914 /* Output just a no-op so that debuggers don't get confused
915 about which function the pc is in at this address. */
916 fprintf (stream, "\tnop\n");
917 return;
920 nregs = 0; fmask = 0; fpoffset = 0;
921 for (regno = 16; regno < 24; regno++)
922 if (regs_ever_live[regno] && ! call_used_regs[regno])
924 nregs++;
925 fmask |= 1 << (23 - regno);
928 foffset = fpoffset + nregs * 12;
929 nregs = 0; mask = 0;
930 if (frame_pointer_needed)
931 regs_ever_live[FRAME_POINTER_REGNUM] = 0;
933 for (regno = 0; regno < 16; regno++)
934 if (regs_ever_live[regno] && ! call_used_regs[regno])
936 nregs++;
937 mask |= 1 << regno;
940 offset = foffset + nregs * 4;
941 if (offset + fsize >= 0x8000
942 && frame_pointer_needed
943 && (mask || fmask || fpoffset))
945 fprintf (stream, "\tmove.l #%d,a0\n", -fsize);
946 fsize = 0, big = 1;
949 if (nregs <= 2)
951 /* Restore each separately in the same order moveml does.
952 Using two movel instructions instead of a single moveml
953 is about 15% faster for the 68020 and 68030 at no expense
954 in code size. */
956 int i;
958 /* Undo the work from above. */
959 for (i = 0; i< 16; i++)
960 if (mask & (1 << i))
962 if (big)
963 fprintf (stream, "\tmove.l -%d(%s,a0.l),%s\n",
964 offset + fsize,
965 reg_names[FRAME_POINTER_REGNUM],
966 reg_names[i]);
967 else if (! frame_pointer_needed)
968 fprintf (stream, "\tmove.l (sp)+,%s\n",
969 reg_names[i]);
970 else
971 fprintf (stream, "\tmove.l -%d(%s),%s\n",
972 offset + fsize,
973 reg_names[FRAME_POINTER_REGNUM],
974 reg_names[i]);
975 offset = offset - 4;
978 else if (mask)
980 first = 1;
981 for (regno = 0; regno < 16; regno++)
982 if (mask & (1 << regno))
984 if (first && big)
986 fprintf (stream, "\tmovem.l -%d(%s,a0.l),%s",
987 offset + fsize,
988 reg_names[FRAME_POINTER_REGNUM],
989 reg_names[regno]);
990 first = 0;
992 else if (first && ! frame_pointer_needed)
994 fprintf (stream, "\tmovem.l (sp)+,%s",
995 reg_names[regno]);
996 first = 0;
998 else if (first)
1000 fprintf (stream, "\tmovem.l -%d(%s),%s",
1001 offset + fsize,
1002 reg_names[FRAME_POINTER_REGNUM],
1003 reg_names[regno]);
1004 first = 0;
1006 else
1007 fprintf (stream, "/%s", reg_names[regno]);
1009 fprintf (stream, "\n");
1012 if (fmask)
1014 first = 1;
1015 for (regno = 16; regno < 24; regno++)
1016 if (fmask & (1 << (23 - regno)))
1018 if (first && big)
1020 fprintf (stream, "\tfmovem.x -%d(%s,a0.l),%s",
1021 foffset + fsize,
1022 reg_names[FRAME_POINTER_REGNUM],
1023 reg_names[regno]);
1024 first = 0;
1026 else if (first && ! frame_pointer_needed)
1028 fprintf (stream, "\tfmovem.x (sp)+,%s",
1029 reg_names[regno]);
1030 first = 0;
1032 else if (first)
1034 fprintf (stream, "\tfmovem.x -%d(%s),%s",
1035 foffset + fsize,
1036 reg_names[FRAME_POINTER_REGNUM],
1037 reg_names[regno]);
1038 first = 0;
1040 else
1041 fprintf (stream, "/%s", reg_names[regno]);
1043 fprintf (stream, "\n");
1046 if (frame_pointer_needed)
1047 fprintf (stream, "\tunlk %s\n",
1048 reg_names[FRAME_POINTER_REGNUM]);
1049 else if (fsize)
1051 if (fsize + 4 < 0x8000)
1052 fprintf (stream, "\tadd.w #%d,sp\n", fsize + 4);
1053 else
1054 fprintf (stream, "\tadd.l #%d,sp\n", fsize + 4);
1057 if (current_function_pops_args)
1058 fprintf (stream, "\trtd #%d\n", current_function_pops_args);
1059 else
1060 fprintf (stream, "\trts\n");
1063 #else
1064 #if defined (NEWS) && defined (MOTOROLA)
1066 static void
1067 m68k_output_function_epilogue (stream, size)
1068 FILE *stream;
1069 HOST_WIDE_INT size;
1071 register int regno;
1072 register int mask, fmask;
1073 register int nregs;
1074 HOST_WIDE_INT offset, foffset;
1075 extern char call_used_regs[];
1076 HOST_WIDE_INT fsize = ((size) + 3) & -4;
1077 int big = 0;
1079 nregs = 0; fmask = 0;
1080 for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++)
1081 if (regs_ever_live[regno] && ! call_used_regs[regno])
1083 nregs++;
1084 fmask |= 1 << (23 - regno);
1087 foffset = nregs * 12;
1088 nregs = 0; mask = 0;
1089 if (frame_pointer_needed)
1090 regs_ever_live[FRAME_POINTER_REGNUM] = 0;
1092 for (regno = 0; regno < 16; regno++)
1093 if (regs_ever_live[regno] && ! call_used_regs[regno])
1095 nregs++;
1096 mask |= 1 << regno;
1099 offset = foffset + nregs * 4;
1100 if (offset + fsize >= 0x8000
1101 && frame_pointer_needed
1102 && (mask || fmask))
1104 fprintf (stream, "\tmove.l #%d,a0\n", -fsize);
1105 fsize = 0, big = 1;
1108 if (exact_log2 (mask) >= 0)
1110 if (big)
1111 fprintf (stream, "\tmove.l (-%d,fp,a0.l),%s\n",
1112 offset + fsize, reg_names[exact_log2 (mask)]);
1113 else if (! frame_pointer_needed)
1114 fprintf (stream, "\tmove.l (sp)+,%s\n",
1115 reg_names[exact_log2 (mask)]);
1116 else
1117 fprintf (stream, "\tmove.l (-%d,fp),%s\n",
1118 offset + fsize, reg_names[exact_log2 (mask)]);
1120 else if (mask)
1122 if (big)
1123 fprintf (stream, "\tmovem.l (-%d,fp,a0.l),#0x%x\n",
1124 offset + fsize, mask);
1125 else if (! frame_pointer_needed)
1126 fprintf (stream, "\tmovem.l (sp)+,#0x%x\n", mask);
1127 else
1128 fprintf (stream, "\tmovem.l (-%d,fp),#0x%x\n",
1129 offset + fsize, mask);
1132 if (fmask)
1134 if (big)
1135 fprintf (stream, "\tfmovem.x (-%d,fp,a0.l),#0x%x\n",
1136 foffset + fsize, fmask);
1137 else if (! frame_pointer_needed)
1138 fprintf (stream, "\tfmovem.x (sp)+,#0x%x\n", fmask);
1139 else
1140 fprintf (stream, "\tfmovem.x (-%d,fp),#0x%x\n",
1141 foffset + fsize, fmask);
1144 if (frame_pointer_needed)
1145 fprintf (stream, "\tunlk fp\n");
1146 else if (fsize)
1148 if (fsize + 4 < 0x8000)
1149 fprintf (stream, "\tadd.w #%d,sp\n", fsize + 4);
1150 else
1151 fprintf (stream, "\tadd.l #%d,sp\n", fsize + 4);
1154 if (current_function_pops_args)
1155 fprintf (stream, "\trtd #%d\n", current_function_pops_args);
1156 else
1157 fprintf (stream, "\trts\n");
1160 #else /* !CRDS && ! (NEWS && MOTOROLA) && ! (DPX2 && MOTOROLA) */
1162 static void
1163 m68k_output_function_epilogue (stream, size)
1164 FILE *stream;
1165 HOST_WIDE_INT size;
1167 register int regno;
1168 register int mask, fmask;
1169 register int nregs;
1170 HOST_WIDE_INT offset, foffset, fpoffset;
1171 extern char call_used_regs[];
1172 HOST_WIDE_INT fsize = (size + 3) & -4;
1173 int big = 0;
1174 rtx insn = get_last_insn ();
1175 int restore_from_sp = 0;
1177 /* If the last insn was a BARRIER, we don't have to write any code. */
1178 if (GET_CODE (insn) == NOTE)
1179 insn = prev_nonnote_insn (insn);
1180 if (insn && GET_CODE (insn) == BARRIER)
1182 /* Output just a no-op so that debuggers don't get confused
1183 about which function the pc is in at this address. */
1184 asm_fprintf (stream, "\tnop\n");
1185 return;
1188 #ifdef FUNCTION_EXTRA_EPILOGUE
1189 FUNCTION_EXTRA_EPILOGUE (stream, size);
1190 #endif
1191 nregs = 0; fmask = 0; fpoffset = 0;
1192 #ifdef SUPPORT_SUN_FPA
1193 for (regno = 24 ; regno < 56 ; regno++)
1194 if (regs_ever_live[regno] && ! call_used_regs[regno])
1195 nregs++;
1196 fpoffset = nregs * 8;
1197 #endif
1198 nregs = 0;
1199 if (TARGET_68881)
1201 for (regno = 16; regno < 24; regno++)
1202 if (regs_ever_live[regno] && ! call_used_regs[regno])
1204 nregs++;
1205 fmask |= 1 << (23 - regno);
1208 foffset = fpoffset + nregs * 12;
1209 nregs = 0; mask = 0;
1210 if (frame_pointer_needed)
1211 regs_ever_live[FRAME_POINTER_REGNUM] = 0;
1212 for (regno = 0; regno < 16; regno++)
1213 if (regs_ever_live[regno] && ! call_used_regs[regno])
1215 nregs++;
1216 mask |= 1 << regno;
1218 if (flag_pic && current_function_uses_pic_offset_table)
1220 nregs++;
1221 mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
1223 offset = foffset + nregs * 4;
1224 /* FIXME : leaf_function_p below is too strong.
1225 What we really need to know there is if there could be pending
1226 stack adjustment needed at that point. */
1227 restore_from_sp = ! frame_pointer_needed
1228 || (! current_function_calls_alloca && leaf_function_p ());
1229 if (offset + fsize >= 0x8000
1230 && ! restore_from_sp
1231 && (mask || fmask || fpoffset))
1233 #ifdef MOTOROLA
1234 asm_fprintf (stream, "\t%Omove.l %0I%d,%Ra1\n", -fsize);
1235 #else
1236 asm_fprintf (stream, "\tmovel %0I%d,%Ra1\n", -fsize);
1237 #endif
1238 fsize = 0, big = 1;
1240 if (TARGET_5200 || nregs <= 2)
1242 /* Restore each separately in the same order moveml does.
1243 Using two movel instructions instead of a single moveml
1244 is about 15% faster for the 68020 and 68030 at no expense
1245 in code size. */
1247 int i;
1249 /* Undo the work from above. */
1250 for (i = 0; i< 16; i++)
1251 if (mask & (1 << i))
1253 if (big)
1255 #ifdef MOTOROLA
1256 asm_fprintf (stream, "\t%Omove.l -%d(%s,%Ra1.l),%s\n",
1257 offset + fsize,
1258 reg_names[FRAME_POINTER_REGNUM],
1259 reg_names[i]);
1260 #else
1261 asm_fprintf (stream, "\tmovel %s@(-%d,%Ra1:l),%s\n",
1262 reg_names[FRAME_POINTER_REGNUM],
1263 offset + fsize, reg_names[i]);
1264 #endif
1266 else if (restore_from_sp)
1268 #ifdef MOTOROLA
1269 asm_fprintf (stream, "\t%Omove.l (%Rsp)+,%s\n",
1270 reg_names[i]);
1271 #else
1272 asm_fprintf (stream, "\tmovel %Rsp@+,%s\n",
1273 reg_names[i]);
1274 #endif
1276 else
1278 #ifdef MOTOROLA
1279 asm_fprintf (stream, "\t%Omove.l -%d(%s),%s\n",
1280 offset + fsize,
1281 reg_names[FRAME_POINTER_REGNUM],
1282 reg_names[i]);
1283 #else
1284 asm_fprintf (stream, "\tmovel %s@(-%d),%s\n",
1285 reg_names[FRAME_POINTER_REGNUM],
1286 offset + fsize, reg_names[i]);
1287 #endif
1289 offset = offset - 4;
1292 else if (mask)
1294 if (big)
1296 #ifdef MOTOROLA
1297 asm_fprintf (stream, "\tmovm.l -%d(%s,%Ra1.l),%0I0x%x\n",
1298 offset + fsize,
1299 reg_names[FRAME_POINTER_REGNUM],
1300 mask);
1301 #else
1302 asm_fprintf (stream, "\tmoveml %s@(-%d,%Ra1:l),%0I0x%x\n",
1303 reg_names[FRAME_POINTER_REGNUM],
1304 offset + fsize, mask);
1305 #endif
1307 else if (restore_from_sp)
1309 #ifdef MOTOROLA
1310 asm_fprintf (stream, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask);
1311 #else
1312 asm_fprintf (stream, "\tmoveml %Rsp@+,%0I0x%x\n", mask);
1313 #endif
1315 else
1317 #ifdef MOTOROLA
1318 asm_fprintf (stream, "\tmovm.l -%d(%s),%0I0x%x\n",
1319 offset + fsize,
1320 reg_names[FRAME_POINTER_REGNUM],
1321 mask);
1322 #else
1323 asm_fprintf (stream, "\tmoveml %s@(-%d),%0I0x%x\n",
1324 reg_names[FRAME_POINTER_REGNUM],
1325 offset + fsize, mask);
1326 #endif
1329 if (fmask)
1331 if (big)
1333 #ifdef MOTOROLA
1334 asm_fprintf (stream, "\tfmovm -%d(%s,%Ra1.l),%0I0x%x\n",
1335 foffset + fsize,
1336 reg_names[FRAME_POINTER_REGNUM],
1337 fmask);
1338 #else
1339 asm_fprintf (stream, "\tfmovem %s@(-%d,%Ra1:l),%0I0x%x\n",
1340 reg_names[FRAME_POINTER_REGNUM],
1341 foffset + fsize, fmask);
1342 #endif
1344 else if (restore_from_sp)
1346 #ifdef MOTOROLA
1347 asm_fprintf (stream, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask);
1348 #else
1349 asm_fprintf (stream, "\tfmovem %Rsp@+,%0I0x%x\n", fmask);
1350 #endif
1352 else
1354 #ifdef MOTOROLA
1355 asm_fprintf (stream, "\tfmovm -%d(%s),%0I0x%x\n",
1356 foffset + fsize,
1357 reg_names[FRAME_POINTER_REGNUM],
1358 fmask);
1359 #else
1360 asm_fprintf (stream, "\tfmovem %s@(-%d),%0I0x%x\n",
1361 reg_names[FRAME_POINTER_REGNUM],
1362 foffset + fsize, fmask);
1363 #endif
1366 if (fpoffset != 0)
1367 for (regno = 55; regno >= 24; regno--)
1368 if (regs_ever_live[regno] && ! call_used_regs[regno])
1370 if (big)
1372 #ifdef MOTOROLA
1373 asm_fprintf (stream, "\tfpmovd -%d(%s,%Ra1.l), %s\n",
1374 fpoffset + fsize,
1375 reg_names[FRAME_POINTER_REGNUM],
1376 reg_names[regno]);
1377 #else
1378 asm_fprintf (stream, "\tfpmoved %s@(-%d,%Ra1:l), %s\n",
1379 reg_names[FRAME_POINTER_REGNUM],
1380 fpoffset + fsize, reg_names[regno]);
1381 #endif
1383 else if (restore_from_sp)
1385 #ifdef MOTOROLA
1386 asm_fprintf (stream, "\tfpmovd (%Rsp)+,%s\n",
1387 reg_names[regno]);
1388 #else
1389 asm_fprintf (stream, "\tfpmoved %Rsp@+, %s\n",
1390 reg_names[regno]);
1391 #endif
1393 else
1395 #ifdef MOTOROLA
1396 asm_fprintf (stream, "\tfpmovd -%d(%s), %s\n",
1397 fpoffset + fsize,
1398 reg_names[FRAME_POINTER_REGNUM],
1399 reg_names[regno]);
1400 #else
1401 asm_fprintf (stream, "\tfpmoved %s@(-%d), %s\n",
1402 reg_names[FRAME_POINTER_REGNUM],
1403 fpoffset + fsize, reg_names[regno]);
1404 #endif
1406 fpoffset -= 8;
1408 if (frame_pointer_needed)
1409 fprintf (stream, "\tunlk %s\n",
1410 reg_names[FRAME_POINTER_REGNUM]);
1411 else if (fsize)
1413 #ifndef NO_ADDSUB_Q
1414 if (fsize + 4 <= 8)
1416 if (!TARGET_5200)
1418 #ifdef MOTOROLA
1419 asm_fprintf (stream, "\taddq.w %0I%d,%Rsp\n", fsize + 4);
1420 #else
1421 asm_fprintf (stream, "\taddqw %0I%d,%Rsp\n", fsize + 4);
1422 #endif
1424 else
1426 #ifdef MOTOROLA
1427 asm_fprintf (stream, "\taddq.l %0I%d,%Rsp\n", fsize + 4);
1428 #else
1429 asm_fprintf (stream, "\taddql %0I%d,%Rsp\n", fsize + 4);
1430 #endif
1433 else if (fsize + 4 <= 16 && TARGET_CPU32)
1435 /* On the CPU32 it is faster to use two addqw instructions to
1436 add a small integer (8 < N <= 16) to a register. */
1437 /* asm_fprintf() cannot handle %. */
1438 #ifdef MOTOROLA
1439 asm_fprintf (stream, "\taddq.w %0I8,%Rsp\n\taddq.w %0I%d,%Rsp\n",
1440 fsize + 4 - 8);
1441 #else
1442 asm_fprintf (stream, "\taddqw %0I8,%Rsp\n\taddqw %0I%d,%Rsp\n",
1443 fsize + 4 - 8);
1444 #endif
1446 else
1447 #endif /* not NO_ADDSUB_Q */
1448 if (fsize + 4 < 0x8000)
1450 if (TARGET_68040)
1452 /* asm_fprintf() cannot handle %. */
1453 #ifdef MOTOROLA
1454 asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", fsize + 4);
1455 #else
1456 asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", fsize + 4);
1457 #endif
1459 else
1461 #ifdef MOTOROLA
1462 asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", fsize + 4);
1463 #else
1464 asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", fsize + 4);
1465 #endif
1468 else
1470 /* asm_fprintf() cannot handle %. */
1471 #ifdef MOTOROLA
1472 asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", fsize + 4);
1473 #else
1474 asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", fsize + 4);
1475 #endif
1478 if (current_function_pops_args)
1479 asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args);
1480 else
1481 fprintf (stream, "\trts\n");
1484 #endif /* ! (DPX2 && MOTOROLA) */
1485 #endif /* ! (NEWS && MOTOROLA) */
1486 #endif /* !CRDS */
1488 /* Similar to general_operand, but exclude stack_pointer_rtx. */
1491 not_sp_operand (op, mode)
1492 register rtx op;
1493 enum machine_mode mode;
1495 return op != stack_pointer_rtx && nonimmediate_operand (op, mode);
1498 /* Return TRUE if X is a valid comparison operator for the dbcc
1499 instruction.
1501 Note it rejects floating point comparison operators.
1502 (In the future we could use Fdbcc).
1504 It also rejects some comparisons when CC_NO_OVERFLOW is set. */
1507 valid_dbcc_comparison_p (x, mode)
1508 rtx x;
1509 enum machine_mode mode ATTRIBUTE_UNUSED;
1511 switch (GET_CODE (x))
1513 case EQ: case NE: case GTU: case LTU:
1514 case GEU: case LEU:
1515 return 1;
1517 /* Reject some when CC_NO_OVERFLOW is set. This may be over
1518 conservative */
1519 case GT: case LT: case GE: case LE:
1520 return ! (cc_prev_status.flags & CC_NO_OVERFLOW);
1521 default:
1522 return 0;
1526 /* Return non-zero if flags are currently in the 68881 flag register. */
1528 flags_in_68881 ()
1530 /* We could add support for these in the future */
1531 return cc_status.flags & CC_IN_68881;
1534 /* Output a dbCC; jCC sequence. Note we do not handle the
1535 floating point version of this sequence (Fdbcc). We also
1536 do not handle alternative conditions when CC_NO_OVERFLOW is
1537 set. It is assumed that valid_dbcc_comparison_p and flags_in_68881 will
1538 kick those out before we get here. */
1540 void
1541 output_dbcc_and_branch (operands)
1542 rtx *operands;
1544 switch (GET_CODE (operands[3]))
1546 case EQ:
1547 #ifdef MOTOROLA
1548 output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands);
1549 #else
1550 output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands);
1551 #endif
1552 break;
1554 case NE:
1555 #ifdef MOTOROLA
1556 output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands);
1557 #else
1558 output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands);
1559 #endif
1560 break;
1562 case GT:
1563 #ifdef MOTOROLA
1564 output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands);
1565 #else
1566 output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands);
1567 #endif
1568 break;
1570 case GTU:
1571 #ifdef MOTOROLA
1572 output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands);
1573 #else
1574 output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands);
1575 #endif
1576 break;
1578 case LT:
1579 #ifdef MOTOROLA
1580 output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands);
1581 #else
1582 output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands);
1583 #endif
1584 break;
1586 case LTU:
1587 #ifdef MOTOROLA
1588 output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands);
1589 #else
1590 output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands);
1591 #endif
1592 break;
1594 case GE:
1595 #ifdef MOTOROLA
1596 output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands);
1597 #else
1598 output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands);
1599 #endif
1600 break;
1602 case GEU:
1603 #ifdef MOTOROLA
1604 output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands);
1605 #else
1606 output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands);
1607 #endif
1608 break;
1610 case LE:
1611 #ifdef MOTOROLA
1612 output_asm_insn ("dble %0,%l1\n\tjble %l2", operands);
1613 #else
1614 output_asm_insn ("dble %0,%l1\n\tjle %l2", operands);
1615 #endif
1616 break;
1618 case LEU:
1619 #ifdef MOTOROLA
1620 output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands);
1621 #else
1622 output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands);
1623 #endif
1624 break;
1626 default:
1627 abort ();
1630 /* If the decrement is to be done in SImode, then we have
1631 to compensate for the fact that dbcc decrements in HImode. */
1632 switch (GET_MODE (operands[0]))
1634 case SImode:
1635 #ifdef MOTOROLA
1636 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands);
1637 #else
1638 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands);
1639 #endif
1640 break;
1642 case HImode:
1643 break;
1645 default:
1646 abort ();
1650 const char *
1651 output_scc_di(op, operand1, operand2, dest)
1652 rtx op;
1653 rtx operand1;
1654 rtx operand2;
1655 rtx dest;
1657 rtx loperands[7];
1658 enum rtx_code op_code = GET_CODE (op);
1660 /* This does not produce a useful cc. */
1661 CC_STATUS_INIT;
1663 /* The m68k cmp.l instruction requires operand1 to be a reg as used
1664 below. Swap the operands and change the op if these requirements
1665 are not fulfilled. */
1666 if (GET_CODE (operand2) == REG && GET_CODE (operand1) != REG)
1668 rtx tmp = operand1;
1670 operand1 = operand2;
1671 operand2 = tmp;
1672 op_code = swap_condition (op_code);
1674 loperands[0] = operand1;
1675 if (GET_CODE (operand1) == REG)
1676 loperands[1] = gen_rtx_REG (SImode, REGNO (operand1) + 1);
1677 else
1678 loperands[1] = adjust_address (operand1, SImode, 4);
1679 if (operand2 != const0_rtx)
1681 loperands[2] = operand2;
1682 if (GET_CODE (operand2) == REG)
1683 loperands[3] = gen_rtx_REG (SImode, REGNO (operand2) + 1);
1684 else
1685 loperands[3] = adjust_address (operand2, SImode, 4);
1687 loperands[4] = gen_label_rtx();
1688 if (operand2 != const0_rtx)
1690 #ifdef MOTOROLA
1691 #ifdef SGS_CMP_ORDER
1692 output_asm_insn ("cmp%.l %0,%2\n\tjbne %l4\n\tcmp%.l %1,%3", loperands);
1693 #else
1694 output_asm_insn ("cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1", loperands);
1695 #endif
1696 #else
1697 #ifdef SGS_CMP_ORDER
1698 output_asm_insn ("cmp%.l %0,%2\n\tjne %l4\n\tcmp%.l %1,%3", loperands);
1699 #else
1700 output_asm_insn ("cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1", loperands);
1701 #endif
1702 #endif
1704 else
1706 if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (loperands[0]))
1707 output_asm_insn ("tst%.l %0", loperands);
1708 else
1710 #ifdef SGS_CMP_ORDER
1711 output_asm_insn ("cmp%.w %0,%#0", loperands);
1712 #else
1713 output_asm_insn ("cmp%.w %#0,%0", loperands);
1714 #endif
1717 #ifdef MOTOROLA
1718 output_asm_insn ("jbne %l4", loperands);
1719 #else
1720 output_asm_insn ("jne %l4", loperands);
1721 #endif
1723 if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (loperands[1]))
1724 output_asm_insn ("tst%.l %1", loperands);
1725 else
1727 #ifdef SGS_CMP_ORDER
1728 output_asm_insn ("cmp%.w %1,%#0", loperands);
1729 #else
1730 output_asm_insn ("cmp%.w %#0,%1", loperands);
1731 #endif
1735 loperands[5] = dest;
1737 switch (op_code)
1739 case EQ:
1740 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1741 CODE_LABEL_NUMBER (loperands[4]));
1742 output_asm_insn ("seq %5", loperands);
1743 break;
1745 case NE:
1746 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1747 CODE_LABEL_NUMBER (loperands[4]));
1748 output_asm_insn ("sne %5", loperands);
1749 break;
1751 case GT:
1752 loperands[6] = gen_label_rtx();
1753 #ifdef MOTOROLA
1754 output_asm_insn ("shi %5\n\tjbra %l6", loperands);
1755 #else
1756 output_asm_insn ("shi %5\n\tjra %l6", loperands);
1757 #endif
1758 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1759 CODE_LABEL_NUMBER (loperands[4]));
1760 output_asm_insn ("sgt %5", loperands);
1761 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1762 CODE_LABEL_NUMBER (loperands[6]));
1763 break;
1765 case GTU:
1766 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1767 CODE_LABEL_NUMBER (loperands[4]));
1768 output_asm_insn ("shi %5", loperands);
1769 break;
1771 case LT:
1772 loperands[6] = gen_label_rtx();
1773 #ifdef MOTOROLA
1774 output_asm_insn ("scs %5\n\tjbra %l6", loperands);
1775 #else
1776 output_asm_insn ("scs %5\n\tjra %l6", loperands);
1777 #endif
1778 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1779 CODE_LABEL_NUMBER (loperands[4]));
1780 output_asm_insn ("slt %5", loperands);
1781 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1782 CODE_LABEL_NUMBER (loperands[6]));
1783 break;
1785 case LTU:
1786 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1787 CODE_LABEL_NUMBER (loperands[4]));
1788 output_asm_insn ("scs %5", loperands);
1789 break;
1791 case GE:
1792 loperands[6] = gen_label_rtx();
1793 #ifdef MOTOROLA
1794 output_asm_insn ("scc %5\n\tjbra %l6", loperands);
1795 #else
1796 output_asm_insn ("scc %5\n\tjra %l6", loperands);
1797 #endif
1798 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1799 CODE_LABEL_NUMBER (loperands[4]));
1800 output_asm_insn ("sge %5", loperands);
1801 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1802 CODE_LABEL_NUMBER (loperands[6]));
1803 break;
1805 case GEU:
1806 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1807 CODE_LABEL_NUMBER (loperands[4]));
1808 output_asm_insn ("scc %5", loperands);
1809 break;
1811 case LE:
1812 loperands[6] = gen_label_rtx();
1813 #ifdef MOTOROLA
1814 output_asm_insn ("sls %5\n\tjbra %l6", loperands);
1815 #else
1816 output_asm_insn ("sls %5\n\tjra %l6", loperands);
1817 #endif
1818 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1819 CODE_LABEL_NUMBER (loperands[4]));
1820 output_asm_insn ("sle %5", loperands);
1821 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1822 CODE_LABEL_NUMBER (loperands[6]));
1823 break;
1825 case LEU:
1826 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1827 CODE_LABEL_NUMBER (loperands[4]));
1828 output_asm_insn ("sls %5", loperands);
1829 break;
1831 default:
1832 abort ();
1834 return "";
1837 const char *
1838 output_btst (operands, countop, dataop, insn, signpos)
1839 rtx *operands;
1840 rtx countop, dataop;
1841 rtx insn;
1842 int signpos;
1844 operands[0] = countop;
1845 operands[1] = dataop;
1847 if (GET_CODE (countop) == CONST_INT)
1849 register int count = INTVAL (countop);
1850 /* If COUNT is bigger than size of storage unit in use,
1851 advance to the containing unit of same size. */
1852 if (count > signpos)
1854 int offset = (count & ~signpos) / 8;
1855 count = count & signpos;
1856 operands[1] = dataop = adjust_address (dataop, QImode, offset);
1858 if (count == signpos)
1859 cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
1860 else
1861 cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
1863 /* These three statements used to use next_insns_test_no...
1864 but it appears that this should do the same job. */
1865 if (count == 31
1866 && next_insn_tests_no_inequality (insn))
1867 return "tst%.l %1";
1868 if (count == 15
1869 && next_insn_tests_no_inequality (insn))
1870 return "tst%.w %1";
1871 if (count == 7
1872 && next_insn_tests_no_inequality (insn))
1873 return "tst%.b %1";
1875 cc_status.flags = CC_NOT_NEGATIVE;
1877 return "btst %0,%1";
1880 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
1881 reference and a constant. */
1884 symbolic_operand (op, mode)
1885 register rtx op;
1886 enum machine_mode mode ATTRIBUTE_UNUSED;
1888 switch (GET_CODE (op))
1890 case SYMBOL_REF:
1891 case LABEL_REF:
1892 return 1;
1894 case CONST:
1895 op = XEXP (op, 0);
1896 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1897 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1898 && GET_CODE (XEXP (op, 1)) == CONST_INT);
1900 #if 0 /* Deleted, with corresponding change in m68k.h,
1901 so as to fit the specs. No CONST_DOUBLE is ever symbolic. */
1902 case CONST_DOUBLE:
1903 return GET_MODE (op) == mode;
1904 #endif
1906 default:
1907 return 0;
1911 /* Check for sign_extend or zero_extend. Used for bit-count operands. */
1914 extend_operator(x, mode)
1915 rtx x;
1916 enum machine_mode mode;
1918 if (mode != VOIDmode && GET_MODE(x) != mode)
1919 return 0;
1920 switch (GET_CODE(x))
1922 case SIGN_EXTEND :
1923 case ZERO_EXTEND :
1924 return 1;
1925 default :
1926 return 0;
1931 /* Legitimize PIC addresses. If the address is already
1932 position-independent, we return ORIG. Newly generated
1933 position-independent addresses go to REG. If we need more
1934 than one register, we lose.
1936 An address is legitimized by making an indirect reference
1937 through the Global Offset Table with the name of the symbol
1938 used as an offset.
1940 The assembler and linker are responsible for placing the
1941 address of the symbol in the GOT. The function prologue
1942 is responsible for initializing a5 to the starting address
1943 of the GOT.
1945 The assembler is also responsible for translating a symbol name
1946 into a constant displacement from the start of the GOT.
1948 A quick example may make things a little clearer:
1950 When not generating PIC code to store the value 12345 into _foo
1951 we would generate the following code:
1953 movel #12345, _foo
1955 When generating PIC two transformations are made. First, the compiler
1956 loads the address of foo into a register. So the first transformation makes:
1958 lea _foo, a0
1959 movel #12345, a0@
1961 The code in movsi will intercept the lea instruction and call this
1962 routine which will transform the instructions into:
1964 movel a5@(_foo:w), a0
1965 movel #12345, a0@
1968 That (in a nutshell) is how *all* symbol and label references are
1969 handled. */
1972 legitimize_pic_address (orig, mode, reg)
1973 rtx orig, reg;
1974 enum machine_mode mode ATTRIBUTE_UNUSED;
1976 rtx pic_ref = orig;
1978 /* First handle a simple SYMBOL_REF or LABEL_REF */
1979 if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
1981 if (reg == 0)
1982 abort ();
1984 pic_ref = gen_rtx_MEM (Pmode,
1985 gen_rtx_PLUS (Pmode,
1986 pic_offset_table_rtx, orig));
1987 current_function_uses_pic_offset_table = 1;
1988 RTX_UNCHANGING_P (pic_ref) = 1;
1989 emit_move_insn (reg, pic_ref);
1990 return reg;
1992 else if (GET_CODE (orig) == CONST)
1994 rtx base;
1996 /* Make sure this is CONST has not already been legitimized */
1997 if (GET_CODE (XEXP (orig, 0)) == PLUS
1998 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
1999 return orig;
2001 if (reg == 0)
2002 abort ();
2004 /* legitimize both operands of the PLUS */
2005 if (GET_CODE (XEXP (orig, 0)) == PLUS)
2007 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
2008 orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
2009 base == reg ? 0 : reg);
2011 else abort ();
2013 if (GET_CODE (orig) == CONST_INT)
2014 return plus_constant (base, INTVAL (orig));
2015 pic_ref = gen_rtx_PLUS (Pmode, base, orig);
2016 /* Likewise, should we set special REG_NOTEs here? */
2018 return pic_ref;
2022 typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ } CONST_METHOD;
2024 static CONST_METHOD const_method PARAMS ((rtx));
2026 #define USE_MOVQ(i) ((unsigned)((i) + 128) <= 255)
2028 static CONST_METHOD
2029 const_method (constant)
2030 rtx constant;
2032 int i;
2033 unsigned u;
2035 i = INTVAL (constant);
2036 if (USE_MOVQ (i))
2037 return MOVQ;
2039 /* The Coldfire doesn't have byte or word operations. */
2040 /* FIXME: This may not be useful for the m68060 either */
2041 if (!TARGET_5200)
2043 /* if -256 < N < 256 but N is not in range for a moveq
2044 N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */
2045 if (USE_MOVQ (i ^ 0xff))
2046 return NOTB;
2047 /* Likewise, try with not.w */
2048 if (USE_MOVQ (i ^ 0xffff))
2049 return NOTW;
2050 /* This is the only value where neg.w is useful */
2051 if (i == -65408)
2052 return NEGW;
2053 /* Try also with swap */
2054 u = i;
2055 if (USE_MOVQ ((u >> 16) | (u << 16)))
2056 return SWAP;
2058 /* Otherwise, use move.l */
2059 return MOVL;
2063 const_int_cost (constant)
2064 rtx constant;
2066 switch (const_method (constant))
2068 case MOVQ :
2069 /* Constants between -128 and 127 are cheap due to moveq */
2070 return 0;
2071 case NOTB :
2072 case NOTW :
2073 case NEGW :
2074 case SWAP :
2075 /* Constants easily generated by moveq + not.b/not.w/neg.w/swap */
2076 return 1;
2077 case MOVL :
2078 return 2;
2079 default :
2080 abort ();
2084 const char *
2085 output_move_const_into_data_reg (operands)
2086 rtx *operands;
2088 int i;
2090 i = INTVAL (operands[1]);
2091 switch (const_method (operands[1]))
2093 case MOVQ :
2094 #if defined (MOTOROLA) && !defined (CRDS)
2095 return "moveq%.l %1,%0";
2096 #else
2097 return "moveq %1,%0";
2098 #endif
2099 case NOTB :
2100 operands[1] = GEN_INT (i ^ 0xff);
2101 #if defined (MOTOROLA) && !defined (CRDS)
2102 return "moveq%.l %1,%0\n\tnot%.b %0";
2103 #else
2104 return "moveq %1,%0\n\tnot%.b %0";
2105 #endif
2106 case NOTW :
2107 operands[1] = GEN_INT (i ^ 0xffff);
2108 #if defined (MOTOROLA) && !defined (CRDS)
2109 return "moveq%.l %1,%0\n\tnot%.w %0";
2110 #else
2111 return "moveq %1,%0\n\tnot%.w %0";
2112 #endif
2113 case NEGW :
2114 #if defined (MOTOROLA) && !defined (CRDS)
2115 return "moveq%.l %#-128,%0\n\tneg%.w %0";
2116 #else
2117 return "moveq %#-128,%0\n\tneg%.w %0";
2118 #endif
2119 case SWAP :
2121 unsigned u = i;
2123 operands[1] = GEN_INT ((u << 16) | (u >> 16));
2124 #if defined (MOTOROLA) && !defined (CRDS)
2125 return "moveq%.l %1,%0\n\tswap %0";
2126 #else
2127 return "moveq %1,%0\n\tswap %0";
2128 #endif
2130 case MOVL :
2131 return "move%.l %1,%0";
2132 default :
2133 abort ();
2137 const char *
2138 output_move_simode_const (operands)
2139 rtx *operands;
2141 if (operands[1] == const0_rtx
2142 && (DATA_REG_P (operands[0])
2143 || GET_CODE (operands[0]) == MEM)
2144 /* clr insns on 68000 read before writing.
2145 This isn't so on the 68010, but we have no TARGET_68010. */
2146 && ((TARGET_68020 || TARGET_5200)
2147 || !(GET_CODE (operands[0]) == MEM
2148 && MEM_VOLATILE_P (operands[0]))))
2149 return "clr%.l %0";
2150 else if (operands[1] == const0_rtx
2151 && ADDRESS_REG_P (operands[0]))
2152 return "sub%.l %0,%0";
2153 else if (DATA_REG_P (operands[0]))
2154 return output_move_const_into_data_reg (operands);
2155 else if (ADDRESS_REG_P (operands[0])
2156 && INTVAL (operands[1]) < 0x8000
2157 && INTVAL (operands[1]) >= -0x8000)
2158 return "move%.w %1,%0";
2159 else if (GET_CODE (operands[0]) == MEM
2160 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
2161 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
2162 && INTVAL (operands[1]) < 0x8000
2163 && INTVAL (operands[1]) >= -0x8000)
2164 return "pea %a1";
2165 return "move%.l %1,%0";
2168 const char *
2169 output_move_simode (operands)
2170 rtx *operands;
2172 if (GET_CODE (operands[1]) == CONST_INT)
2173 return output_move_simode_const (operands);
2174 else if ((GET_CODE (operands[1]) == SYMBOL_REF
2175 || GET_CODE (operands[1]) == CONST)
2176 && push_operand (operands[0], SImode))
2177 return "pea %a1";
2178 else if ((GET_CODE (operands[1]) == SYMBOL_REF
2179 || GET_CODE (operands[1]) == CONST)
2180 && ADDRESS_REG_P (operands[0]))
2181 return "lea %a1,%0";
2182 return "move%.l %1,%0";
2185 const char *
2186 output_move_himode (operands)
2187 rtx *operands;
2189 if (GET_CODE (operands[1]) == CONST_INT)
2191 if (operands[1] == const0_rtx
2192 && (DATA_REG_P (operands[0])
2193 || GET_CODE (operands[0]) == MEM)
2194 /* clr insns on 68000 read before writing.
2195 This isn't so on the 68010, but we have no TARGET_68010. */
2196 && ((TARGET_68020 || TARGET_5200)
2197 || !(GET_CODE (operands[0]) == MEM
2198 && MEM_VOLATILE_P (operands[0]))))
2199 return "clr%.w %0";
2200 else if (operands[1] == const0_rtx
2201 && ADDRESS_REG_P (operands[0]))
2202 return "sub%.l %0,%0";
2203 else if (DATA_REG_P (operands[0])
2204 && INTVAL (operands[1]) < 128
2205 && INTVAL (operands[1]) >= -128)
2207 #if defined(MOTOROLA) && !defined(CRDS)
2208 return "moveq%.l %1,%0";
2209 #else
2210 return "moveq %1,%0";
2211 #endif
2213 else if (INTVAL (operands[1]) < 0x8000
2214 && INTVAL (operands[1]) >= -0x8000)
2215 return "move%.w %1,%0";
2217 else if (CONSTANT_P (operands[1]))
2218 return "move%.l %1,%0";
2219 #ifndef SGS_NO_LI
2220 /* Recognize the insn before a tablejump, one that refers
2221 to a table of offsets. Such an insn will need to refer
2222 to a label on the insn. So output one. Use the label-number
2223 of the table of offsets to generate this label. This code,
2224 and similar code below, assumes that there will be at most one
2225 reference to each table. */
2226 if (GET_CODE (operands[1]) == MEM
2227 && GET_CODE (XEXP (operands[1], 0)) == PLUS
2228 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF
2229 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS)
2231 rtx labelref = XEXP (XEXP (operands[1], 0), 1);
2232 #if defined (MOTOROLA) && !defined (SGS_SWITCH_TABLES)
2233 #ifdef SGS
2234 asm_fprintf (asm_out_file, "\tset %LLI%d,.+2\n",
2235 CODE_LABEL_NUMBER (XEXP (labelref, 0)));
2236 #else /* not SGS */
2237 asm_fprintf (asm_out_file, "\t.set %LLI%d,.+2\n",
2238 CODE_LABEL_NUMBER (XEXP (labelref, 0)));
2239 #endif /* not SGS */
2240 #else /* SGS_SWITCH_TABLES or not MOTOROLA */
2241 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LI",
2242 CODE_LABEL_NUMBER (XEXP (labelref, 0)));
2243 #ifdef SGS_SWITCH_TABLES
2244 /* Set flag saying we need to define the symbol
2245 LD%n (with value L%n-LI%n) at the end of the switch table. */
2246 switch_table_difference_label_flag = 1;
2247 #endif /* SGS_SWITCH_TABLES */
2248 #endif /* SGS_SWITCH_TABLES or not MOTOROLA */
2250 #endif /* SGS_NO_LI */
2251 return "move%.w %1,%0";
2254 const char *
2255 output_move_qimode (operands)
2256 rtx *operands;
2258 rtx xoperands[4];
2260 /* This is probably useless, since it loses for pushing a struct
2261 of several bytes a byte at a time. */
2262 /* 68k family always modifies the stack pointer by at least 2, even for
2263 byte pushes. The 5200 (coldfire) does not do this. */
2264 if (GET_CODE (operands[0]) == MEM
2265 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
2266 && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx
2267 && ! ADDRESS_REG_P (operands[1])
2268 && ! TARGET_5200)
2270 xoperands[1] = operands[1];
2271 xoperands[2]
2272 = gen_rtx_MEM (QImode,
2273 gen_rtx_PLUS (VOIDmode, stack_pointer_rtx, const1_rtx));
2274 /* Just pushing a byte puts it in the high byte of the halfword. */
2275 /* We must put it in the low-order, high-numbered byte. */
2276 if (!reg_mentioned_p (stack_pointer_rtx, operands[1]))
2278 xoperands[3] = stack_pointer_rtx;
2279 #ifndef NO_ADDSUB_Q
2280 output_asm_insn ("subq%.l %#2,%3\n\tmove%.b %1,%2", xoperands);
2281 #else
2282 output_asm_insn ("sub%.l %#2,%3\n\tmove%.b %1,%2", xoperands);
2283 #endif
2285 else
2286 output_asm_insn ("move%.b %1,%-\n\tmove%.b %@,%2", xoperands);
2287 return "";
2290 /* clr and st insns on 68000 read before writing.
2291 This isn't so on the 68010, but we have no TARGET_68010. */
2292 if (!ADDRESS_REG_P (operands[0])
2293 && ((TARGET_68020 || TARGET_5200)
2294 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
2296 if (operands[1] == const0_rtx)
2297 return "clr%.b %0";
2298 if ((!TARGET_5200 || DATA_REG_P (operands[0]))
2299 && GET_CODE (operands[1]) == CONST_INT
2300 && (INTVAL (operands[1]) & 255) == 255)
2302 CC_STATUS_INIT;
2303 return "st %0";
2306 if (GET_CODE (operands[1]) == CONST_INT
2307 && DATA_REG_P (operands[0])
2308 && INTVAL (operands[1]) < 128
2309 && INTVAL (operands[1]) >= -128)
2311 #if defined(MOTOROLA) && !defined(CRDS)
2312 return "moveq%.l %1,%0";
2313 #else
2314 return "moveq %1,%0";
2315 #endif
2317 if (operands[1] == const0_rtx && ADDRESS_REG_P (operands[0]))
2318 return "sub%.l %0,%0";
2319 if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
2320 return "move%.l %1,%0";
2321 /* 68k family (including the 5200 coldfire) does not support byte moves to
2322 from address registers. */
2323 if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1]))
2324 return "move%.w %1,%0";
2325 return "move%.b %1,%0";
2328 const char *
2329 output_move_stricthi (operands)
2330 rtx *operands;
2332 if (operands[1] == const0_rtx
2333 /* clr insns on 68000 read before writing.
2334 This isn't so on the 68010, but we have no TARGET_68010. */
2335 && ((TARGET_68020 || TARGET_5200)
2336 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
2337 return "clr%.w %0";
2338 return "move%.w %1,%0";
2341 const char *
2342 output_move_strictqi (operands)
2343 rtx *operands;
2345 if (operands[1] == const0_rtx
2346 /* clr insns on 68000 read before writing.
2347 This isn't so on the 68010, but we have no TARGET_68010. */
2348 && ((TARGET_68020 || TARGET_5200)
2349 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
2350 return "clr%.b %0";
2351 return "move%.b %1,%0";
2354 /* Return the best assembler insn template
2355 for moving operands[1] into operands[0] as a fullword. */
2357 static const char *
2358 singlemove_string (operands)
2359 rtx *operands;
2361 #ifdef SUPPORT_SUN_FPA
2362 if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
2363 return "fpmoves %1,%0";
2364 #endif
2365 if (GET_CODE (operands[1]) == CONST_INT)
2366 return output_move_simode_const (operands);
2367 return "move%.l %1,%0";
2371 /* Output assembler code to perform a doubleword move insn
2372 with operands OPERANDS. */
2374 const char *
2375 output_move_double (operands)
2376 rtx *operands;
2378 enum
2380 REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP
2381 } optype0, optype1;
2382 rtx latehalf[2];
2383 rtx middlehalf[2];
2384 rtx xops[2];
2385 rtx addreg0 = 0, addreg1 = 0;
2386 int dest_overlapped_low = 0;
2387 int size = GET_MODE_SIZE (GET_MODE (operands[0]));
2389 middlehalf[0] = 0;
2390 middlehalf[1] = 0;
2392 /* First classify both operands. */
2394 if (REG_P (operands[0]))
2395 optype0 = REGOP;
2396 else if (offsettable_memref_p (operands[0]))
2397 optype0 = OFFSOP;
2398 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
2399 optype0 = POPOP;
2400 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
2401 optype0 = PUSHOP;
2402 else if (GET_CODE (operands[0]) == MEM)
2403 optype0 = MEMOP;
2404 else
2405 optype0 = RNDOP;
2407 if (REG_P (operands[1]))
2408 optype1 = REGOP;
2409 else if (CONSTANT_P (operands[1]))
2410 optype1 = CNSTOP;
2411 else if (offsettable_memref_p (operands[1]))
2412 optype1 = OFFSOP;
2413 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
2414 optype1 = POPOP;
2415 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
2416 optype1 = PUSHOP;
2417 else if (GET_CODE (operands[1]) == MEM)
2418 optype1 = MEMOP;
2419 else
2420 optype1 = RNDOP;
2422 /* Check for the cases that the operand constraints are not
2423 supposed to allow to happen. Abort if we get one,
2424 because generating code for these cases is painful. */
2426 if (optype0 == RNDOP || optype1 == RNDOP)
2427 abort ();
2429 /* If one operand is decrementing and one is incrementing
2430 decrement the former register explicitly
2431 and change that operand into ordinary indexing. */
2433 if (optype0 == PUSHOP && optype1 == POPOP)
2435 operands[0] = XEXP (XEXP (operands[0], 0), 0);
2436 if (size == 12)
2437 output_asm_insn ("sub%.l %#12,%0", operands);
2438 else
2439 output_asm_insn ("subq%.l %#8,%0", operands);
2440 if (GET_MODE (operands[1]) == XFmode)
2441 operands[0] = gen_rtx_MEM (XFmode, operands[0]);
2442 else if (GET_MODE (operands[0]) == DFmode)
2443 operands[0] = gen_rtx_MEM (DFmode, operands[0]);
2444 else
2445 operands[0] = gen_rtx_MEM (DImode, operands[0]);
2446 optype0 = OFFSOP;
2448 if (optype0 == POPOP && optype1 == PUSHOP)
2450 operands[1] = XEXP (XEXP (operands[1], 0), 0);
2451 if (size == 12)
2452 output_asm_insn ("sub%.l %#12,%1", operands);
2453 else
2454 output_asm_insn ("subq%.l %#8,%1", operands);
2455 if (GET_MODE (operands[1]) == XFmode)
2456 operands[1] = gen_rtx_MEM (XFmode, operands[1]);
2457 else if (GET_MODE (operands[1]) == DFmode)
2458 operands[1] = gen_rtx_MEM (DFmode, operands[1]);
2459 else
2460 operands[1] = gen_rtx_MEM (DImode, operands[1]);
2461 optype1 = OFFSOP;
2464 /* If an operand is an unoffsettable memory ref, find a register
2465 we can increment temporarily to make it refer to the second word. */
2467 if (optype0 == MEMOP)
2468 addreg0 = find_addr_reg (XEXP (operands[0], 0));
2470 if (optype1 == MEMOP)
2471 addreg1 = find_addr_reg (XEXP (operands[1], 0));
2473 /* Ok, we can do one word at a time.
2474 Normally we do the low-numbered word first,
2475 but if either operand is autodecrementing then we
2476 do the high-numbered word first.
2478 In either case, set up in LATEHALF the operands to use
2479 for the high-numbered word and in some cases alter the
2480 operands in OPERANDS to be suitable for the low-numbered word. */
2482 if (size == 12)
2484 if (optype0 == REGOP)
2486 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
2487 middlehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
2489 else if (optype0 == OFFSOP)
2491 middlehalf[0] = adjust_address (operands[0], SImode, 4);
2492 latehalf[0] = adjust_address (operands[0], SImode, size - 4);
2494 else
2496 middlehalf[0] = operands[0];
2497 latehalf[0] = operands[0];
2500 if (optype1 == REGOP)
2502 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
2503 middlehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
2505 else if (optype1 == OFFSOP)
2507 middlehalf[1] = adjust_address (operands[1], SImode, 4);
2508 latehalf[1] = adjust_address (operands[1], SImode, size - 4);
2510 else if (optype1 == CNSTOP)
2512 if (GET_CODE (operands[1]) == CONST_DOUBLE)
2514 REAL_VALUE_TYPE r;
2515 long l[3];
2517 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2518 REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
2519 operands[1] = GEN_INT (l[0]);
2520 middlehalf[1] = GEN_INT (l[1]);
2521 latehalf[1] = GEN_INT (l[2]);
2523 else if (CONSTANT_P (operands[1]))
2525 /* actually, no non-CONST_DOUBLE constant should ever
2526 appear here. */
2527 abort ();
2528 if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
2529 latehalf[1] = constm1_rtx;
2530 else
2531 latehalf[1] = const0_rtx;
2534 else
2536 middlehalf[1] = operands[1];
2537 latehalf[1] = operands[1];
2540 else
2541 /* size is not 12: */
2543 if (optype0 == REGOP)
2544 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
2545 else if (optype0 == OFFSOP)
2546 latehalf[0] = adjust_address (operands[0], SImode, size - 4);
2547 else
2548 latehalf[0] = operands[0];
2550 if (optype1 == REGOP)
2551 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
2552 else if (optype1 == OFFSOP)
2553 latehalf[1] = adjust_address (operands[1], SImode, size - 4);
2554 else if (optype1 == CNSTOP)
2555 split_double (operands[1], &operands[1], &latehalf[1]);
2556 else
2557 latehalf[1] = operands[1];
2560 /* If insn is effectively movd N(sp),-(sp) then we will do the
2561 high word first. We should use the adjusted operand 1 (which is N+4(sp))
2562 for the low word as well, to compensate for the first decrement of sp. */
2563 if (optype0 == PUSHOP
2564 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
2565 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
2566 operands[1] = middlehalf[1] = latehalf[1];
2568 /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
2569 if the upper part of reg N does not appear in the MEM, arrange to
2570 emit the move late-half first. Otherwise, compute the MEM address
2571 into the upper part of N and use that as a pointer to the memory
2572 operand. */
2573 if (optype0 == REGOP
2574 && (optype1 == OFFSOP || optype1 == MEMOP))
2576 rtx testlow = gen_rtx_REG (SImode, REGNO (operands[0]));
2578 if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
2579 && reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
2581 /* If both halves of dest are used in the src memory address,
2582 compute the address into latehalf of dest.
2583 Note that this can't happen if the dest is two data regs. */
2584 compadr:
2585 xops[0] = latehalf[0];
2586 xops[1] = XEXP (operands[1], 0);
2587 output_asm_insn ("lea %a1,%0", xops);
2588 if (GET_MODE (operands[1]) == XFmode )
2590 operands[1] = gen_rtx_MEM (XFmode, latehalf[0]);
2591 middlehalf[1] = adjust_address (operands[1], DImode, size - 8);
2592 latehalf[1] = adjust_address (operands[1], DImode, size - 4);
2594 else
2596 operands[1] = gen_rtx_MEM (DImode, latehalf[0]);
2597 latehalf[1] = adjust_address (operands[1], DImode, size - 4);
2600 else if (size == 12
2601 && reg_overlap_mentioned_p (middlehalf[0],
2602 XEXP (operands[1], 0)))
2604 /* Check for two regs used by both source and dest.
2605 Note that this can't happen if the dest is all data regs.
2606 It can happen if the dest is d6, d7, a0.
2607 But in that case, latehalf is an addr reg, so
2608 the code at compadr does ok. */
2610 if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
2611 || reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
2612 goto compadr;
2614 /* JRV says this can't happen: */
2615 if (addreg0 || addreg1)
2616 abort ();
2618 /* Only the middle reg conflicts; simply put it last. */
2619 output_asm_insn (singlemove_string (operands), operands);
2620 output_asm_insn (singlemove_string (latehalf), latehalf);
2621 output_asm_insn (singlemove_string (middlehalf), middlehalf);
2622 return "";
2624 else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)))
2625 /* If the low half of dest is mentioned in the source memory
2626 address, the arrange to emit the move late half first. */
2627 dest_overlapped_low = 1;
2630 /* If one or both operands autodecrementing,
2631 do the two words, high-numbered first. */
2633 /* Likewise, the first move would clobber the source of the second one,
2634 do them in the other order. This happens only for registers;
2635 such overlap can't happen in memory unless the user explicitly
2636 sets it up, and that is an undefined circumstance. */
2638 if (optype0 == PUSHOP || optype1 == PUSHOP
2639 || (optype0 == REGOP && optype1 == REGOP
2640 && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1]))
2641 || REGNO (operands[0]) == REGNO (latehalf[1])))
2642 || dest_overlapped_low)
2644 /* Make any unoffsettable addresses point at high-numbered word. */
2645 if (addreg0)
2647 if (size == 12)
2648 output_asm_insn ("addq%.l %#8,%0", &addreg0);
2649 else
2650 output_asm_insn ("addq%.l %#4,%0", &addreg0);
2652 if (addreg1)
2654 if (size == 12)
2655 output_asm_insn ("addq%.l %#8,%0", &addreg1);
2656 else
2657 output_asm_insn ("addq%.l %#4,%0", &addreg1);
2660 /* Do that word. */
2661 output_asm_insn (singlemove_string (latehalf), latehalf);
2663 /* Undo the adds we just did. */
2664 if (addreg0)
2665 output_asm_insn ("subq%.l %#4,%0", &addreg0);
2666 if (addreg1)
2667 output_asm_insn ("subq%.l %#4,%0", &addreg1);
2669 if (size == 12)
2671 output_asm_insn (singlemove_string (middlehalf), middlehalf);
2672 if (addreg0)
2673 output_asm_insn ("subq%.l %#4,%0", &addreg0);
2674 if (addreg1)
2675 output_asm_insn ("subq%.l %#4,%0", &addreg1);
2678 /* Do low-numbered word. */
2679 return singlemove_string (operands);
2682 /* Normal case: do the two words, low-numbered first. */
2684 output_asm_insn (singlemove_string (operands), operands);
2686 /* Do the middle one of the three words for long double */
2687 if (size == 12)
2689 if (addreg0)
2690 output_asm_insn ("addq%.l %#4,%0", &addreg0);
2691 if (addreg1)
2692 output_asm_insn ("addq%.l %#4,%0", &addreg1);
2694 output_asm_insn (singlemove_string (middlehalf), middlehalf);
2697 /* Make any unoffsettable addresses point at high-numbered word. */
2698 if (addreg0)
2699 output_asm_insn ("addq%.l %#4,%0", &addreg0);
2700 if (addreg1)
2701 output_asm_insn ("addq%.l %#4,%0", &addreg1);
2703 /* Do that word. */
2704 output_asm_insn (singlemove_string (latehalf), latehalf);
2706 /* Undo the adds we just did. */
2707 if (addreg0)
2709 if (size == 12)
2710 output_asm_insn ("subq%.l %#8,%0", &addreg0);
2711 else
2712 output_asm_insn ("subq%.l %#4,%0", &addreg0);
2714 if (addreg1)
2716 if (size == 12)
2717 output_asm_insn ("subq%.l %#8,%0", &addreg1);
2718 else
2719 output_asm_insn ("subq%.l %#4,%0", &addreg1);
2722 return "";
2725 /* Return a REG that occurs in ADDR with coefficient 1.
2726 ADDR can be effectively incremented by incrementing REG. */
2728 static rtx
2729 find_addr_reg (addr)
2730 rtx addr;
2732 while (GET_CODE (addr) == PLUS)
2734 if (GET_CODE (XEXP (addr, 0)) == REG)
2735 addr = XEXP (addr, 0);
2736 else if (GET_CODE (XEXP (addr, 1)) == REG)
2737 addr = XEXP (addr, 1);
2738 else if (CONSTANT_P (XEXP (addr, 0)))
2739 addr = XEXP (addr, 1);
2740 else if (CONSTANT_P (XEXP (addr, 1)))
2741 addr = XEXP (addr, 0);
2742 else
2743 abort ();
2745 if (GET_CODE (addr) == REG)
2746 return addr;
2747 abort ();
2750 /* Output assembler code to perform a 32 bit 3 operand add. */
2752 const char *
2753 output_addsi3 (operands)
2754 rtx *operands;
2756 if (! operands_match_p (operands[0], operands[1]))
2758 if (!ADDRESS_REG_P (operands[1]))
2760 rtx tmp = operands[1];
2762 operands[1] = operands[2];
2763 operands[2] = tmp;
2766 /* These insns can result from reloads to access
2767 stack slots over 64k from the frame pointer. */
2768 if (GET_CODE (operands[2]) == CONST_INT
2769 && INTVAL (operands[2]) + 0x8000 >= (unsigned) 0x10000)
2770 return "move%.l %2,%0\n\tadd%.l %1,%0";
2771 #ifdef SGS
2772 if (GET_CODE (operands[2]) == REG)
2773 return "lea 0(%1,%2.l),%0";
2774 else
2775 return "lea %c2(%1),%0";
2776 #else /* not SGS */
2777 #ifdef MOTOROLA
2778 if (GET_CODE (operands[2]) == REG)
2779 return "lea (%1,%2.l),%0";
2780 else
2781 return "lea (%c2,%1),%0";
2782 #else /* not MOTOROLA (MIT syntax) */
2783 if (GET_CODE (operands[2]) == REG)
2784 return "lea %1@(0,%2:l),%0";
2785 else
2786 return "lea %1@(%c2),%0";
2787 #endif /* not MOTOROLA */
2788 #endif /* not SGS */
2790 if (GET_CODE (operands[2]) == CONST_INT)
2792 #ifndef NO_ADDSUB_Q
2793 if (INTVAL (operands[2]) > 0
2794 && INTVAL (operands[2]) <= 8)
2795 return "addq%.l %2,%0";
2796 if (INTVAL (operands[2]) < 0
2797 && INTVAL (operands[2]) >= -8)
2799 operands[2] = GEN_INT (- INTVAL (operands[2]));
2800 return "subq%.l %2,%0";
2802 /* On the CPU32 it is faster to use two addql instructions to
2803 add a small integer (8 < N <= 16) to a register.
2804 Likewise for subql. */
2805 if (TARGET_CPU32 && REG_P (operands[0]))
2807 if (INTVAL (operands[2]) > 8
2808 && INTVAL (operands[2]) <= 16)
2810 operands[2] = GEN_INT (INTVAL (operands[2]) - 8);
2811 return "addq%.l %#8,%0\n\taddq%.l %2,%0";
2813 if (INTVAL (operands[2]) < -8
2814 && INTVAL (operands[2]) >= -16)
2816 operands[2] = GEN_INT (- INTVAL (operands[2]) - 8);
2817 return "subq%.l %#8,%0\n\tsubq%.l %2,%0";
2820 #endif
2821 if (ADDRESS_REG_P (operands[0])
2822 && INTVAL (operands[2]) >= -0x8000
2823 && INTVAL (operands[2]) < 0x8000)
2825 if (TARGET_68040)
2826 return "add%.w %2,%0";
2827 else
2828 #ifdef MOTOROLA
2829 return "lea (%c2,%0),%0";
2830 #else
2831 return "lea %0@(%c2),%0";
2832 #endif
2835 return "add%.l %2,%0";
2838 /* Store in cc_status the expressions that the condition codes will
2839 describe after execution of an instruction whose pattern is EXP.
2840 Do not alter them if the instruction would not alter the cc's. */
2842 /* On the 68000, all the insns to store in an address register fail to
2843 set the cc's. However, in some cases these instructions can make it
2844 possibly invalid to use the saved cc's. In those cases we clear out
2845 some or all of the saved cc's so they won't be used. */
2847 void
2848 notice_update_cc (exp, insn)
2849 rtx exp;
2850 rtx insn;
2852 /* If the cc is being set from the fpa and the expression is not an
2853 explicit floating point test instruction (which has code to deal with
2854 this), reinit the CC. */
2855 if (((cc_status.value1 && FPA_REG_P (cc_status.value1))
2856 || (cc_status.value2 && FPA_REG_P (cc_status.value2)))
2857 && !(GET_CODE (exp) == PARALLEL
2858 && GET_CODE (XVECEXP (exp, 0, 0)) == SET
2859 && XEXP (XVECEXP (exp, 0, 0), 0) == cc0_rtx))
2861 CC_STATUS_INIT;
2863 else if (GET_CODE (exp) == SET)
2865 if (GET_CODE (SET_SRC (exp)) == CALL)
2867 CC_STATUS_INIT;
2869 else if (ADDRESS_REG_P (SET_DEST (exp)))
2871 if (cc_status.value1 && modified_in_p (cc_status.value1, insn))
2872 cc_status.value1 = 0;
2873 if (cc_status.value2 && modified_in_p (cc_status.value2, insn))
2874 cc_status.value2 = 0;
2876 else if (!FP_REG_P (SET_DEST (exp))
2877 && SET_DEST (exp) != cc0_rtx
2878 && (FP_REG_P (SET_SRC (exp))
2879 || GET_CODE (SET_SRC (exp)) == FIX
2880 || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE
2881 || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND))
2883 CC_STATUS_INIT;
2885 /* A pair of move insns doesn't produce a useful overall cc. */
2886 else if (!FP_REG_P (SET_DEST (exp))
2887 && !FP_REG_P (SET_SRC (exp))
2888 && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
2889 && (GET_CODE (SET_SRC (exp)) == REG
2890 || GET_CODE (SET_SRC (exp)) == MEM
2891 || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
2893 CC_STATUS_INIT;
2895 else if (GET_CODE (SET_SRC (exp)) == CALL)
2897 CC_STATUS_INIT;
2899 else if (XEXP (exp, 0) != pc_rtx)
2901 cc_status.flags = 0;
2902 cc_status.value1 = XEXP (exp, 0);
2903 cc_status.value2 = XEXP (exp, 1);
2906 else if (GET_CODE (exp) == PARALLEL
2907 && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
2909 if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0)))
2910 CC_STATUS_INIT;
2911 else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx)
2913 cc_status.flags = 0;
2914 cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
2915 cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
2918 else
2919 CC_STATUS_INIT;
2920 if (cc_status.value2 != 0
2921 && ADDRESS_REG_P (cc_status.value2)
2922 && GET_MODE (cc_status.value2) == QImode)
2923 CC_STATUS_INIT;
2924 if (cc_status.value2 != 0
2925 && !(cc_status.value1 && FPA_REG_P (cc_status.value1)))
2926 switch (GET_CODE (cc_status.value2))
2928 case PLUS: case MINUS: case MULT:
2929 case DIV: case UDIV: case MOD: case UMOD: case NEG:
2930 #if 0 /* These instructions always clear the overflow bit */
2931 case ASHIFT: case ASHIFTRT: case LSHIFTRT:
2932 case ROTATE: case ROTATERT:
2933 #endif
2934 if (GET_MODE (cc_status.value2) != VOIDmode)
2935 cc_status.flags |= CC_NO_OVERFLOW;
2936 break;
2937 case ZERO_EXTEND:
2938 /* (SET r1 (ZERO_EXTEND r2)) on this machine
2939 ends with a move insn moving r2 in r2's mode.
2940 Thus, the cc's are set for r2.
2941 This can set N bit spuriously. */
2942 cc_status.flags |= CC_NOT_NEGATIVE;
2944 default:
2945 break;
2947 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
2948 && cc_status.value2
2949 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
2950 cc_status.value2 = 0;
2951 if (((cc_status.value1 && FP_REG_P (cc_status.value1))
2952 || (cc_status.value2 && FP_REG_P (cc_status.value2)))
2953 && !((cc_status.value1 && FPA_REG_P (cc_status.value1))
2954 || (cc_status.value2 && FPA_REG_P (cc_status.value2))))
2955 cc_status.flags = CC_IN_68881;
2958 const char *
2959 output_move_const_double (operands)
2960 rtx *operands;
2962 #ifdef SUPPORT_SUN_FPA
2963 if (TARGET_FPA && FPA_REG_P (operands[0]))
2965 int code = standard_sun_fpa_constant_p (operands[1]);
2967 if (code != 0)
2969 static char buf[40];
2971 sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff);
2972 return buf;
2974 return "fpmove%.d %1,%0";
2976 else
2977 #endif
2979 int code = standard_68881_constant_p (operands[1]);
2981 if (code != 0)
2983 static char buf[40];
2985 sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
2986 return buf;
2988 return "fmove%.d %1,%0";
2992 const char *
2993 output_move_const_single (operands)
2994 rtx *operands;
2996 #ifdef SUPPORT_SUN_FPA
2997 if (TARGET_FPA)
2999 int code = standard_sun_fpa_constant_p (operands[1]);
3001 if (code != 0)
3003 static char buf[40];
3005 sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff);
3006 return buf;
3008 return "fpmove%.s %1,%0";
3010 else
3011 #endif /* defined SUPPORT_SUN_FPA */
3013 int code = standard_68881_constant_p (operands[1]);
3015 if (code != 0)
3017 static char buf[40];
3019 sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
3020 return buf;
3022 return "fmove%.s %f1,%0";
3026 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
3027 from the "fmovecr" instruction.
3028 The value, anded with 0xff, gives the code to use in fmovecr
3029 to get the desired constant. */
3031 /* This code has been fixed for cross-compilation. */
3033 static int inited_68881_table = 0;
3035 static const char *const strings_68881[7] = {
3036 "0.0",
3037 "1.0",
3038 "10.0",
3039 "100.0",
3040 "10000.0",
3041 "1e8",
3042 "1e16"
3045 static const int codes_68881[7] = {
3046 0x0f,
3047 0x32,
3048 0x33,
3049 0x34,
3050 0x35,
3051 0x36,
3052 0x37
3055 REAL_VALUE_TYPE values_68881[7];
3057 /* Set up values_68881 array by converting the decimal values
3058 strings_68881 to binary. */
3060 void
3061 init_68881_table ()
3063 int i;
3064 REAL_VALUE_TYPE r;
3065 enum machine_mode mode;
3067 mode = SFmode;
3068 for (i = 0; i < 7; i++)
3070 if (i == 6)
3071 mode = DFmode;
3072 r = REAL_VALUE_ATOF (strings_68881[i], mode);
3073 values_68881[i] = r;
3075 inited_68881_table = 1;
3079 standard_68881_constant_p (x)
3080 rtx x;
3082 REAL_VALUE_TYPE r;
3083 int i;
3085 #ifdef NO_ASM_FMOVECR
3086 return 0;
3087 #endif
3089 /* fmovecr must be emulated on the 68040 and 68060, so it shouldn't be
3090 used at all on those chips. */
3091 if (TARGET_68040 || TARGET_68060)
3092 return 0;
3094 #ifndef REAL_ARITHMETIC
3095 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
3096 if (! flag_pretend_float)
3097 return 0;
3098 #endif
3099 #endif
3101 if (! inited_68881_table)
3102 init_68881_table ();
3104 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
3106 /* Use REAL_VALUES_IDENTICAL instead of REAL_VALUES_EQUAL so that -0.0
3107 is rejected. */
3108 for (i = 0; i < 6; i++)
3110 if (REAL_VALUES_IDENTICAL (r, values_68881[i]))
3111 return (codes_68881[i]);
3114 if (GET_MODE (x) == SFmode)
3115 return 0;
3117 if (REAL_VALUES_EQUAL (r, values_68881[6]))
3118 return (codes_68881[6]);
3120 /* larger powers of ten in the constants ram are not used
3121 because they are not equal to a `double' C constant. */
3122 return 0;
3125 /* If X is a floating-point constant, return the logarithm of X base 2,
3126 or 0 if X is not a power of 2. */
3129 floating_exact_log2 (x)
3130 rtx x;
3132 REAL_VALUE_TYPE r, r1;
3133 int i;
3135 #ifndef REAL_ARITHMETIC
3136 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
3137 if (! flag_pretend_float)
3138 return 0;
3139 #endif
3140 #endif
3142 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
3144 if (REAL_VALUES_LESS (r, dconst0))
3145 return 0;
3147 r1 = dconst1;
3148 i = 0;
3149 while (REAL_VALUES_LESS (r1, r))
3151 r1 = REAL_VALUE_LDEXP (dconst1, i);
3152 if (REAL_VALUES_EQUAL (r1, r))
3153 return i;
3154 i = i + 1;
3156 return 0;
3159 #ifdef SUPPORT_SUN_FPA
3160 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
3161 from the Sun FPA's constant RAM.
3162 The value returned, anded with 0x1ff, gives the code to use in fpmove
3163 to get the desired constant. */
3165 static int inited_FPA_table = 0;
3167 static const char *const strings_FPA[38] = {
3168 /* small rationals */
3169 "0.0",
3170 "1.0",
3171 "0.5",
3172 "-1.0",
3173 "2.0",
3174 "3.0",
3175 "4.0",
3176 "8.0",
3177 "0.25",
3178 "0.125",
3179 "10.0",
3180 "-0.5",
3181 /* Decimal equivalents of double precision values */
3182 "2.718281828459045091", /* D_E */
3183 "6.283185307179586477", /* 2 pi */
3184 "3.141592653589793116", /* D_PI */
3185 "1.570796326794896619", /* pi/2 */
3186 "1.414213562373095145", /* D_SQRT2 */
3187 "0.7071067811865475244", /* 1/sqrt(2) */
3188 "-1.570796326794896619", /* -pi/2 */
3189 "1.442695040888963387", /* D_LOG2ofE */
3190 "3.321928024887362182", /* D_LOG2of10 */
3191 "0.6931471805599452862", /* D_LOGEof2 */
3192 "2.302585092994045901", /* D_LOGEof10 */
3193 "0.3010299956639811980", /* D_LOG10of2 */
3194 "0.4342944819032518167", /* D_LOG10ofE */
3195 /* Decimal equivalents of single precision values */
3196 "2.718281745910644531", /* S_E */
3197 "6.283185307179586477", /* 2 pi */
3198 "3.141592741012573242", /* S_PI */
3199 "1.570796326794896619", /* pi/2 */
3200 "1.414213538169860840", /* S_SQRT2 */
3201 "0.7071067811865475244", /* 1/sqrt(2) */
3202 "-1.570796326794896619", /* -pi/2 */
3203 "1.442695021629333496", /* S_LOG2ofE */
3204 "3.321928024291992188", /* S_LOG2of10 */
3205 "0.6931471824645996094", /* S_LOGEof2 */
3206 "2.302585124969482442", /* S_LOGEof10 */
3207 "0.3010300099849700928", /* S_LOG10of2 */
3208 "0.4342944920063018799", /* S_LOG10ofE */
3212 static const int codes_FPA[38] = {
3213 /* small rationals */
3214 0x200,
3215 0xe,
3216 0xf,
3217 0x10,
3218 0x11,
3219 0xb1,
3220 0x12,
3221 0x13,
3222 0x15,
3223 0x16,
3224 0x17,
3225 0x2e,
3226 /* double precision */
3227 0x8,
3228 0x9,
3229 0xa,
3230 0xb,
3231 0xc,
3232 0xd,
3233 0x27,
3234 0x28,
3235 0x29,
3236 0x2a,
3237 0x2b,
3238 0x2c,
3239 0x2d,
3240 /* single precision */
3241 0x8,
3242 0x9,
3243 0xa,
3244 0xb,
3245 0xc,
3246 0xd,
3247 0x27,
3248 0x28,
3249 0x29,
3250 0x2a,
3251 0x2b,
3252 0x2c,
3253 0x2d
3256 REAL_VALUE_TYPE values_FPA[38];
3258 /* This code has been fixed for cross-compilation. */
3260 static void init_FPA_table PARAMS ((void));
3261 static void
3262 init_FPA_table ()
3264 enum machine_mode mode;
3265 int i;
3266 REAL_VALUE_TYPE r;
3268 mode = DFmode;
3269 for (i = 0; i < 38; i++)
3271 if (i == 25)
3272 mode = SFmode;
3273 r = REAL_VALUE_ATOF (strings_FPA[i], mode);
3274 values_FPA[i] = r;
3276 inited_FPA_table = 1;
3281 standard_sun_fpa_constant_p (x)
3282 rtx x;
3284 REAL_VALUE_TYPE r;
3285 int i;
3287 #ifndef REAL_ARITHMETIC
3288 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
3289 if (! flag_pretend_float)
3290 return 0;
3291 #endif
3292 #endif
3294 if (! inited_FPA_table)
3295 init_FPA_table ();
3297 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
3299 for (i=0; i<12; i++)
3301 if (REAL_VALUES_EQUAL (r, values_FPA[i]))
3302 return (codes_FPA[i]);
3305 if (GET_MODE (x) == SFmode)
3307 for (i=25; i<38; i++)
3309 if (REAL_VALUES_EQUAL (r, values_FPA[i]))
3310 return (codes_FPA[i]);
3313 else
3315 for (i=12; i<25; i++)
3317 if (REAL_VALUES_EQUAL (r, values_FPA[i]))
3318 return (codes_FPA[i]);
3321 return 0x0;
3323 #endif /* define SUPPORT_SUN_FPA */
3325 /* A C compound statement to output to stdio stream STREAM the
3326 assembler syntax for an instruction operand X. X is an RTL
3327 expression.
3329 CODE is a value that can be used to specify one of several ways
3330 of printing the operand. It is used when identical operands
3331 must be printed differently depending on the context. CODE
3332 comes from the `%' specification that was used to request
3333 printing of the operand. If the specification was just `%DIGIT'
3334 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
3335 is the ASCII code for LTR.
3337 If X is a register, this macro should print the register's name.
3338 The names can be found in an array `reg_names' whose type is
3339 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
3341 When the machine description has a specification `%PUNCT' (a `%'
3342 followed by a punctuation character), this macro is called with
3343 a null pointer for X and the punctuation character for CODE.
3345 The m68k specific codes are:
3347 '.' for dot needed in Motorola-style opcode names.
3348 '-' for an operand pushing on the stack:
3349 sp@-, -(sp) or -(%sp) depending on the style of syntax.
3350 '+' for an operand pushing on the stack:
3351 sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
3352 '@' for a reference to the top word on the stack:
3353 sp@, (sp) or (%sp) depending on the style of syntax.
3354 '#' for an immediate operand prefix (# in MIT and Motorola syntax
3355 but & in SGS syntax, $ in CRDS/UNOS syntax).
3356 '!' for the cc register (used in an `and to cc' insn).
3357 '$' for the letter `s' in an op code, but only on the 68040.
3358 '&' for the letter `d' in an op code, but only on the 68040.
3359 '/' for register prefix needed by longlong.h.
3361 'b' for byte insn (no effect, on the Sun; this is for the ISI).
3362 'd' to force memory addressing to be absolute, not relative.
3363 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
3364 'o' for operands to go directly to output_operand_address (bypassing
3365 print_operand_address--used only for SYMBOL_REFs under TARGET_PCREL)
3366 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
3367 than directly). Second part of 'y' below.
3368 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
3369 or print pair of registers as rx:ry.
3370 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
3371 CONST_DOUBLE's as SunFPA constant RAM registers if
3372 possible, so it should not be used except for the SunFPA.
3376 void
3377 print_operand (file, op, letter)
3378 FILE *file; /* file to write to */
3379 rtx op; /* operand to print */
3380 int letter; /* %<letter> or 0 */
3382 #ifdef SUPPORT_SUN_FPA
3383 int i;
3384 #endif
3386 if (letter == '.')
3388 #if defined (MOTOROLA) && !defined (CRDS)
3389 asm_fprintf (file, ".");
3390 #endif
3392 else if (letter == '#')
3394 asm_fprintf (file, "%0I");
3396 else if (letter == '-')
3398 #ifdef MOTOROLA
3399 asm_fprintf (file, "-(%Rsp)");
3400 #else
3401 asm_fprintf (file, "%Rsp@-");
3402 #endif
3404 else if (letter == '+')
3406 #ifdef MOTOROLA
3407 asm_fprintf (file, "(%Rsp)+");
3408 #else
3409 asm_fprintf (file, "%Rsp@+");
3410 #endif
3412 else if (letter == '@')
3414 #ifdef MOTOROLA
3415 asm_fprintf (file, "(%Rsp)");
3416 #else
3417 asm_fprintf (file, "%Rsp@");
3418 #endif
3420 else if (letter == '!')
3422 asm_fprintf (file, "%Rfpcr");
3424 else if (letter == '$')
3426 if (TARGET_68040_ONLY)
3428 fprintf (file, "s");
3431 else if (letter == '&')
3433 if (TARGET_68040_ONLY)
3435 fprintf (file, "d");
3438 else if (letter == '/')
3440 asm_fprintf (file, "%R");
3442 else if (letter == 'o')
3444 /* This is only for direct addresses with TARGET_PCREL */
3445 if (GET_CODE (op) != MEM || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
3446 || !TARGET_PCREL)
3447 abort ();
3448 output_addr_const (file, XEXP (op, 0));
3450 else if (GET_CODE (op) == REG)
3452 #ifdef SUPPORT_SUN_FPA
3453 if (REGNO (op) < 16
3454 && (letter == 'y' || letter == 'x')
3455 && GET_MODE (op) == DFmode)
3457 fprintf (file, "%s:%s", reg_names[REGNO (op)],
3458 reg_names[REGNO (op)+1]);
3460 else
3461 #endif
3463 if (letter == 'R')
3464 /* Print out the second register name of a register pair.
3465 I.e., R (6) => 7. */
3466 fputs (reg_names[REGNO (op) + 1], file);
3467 else
3468 fputs (reg_names[REGNO (op)], file);
3471 else if (GET_CODE (op) == MEM)
3473 output_address (XEXP (op, 0));
3474 if (letter == 'd' && ! TARGET_68020
3475 && CONSTANT_ADDRESS_P (XEXP (op, 0))
3476 && !(GET_CODE (XEXP (op, 0)) == CONST_INT
3477 && INTVAL (XEXP (op, 0)) < 0x8000
3478 && INTVAL (XEXP (op, 0)) >= -0x8000))
3480 #ifdef MOTOROLA
3481 fprintf (file, ".l");
3482 #else
3483 fprintf (file, ":l");
3484 #endif
3487 #ifdef SUPPORT_SUN_FPA
3488 else if ((letter == 'y' || letter == 'w')
3489 && GET_CODE (op) == CONST_DOUBLE
3490 && (i = standard_sun_fpa_constant_p (op)))
3492 fprintf (file, "%%%d", i & 0x1ff);
3494 #endif
3495 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
3497 REAL_VALUE_TYPE r;
3498 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
3499 ASM_OUTPUT_FLOAT_OPERAND (letter, file, r);
3501 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode)
3503 REAL_VALUE_TYPE r;
3504 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
3505 ASM_OUTPUT_LONG_DOUBLE_OPERAND (file, r);
3507 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
3509 REAL_VALUE_TYPE r;
3510 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
3511 ASM_OUTPUT_DOUBLE_OPERAND (file, r);
3513 else
3515 /* Use `print_operand_address' instead of `output_addr_const'
3516 to ensure that we print relevant PIC stuff. */
3517 asm_fprintf (file, "%0I");
3518 if (TARGET_PCREL
3519 && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST))
3520 print_operand_address (file, op);
3521 else
3522 output_addr_const (file, op);
3527 /* A C compound statement to output to stdio stream STREAM the
3528 assembler syntax for an instruction operand that is a memory
3529 reference whose address is ADDR. ADDR is an RTL expression.
3531 Note that this contains a kludge that knows that the only reason
3532 we have an address (plus (label_ref...) (reg...)) when not generating
3533 PIC code is in the insn before a tablejump, and we know that m68k.md
3534 generates a label LInnn: on such an insn.
3536 It is possible for PIC to generate a (plus (label_ref...) (reg...))
3537 and we handle that just like we would a (plus (symbol_ref...) (reg...)).
3539 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
3540 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
3541 we want. This difference can be accommodated by using an assembler
3542 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
3543 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
3544 macro. See m68k/sgs.h for an example; for versions without the bug.
3545 Some assemblers refuse all the above solutions. The workaround is to
3546 emit "K(pc,d0.l*2)" with K being a small constant known to give the
3547 right behaviour.
3549 They also do not like things like "pea 1.w", so we simple leave off
3550 the .w on small constants.
3552 This routine is responsible for distinguishing between -fpic and -fPIC
3553 style relocations in an address. When generating -fpic code the
3554 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating
3555 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
3557 #ifndef ASM_OUTPUT_CASE_FETCH
3558 #ifdef MOTOROLA
3559 #ifdef SGS
3560 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
3561 asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
3562 #else
3563 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
3564 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
3565 #endif
3566 #else
3567 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
3568 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
3569 #endif
3570 #endif /* ASM_OUTPUT_CASE_FETCH */
3572 void
3573 print_operand_address (file, addr)
3574 FILE *file;
3575 rtx addr;
3577 register rtx reg1, reg2, breg, ireg;
3578 rtx offset;
3580 switch (GET_CODE (addr))
3582 case REG:
3583 #ifdef MOTOROLA
3584 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
3585 #else
3586 fprintf (file, "%s@", reg_names[REGNO (addr)]);
3587 #endif
3588 break;
3589 case PRE_DEC:
3590 #ifdef MOTOROLA
3591 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
3592 #else
3593 fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);
3594 #endif
3595 break;
3596 case POST_INC:
3597 #ifdef MOTOROLA
3598 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
3599 #else
3600 fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);
3601 #endif
3602 break;
3603 case PLUS:
3604 reg1 = reg2 = ireg = breg = offset = 0;
3605 if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
3607 offset = XEXP (addr, 0);
3608 addr = XEXP (addr, 1);
3610 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
3612 offset = XEXP (addr, 1);
3613 addr = XEXP (addr, 0);
3615 if (GET_CODE (addr) != PLUS)
3619 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
3621 reg1 = XEXP (addr, 0);
3622 addr = XEXP (addr, 1);
3624 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
3626 reg1 = XEXP (addr, 1);
3627 addr = XEXP (addr, 0);
3629 else if (GET_CODE (XEXP (addr, 0)) == MULT)
3631 reg1 = XEXP (addr, 0);
3632 addr = XEXP (addr, 1);
3634 else if (GET_CODE (XEXP (addr, 1)) == MULT)
3636 reg1 = XEXP (addr, 1);
3637 addr = XEXP (addr, 0);
3639 else if (GET_CODE (XEXP (addr, 0)) == REG)
3641 reg1 = XEXP (addr, 0);
3642 addr = XEXP (addr, 1);
3644 else if (GET_CODE (XEXP (addr, 1)) == REG)
3646 reg1 = XEXP (addr, 1);
3647 addr = XEXP (addr, 0);
3649 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
3650 || GET_CODE (addr) == SIGN_EXTEND)
3652 if (reg1 == 0)
3654 reg1 = addr;
3656 else
3658 reg2 = addr;
3660 addr = 0;
3662 #if 0 /* for OLD_INDEXING */
3663 else if (GET_CODE (addr) == PLUS)
3665 if (GET_CODE (XEXP (addr, 0)) == REG)
3667 reg2 = XEXP (addr, 0);
3668 addr = XEXP (addr, 1);
3670 else if (GET_CODE (XEXP (addr, 1)) == REG)
3672 reg2 = XEXP (addr, 1);
3673 addr = XEXP (addr, 0);
3676 #endif
3677 if (offset != 0)
3679 if (addr != 0)
3681 abort ();
3683 addr = offset;
3685 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
3686 || GET_CODE (reg1) == MULT))
3687 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
3689 breg = reg2;
3690 ireg = reg1;
3692 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
3694 breg = reg1;
3695 ireg = reg2;
3697 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
3698 && ! (flag_pic && ireg == pic_offset_table_rtx))
3700 int scale = 1;
3701 if (GET_CODE (ireg) == MULT)
3703 scale = INTVAL (XEXP (ireg, 1));
3704 ireg = XEXP (ireg, 0);
3706 if (GET_CODE (ireg) == SIGN_EXTEND)
3708 ASM_OUTPUT_CASE_FETCH (file,
3709 CODE_LABEL_NUMBER (XEXP (addr, 0)),
3710 reg_names[REGNO (XEXP (ireg, 0))]);
3711 fprintf (file, "w");
3713 else
3715 ASM_OUTPUT_CASE_FETCH (file,
3716 CODE_LABEL_NUMBER (XEXP (addr, 0)),
3717 reg_names[REGNO (ireg)]);
3718 fprintf (file, "l");
3720 if (scale != 1)
3722 #ifdef MOTOROLA
3723 fprintf (file, "*%d", scale);
3724 #else
3725 fprintf (file, ":%d", scale);
3726 #endif
3728 putc (')', file);
3729 break;
3731 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
3732 && ! (flag_pic && breg == pic_offset_table_rtx))
3734 ASM_OUTPUT_CASE_FETCH (file,
3735 CODE_LABEL_NUMBER (XEXP (addr, 0)),
3736 reg_names[REGNO (breg)]);
3737 fprintf (file, "l)");
3738 break;
3740 if (ireg != 0 || breg != 0)
3742 int scale = 1;
3743 if (breg == 0)
3745 abort ();
3747 if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
3749 abort ();
3751 #ifdef MOTOROLA
3752 if (addr != 0)
3754 output_addr_const (file, addr);
3755 if (flag_pic && (breg == pic_offset_table_rtx))
3757 fprintf (file, "@GOT");
3758 if (flag_pic == 1)
3759 fprintf (file, ".w");
3762 fprintf (file, "(%s", reg_names[REGNO (breg)]);
3763 if (ireg != 0)
3765 putc (',', file);
3767 #else
3768 fprintf (file, "%s@(", reg_names[REGNO (breg)]);
3769 if (addr != 0)
3771 output_addr_const (file, addr);
3772 if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
3773 fprintf (file, ":w");
3774 if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
3775 fprintf (file, ":l");
3777 if (addr != 0 && ireg != 0)
3779 putc (',', file);
3781 #endif
3782 if (ireg != 0 && GET_CODE (ireg) == MULT)
3784 scale = INTVAL (XEXP (ireg, 1));
3785 ireg = XEXP (ireg, 0);
3787 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
3789 #ifdef MOTOROLA
3790 fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);
3791 #else
3792 fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);
3793 #endif
3795 else if (ireg != 0)
3797 #ifdef MOTOROLA
3798 fprintf (file, "%s.l", reg_names[REGNO (ireg)]);
3799 #else
3800 fprintf (file, "%s:l", reg_names[REGNO (ireg)]);
3801 #endif
3803 if (scale != 1)
3805 #ifdef MOTOROLA
3806 fprintf (file, "*%d", scale);
3807 #else
3808 fprintf (file, ":%d", scale);
3809 #endif
3811 putc (')', file);
3812 break;
3814 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
3815 && ! (flag_pic && reg1 == pic_offset_table_rtx))
3817 ASM_OUTPUT_CASE_FETCH (file,
3818 CODE_LABEL_NUMBER (XEXP (addr, 0)),
3819 reg_names[REGNO (reg1)]);
3820 fprintf (file, "l)");
3821 break;
3823 /* FALL-THROUGH (is this really what we want?) */
3824 default:
3825 if (GET_CODE (addr) == CONST_INT
3826 && INTVAL (addr) < 0x8000
3827 && INTVAL (addr) >= -0x8000)
3829 #ifdef MOTOROLA
3830 #ifdef SGS
3831 /* Many SGS assemblers croak on size specifiers for constants. */
3832 fprintf (file, "%d", (int) INTVAL (addr));
3833 #else
3834 fprintf (file, "%d.w", (int) INTVAL (addr));
3835 #endif
3836 #else
3837 fprintf (file, "%d:w", (int) INTVAL (addr));
3838 #endif
3840 else if (GET_CODE (addr) == CONST_INT)
3842 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr));
3844 else if (TARGET_PCREL)
3846 fputc ('(', file);
3847 output_addr_const (file, addr);
3848 if (flag_pic == 1)
3849 asm_fprintf (file, ":w,%Rpc)");
3850 else
3851 asm_fprintf (file, ":l,%Rpc)");
3853 else
3855 /* Special case for SYMBOL_REF if the symbol name ends in
3856 `.<letter>', this can be mistaken as a size suffix. Put
3857 the name in parentheses. */
3858 if (GET_CODE (addr) == SYMBOL_REF
3859 && strlen (XSTR (addr, 0)) > 2
3860 && XSTR (addr, 0)[strlen (XSTR (addr, 0)) - 2] == '.')
3862 putc ('(', file);
3863 output_addr_const (file, addr);
3864 putc (')', file);
3866 else
3867 output_addr_const (file, addr);
3869 break;
3873 /* Check for cases where a clr insns can be omitted from code using
3874 strict_low_part sets. For example, the second clrl here is not needed:
3875 clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
3877 MODE is the mode of this STRICT_LOW_PART set. FIRST_INSN is the clear
3878 insn we are checking for redundancy. TARGET is the register set by the
3879 clear insn. */
3882 strict_low_part_peephole_ok (mode, first_insn, target)
3883 enum machine_mode mode;
3884 rtx first_insn;
3885 rtx target;
3887 rtx p;
3889 p = prev_nonnote_insn (first_insn);
3891 while (p)
3893 /* If it isn't an insn, then give up. */
3894 if (GET_CODE (p) != INSN)
3895 return 0;
3897 if (reg_set_p (target, p))
3899 rtx set = single_set (p);
3900 rtx dest;
3902 /* If it isn't an easy to recognize insn, then give up. */
3903 if (! set)
3904 return 0;
3906 dest = SET_DEST (set);
3908 /* If this sets the entire target register to zero, then our
3909 first_insn is redundant. */
3910 if (rtx_equal_p (dest, target)
3911 && SET_SRC (set) == const0_rtx)
3912 return 1;
3913 else if (GET_CODE (dest) == STRICT_LOW_PART
3914 && GET_CODE (XEXP (dest, 0)) == REG
3915 && REGNO (XEXP (dest, 0)) == REGNO (target)
3916 && (GET_MODE_SIZE (GET_MODE (XEXP (dest, 0)))
3917 <= GET_MODE_SIZE (mode)))
3918 /* This is a strict low part set which modifies less than
3919 we are using, so it is safe. */
3921 else
3922 return 0;
3925 p = prev_nonnote_insn (p);
3929 return 0;
3932 /* Accept integer operands in the range 0..0xffffffff. We have to check the
3933 range carefully since this predicate is used in DImode contexts. Also, we
3934 need some extra crud to make it work when hosted on 64-bit machines. */
3937 const_uint32_operand (op, mode)
3938 rtx op;
3939 enum machine_mode mode;
3941 /* It doesn't make sense to ask this question with a mode that is
3942 not larger than 32 bits. */
3943 if (GET_MODE_BITSIZE (mode) <= 32)
3944 abort ();
3946 #if HOST_BITS_PER_WIDE_INT > 32
3947 /* All allowed constants will fit a CONST_INT. */
3948 return (GET_CODE (op) == CONST_INT
3949 && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
3950 #else
3951 return (GET_CODE (op) == CONST_INT
3952 || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
3953 #endif
3956 /* Accept integer operands in the range -0x80000000..0x7fffffff. We have
3957 to check the range carefully since this predicate is used in DImode
3958 contexts. */
3961 const_sint32_operand (op, mode)
3962 rtx op;
3963 enum machine_mode mode;
3965 /* It doesn't make sense to ask this question with a mode that is
3966 not larger than 32 bits. */
3967 if (GET_MODE_BITSIZE (mode) <= 32)
3968 abort ();
3970 /* All allowed constants will fit a CONST_INT. */
3971 return (GET_CODE (op) == CONST_INT
3972 && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
3975 /* Operand predicates for implementing asymmetric pc-relative addressing
3976 on m68k. The m68k supports pc-relative addressing (mode 7, register 2)
3977 when used as a source operand, but not as a destintation operand.
3979 We model this by restricting the meaning of the basic predicates
3980 (general_operand, memory_operand, etc) to forbid the use of this
3981 addressing mode, and then define the following predicates that permit
3982 this addressing mode. These predicates can then be used for the
3983 source operands of the appropriate instructions.
3985 n.b. While it is theoretically possible to change all machine patterns
3986 to use this addressing more where permitted by the architecture,
3987 it has only been implemented for "common" cases: SImode, HImode, and
3988 QImode operands, and only for the principle operations that would
3989 require this addressing mode: data movement and simple integer operations.
3991 In parallel with these new predicates, two new constraint letters
3992 were defined: 'S' and 'T'. 'S' is the -mpcrel analog of 'm'.
3993 'T' replaces 's' in the non-pcrel case. It is a no-op in the pcrel case.
3994 In the pcrel case 's' is only valid in combination with 'a' registers.
3995 See addsi3, subsi3, cmpsi, and movsi patterns for a better understanding
3996 of how these constraints are used.
3998 The use of these predicates is strictly optional, though patterns that
3999 don't will cause an extra reload register to be allocated where one
4000 was not necessary:
4002 lea (abc:w,%pc),%a0 ; need to reload address
4003 moveq &1,%d1 ; since write to pc-relative space
4004 movel %d1,%a0@ ; is not allowed
4006 lea (abc:w,%pc),%a1 ; no need to reload address here
4007 movel %a1@,%d0 ; since "movel (abc:w,%pc),%d0" is ok
4009 For more info, consult tiemann@cygnus.com.
4012 All of the ugliness with predicates and constraints is due to the
4013 simple fact that the m68k does not allow a pc-relative addressing
4014 mode as a destination. gcc does not distinguish between source and
4015 destination addresses. Hence, if we claim that pc-relative address
4016 modes are valid, e.g. GO_IF_LEGITIMATE_ADDRESS accepts them, then we
4017 end up with invalid code. To get around this problem, we left
4018 pc-relative modes as invalid addresses, and then added special
4019 predicates and constraints to accept them.
4021 A cleaner way to handle this is to modify gcc to distinguish
4022 between source and destination addresses. We can then say that
4023 pc-relative is a valid source address but not a valid destination
4024 address, and hopefully avoid a lot of the predicate and constraint
4025 hackery. Unfortunately, this would be a pretty big change. It would
4026 be a useful change for a number of ports, but there aren't any current
4027 plans to undertake this.
4029 ***************************************************************************/
4032 /* Special case of a general operand that's used as a source operand.
4033 Use this to permit reads from PC-relative memory when -mpcrel
4034 is specified. */
4037 general_src_operand (op, mode)
4038 rtx op;
4039 enum machine_mode mode;
4041 if (TARGET_PCREL
4042 && GET_CODE (op) == MEM
4043 && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
4044 || GET_CODE (XEXP (op, 0)) == LABEL_REF
4045 || GET_CODE (XEXP (op, 0)) == CONST))
4046 return 1;
4047 return general_operand (op, mode);
4050 /* Special case of a nonimmediate operand that's used as a source.
4051 Use this to permit reads from PC-relative memory when -mpcrel
4052 is specified. */
4055 nonimmediate_src_operand (op, mode)
4056 rtx op;
4057 enum machine_mode mode;
4059 if (TARGET_PCREL && GET_CODE (op) == MEM
4060 && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
4061 || GET_CODE (XEXP (op, 0)) == LABEL_REF
4062 || GET_CODE (XEXP (op, 0)) == CONST))
4063 return 1;
4064 return nonimmediate_operand (op, mode);
4067 /* Special case of a memory operand that's used as a source.
4068 Use this to permit reads from PC-relative memory when -mpcrel
4069 is specified. */
4072 memory_src_operand (op, mode)
4073 rtx op;
4074 enum machine_mode mode;
4076 if (TARGET_PCREL && GET_CODE (op) == MEM
4077 && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
4078 || GET_CODE (XEXP (op, 0)) == LABEL_REF
4079 || GET_CODE (XEXP (op, 0)) == CONST))
4080 return 1;
4081 return memory_operand (op, mode);
4084 /* Predicate that accepts only a pc-relative address. This is needed
4085 because pc-relative addresses don't satisfy the predicate
4086 "general_src_operand". */
4089 pcrel_address (op, mode)
4090 rtx op;
4091 enum machine_mode mode ATTRIBUTE_UNUSED;
4093 return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF
4094 || GET_CODE (op) == CONST);
4097 const char *
4098 output_andsi3 (operands)
4099 rtx *operands;
4101 int logval;
4102 if (GET_CODE (operands[2]) == CONST_INT
4103 && (INTVAL (operands[2]) | 0xffff) == 0xffffffff
4104 && (DATA_REG_P (operands[0])
4105 || offsettable_memref_p (operands[0]))
4106 && !TARGET_5200)
4108 if (GET_CODE (operands[0]) != REG)
4109 operands[0] = adjust_address (operands[0], HImode, 2);
4110 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
4111 /* Do not delete a following tstl %0 insn; that would be incorrect. */
4112 CC_STATUS_INIT;
4113 if (operands[2] == const0_rtx)
4114 return "clr%.w %0";
4115 return "and%.w %2,%0";
4117 if (GET_CODE (operands[2]) == CONST_INT
4118 && (logval = exact_log2 (~ INTVAL (operands[2]))) >= 0
4119 && (DATA_REG_P (operands[0])
4120 || offsettable_memref_p (operands[0])))
4122 if (DATA_REG_P (operands[0]))
4124 operands[1] = GEN_INT (logval);
4126 else
4128 operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
4129 operands[1] = GEN_INT (logval % 8);
4131 /* This does not set condition codes in a standard way. */
4132 CC_STATUS_INIT;
4133 return "bclr %1,%0";
4135 return "and%.l %2,%0";
4138 const char *
4139 output_iorsi3 (operands)
4140 rtx *operands;
4142 register int logval;
4143 if (GET_CODE (operands[2]) == CONST_INT
4144 && INTVAL (operands[2]) >> 16 == 0
4145 && (DATA_REG_P (operands[0])
4146 || offsettable_memref_p (operands[0]))
4147 && !TARGET_5200)
4149 if (GET_CODE (operands[0]) != REG)
4150 operands[0] = adjust_address (operands[0], HImode, 2);
4151 /* Do not delete a following tstl %0 insn; that would be incorrect. */
4152 CC_STATUS_INIT;
4153 if (INTVAL (operands[2]) == 0xffff)
4154 return "mov%.w %2,%0";
4155 return "or%.w %2,%0";
4157 if (GET_CODE (operands[2]) == CONST_INT
4158 && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
4159 && (DATA_REG_P (operands[0])
4160 || offsettable_memref_p (operands[0])))
4162 if (DATA_REG_P (operands[0]))
4163 operands[1] = GEN_INT (logval);
4164 else
4166 operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
4167 operands[1] = GEN_INT (logval % 8);
4169 CC_STATUS_INIT;
4170 return "bset %1,%0";
4172 return "or%.l %2,%0";
4175 const char *
4176 output_xorsi3 (operands)
4177 rtx *operands;
4179 register int logval;
4180 if (GET_CODE (operands[2]) == CONST_INT
4181 && INTVAL (operands[2]) >> 16 == 0
4182 && (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0]))
4183 && !TARGET_5200)
4185 if (! DATA_REG_P (operands[0]))
4186 operands[0] = adjust_address (operands[0], HImode, 2);
4187 /* Do not delete a following tstl %0 insn; that would be incorrect. */
4188 CC_STATUS_INIT;
4189 if (INTVAL (operands[2]) == 0xffff)
4190 return "not%.w %0";
4191 return "eor%.w %2,%0";
4193 if (GET_CODE (operands[2]) == CONST_INT
4194 && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
4195 && (DATA_REG_P (operands[0])
4196 || offsettable_memref_p (operands[0])))
4198 if (DATA_REG_P (operands[0]))
4199 operands[1] = GEN_INT (logval);
4200 else
4202 operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
4203 operands[1] = GEN_INT (logval % 8);
4205 CC_STATUS_INIT;
4206 return "bchg %1,%0";
4208 return "eor%.l %2,%0";
4211 /* Output assembly to switch to section NAME with attribute FLAGS. */
4213 static void
4214 m68k_coff_asm_named_section (name, flags)
4215 const char *name;
4216 unsigned int flags;
4218 char flagchar;
4220 if (flags & SECTION_WRITE)
4221 flagchar = 'd';
4222 else
4223 flagchar = 'x';
4225 fprintf (asm_out_file, "\t.section\t%s,\"%c\"\n", name, flagchar);
4228 #ifdef CTOR_LIST_BEGIN
4229 static void
4230 m68k_svr3_asm_out_constructor (symbol, priority)
4231 rtx symbol;
4232 int priority ATTRIBUTE_UNUSED;
4234 rtx xop[2];
4236 xop[1] = symbol;
4237 xop[0] = gen_rtx_MEM (SImode, gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
4239 init_section ();
4240 output_asm_insn (output_move_simode (xop), xop);
4242 #endif