OSDN Git Service

* final.c (count_basic_block, add_bb, add_bb_string):
[pf3gnuchains/gcc-fork.git] / gcc / config / m68k / m68k.c
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.
4
5 This file is part of GNU CC.
6
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.
11
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.
16
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.  */
21
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"
42
43 /* Needed for use_return_insn.  */
44 #include "flags.h"
45
46 #ifdef SUPPORT_SUN_FPA
47
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 };
53
54 #endif /* defined SUPPORT_SUN_FPA */
55
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;
59
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
68 \f
69
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;
77
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;
84
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;
89 \f
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
95
96 struct gcc_target targetm = TARGET_INITIALIZER;
97 \f
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.
103
104    Don't use this macro to turn on various extra optimizations for
105    `-O'.  That is what `OPTIMIZATION_OPTIONS' is for.  */
106
107 void
108 override_options ()
109 {
110   int def_align;
111   int i;
112
113   def_align = 1;
114
115   /* Validate -malign-loops= value, or provide default */
116   m68k_align_loops = def_align;
117   if (m68k_align_loops_string)
118     {
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;
124     }
125
126   /* Validate -malign-jumps= value, or provide default */
127   m68k_align_jumps = def_align;
128   if (m68k_align_jumps_string)
129     {
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;
135     }
136
137   /* Validate -malign-functions= value, or provide default */
138   m68k_align_funcs = def_align;
139   if (m68k_align_funcs_string)
140     {
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;
147     }
148 }
149 \f
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.  */
157
158
159 /* Note that the order of the bit mask for fmovem is the opposite
160    of the order for movem!  */
161
162 #ifdef CRDS
163
164 static void
165 m68k_output_function_prologue (stream, size)
166      FILE *stream;
167      HOST_WIDE_INT size;
168 {
169   register int regno;
170   register int mask = 0;
171   extern char call_used_regs[];
172   HOST_WIDE_INT fsize = ((size) + 3) & -4;
173
174   /* unos stack probe */
175   if (fsize > 30000)
176     {
177       fprintf (stream, "\tmovel sp,a0\n");
178       fprintf (stream, "\taddl $-%d,a0\n", 2048 + fsize);
179       fprintf (stream, "\ttstb (a0)\n");
180     }
181   else
182     fprintf (stream, "\ttstb -%d(sp)\n", 2048 + fsize);
183
184   if (frame_pointer_needed)
185     {
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);
190     }
191   else if (fsize)
192     {
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));
198     }
199
200   for (regno = 16; regno < 24; regno++)
201     if (regs_ever_live[regno] && ! call_used_regs[regno])
202       mask |= 1 << (regno - 16);
203
204   if ((mask & 0xff) != 0)
205     fprintf (stream, "\tfmovem $0x%x,-(sp)\n", mask & 0xff);
206
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));
213
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);
218 }
219
220 #else
221 #if defined (DPX2) && defined (MOTOROLA)
222
223 static void
224 m68k_output_function_prologue (stream, size)
225      FILE *stream;
226      HOST_WIDE_INT size;
227 {
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;
233
234   if (frame_pointer_needed)
235     {
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);
246     }
247   else if (fsize)
248     {
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));
254     }
255
256   for (regno = 23; regno >= 16; regno--)
257     if (regs_ever_live[regno] && ! call_used_regs[regno])
258       {
259         if (first)
260           {
261             fprintf (stream, "\tfmovem.x %s", reg_names[regno]);
262             first = 0;
263           }
264         else
265           fprintf (stream, "/%s", reg_names[regno]);
266       }
267   if (!first)
268     fprintf (stream, ",-(sp)\n");
269
270   mask = 0;
271   for (regno = 0; regno < 16; regno++)
272     if (regs_ever_live[regno] && ! call_used_regs[regno])
273       {
274         mask |= 1 << (15 - regno);
275         num_saved_regs++;
276       }
277
278   if (frame_pointer_needed)
279     {
280       mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));
281       num_saved_regs--;
282     }
283
284   if (num_saved_regs <= 2)
285     {
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 */
290
291       int i;
292
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]);
297     }
298   else if (mask)
299     {
300       first = 1;
301       for (regno = 0; regno < 16; regno++)
302         if (mask & (1 << regno))
303           {
304             if (first)
305               {
306                 fprintf (stream, "\tmovem.l %s", reg_names[15 - regno]);
307                 first = 0;
308               }
309             else
310               fprintf (stream, "/%s", reg_names[15 - regno]);
311           }
312       fprintf (stream, ",-(sp)\n");
313     }
314
315   if (flag_pic && current_function_uses_pic_offset_table)
316     {
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]);
322     }
323 }
324
325 #else
326 #if defined (NEWS) && defined (MOTOROLA)
327
328 static void
329 m68k_output_function_prologue (stream, size)
330      FILE *stream;
331      HOST_WIDE_INT size;
332 {
333   register int regno;
334   register int mask = 0;
335   extern char call_used_regs[];
336   HOST_WIDE_INT fsize = ((size) + 3) & -4;
337
338   if (frame_pointer_needed)
339     {
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);
346     }
347   else if (fsize)
348     {
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);
355     }
356
357   for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++)
358     if (regs_ever_live[regno] && ! call_used_regs[regno])
359       mask |= 1 << (regno - 16);
360
361   if (mask != 0)
362     fprintf (stream, "\tfmovem.x #0x%x,-(sp)\n", mask & 0xff);
363
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);
368
369   if (frame_pointer_needed)
370     mask &= ~ (1 << (15-FRAME_POINTER_REGNUM));
371
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);
376 }
377
378 #else  /* !CRDS && ! (NEWS && MOTOROLA) && ! (DPX2 && MOTOROLA) */
379
380 static void
381 m68k_output_function_prologue (stream, size)
382      FILE *stream;
383      HOST_WIDE_INT size;
384 {
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;
392   
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)
397     {
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
405     }
406
407   if (frame_pointer_needed)
408     {
409       if (fsize == 0 && TARGET_68040)
410         {
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
421         }
422       else if (fsize < 0x8000)
423         {
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
431         }
432       else if (TARGET_68020)
433         {
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
441         }
442       else
443         {
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
452         }
453       if (dwarf2out_do_frame ())
454         {
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;
462         }
463     }
464   else if (fsize)
465     {
466       if (fsize + 4 < 0x8000)
467         {
468 #ifndef NO_ADDSUB_Q
469           if (fsize + 4 <= 8)
470             {
471               if (!TARGET_5200)
472                 {
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
479                 }
480               else
481                 {
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
488                 }
489             }
490           else if (fsize + 4 <= 16 && TARGET_CPU32)
491             {
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
502             }
503           else 
504 #endif /* not NO_ADDSUB_Q */
505           if (TARGET_68040)
506             {
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
514             }
515           else
516             {
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
522             }
523         }
524       else
525         {
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
532         }
533       if (dwarf2out_do_frame ())
534         {
535           cfa_store_offset += fsize;
536           cfa_offset = cfa_store_offset;
537           dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset);
538         }
539     }
540 #ifdef SUPPORT_SUN_FPA
541   for (regno = 24; regno < 56; regno++)
542     if (regs_ever_live[regno] && ! call_used_regs[regno])
543       {
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 ())
552           {
553             char *l = dwarf2out_cfi_label ();
554
555             cfa_store_offset += 8;
556             if (! frame_pointer_needed)
557               {
558                 cfa_offset = cfa_store_offset;
559                 dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
560               }
561             dwarf2out_reg_save (l, regno, -cfa_store_offset);
562           }
563       }
564 #endif
565   if (TARGET_68881)
566     {
567       for (regno = 16; regno < 24; regno++)
568         if (regs_ever_live[regno] && ! call_used_regs[regno])
569           {
570             mask |= 1 << (regno - 16);
571             num_saved_regs++;
572           }
573       if ((mask & 0xff) != 0)
574         {
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 ())
581             {
582               char *l = (char *) dwarf2out_cfi_label ();
583               int n_regs;
584
585               cfa_store_offset += num_saved_regs * 12;
586               if (! frame_pointer_needed)
587                 {
588                   cfa_offset = cfa_store_offset;
589                   dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
590                 }
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);
595             }
596         }
597       mask = 0;
598       num_saved_regs = 0;
599     }
600   for (regno = 0; regno < 16; regno++)
601     if (regs_ever_live[regno] && ! call_used_regs[regno])
602       {
603         mask |= 1 << (15 - regno);
604         num_saved_regs++;
605       }
606   if (frame_pointer_needed)
607     {
608       mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));
609       num_saved_regs--;
610     }
611   if (flag_pic && current_function_uses_pic_offset_table)
612     {
613       mask |= 1 << (15 - PIC_OFFSET_TABLE_REGNUM);
614       num_saved_regs++;
615     }
616
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
624
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)
628     {
629       if (REG_P (stack_limit_rtx))
630         {
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
638         }
639       else if (GET_CODE (stack_limit_rtx) != SYMBOL_REF)
640         warning ("stack limit expression is not supported");
641     }
642   
643   if (num_saved_regs <= 2)
644     {
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 */
649
650       int i;
651
652       /* Undo the work from above.  */
653       for (i = 0; i< 16; i++)
654         if (mask & (1 << i))
655           {
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 ())
664               {
665                 char *l = (char *) dwarf2out_cfi_label ();
666
667                 cfa_store_offset += 4;
668                 if (! frame_pointer_needed)
669                   {
670                     cfa_offset = cfa_store_offset;
671                     dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
672                   }
673                 dwarf2out_reg_save (l, 15 - i, -cfa_store_offset);
674               }
675           }
676     }
677   else if (mask)
678     {
679       if (TARGET_5200)
680         {
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.
685
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 */
690              
691           int newmask = 0;
692           int i;
693
694           for (i = 0; i < 16; i++)
695             if (mask & (1 << i))
696                 newmask |= (1 << (15-i));
697
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
705         }
706       else
707         {
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
713         }
714       if (dwarf2out_do_frame ())
715         {
716           char *l = (char *) dwarf2out_cfi_label ();
717           int n_regs;
718
719           cfa_store_offset += num_saved_regs * 4;
720           if (! frame_pointer_needed)
721             {
722               cfa_offset = cfa_store_offset;
723               dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
724             }
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);
729         }
730     }
731   if (flag_pic && current_function_uses_pic_offset_table)
732     {
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
743     }
744 }
745 #endif   /* ! (DPX2 && MOTOROLA)  */
746 #endif   /* ! (NEWS && MOTOROLA)  */
747 #endif   /* !CRDS  */
748 \f
749 /* Return true if this function's epilogue can be output as RTL.  */
750
751 int
752 use_return_insn ()
753 {
754   int regno;
755
756   if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)
757     return 0;
758   
759   /* Copied from output_function_epilogue ().  We should probably create a
760      separate layout routine to perform the common work.  */
761   
762   for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++)
763     if (regs_ever_live[regno] && ! call_used_regs[regno])
764       return 0;
765
766   if (flag_pic && current_function_uses_pic_offset_table)
767     return 0;
768
769   return 1;
770 }
771
772 /* This function generates the assembly code for function exit,
773    on machines that need it.
774
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.  */
779
780 #ifdef CRDS
781
782 static void
783 m68k_output_function_epilogue (stream, size)
784      FILE *stream;
785      HOST_WIDE_INT size;
786 {
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;
794
795   nregs = 0;  fmask = 0; fpoffset = 0;
796   for (regno = 16; regno < 24; regno++)
797     if (regs_ever_live[regno] && ! call_used_regs[regno])
798       {
799         nregs++;
800         fmask |= 1 << (23 - regno);
801       }
802
803   foffset = fpoffset + nregs * 12;
804   nregs = 0;  mask = 0;
805   if (frame_pointer_needed)
806     regs_ever_live[FRAME_POINTER_REGNUM] = 0;
807
808   for (regno = 0; regno < 16; regno++)
809     if (regs_ever_live[regno] && ! call_used_regs[regno])
810       {
811         nregs++;
812         mask |= 1 << regno;
813       }
814
815   offset = foffset + nregs * 4;
816   if (offset + fsize >= 0x8000
817       && frame_pointer_needed
818       && (mask || fmask || fpoffset))
819     {
820       fprintf (stream, "\tmovel $%d,a0\n", -fsize);
821       fsize = 0, big = 1;
822     }
823
824   if (exact_log2 (mask) >= 0)
825     {
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)]);
835     }
836   else if (mask)
837     {
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);
846     }
847
848   if (fmask)
849     {
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);
858     }
859
860   if (fpoffset != 0)
861     for (regno = 55; regno >= 24; regno--)
862       if (regs_ever_live[regno] && ! call_used_regs[regno])
863         {
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;
874         }
875
876   if (frame_pointer_needed)
877     fprintf (stream, "\tunlk a6\n");
878   else if (fsize)
879     {
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);
884     }
885
886   if (current_function_pops_args)
887     fprintf (stream, "\trtd $%d\n", current_function_pops_args);
888   else
889     fprintf (stream, "\trts\n");
890 }
891
892 #else
893 #if defined (DPX2) && defined (MOTOROLA)
894
895 static void
896 m68k_output_function_epilogue (stream, size)
897      FILE *stream;
898      HOST_WIDE_INT size;
899 {
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 ();
908
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)
913     {
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;
918     }
919
920   nregs = 0;  fmask = 0; fpoffset = 0;
921   for (regno = 16; regno < 24; regno++)
922     if (regs_ever_live[regno] && ! call_used_regs[regno])
923       {
924         nregs++;
925         fmask |= 1 << (23 - regno);
926       }
927
928   foffset = fpoffset + nregs * 12;
929   nregs = 0;  mask = 0;
930   if (frame_pointer_needed)
931     regs_ever_live[FRAME_POINTER_REGNUM] = 0;
932
933   for (regno = 0; regno < 16; regno++)
934     if (regs_ever_live[regno] && ! call_used_regs[regno])
935       {
936         nregs++;
937         mask |= 1 << regno;
938       }
939
940   offset = foffset + nregs * 4;
941   if (offset + fsize >= 0x8000
942       && frame_pointer_needed
943       && (mask || fmask || fpoffset))
944     {
945       fprintf (stream, "\tmove.l #%d,a0\n", -fsize);
946       fsize = 0, big = 1;
947     }
948
949   if (nregs <= 2)
950     {
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.  */
955
956       int i;
957
958       /* Undo the work from above.  */
959       for (i = 0; i< 16; i++)
960         if (mask & (1 << i))
961           {
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;
976           }
977     }
978   else if (mask)
979     {
980       first = 1;
981       for (regno = 0; regno < 16; regno++)
982         if (mask & (1 << regno))
983           {
984             if (first && big)
985               {
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;
991               }
992             else if (first && ! frame_pointer_needed)
993               {
994                 fprintf (stream, "\tmovem.l (sp)+,%s",
995                          reg_names[regno]);
996                 first = 0;
997               }
998             else if (first)
999               {
1000                 fprintf (stream, "\tmovem.l -%d(%s),%s",
1001                          offset + fsize,
1002                          reg_names[FRAME_POINTER_REGNUM],
1003                          reg_names[regno]);
1004                 first = 0;
1005               }
1006             else
1007               fprintf (stream, "/%s", reg_names[regno]);
1008           }
1009       fprintf (stream, "\n");
1010     }
1011
1012   if (fmask)
1013     {
1014       first = 1;
1015       for (regno = 16; regno < 24; regno++)
1016         if (fmask & (1 << (23 - regno)))
1017           {
1018             if (first && big)
1019               {
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;
1025               }
1026             else if (first && ! frame_pointer_needed)
1027               {
1028                 fprintf (stream, "\tfmovem.x (sp)+,%s",
1029                          reg_names[regno]);
1030                 first = 0;
1031               }
1032             else if (first)
1033               {
1034                 fprintf (stream, "\tfmovem.x -%d(%s),%s",
1035                          foffset + fsize,
1036                          reg_names[FRAME_POINTER_REGNUM],
1037                          reg_names[regno]);
1038                 first = 0;
1039               }
1040             else
1041               fprintf (stream, "/%s", reg_names[regno]);
1042           }
1043       fprintf (stream, "\n");
1044     }
1045
1046   if (frame_pointer_needed)
1047     fprintf (stream, "\tunlk %s\n",
1048              reg_names[FRAME_POINTER_REGNUM]);
1049   else if (fsize)
1050     {
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);
1055     }
1056
1057   if (current_function_pops_args)
1058     fprintf (stream, "\trtd #%d\n", current_function_pops_args);
1059   else
1060     fprintf (stream, "\trts\n");
1061 }
1062
1063 #else
1064 #if defined (NEWS) && defined (MOTOROLA)
1065
1066 static void
1067 m68k_output_function_epilogue (stream, size)
1068      FILE *stream;
1069      HOST_WIDE_INT size;
1070 {
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;
1078
1079   nregs = 0;  fmask = 0;
1080   for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++)
1081     if (regs_ever_live[regno] && ! call_used_regs[regno])
1082       {
1083         nregs++;
1084         fmask |= 1 << (23 - regno);
1085       }
1086
1087   foffset = nregs * 12;
1088   nregs = 0;  mask = 0;
1089   if (frame_pointer_needed)
1090     regs_ever_live[FRAME_POINTER_REGNUM] = 0;
1091
1092   for (regno = 0; regno < 16; regno++)
1093     if (regs_ever_live[regno] && ! call_used_regs[regno])
1094       {
1095         nregs++;
1096         mask |= 1 << regno;
1097       }
1098
1099   offset = foffset + nregs * 4;
1100   if (offset + fsize >= 0x8000
1101       && frame_pointer_needed
1102       && (mask || fmask))
1103     {
1104       fprintf (stream, "\tmove.l #%d,a0\n", -fsize);
1105       fsize = 0, big = 1;
1106     }
1107
1108   if (exact_log2 (mask) >= 0)
1109     {
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)]);
1119     }
1120   else if (mask)
1121     {
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);
1130     }
1131
1132   if (fmask)
1133     {
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);
1142     }
1143
1144   if (frame_pointer_needed)
1145     fprintf (stream, "\tunlk fp\n");
1146   else if (fsize)
1147     {
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);
1152     }
1153
1154   if (current_function_pops_args)
1155     fprintf (stream, "\trtd #%d\n", current_function_pops_args);
1156   else
1157     fprintf (stream, "\trts\n");
1158 }
1159
1160 #else  /* !CRDS && ! (NEWS && MOTOROLA) && ! (DPX2 && MOTOROLA) */
1161
1162 static void
1163 m68k_output_function_epilogue (stream, size)
1164      FILE *stream;
1165      HOST_WIDE_INT size;
1166 {
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;
1176   
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)
1181     {
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;
1186     }
1187
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)
1200     {
1201       for (regno = 16; regno < 24; regno++)
1202         if (regs_ever_live[regno] && ! call_used_regs[regno])
1203           {
1204             nregs++;
1205             fmask |= 1 << (23 - regno);
1206           }
1207     }
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])
1214       {
1215         nregs++;
1216         mask |= 1 << regno;
1217       }
1218   if (flag_pic && current_function_uses_pic_offset_table)
1219     {
1220       nregs++;
1221       mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
1222     }
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))
1232     {
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;
1239     }
1240   if (TARGET_5200 || nregs <= 2)
1241     {
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.  */
1246
1247       int i;
1248
1249       /* Undo the work from above.  */
1250       for (i = 0; i< 16; i++)
1251         if (mask & (1 << i))
1252           {
1253             if (big)
1254               {
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
1265               }
1266             else if (restore_from_sp)
1267               {
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
1275               }
1276             else
1277               {
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
1288               }
1289             offset = offset - 4;
1290           }
1291     }
1292   else if (mask)
1293     {
1294       if (big)
1295         {
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
1306         }
1307       else if (restore_from_sp)
1308         {
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
1314         }
1315       else
1316         {
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
1327         }
1328     }
1329   if (fmask)
1330     {
1331       if (big)
1332         {
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
1343         }
1344       else if (restore_from_sp)
1345         {
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
1351         }
1352       else
1353         {
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
1364         }
1365     }
1366   if (fpoffset != 0)
1367     for (regno = 55; regno >= 24; regno--)
1368       if (regs_ever_live[regno] && ! call_used_regs[regno])
1369         {
1370           if (big)
1371             {
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
1382             }
1383           else if (restore_from_sp)
1384             {
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
1392             }
1393           else
1394             {
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
1405             }
1406           fpoffset -= 8;
1407         }
1408   if (frame_pointer_needed)
1409     fprintf (stream, "\tunlk %s\n",
1410              reg_names[FRAME_POINTER_REGNUM]);
1411   else if (fsize)
1412     {
1413 #ifndef NO_ADDSUB_Q
1414       if (fsize + 4 <= 8) 
1415         {
1416           if (!TARGET_5200)
1417             {
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
1423             }
1424           else
1425             {
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
1431             }
1432         }
1433       else if (fsize + 4 <= 16 && TARGET_CPU32)
1434         {
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
1445         }
1446       else
1447 #endif /* not NO_ADDSUB_Q */
1448       if (fsize + 4 < 0x8000)
1449         {
1450           if (TARGET_68040)
1451             { 
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
1458             }
1459           else
1460             {
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
1466             }
1467         }
1468       else
1469         {
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
1476         }
1477     }
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");
1482 }
1483
1484 #endif   /* ! (DPX2 && MOTOROLA)  */
1485 #endif   /* ! (NEWS && MOTOROLA)  */
1486 #endif   /* !CRDS  */
1487 \f
1488 /* Similar to general_operand, but exclude stack_pointer_rtx.  */
1489
1490 int
1491 not_sp_operand (op, mode)
1492      register rtx op;
1493      enum machine_mode mode;
1494 {
1495   return op != stack_pointer_rtx && nonimmediate_operand (op, mode);
1496 }
1497
1498 /* Return TRUE if X is a valid comparison operator for the dbcc 
1499    instruction.  
1500
1501    Note it rejects floating point comparison operators.
1502    (In the future we could use Fdbcc).
1503
1504    It also rejects some comparisons when CC_NO_OVERFLOW is set.  */
1505    
1506 int
1507 valid_dbcc_comparison_p (x, mode)
1508      rtx x;
1509      enum machine_mode mode ATTRIBUTE_UNUSED;
1510 {
1511   switch (GET_CODE (x))
1512     {
1513       case EQ: case NE: case GTU: case LTU:
1514       case GEU: case LEU:
1515         return 1;
1516
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;
1523     }
1524 }
1525
1526 /* Return non-zero if flags are currently in the 68881 flag register.  */
1527 int
1528 flags_in_68881 ()
1529 {
1530   /* We could add support for these in the future */
1531   return cc_status.flags & CC_IN_68881;
1532 }
1533
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.  */
1539
1540 void
1541 output_dbcc_and_branch (operands)
1542      rtx *operands;
1543 {
1544   switch (GET_CODE (operands[3]))
1545     {
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;
1553
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;
1561
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;
1569
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;
1577
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;
1585
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;
1593
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;
1601
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;
1609
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;
1617
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;
1625
1626       default:
1627         abort ();
1628     }
1629
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]))
1633     {
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;
1641
1642       case HImode:
1643         break;
1644
1645       default:
1646         abort ();
1647     }
1648 }
1649
1650 const char *
1651 output_scc_di(op, operand1, operand2, dest)
1652      rtx op;
1653      rtx operand1;
1654      rtx operand2;
1655      rtx dest;
1656 {
1657   rtx loperands[7];
1658   enum rtx_code op_code = GET_CODE (op);
1659
1660   /* This does not produce a useful cc.  */
1661   CC_STATUS_INIT;
1662
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)
1667     {
1668       rtx tmp = operand1;
1669
1670       operand1 = operand2;
1671       operand2 = tmp;
1672       op_code = swap_condition (op_code);
1673     }
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)
1680     {
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);
1686     }
1687   loperands[4] = gen_label_rtx();
1688   if (operand2 != const0_rtx)
1689     {
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
1703     }
1704   else
1705     {
1706       if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (loperands[0]))
1707         output_asm_insn ("tst%.l %0", loperands);
1708       else
1709         {
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
1715         }
1716
1717 #ifdef MOTOROLA
1718       output_asm_insn ("jbne %l4", loperands);
1719 #else
1720       output_asm_insn ("jne %l4", loperands);
1721 #endif
1722
1723       if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (loperands[1]))
1724         output_asm_insn ("tst%.l %1", loperands);
1725       else
1726         {
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
1732         }
1733     }
1734
1735   loperands[5] = dest;
1736   
1737   switch (op_code)
1738     {
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;
1744
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;
1750
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;
1764
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;
1770
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;
1784
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;
1790
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;
1804
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;
1810
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;
1824
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;
1830
1831       default:
1832         abort ();
1833     }
1834   return "";
1835 }
1836
1837 const char *
1838 output_btst (operands, countop, dataop, insn, signpos)
1839      rtx *operands;
1840      rtx countop, dataop;
1841      rtx insn;
1842      int signpos;
1843 {
1844   operands[0] = countop;
1845   operands[1] = dataop;
1846
1847   if (GET_CODE (countop) == CONST_INT)
1848     {
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)
1853         {
1854           int offset = (count & ~signpos) / 8;
1855           count = count & signpos;
1856           operands[1] = dataop = adjust_address (dataop, QImode, offset);
1857         }
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;
1862
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";
1874
1875       cc_status.flags = CC_NOT_NEGATIVE;
1876     }
1877   return "btst %0,%1";
1878 }
1879 \f
1880 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
1881    reference and a constant.  */
1882
1883 int
1884 symbolic_operand (op, mode)
1885      register rtx op;
1886      enum machine_mode mode ATTRIBUTE_UNUSED;
1887 {
1888   switch (GET_CODE (op))
1889     {
1890     case SYMBOL_REF:
1891     case LABEL_REF:
1892       return 1;
1893
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);
1899
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
1905
1906     default:
1907       return 0;
1908     }
1909 }
1910 \f
1911 /* Check for sign_extend or zero_extend.  Used for bit-count operands.  */
1912
1913 int
1914 extend_operator(x, mode)
1915      rtx x;
1916      enum machine_mode mode;
1917 {
1918     if (mode != VOIDmode && GET_MODE(x) != mode)
1919         return 0;
1920     switch (GET_CODE(x))
1921         {
1922         case SIGN_EXTEND :
1923         case ZERO_EXTEND :
1924             return 1;
1925         default :
1926             return 0;
1927         }
1928 }
1929
1930 \f
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.  
1935
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.  
1939
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.
1944
1945    The assembler is also responsible for translating a symbol name
1946    into a constant displacement from the start of the GOT.  
1947
1948    A quick example may make things a little clearer:
1949
1950    When not generating PIC code to store the value 12345 into _foo
1951    we would generate the following code:
1952
1953         movel #12345, _foo
1954
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:
1957
1958         lea     _foo, a0
1959         movel   #12345, a0@
1960
1961    The code in movsi will intercept the lea instruction and call this
1962    routine which will transform the instructions into:
1963
1964         movel   a5@(_foo:w), a0
1965         movel   #12345, a0@
1966    
1967
1968    That (in a nutshell) is how *all* symbol and label references are 
1969    handled.  */
1970
1971 rtx
1972 legitimize_pic_address (orig, mode, reg)
1973      rtx orig, reg;
1974      enum machine_mode mode ATTRIBUTE_UNUSED;
1975 {
1976   rtx pic_ref = orig;
1977
1978   /* First handle a simple SYMBOL_REF or LABEL_REF */
1979   if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
1980     {
1981       if (reg == 0)
1982         abort ();
1983
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;
1991     }
1992   else if (GET_CODE (orig) == CONST)
1993     {
1994       rtx base;
1995
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;
2000
2001       if (reg == 0)
2002         abort ();
2003
2004       /* legitimize both operands of the PLUS */
2005       if (GET_CODE (XEXP (orig, 0)) == PLUS)
2006         {
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);
2010         }
2011       else abort ();
2012
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?  */
2017     }
2018   return pic_ref;
2019 }
2020
2021 \f
2022 typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ } CONST_METHOD;
2023
2024 static CONST_METHOD const_method PARAMS ((rtx));
2025
2026 #define USE_MOVQ(i)     ((unsigned)((i) + 128) <= 255)
2027
2028 static CONST_METHOD
2029 const_method (constant)
2030      rtx constant;
2031 {
2032   int i;
2033   unsigned u;
2034
2035   i = INTVAL (constant);
2036   if (USE_MOVQ (i))
2037     return MOVQ;
2038
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) 
2042     {
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;
2057     }
2058   /* Otherwise, use move.l */
2059   return MOVL;
2060 }
2061
2062 int
2063 const_int_cost (constant)
2064      rtx constant;
2065 {
2066   switch (const_method (constant))
2067     {
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 ();
2081     }
2082 }
2083
2084 const char *
2085 output_move_const_into_data_reg (operands)
2086      rtx *operands;
2087 {
2088   int i;
2089
2090   i = INTVAL (operands[1]);
2091   switch (const_method (operands[1]))
2092     {
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 :
2120       {
2121         unsigned u = i;
2122
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   
2129       }
2130     case MOVL :
2131         return "move%.l %1,%0";
2132     default :
2133         abort ();
2134     }
2135 }
2136
2137 const char *
2138 output_move_simode_const (operands)
2139      rtx *operands;
2140 {
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";
2166 }
2167
2168 const char *
2169 output_move_simode (operands)
2170      rtx *operands;
2171 {
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";
2183 }
2184
2185 const char *
2186 output_move_himode (operands)
2187      rtx *operands;
2188 {
2189  if (GET_CODE (operands[1]) == CONST_INT)
2190     {
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)
2206         {
2207 #if defined(MOTOROLA) && !defined(CRDS)
2208           return "moveq%.l %1,%0";
2209 #else
2210           return "moveq %1,%0";
2211 #endif
2212         }
2213       else if (INTVAL (operands[1]) < 0x8000
2214                && INTVAL (operands[1]) >= -0x8000)
2215         return "move%.w %1,%0";
2216     }
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)
2230     {
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 */
2249     }
2250 #endif /* SGS_NO_LI */
2251   return "move%.w %1,%0";
2252 }
2253
2254 const char *
2255 output_move_qimode (operands)
2256      rtx *operands;
2257 {
2258   rtx xoperands[4];
2259
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)
2269     {
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]))
2277         {
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
2284         }
2285       else
2286         output_asm_insn ("move%.b %1,%-\n\tmove%.b %@,%2", xoperands);
2287       return "";
2288     }
2289
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]))))
2295     {
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)
2301         {
2302           CC_STATUS_INIT;
2303           return "st %0";
2304         }
2305     }
2306   if (GET_CODE (operands[1]) == CONST_INT
2307       && DATA_REG_P (operands[0])
2308       && INTVAL (operands[1]) < 128
2309       && INTVAL (operands[1]) >= -128)
2310     {
2311 #if defined(MOTOROLA) && !defined(CRDS)
2312       return "moveq%.l %1,%0";
2313 #else
2314       return "moveq %1,%0";
2315 #endif
2316     }
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";
2326 }
2327
2328 const char *
2329 output_move_stricthi (operands)
2330      rtx *operands;
2331 {
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";
2339 }
2340
2341 const char *
2342 output_move_strictqi (operands)
2343      rtx *operands;
2344 {
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";
2352 }
2353
2354 /* Return the best assembler insn template
2355    for moving operands[1] into operands[0] as a fullword.  */
2356
2357 static const char *
2358 singlemove_string (operands)
2359      rtx *operands;
2360 {
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";
2368 }
2369
2370
2371 /* Output assembler code to perform a doubleword move insn
2372    with operands OPERANDS.  */
2373
2374 const char *
2375 output_move_double (operands)
2376      rtx *operands;
2377 {
2378   enum
2379     {
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]));
2388
2389   middlehalf[0] = 0;
2390   middlehalf[1] = 0;
2391
2392   /* First classify both operands.  */
2393
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;
2406
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;
2421
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.  */
2425
2426   if (optype0 == RNDOP || optype1 == RNDOP)
2427     abort ();
2428
2429   /* If one operand is decrementing and one is incrementing
2430      decrement the former register explicitly
2431      and change that operand into ordinary indexing.  */
2432
2433   if (optype0 == PUSHOP && optype1 == POPOP)
2434     {
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;
2447     }
2448   if (optype0 == POPOP && optype1 == PUSHOP)
2449     {
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;
2462     }
2463
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.  */
2466
2467   if (optype0 == MEMOP)
2468     addreg0 = find_addr_reg (XEXP (operands[0], 0));
2469
2470   if (optype1 == MEMOP)
2471     addreg1 = find_addr_reg (XEXP (operands[1], 0));
2472
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.
2477
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.  */
2481
2482   if (size == 12)
2483     {
2484       if (optype0 == REGOP)
2485         {
2486           latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
2487           middlehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
2488         }
2489       else if (optype0 == OFFSOP)
2490         {
2491           middlehalf[0] = adjust_address (operands[0], SImode, 4);
2492           latehalf[0] = adjust_address (operands[0], SImode, size - 4);
2493         }
2494       else
2495         {
2496           middlehalf[0] = operands[0];
2497           latehalf[0] = operands[0];
2498         }
2499
2500       if (optype1 == REGOP)
2501         {
2502           latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
2503           middlehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
2504         }
2505       else if (optype1 == OFFSOP)
2506         {
2507           middlehalf[1] = adjust_address (operands[1], SImode, 4);
2508           latehalf[1] = adjust_address (operands[1], SImode, size - 4);
2509         }
2510       else if (optype1 == CNSTOP)
2511         {
2512           if (GET_CODE (operands[1]) == CONST_DOUBLE)
2513             {
2514               REAL_VALUE_TYPE r;
2515               long l[3];
2516
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]);
2522             }
2523           else if (CONSTANT_P (operands[1]))
2524             {
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;
2532             }
2533         }
2534       else
2535         {
2536           middlehalf[1] = operands[1];
2537           latehalf[1] = operands[1];
2538         }
2539     }
2540   else
2541     /* size is not 12: */
2542     {
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];
2549
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];
2558     }
2559
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];
2567
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))
2575     {
2576       rtx testlow = gen_rtx_REG (SImode, REGNO (operands[0]));
2577
2578       if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
2579           && reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
2580         {
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 )
2589             {
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);
2593             }
2594           else
2595             {
2596               operands[1] = gen_rtx_MEM (DImode, latehalf[0]);
2597               latehalf[1] = adjust_address (operands[1], DImode, size - 4);
2598             }
2599         }
2600       else if (size == 12
2601                && reg_overlap_mentioned_p (middlehalf[0],
2602                                            XEXP (operands[1], 0)))
2603         {
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.  */
2609
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;
2613
2614           /* JRV says this can't happen: */
2615           if (addreg0 || addreg1)
2616             abort ();
2617
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 "";
2623         }
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;
2628     }
2629
2630   /* If one or both operands autodecrementing,
2631      do the two words, high-numbered first.  */
2632
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.  */
2637
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)
2643     {
2644       /* Make any unoffsettable addresses point at high-numbered word.  */
2645       if (addreg0)
2646         {
2647           if (size == 12)
2648             output_asm_insn ("addq%.l %#8,%0", &addreg0);
2649           else
2650             output_asm_insn ("addq%.l %#4,%0", &addreg0);
2651         }
2652       if (addreg1)
2653         {
2654           if (size == 12)
2655             output_asm_insn ("addq%.l %#8,%0", &addreg1);
2656           else
2657             output_asm_insn ("addq%.l %#4,%0", &addreg1);
2658         }
2659
2660       /* Do that word.  */
2661       output_asm_insn (singlemove_string (latehalf), latehalf);
2662
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);
2668
2669       if (size == 12)
2670         {
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);
2676         }
2677
2678       /* Do low-numbered word.  */
2679       return singlemove_string (operands);
2680     }
2681
2682   /* Normal case: do the two words, low-numbered first.  */
2683
2684   output_asm_insn (singlemove_string (operands), operands);
2685
2686   /* Do the middle one of the three words for long double */
2687   if (size == 12)
2688     {
2689       if (addreg0)
2690         output_asm_insn ("addq%.l %#4,%0", &addreg0);
2691       if (addreg1)
2692         output_asm_insn ("addq%.l %#4,%0", &addreg1);
2693
2694       output_asm_insn (singlemove_string (middlehalf), middlehalf);
2695     }
2696
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);
2702
2703   /* Do that word.  */
2704   output_asm_insn (singlemove_string (latehalf), latehalf);
2705
2706   /* Undo the adds we just did.  */
2707   if (addreg0)
2708     {
2709       if (size == 12)
2710         output_asm_insn ("subq%.l %#8,%0", &addreg0);
2711       else
2712         output_asm_insn ("subq%.l %#4,%0", &addreg0);
2713     }
2714   if (addreg1)
2715     {
2716       if (size == 12)
2717         output_asm_insn ("subq%.l %#8,%0", &addreg1);
2718       else
2719         output_asm_insn ("subq%.l %#4,%0", &addreg1);
2720     }
2721
2722   return "";
2723 }
2724
2725 /* Return a REG that occurs in ADDR with coefficient 1.
2726    ADDR can be effectively incremented by incrementing REG.  */
2727
2728 static rtx
2729 find_addr_reg (addr)
2730      rtx addr;
2731 {
2732   while (GET_CODE (addr) == PLUS)
2733     {
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 ();
2744     }
2745   if (GET_CODE (addr) == REG)
2746     return addr;
2747   abort ();
2748 }
2749
2750 /* Output assembler code to perform a 32 bit 3 operand add.  */
2751
2752 const char *
2753 output_addsi3 (operands)
2754      rtx *operands;
2755 {
2756   if (! operands_match_p (operands[0], operands[1]))
2757     {
2758       if (!ADDRESS_REG_P (operands[1]))
2759         {
2760           rtx tmp = operands[1];
2761
2762           operands[1] = operands[2];
2763           operands[2] = tmp;
2764         }
2765
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 */
2789     }
2790   if (GET_CODE (operands[2]) == CONST_INT)
2791     {
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)
2798         {
2799           operands[2] = GEN_INT (- INTVAL (operands[2]));
2800           return "subq%.l %2,%0";
2801         }
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]))
2806         {
2807           if (INTVAL (operands[2]) > 8
2808               && INTVAL (operands[2]) <= 16)
2809             {
2810               operands[2] = GEN_INT (INTVAL (operands[2]) - 8);
2811               return "addq%.l %#8,%0\n\taddq%.l %2,%0";
2812             }
2813           if (INTVAL (operands[2]) < -8
2814               && INTVAL (operands[2]) >= -16)
2815             {
2816               operands[2] = GEN_INT (- INTVAL (operands[2]) - 8);
2817               return "subq%.l %#8,%0\n\tsubq%.l %2,%0";
2818             }
2819         }
2820 #endif
2821       if (ADDRESS_REG_P (operands[0])
2822           && INTVAL (operands[2]) >= -0x8000
2823           && INTVAL (operands[2]) < 0x8000)
2824         {
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
2833         }
2834     }
2835   return "add%.l %2,%0";
2836 }
2837 \f
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.  */
2841
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.  */
2846
2847 void
2848 notice_update_cc (exp, insn)
2849      rtx exp;
2850      rtx insn;
2851 {
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))
2860     {
2861       CC_STATUS_INIT; 
2862     }
2863   else if (GET_CODE (exp) == SET)
2864     {
2865       if (GET_CODE (SET_SRC (exp)) == CALL)
2866         {
2867           CC_STATUS_INIT; 
2868         }
2869       else if (ADDRESS_REG_P (SET_DEST (exp)))
2870         {
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; 
2875         }
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))
2882         {
2883           CC_STATUS_INIT; 
2884         }
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))
2892         {
2893           CC_STATUS_INIT; 
2894         }
2895       else if (GET_CODE (SET_SRC (exp)) == CALL)
2896         {
2897           CC_STATUS_INIT; 
2898         }
2899       else if (XEXP (exp, 0) != pc_rtx)
2900         {
2901           cc_status.flags = 0;
2902           cc_status.value1 = XEXP (exp, 0);
2903           cc_status.value2 = XEXP (exp, 1);
2904         }
2905     }
2906   else if (GET_CODE (exp) == PARALLEL
2907            && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
2908     {
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)
2912         {
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);
2916         }
2917     }
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))
2927       {
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; 
2943
2944       default:
2945         break;
2946       }
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;
2956 }
2957 \f
2958 const char *
2959 output_move_const_double (operands)
2960      rtx *operands;
2961 {
2962 #ifdef SUPPORT_SUN_FPA
2963   if (TARGET_FPA && FPA_REG_P (operands[0]))
2964     {
2965       int code = standard_sun_fpa_constant_p (operands[1]);
2966
2967       if (code != 0)
2968         {
2969           static char buf[40];
2970
2971           sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff);
2972           return buf;
2973         }
2974       return "fpmove%.d %1,%0";
2975     }
2976   else
2977 #endif
2978     {
2979       int code = standard_68881_constant_p (operands[1]);
2980
2981       if (code != 0)
2982         {
2983           static char buf[40];
2984
2985           sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
2986           return buf;
2987         }
2988       return "fmove%.d %1,%0";
2989     }
2990 }
2991
2992 const char *
2993 output_move_const_single (operands)
2994      rtx *operands;
2995 {
2996 #ifdef SUPPORT_SUN_FPA
2997   if (TARGET_FPA)
2998     {
2999       int code = standard_sun_fpa_constant_p (operands[1]);
3000
3001       if (code != 0)
3002         {
3003           static char buf[40];
3004
3005           sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff);
3006           return buf;
3007         }
3008       return "fpmove%.s %1,%0";
3009     }
3010   else
3011 #endif /* defined SUPPORT_SUN_FPA */
3012     {
3013       int code = standard_68881_constant_p (operands[1]);
3014
3015       if (code != 0)
3016         {
3017           static char buf[40];
3018
3019           sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
3020           return buf;
3021         }
3022       return "fmove%.s %f1,%0";
3023     }
3024 }
3025
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.  */
3030
3031 /* This code has been fixed for cross-compilation.  */
3032   
3033 static int inited_68881_table = 0;
3034
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"
3043   };
3044
3045 static const int codes_68881[7] = {
3046   0x0f,
3047   0x32,
3048   0x33,
3049   0x34,
3050   0x35,
3051   0x36,
3052   0x37
3053   };
3054
3055 REAL_VALUE_TYPE values_68881[7];
3056
3057 /* Set up values_68881 array by converting the decimal values
3058    strings_68881 to binary.  */
3059
3060 void
3061 init_68881_table ()
3062 {
3063   int i;
3064   REAL_VALUE_TYPE r;
3065   enum machine_mode mode;
3066
3067   mode = SFmode;
3068   for (i = 0; i < 7; i++)
3069     {
3070       if (i == 6)
3071         mode = DFmode;
3072       r = REAL_VALUE_ATOF (strings_68881[i], mode);
3073       values_68881[i] = r;
3074     }
3075   inited_68881_table = 1;
3076 }
3077
3078 int
3079 standard_68881_constant_p (x)
3080      rtx x;
3081 {
3082   REAL_VALUE_TYPE r;
3083   int i;
3084
3085 #ifdef NO_ASM_FMOVECR
3086   return 0;
3087 #endif
3088
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;
3093
3094 #ifndef REAL_ARITHMETIC
3095 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
3096   if (! flag_pretend_float)
3097     return 0;
3098 #endif
3099 #endif
3100
3101   if (! inited_68881_table)
3102     init_68881_table ();
3103
3104   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
3105
3106   /* Use REAL_VALUES_IDENTICAL instead of REAL_VALUES_EQUAL so that -0.0
3107      is rejected.  */
3108   for (i = 0; i < 6; i++)
3109     {
3110       if (REAL_VALUES_IDENTICAL (r, values_68881[i]))
3111         return (codes_68881[i]);
3112     }
3113   
3114   if (GET_MODE (x) == SFmode)
3115     return 0;
3116
3117   if (REAL_VALUES_EQUAL (r, values_68881[6]))
3118     return (codes_68881[6]);
3119
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;
3123 }
3124
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.  */
3127
3128 int
3129 floating_exact_log2 (x)
3130      rtx x;
3131 {
3132   REAL_VALUE_TYPE r, r1;
3133   int i;
3134
3135 #ifndef REAL_ARITHMETIC
3136 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
3137   if (! flag_pretend_float)
3138     return 0;
3139 #endif
3140 #endif
3141
3142   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
3143
3144   if (REAL_VALUES_LESS (r, dconst0))
3145     return 0;
3146
3147   r1 = dconst1;
3148   i = 0;
3149   while (REAL_VALUES_LESS (r1, r))
3150     {
3151       r1 = REAL_VALUE_LDEXP (dconst1, i);
3152       if (REAL_VALUES_EQUAL (r1, r))
3153         return i;
3154       i = i + 1;
3155     }
3156   return 0;
3157 }
3158 \f
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.  */
3164
3165 static int inited_FPA_table = 0;
3166
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 */
3209 };
3210
3211
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
3254   };
3255
3256 REAL_VALUE_TYPE values_FPA[38];
3257
3258 /* This code has been fixed for cross-compilation.  */
3259
3260 static void init_FPA_table PARAMS ((void));
3261 static void
3262 init_FPA_table ()
3263 {
3264   enum machine_mode mode;
3265   int i;
3266   REAL_VALUE_TYPE r;
3267
3268   mode = DFmode;
3269   for (i = 0; i < 38; i++)
3270     {
3271       if (i == 25)
3272         mode = SFmode;
3273       r = REAL_VALUE_ATOF (strings_FPA[i], mode);
3274       values_FPA[i] = r;
3275     }
3276   inited_FPA_table = 1;
3277 }
3278
3279
3280 int
3281 standard_sun_fpa_constant_p (x)
3282      rtx x;
3283 {
3284   REAL_VALUE_TYPE r;
3285   int i;
3286
3287 #ifndef REAL_ARITHMETIC
3288 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
3289   if (! flag_pretend_float)
3290     return 0;
3291 #endif
3292 #endif
3293
3294   if (! inited_FPA_table)
3295     init_FPA_table ();
3296
3297   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
3298
3299   for (i=0; i<12; i++)
3300     {
3301       if (REAL_VALUES_EQUAL (r, values_FPA[i]))
3302         return (codes_FPA[i]);
3303     }
3304
3305   if (GET_MODE (x) == SFmode)
3306     {
3307       for (i=25; i<38; i++)
3308         {
3309           if (REAL_VALUES_EQUAL (r, values_FPA[i]))
3310             return (codes_FPA[i]);
3311         }
3312     }
3313   else
3314     {
3315       for (i=12; i<25; i++)
3316         {
3317           if (REAL_VALUES_EQUAL (r, values_FPA[i]))
3318             return (codes_FPA[i]);
3319         }
3320     }
3321   return 0x0;
3322 }
3323 #endif /* define SUPPORT_SUN_FPA */
3324 \f
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.
3328
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.
3336
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'.
3340
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.
3344
3345    The m68k specific codes are:
3346
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.
3360
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.
3373
3374    */
3375
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 */
3381 {
3382 #ifdef SUPPORT_SUN_FPA
3383   int i;
3384 #endif
3385
3386   if (letter == '.')
3387     {
3388 #if defined (MOTOROLA) && !defined (CRDS)
3389       asm_fprintf (file, ".");
3390 #endif
3391     }
3392   else if (letter == '#')
3393     {
3394       asm_fprintf (file, "%0I");
3395     }
3396   else if (letter == '-')
3397     {
3398 #ifdef MOTOROLA
3399       asm_fprintf (file, "-(%Rsp)");
3400 #else
3401       asm_fprintf (file, "%Rsp@-");
3402 #endif
3403     }
3404   else if (letter == '+')
3405     {
3406 #ifdef MOTOROLA
3407       asm_fprintf (file, "(%Rsp)+");
3408 #else
3409       asm_fprintf (file, "%Rsp@+");
3410 #endif
3411     }
3412   else if (letter == '@')
3413     {
3414 #ifdef MOTOROLA
3415       asm_fprintf (file, "(%Rsp)");
3416 #else
3417       asm_fprintf (file, "%Rsp@");
3418 #endif
3419     }
3420   else if (letter == '!')
3421     {
3422       asm_fprintf (file, "%Rfpcr");
3423     }
3424   else if (letter == '$')
3425     {
3426       if (TARGET_68040_ONLY)
3427         {
3428           fprintf (file, "s");
3429         }
3430     }
3431   else if (letter == '&')
3432     {
3433       if (TARGET_68040_ONLY)
3434         {
3435           fprintf (file, "d");
3436         }
3437     }
3438   else if (letter == '/')
3439     {
3440       asm_fprintf (file, "%R");
3441     }
3442   else if (letter == 'o')
3443     {
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));
3449     }
3450   else if (GET_CODE (op) == REG)
3451     {
3452 #ifdef SUPPORT_SUN_FPA
3453       if (REGNO (op) < 16
3454           && (letter == 'y' || letter == 'x')
3455           && GET_MODE (op) == DFmode)
3456         {
3457           fprintf (file, "%s:%s", reg_names[REGNO (op)],
3458                    reg_names[REGNO (op)+1]);
3459         }
3460       else
3461 #endif
3462         {
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);
3469         }
3470     }
3471   else if (GET_CODE (op) == MEM)
3472     {
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))
3479         {
3480 #ifdef MOTOROLA
3481           fprintf (file, ".l");
3482 #else
3483           fprintf (file, ":l");
3484 #endif
3485         }
3486     }
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)))
3491     {
3492       fprintf (file, "%%%d", i & 0x1ff);
3493     }
3494 #endif
3495   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
3496     {
3497       REAL_VALUE_TYPE r;
3498       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
3499       ASM_OUTPUT_FLOAT_OPERAND (letter, file, r);
3500     }
3501   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode)
3502     {
3503       REAL_VALUE_TYPE r;
3504       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
3505       ASM_OUTPUT_LONG_DOUBLE_OPERAND (file, r);
3506     }
3507   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
3508     {
3509       REAL_VALUE_TYPE r;
3510       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
3511       ASM_OUTPUT_DOUBLE_OPERAND (file, r);
3512     }
3513   else
3514     {
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);
3523     }
3524 }
3525
3526 \f
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.
3530
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.
3535
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...)).
3538
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.
3548
3549    They also do not like things like "pea 1.w", so we simple leave off
3550    the .w on small constants. 
3551
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) */
3556
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 */
3571
3572 void
3573 print_operand_address (file, addr)
3574      FILE *file;
3575      rtx addr;
3576 {
3577   register rtx reg1, reg2, breg, ireg;
3578   rtx offset;
3579
3580   switch (GET_CODE (addr))
3581     {
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)))
3606           {
3607             offset = XEXP (addr, 0);
3608             addr = XEXP (addr, 1);
3609           }
3610         else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
3611           {
3612             offset = XEXP (addr, 1);
3613             addr = XEXP (addr, 0);
3614           }
3615         if (GET_CODE (addr) != PLUS)
3616           {
3617             ;
3618           }
3619         else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
3620           {
3621             reg1 = XEXP (addr, 0);
3622             addr = XEXP (addr, 1);
3623           }
3624         else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
3625           {
3626             reg1 = XEXP (addr, 1);
3627             addr = XEXP (addr, 0);
3628           }
3629         else if (GET_CODE (XEXP (addr, 0)) == MULT)
3630           {
3631             reg1 = XEXP (addr, 0);
3632             addr = XEXP (addr, 1);
3633           }
3634         else if (GET_CODE (XEXP (addr, 1)) == MULT)
3635           {
3636             reg1 = XEXP (addr, 1);
3637             addr = XEXP (addr, 0);
3638           }
3639         else if (GET_CODE (XEXP (addr, 0)) == REG)
3640           {
3641             reg1 = XEXP (addr, 0);
3642             addr = XEXP (addr, 1);
3643           }
3644         else if (GET_CODE (XEXP (addr, 1)) == REG)
3645           {
3646             reg1 = XEXP (addr, 1);
3647             addr = XEXP (addr, 0);
3648           }
3649         if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
3650             || GET_CODE (addr) == SIGN_EXTEND)
3651           {
3652             if (reg1 == 0)
3653               {
3654                 reg1 = addr;
3655               }
3656             else
3657               {
3658                 reg2 = addr;
3659               }
3660             addr = 0;
3661           }
3662 #if 0   /* for OLD_INDEXING */
3663         else if (GET_CODE (addr) == PLUS)
3664           {
3665             if (GET_CODE (XEXP (addr, 0)) == REG)
3666               {
3667                 reg2 = XEXP (addr, 0);
3668                 addr = XEXP (addr, 1);
3669               }
3670             else if (GET_CODE (XEXP (addr, 1)) == REG)
3671               {
3672                 reg2 = XEXP (addr, 1);
3673                 addr = XEXP (addr, 0);
3674               }
3675           }
3676 #endif
3677         if (offset != 0)
3678           {
3679             if (addr != 0)
3680               {
3681                 abort ();
3682               }
3683             addr = offset;
3684           }
3685         if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
3686                       || GET_CODE (reg1) == MULT))
3687             || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
3688           {
3689             breg = reg2;
3690             ireg = reg1;
3691           }
3692         else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
3693           {
3694             breg = reg1;
3695             ireg = reg2;
3696           }
3697         if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
3698             && ! (flag_pic && ireg == pic_offset_table_rtx))
3699           {
3700             int scale = 1;
3701             if (GET_CODE (ireg) == MULT)
3702               {
3703                 scale = INTVAL (XEXP (ireg, 1));
3704                 ireg = XEXP (ireg, 0);
3705               }
3706             if (GET_CODE (ireg) == SIGN_EXTEND)
3707               {
3708                 ASM_OUTPUT_CASE_FETCH (file,
3709                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
3710                              reg_names[REGNO (XEXP (ireg, 0))]);
3711                 fprintf (file, "w");
3712               }
3713             else
3714               {
3715                 ASM_OUTPUT_CASE_FETCH (file,
3716                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
3717                              reg_names[REGNO (ireg)]);
3718                 fprintf (file, "l");
3719               }
3720             if (scale != 1)
3721               {
3722 #ifdef MOTOROLA
3723                 fprintf (file, "*%d", scale);
3724 #else
3725                 fprintf (file, ":%d", scale);
3726 #endif
3727               }
3728             putc (')', file);
3729             break;
3730           }
3731         if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
3732             && ! (flag_pic && breg == pic_offset_table_rtx))
3733           {
3734             ASM_OUTPUT_CASE_FETCH (file,
3735                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
3736                          reg_names[REGNO (breg)]);
3737             fprintf (file, "l)");
3738             break;
3739           }
3740         if (ireg != 0 || breg != 0)
3741           {
3742             int scale = 1;
3743             if (breg == 0)
3744               {
3745                 abort ();
3746               }
3747             if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
3748               {
3749                 abort ();
3750               }
3751 #ifdef MOTOROLA
3752             if (addr != 0)
3753               {
3754                 output_addr_const (file, addr);
3755                 if (flag_pic && (breg == pic_offset_table_rtx))
3756                   {
3757                     fprintf (file, "@GOT");
3758                     if (flag_pic == 1)
3759                       fprintf (file, ".w");
3760                   }
3761               }
3762             fprintf (file, "(%s", reg_names[REGNO (breg)]);
3763             if (ireg != 0)
3764               {
3765                 putc (',', file);
3766               }
3767 #else
3768             fprintf (file, "%s@(", reg_names[REGNO (breg)]);
3769             if (addr != 0)
3770               {
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");
3776               }
3777             if (addr != 0 && ireg != 0)
3778               {
3779                 putc (',', file);
3780               }
3781 #endif
3782             if (ireg != 0 && GET_CODE (ireg) == MULT)
3783               {
3784                 scale = INTVAL (XEXP (ireg, 1));
3785                 ireg = XEXP (ireg, 0);
3786               }
3787             if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
3788               {
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
3794               }
3795             else if (ireg != 0)
3796               {
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
3802               }
3803             if (scale != 1)
3804               {
3805 #ifdef MOTOROLA
3806                 fprintf (file, "*%d", scale);
3807 #else
3808                 fprintf (file, ":%d", scale);
3809 #endif
3810               }
3811             putc (')', file);
3812             break;
3813           }
3814         else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
3815                  && ! (flag_pic && reg1 == pic_offset_table_rtx))       
3816           {
3817             ASM_OUTPUT_CASE_FETCH (file,
3818                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
3819                          reg_names[REGNO (reg1)]);
3820             fprintf (file, "l)");
3821             break;
3822           }
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)
3828           {
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
3839           }
3840         else if (GET_CODE (addr) == CONST_INT)
3841           {
3842             fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr));
3843           }
3844         else if (TARGET_PCREL)
3845           {
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)");
3852           }
3853         else
3854           {
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] == '.')
3861               {
3862                 putc ('(', file);
3863                 output_addr_const (file, addr);
3864                 putc (')', file);
3865               }
3866             else
3867               output_addr_const (file, addr);
3868           }
3869         break;
3870     }
3871 }
3872 \f
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; ...
3876
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.  */
3880
3881 int
3882 strict_low_part_peephole_ok (mode, first_insn, target)
3883      enum machine_mode mode;
3884      rtx first_insn;
3885      rtx target;
3886 {
3887   rtx p;
3888
3889   p = prev_nonnote_insn (first_insn);
3890
3891   while (p)
3892     {
3893       /* If it isn't an insn, then give up.  */
3894       if (GET_CODE (p) != INSN)
3895         return 0;
3896
3897       if (reg_set_p (target, p))
3898         {
3899           rtx set = single_set (p);
3900           rtx dest;
3901
3902           /* If it isn't an easy to recognize insn, then give up.  */
3903           if (! set)
3904             return 0;
3905
3906           dest = SET_DEST (set);
3907
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.  */
3920             ;
3921           else
3922             return 0;
3923         }
3924
3925       p = prev_nonnote_insn (p);
3926
3927     }
3928
3929   return 0;
3930 }
3931
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.  */
3935
3936 int
3937 const_uint32_operand (op, mode)
3938      rtx op;
3939      enum machine_mode mode;
3940 {
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 ();
3945
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
3954 }
3955
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.  */
3959
3960 int
3961 const_sint32_operand (op, mode)
3962      rtx op;
3963      enum machine_mode mode;
3964 {
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 ();
3969
3970   /* All allowed constants will fit a CONST_INT.  */
3971   return (GET_CODE (op) == CONST_INT
3972           && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
3973 }
3974
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.
3978
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.
3984
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.
3990
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.
3997
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:
4001
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
4005         ...
4006         lea (abc:w,%pc),%a1     ; no need to reload address here
4007         movel %a1@,%d0          ; since "movel (abc:w,%pc),%d0" is ok
4008
4009    For more info, consult tiemann@cygnus.com.
4010
4011
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.
4020
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.
4028
4029    ***************************************************************************/
4030
4031
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.  */
4035
4036 int
4037 general_src_operand (op, mode)
4038      rtx op;
4039      enum machine_mode mode;
4040 {
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);
4048 }
4049
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.  */
4053
4054 int
4055 nonimmediate_src_operand (op, mode)
4056      rtx op;
4057      enum machine_mode mode;
4058 {
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);
4065 }
4066
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.  */
4070
4071 int
4072 memory_src_operand (op, mode)
4073      rtx op;
4074      enum machine_mode mode;
4075 {
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);
4082 }
4083
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".  */
4087
4088 int
4089 pcrel_address (op, mode)
4090      rtx op;
4091      enum machine_mode mode ATTRIBUTE_UNUSED;
4092 {
4093   return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF
4094           || GET_CODE (op) == CONST);
4095 }
4096
4097 const char *
4098 output_andsi3 (operands)
4099      rtx *operands;
4100 {
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)
4107     {
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";
4116     }
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])))
4121     {
4122       if (DATA_REG_P (operands[0]))
4123         {
4124           operands[1] = GEN_INT (logval);
4125         }
4126       else
4127         {
4128           operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
4129           operands[1] = GEN_INT (logval % 8);
4130         }
4131       /* This does not set condition codes in a standard way.  */
4132       CC_STATUS_INIT;
4133       return "bclr %1,%0";
4134     }
4135   return "and%.l %2,%0";
4136 }
4137
4138 const char *
4139 output_iorsi3 (operands)
4140      rtx *operands;
4141 {
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)
4148     {
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";
4156     }
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])))
4161     {
4162       if (DATA_REG_P (operands[0]))
4163         operands[1] = GEN_INT (logval);
4164       else
4165         {
4166           operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
4167           operands[1] = GEN_INT (logval % 8);
4168         }
4169       CC_STATUS_INIT;
4170       return "bset %1,%0";
4171     }
4172   return "or%.l %2,%0";
4173 }
4174
4175 const char *
4176 output_xorsi3 (operands)
4177      rtx *operands;
4178 {
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)
4184     {
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";
4192     }
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])))
4197     {
4198       if (DATA_REG_P (operands[0]))
4199         operands[1] = GEN_INT (logval);
4200       else
4201         {
4202           operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
4203           operands[1] = GEN_INT (logval % 8);
4204         }
4205       CC_STATUS_INIT;
4206       return "bchg %1,%0";
4207     }
4208   return "eor%.l %2,%0";
4209 }
4210
4211 /* Output assembly to switch to section NAME with attribute FLAGS.  */
4212
4213 static void
4214 m68k_coff_asm_named_section (name, flags)
4215      const char *name;
4216      unsigned int flags;
4217 {
4218   char flagchar;
4219
4220   if (flags & SECTION_WRITE)
4221     flagchar = 'd';
4222   else
4223     flagchar = 'x';
4224
4225   fprintf (asm_out_file, "\t.section\t%s,\"%c\"\n", name, flagchar);
4226 }
4227
4228 #ifdef CTOR_LIST_BEGIN
4229 static void
4230 m68k_svr3_asm_out_constructor (symbol, priority)
4231      rtx symbol;
4232      int priority ATTRIBUTE_UNUSED;
4233 {
4234   rtx xop[2];
4235
4236   xop[1] = symbol;
4237   xop[0] = gen_rtx_MEM (SImode, gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
4238
4239   init_section ();
4240   output_asm_insn (output_move_simode (xop), xop);
4241 }
4242 #endif