OSDN Git Service

* m68k.c (const_uint32_operand): Abort if mode is <= 32 bits.
[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
42 /* Needed for use_return_insn.  */
43 #include "flags.h"
44
45 #ifdef SUPPORT_SUN_FPA
46
47 /* Index into this array by (register number >> 3) to find the
48    smallest class which contains that register.  */
49 enum reg_class regno_reg_class[]
50   = { DATA_REGS, ADDR_REGS, FP_REGS,
51       LO_FPA_REGS, LO_FPA_REGS, FPA_REGS, FPA_REGS };
52
53 #endif /* defined SUPPORT_SUN_FPA */
54
55 /* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
56    if SGS_SWITCH_TABLE.  */
57 int switch_table_difference_label_flag;
58
59 static rtx find_addr_reg PARAMS ((rtx));
60 static const char *singlemove_string PARAMS ((rtx *));
61 static void m68k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
62 static void m68k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
63 \f
64
65 /* Alignment to use for loops and jumps */
66 /* Specify power of two alignment used for loops. */
67 const char *m68k_align_loops_string;
68 /* Specify power of two alignment used for non-loop jumps. */
69 const char *m68k_align_jumps_string;
70 /* Specify power of two alignment used for functions. */
71 const char *m68k_align_funcs_string;
72
73 /* Specify power of two alignment used for loops. */
74 int m68k_align_loops;
75 /* Specify power of two alignment used for non-loop jumps. */
76 int m68k_align_jumps;
77 /* Specify power of two alignment used for functions. */
78 int m68k_align_funcs;
79
80 /* Nonzero if the last compare/test insn had FP operands.  The
81    sCC expanders peek at this to determine what to do for the
82    68060, which has no fsCC instructions.  */
83 int m68k_last_compare_had_fp_operands;
84 \f
85 /* Initialize the GCC target structure.  */
86 #undef TARGET_ASM_FUNCTION_PROLOGUE
87 #define TARGET_ASM_FUNCTION_PROLOGUE m68k_output_function_prologue
88 #undef TARGET_ASM_FUNCTION_EPILOGUE
89 #define TARGET_ASM_FUNCTION_EPILOGUE m68k_output_function_epilogue
90
91 struct gcc_target targetm = TARGET_INITIALIZER;
92 \f
93 /* Sometimes certain combinations of command options do not make
94    sense on a particular target machine.  You can define a macro
95    `OVERRIDE_OPTIONS' to take account of this.  This macro, if
96    defined, is executed once just after all the command options have
97    been parsed.
98
99    Don't use this macro to turn on various extra optimizations for
100    `-O'.  That is what `OPTIMIZATION_OPTIONS' is for.  */
101
102 void
103 override_options ()
104 {
105   int def_align;
106   int i;
107
108   def_align = 1;
109
110   /* Validate -malign-loops= value, or provide default */
111   m68k_align_loops = def_align;
112   if (m68k_align_loops_string)
113     {
114       i = atoi (m68k_align_loops_string);
115       if (i < 1 || i > MAX_CODE_ALIGN)
116         error ("-malign-loops=%d is not between 1 and %d", i, MAX_CODE_ALIGN);
117       else
118         m68k_align_loops = i;
119     }
120
121   /* Validate -malign-jumps= value, or provide default */
122   m68k_align_jumps = def_align;
123   if (m68k_align_jumps_string)
124     {
125       i = atoi (m68k_align_jumps_string);
126       if (i < 1 || i > MAX_CODE_ALIGN)
127         error ("-malign-jumps=%d is not between 1 and %d", i, MAX_CODE_ALIGN);
128       else
129         m68k_align_jumps = i;
130     }
131
132   /* Validate -malign-functions= value, or provide default */
133   m68k_align_funcs = def_align;
134   if (m68k_align_funcs_string)
135     {
136       i = atoi (m68k_align_funcs_string);
137       if (i < 1 || i > MAX_CODE_ALIGN)
138         error ("-malign-functions=%d is not between 1 and %d",
139                i, MAX_CODE_ALIGN);
140       else
141         m68k_align_funcs = i;
142     }
143 }
144 \f
145 /* This function generates the assembly code for function entry.
146    STREAM is a stdio stream to output the code to.
147    SIZE is an int: how many units of temporary storage to allocate.
148    Refer to the array `regs_ever_live' to determine which registers
149    to save; `regs_ever_live[I]' is nonzero if register number I
150    is ever used in the function.  This function is responsible for
151    knowing which registers should not be saved even if used.  */
152
153
154 /* Note that the order of the bit mask for fmovem is the opposite
155    of the order for movem!  */
156
157 #ifdef CRDS
158
159 static void
160 m68k_output_function_prologue (stream, size)
161      FILE *stream;
162      HOST_WIDE_INT size;
163 {
164   register int regno;
165   register int mask = 0;
166   extern char call_used_regs[];
167   HOST_WIDE_INT fsize = ((size) + 3) & -4;
168
169   /* unos stack probe */
170   if (fsize > 30000)
171     {
172       fprintf (stream, "\tmovel sp,a0\n");
173       fprintf (stream, "\taddl $-%d,a0\n", 2048 + fsize);
174       fprintf (stream, "\ttstb (a0)\n");
175     }
176   else
177     fprintf (stream, "\ttstb -%d(sp)\n", 2048 + fsize);
178
179   if (frame_pointer_needed)
180     {
181       if (TARGET_68020 || fsize < 0x8000)
182         fprintf (stream, "\tlink a6,$%d\n", -fsize);
183       else
184         fprintf (stream, "\tlink a6,$0\n\tsubl $%d,sp\n", fsize);
185     }
186   else if (fsize)
187     {
188       /* Adding negative number is faster on the 68040.  */
189       if (fsize + 4 < 0x8000)
190           fprintf (stream, "\tadd.w #%d,sp\n", - (fsize + 4));
191       else
192           fprintf (stream, "\tadd.l #%d,sp\n", - (fsize + 4));
193     }
194
195   for (regno = 16; regno < 24; regno++)
196     if (regs_ever_live[regno] && ! call_used_regs[regno])
197       mask |= 1 << (regno - 16);
198
199   if ((mask & 0xff) != 0)
200     fprintf (stream, "\tfmovem $0x%x,-(sp)\n", mask & 0xff);
201
202   mask = 0;
203   for (regno = 0; regno < 16; regno++)
204     if (regs_ever_live[regno] && ! call_used_regs[regno])
205       mask |= 1 << (15 - regno);
206   if (frame_pointer_needed)
207     mask &= ~ (1 << (15-FRAME_POINTER_REGNUM));
208
209   if (exact_log2 (mask) >= 0)
210     fprintf (stream, "\tmovel %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]);
211   else if (mask)
212     fprintf (stream, "\tmovem $0x%x,-(sp)\n", mask);
213 }
214
215 #else
216 #if defined (DPX2) && defined (MOTOROLA)
217
218 static void
219 m68k_output_function_prologue (stream, size)
220      FILE *stream;
221      HOST_WIDE_INT size;
222 {
223   register int regno;
224   register int mask = 0;
225   int num_saved_regs = 0, first = 1;
226   extern char call_used_regs[];
227   HOST_WIDE_INT fsize = ((size) + 3) & -4;
228
229   if (frame_pointer_needed)
230     {
231       /* Adding negative number is faster on the 68040.  */
232       if (fsize < 0x8000 && !TARGET_68040)
233         fprintf (stream, "\tlink %s,#%d\n",
234                  reg_names[FRAME_POINTER_REGNUM], -fsize);
235       else if (TARGET_68020)
236         fprintf (stream, "\tlink %s,#%d\n",
237                  reg_names[FRAME_POINTER_REGNUM], -fsize);
238       else
239         fprintf (stream, "\tlink %s,#0\n\tadd.l #%d,sp\n",
240                  reg_names[FRAME_POINTER_REGNUM], -fsize);
241     }
242   else if (fsize)
243     {
244       /* Adding negative number is faster on the 68040.  */
245       if (fsize + 4 < 0x8000)
246         fprintf (stream, "\tadd.w #%d,sp\n", - (fsize + 4));
247       else
248         fprintf (stream, "\tadd.l #%d,sp\n", - (fsize + 4));
249     }
250
251   for (regno = 23; regno >= 16; regno--)
252     if (regs_ever_live[regno] && ! call_used_regs[regno])
253       {
254         if (first)
255           {
256             fprintf (stream, "\tfmovem.x %s", reg_names[regno]);
257             first = 0;
258           }
259         else
260           fprintf (stream, "/%s", reg_names[regno]);
261       }
262   if (!first)
263     fprintf (stream, ",-(sp)\n");
264
265   mask = 0;
266   for (regno = 0; regno < 16; regno++)
267     if (regs_ever_live[regno] && ! call_used_regs[regno])
268       {
269         mask |= 1 << (15 - regno);
270         num_saved_regs++;
271       }
272
273   if (frame_pointer_needed)
274     {
275       mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));
276       num_saved_regs--;
277     }
278
279   if (num_saved_regs <= 2)
280     {
281       /* Store each separately in the same order moveml uses.
282          Using two movel instructions instead of a single moveml
283          is about 15% faster for the 68020 and 68030 at no expense
284          in code size */
285
286       int i;
287
288       /* Undo the work from above. */
289       for (i = 0; i< 16; i++)
290         if (mask & (1 << i))
291           fprintf (stream, "\tmove.l %s,-(sp)\n", reg_names[15 - i]);
292     }
293   else if (mask)
294     {
295       first = 1;
296       for (regno = 0; regno < 16; regno++)
297         if (mask & (1 << regno))
298           {
299             if (first)
300               {
301                 fprintf (stream, "\tmovem.l %s", reg_names[15 - regno]);
302                 first = 0;
303               }
304             else
305               fprintf (stream, "/%s", reg_names[15 - regno]);
306           }
307       fprintf (stream, ",-(sp)\n");
308     }
309
310   if (flag_pic && current_function_uses_pic_offset_table)
311     {
312       fprintf (stream, "\tmove.l #__GLOBAL_OFFSET_TABLE_, %s\n",
313                reg_names[PIC_OFFSET_TABLE_REGNUM]);
314       fprintf (stream, "\tlea.l (pc,%s.l),%s\n",
315                reg_names[PIC_OFFSET_TABLE_REGNUM],
316                reg_names[PIC_OFFSET_TABLE_REGNUM]);
317     }
318 }
319
320 #else
321 #if defined (NEWS) && defined (MOTOROLA)
322
323 static void
324 m68k_output_function_prologue (stream, size)
325      FILE *stream;
326      HOST_WIDE_INT size;
327 {
328   register int regno;
329   register int mask = 0;
330   extern char call_used_regs[];
331   HOST_WIDE_INT fsize = ((size) + 3) & -4;
332
333   if (frame_pointer_needed)
334     {
335       if (fsize < 0x8000)
336         fprintf (stream, "\tlink fp,#%d\n", -fsize);
337       else if (TARGET_68020)
338         fprintf (stream, "\tlink.l fp,#%d\n", -fsize);
339       else
340         fprintf (stream, "\tlink fp,#0\n\tsub.l #%d,sp\n", fsize);
341     }
342   else if (fsize)
343     {
344       int amt = fsize + 4;
345       /* Adding negative number is faster on the 68040.  */
346       if (fsize + 4 < 0x8000)
347         asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - amt);
348       else
349         asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", - amt);
350     }
351
352   for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++)
353     if (regs_ever_live[regno] && ! call_used_regs[regno])
354       mask |= 1 << (regno - 16);
355
356   if (mask != 0)
357     fprintf (stream, "\tfmovem.x #0x%x,-(sp)\n", mask & 0xff);
358
359   mask = 0;
360   for (regno = 0; regno < 16; regno++)
361     if (regs_ever_live[regno] && ! call_used_regs[regno])
362       mask |= 1 << (15 - regno);
363
364   if (frame_pointer_needed)
365     mask &= ~ (1 << (15-FRAME_POINTER_REGNUM));
366
367   if (exact_log2 (mask) >= 0)
368     fprintf (stream, "\tmove.l %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]);
369   else
370     if (mask) fprintf (stream, "\tmovem.l #0x%x,-(sp)\n", mask);
371 }
372
373 #else  /* !CRDS && ! (NEWS && MOTOROLA) && ! (DPX2 && MOTOROLA) */
374
375 static void
376 m68k_output_function_prologue (stream, size)
377      FILE *stream;
378      HOST_WIDE_INT size;
379 {
380   register int regno;
381   register int mask = 0;
382   int num_saved_regs = 0;
383   extern char call_used_regs[];
384   HOST_WIDE_INT fsize = (size + 3) & -4;
385   HOST_WIDE_INT cfa_offset = INCOMING_FRAME_SP_OFFSET;
386   HOST_WIDE_INT cfa_store_offset = cfa_offset;
387   
388   /* If the stack limit is a symbol, we can check it here,
389      before actually allocating the space.  */
390   if (current_function_limit_stack
391       && GET_CODE (stack_limit_rtx) == SYMBOL_REF)
392     {
393 #if defined (MOTOROLA)
394       asm_fprintf (stream, "\tcmp.l %0I%s+%d,%Rsp\n\ttrapcs\n",
395                    XSTR (stack_limit_rtx, 0), fsize + 4);
396 #else
397       asm_fprintf (stream, "\tcmpl %0I%s+%d,%Rsp\n\ttrapcs\n",
398                    XSTR (stack_limit_rtx, 0), fsize + 4);
399 #endif
400     }
401
402   if (frame_pointer_needed)
403     {
404       if (fsize == 0 && TARGET_68040)
405         {
406         /* on the 68040, pea + move is faster than link.w 0 */
407 #ifdef MOTOROLA
408           asm_fprintf (stream, "\tpea (%s)\n\tmove.l %s,%s\n",
409                reg_names[FRAME_POINTER_REGNUM], reg_names[STACK_POINTER_REGNUM],
410                reg_names[FRAME_POINTER_REGNUM]);
411 #else
412           asm_fprintf (stream, "\tpea %s@\n\tmovel %s,%s\n",
413                reg_names[FRAME_POINTER_REGNUM], reg_names[STACK_POINTER_REGNUM],
414                reg_names[FRAME_POINTER_REGNUM]);
415 #endif
416         }
417       else if (fsize < 0x8000)
418         {
419 #ifdef MOTOROLA
420           asm_fprintf (stream, "\tlink.w %s,%0I%d\n",
421                        reg_names[FRAME_POINTER_REGNUM], -fsize);
422 #else
423           asm_fprintf (stream, "\tlink %s,%0I%d\n",
424                        reg_names[FRAME_POINTER_REGNUM], -fsize);
425 #endif
426         }
427       else if (TARGET_68020)
428         {
429 #ifdef MOTOROLA
430           asm_fprintf (stream, "\tlink.l %s,%0I%d\n",
431                        reg_names[FRAME_POINTER_REGNUM], -fsize);
432 #else
433           asm_fprintf (stream, "\tlink %s,%0I%d\n",
434                        reg_names[FRAME_POINTER_REGNUM], -fsize);
435 #endif
436         }
437       else
438         {
439       /* Adding negative number is faster on the 68040.  */
440 #ifdef MOTOROLA
441           asm_fprintf (stream, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
442                        reg_names[FRAME_POINTER_REGNUM], -fsize);
443 #else
444           asm_fprintf (stream, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
445                        reg_names[FRAME_POINTER_REGNUM], -fsize);
446 #endif
447         }
448       if (dwarf2out_do_frame ())
449         {
450           char *l;
451           l = (char *) dwarf2out_cfi_label ();   
452           cfa_store_offset += 4;
453           cfa_offset = cfa_store_offset;
454           dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, -cfa_store_offset);
455           dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, cfa_offset);
456           cfa_store_offset += fsize;
457         }
458     }
459   else if (fsize)
460     {
461       if (fsize + 4 < 0x8000)
462         {
463 #ifndef NO_ADDSUB_Q
464           if (fsize + 4 <= 8)
465             {
466               if (!TARGET_5200)
467                 {
468                   /* asm_fprintf() cannot handle %. */
469 #ifdef MOTOROLA
470                   asm_fprintf (stream, "\tsubq.w %0I%d,%Rsp\n", fsize + 4);
471 #else
472                   asm_fprintf (stream, "\tsubqw %0I%d,%Rsp\n", fsize + 4);
473 #endif
474                 }
475               else
476                 {
477                   /* asm_fprintf() cannot handle %. */
478 #ifdef MOTOROLA
479                   asm_fprintf (stream, "\tsubq.l %0I%d,%Rsp\n", fsize + 4);
480 #else
481                   asm_fprintf (stream, "\tsubql %0I%d,%Rsp\n", fsize + 4);
482 #endif
483                 }
484             }
485           else if (fsize + 4 <= 16 && TARGET_CPU32)
486             {
487               /* On the CPU32 it is faster to use two subqw instructions to
488                  subtract a small integer (8 < N <= 16) to a register. */
489               /* asm_fprintf() cannot handle %. */
490 #ifdef MOTOROLA
491               asm_fprintf (stream, "\tsubq.w %0I8,%Rsp\n\tsubq.w %0I%d,%Rsp\n",
492                            fsize + 4 - 8);
493 #else
494               asm_fprintf (stream, "\tsubqw %0I8,%Rsp\n\tsubqw %0I%d,%Rsp\n",
495                            fsize + 4 - 8);
496 #endif
497             }
498           else 
499 #endif /* not NO_ADDSUB_Q */
500           if (TARGET_68040)
501             {
502               /* Adding negative number is faster on the 68040.  */
503               /* asm_fprintf() cannot handle %. */
504 #ifdef MOTOROLA
505               asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - (fsize + 4));
506 #else
507               asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", - (fsize + 4));
508 #endif
509             }
510           else
511             {
512 #ifdef MOTOROLA
513               asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", - (fsize + 4));
514 #else
515               asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", - (fsize + 4));
516 #endif
517             }
518         }
519       else
520         {
521         /* asm_fprintf() cannot handle %. */
522 #ifdef MOTOROLA
523           asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", - (fsize + 4));
524 #else
525           asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", - (fsize + 4));
526 #endif
527         }
528       if (dwarf2out_do_frame ())
529         {
530           cfa_store_offset += fsize;
531           cfa_offset = cfa_store_offset;
532           dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset);
533         }
534     }
535 #ifdef SUPPORT_SUN_FPA
536   for (regno = 24; regno < 56; regno++)
537     if (regs_ever_live[regno] && ! call_used_regs[regno])
538       {
539 #ifdef MOTOROLA
540         asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n",
541                      reg_names[regno]);
542 #else
543         asm_fprintf (stream, "\tfpmoved %s,%Rsp@-\n",
544                      reg_names[regno]);
545 #endif
546         if (dwarf2out_do_frame ())
547           {
548             char *l = dwarf2out_cfi_label ();
549
550             cfa_store_offset += 8;
551             if (! frame_pointer_needed)
552               {
553                 cfa_offset = cfa_store_offset;
554                 dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
555               }
556             dwarf2out_reg_save (l, regno, -cfa_store_offset);
557           }
558       }
559 #endif
560   if (TARGET_68881)
561     {
562       for (regno = 16; regno < 24; regno++)
563         if (regs_ever_live[regno] && ! call_used_regs[regno])
564           {
565             mask |= 1 << (regno - 16);
566             num_saved_regs++;
567           }
568       if ((mask & 0xff) != 0)
569         {
570 #ifdef MOTOROLA
571           asm_fprintf (stream, "\tfmovm %0I0x%x,-(%Rsp)\n", mask & 0xff);
572 #else
573           asm_fprintf (stream, "\tfmovem %0I0x%x,%Rsp@-\n", mask & 0xff);
574 #endif
575           if (dwarf2out_do_frame ())
576             {
577               char *l = (char *) dwarf2out_cfi_label ();
578               int n_regs;
579
580               cfa_store_offset += num_saved_regs * 12;
581               if (! frame_pointer_needed)
582                 {
583                   cfa_offset = cfa_store_offset;
584                   dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
585                 }
586               for (regno = 16, n_regs = 0; regno < 24; regno++)
587                 if (mask & (1 << (regno - 16)))
588                   dwarf2out_reg_save (l, regno,
589                                       -cfa_store_offset + n_regs++ * 12);
590             }
591         }
592       mask = 0;
593       num_saved_regs = 0;
594     }
595   for (regno = 0; regno < 16; regno++)
596     if (regs_ever_live[regno] && ! call_used_regs[regno])
597       {
598         mask |= 1 << (15 - regno);
599         num_saved_regs++;
600       }
601   if (frame_pointer_needed)
602     {
603       mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));
604       num_saved_regs--;
605     }
606   if (flag_pic && current_function_uses_pic_offset_table)
607     {
608       mask |= 1 << (15 - PIC_OFFSET_TABLE_REGNUM);
609       num_saved_regs++;
610     }
611
612 #if NEED_PROBE
613 #ifdef MOTOROLA
614   asm_fprintf (stream, "\ttst.l %d(%Rsp)\n", NEED_PROBE - num_saved_regs * 4);
615 #else
616   asm_fprintf (stream, "\ttstl %Rsp@(%d)\n", NEED_PROBE - num_saved_regs * 4);
617 #endif
618 #endif
619
620   /* If the stack limit is not a symbol, check it here.  
621      This has the disadvantage that it may be too late...  */
622   if (current_function_limit_stack)
623     {
624       if (REG_P (stack_limit_rtx))
625         {
626 #if defined (MOTOROLA)
627           asm_fprintf (stream, "\tcmp.l %s,%Rsp\n\ttrapcs\n",
628                        reg_names[REGNO (stack_limit_rtx)]);
629 #else
630           asm_fprintf (stream, "\tcmpl %s,%Rsp\n\ttrapcs\n",
631                        reg_names[REGNO (stack_limit_rtx)]);
632 #endif
633         }
634       else if (GET_CODE (stack_limit_rtx) != SYMBOL_REF)
635         warning ("stack limit expression is not supported");
636     }
637   
638   if (num_saved_regs <= 2)
639     {
640       /* Store each separately in the same order moveml uses.
641          Using two movel instructions instead of a single moveml
642          is about 15% faster for the 68020 and 68030 at no expense
643          in code size */
644
645       int i;
646
647       /* Undo the work from above. */
648       for (i = 0; i< 16; i++)
649         if (mask & (1 << i))
650           {
651             asm_fprintf (stream,
652 #ifdef MOTOROLA
653                          "\t%Omove.l %s,-(%Rsp)\n",
654 #else
655                          "\tmovel %s,%Rsp@-\n",
656 #endif
657                          reg_names[15 - i]);
658             if (dwarf2out_do_frame ())
659               {
660                 char *l = (char *) dwarf2out_cfi_label ();
661
662                 cfa_store_offset += 4;
663                 if (! frame_pointer_needed)
664                   {
665                     cfa_offset = cfa_store_offset;
666                     dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
667                   }
668                 dwarf2out_reg_save (l, 15 - i, -cfa_store_offset);
669               }
670           }
671     }
672   else if (mask)
673     {
674       if (TARGET_5200)
675         {
676           /* The coldfire does not support the predecrement form of the 
677              movml instruction, so we must adjust the stack pointer and
678              then use the plain address register indirect mode.  We also
679              have to invert the register save mask to use the new mode.
680
681              FIXME: if num_saved_regs was calculated earlier, we could
682              combine the stack pointer adjustment with any adjustment
683              done when the initial stack frame is created.  This would
684              save an instruction */
685              
686           int newmask = 0;
687           int i;
688
689           for (i = 0; i < 16; i++)
690             if (mask & (1 << i))
691                 newmask |= (1 << (15-i));
692
693 #ifdef MOTOROLA
694           asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", -num_saved_regs*4);
695           asm_fprintf (stream, "\tmovm.l %0I0x%x,(%Rsp)\n", newmask);
696 #else
697           asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", -num_saved_regs*4);
698           asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@\n", newmask);
699 #endif
700         }
701       else
702         {
703 #ifdef MOTOROLA
704           asm_fprintf (stream, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask);
705 #else
706           asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@-\n", mask);
707 #endif
708         }
709       if (dwarf2out_do_frame ())
710         {
711           char *l = (char *) dwarf2out_cfi_label ();
712           int n_regs;
713
714           cfa_store_offset += num_saved_regs * 4;
715           if (! frame_pointer_needed)
716             {
717               cfa_offset = cfa_store_offset;
718               dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
719             }
720           for (regno = 0, n_regs = 0; regno < 16; regno++)
721             if (mask & (1 << (15 - regno)))
722               dwarf2out_reg_save (l, regno,
723                                   -cfa_store_offset + n_regs++ * 4);
724         }
725     }
726   if (flag_pic && current_function_uses_pic_offset_table)
727     {
728 #ifdef MOTOROLA
729       asm_fprintf (stream, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
730                    reg_names[PIC_OFFSET_TABLE_REGNUM]);
731 #else
732       asm_fprintf (stream, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
733                    reg_names[PIC_OFFSET_TABLE_REGNUM]);
734       asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n",
735                    reg_names[PIC_OFFSET_TABLE_REGNUM],
736                    reg_names[PIC_OFFSET_TABLE_REGNUM]);
737 #endif
738     }
739 }
740 #endif   /* ! (DPX2 && MOTOROLA)  */
741 #endif   /* ! (NEWS && MOTOROLA)  */
742 #endif   /* !CRDS  */
743 \f
744 /* Return true if this function's epilogue can be output as RTL.  */
745
746 int
747 use_return_insn ()
748 {
749   int regno;
750
751   if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)
752     return 0;
753   
754   /* Copied from output_function_epilogue ().  We should probably create a
755      separate layout routine to perform the common work.  */
756   
757   for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++)
758     if (regs_ever_live[regno] && ! call_used_regs[regno])
759       return 0;
760
761   if (flag_pic && current_function_uses_pic_offset_table)
762     return 0;
763
764   return 1;
765 }
766
767 /* This function generates the assembly code for function exit,
768    on machines that need it.
769
770    The function epilogue should not depend on the current stack pointer!
771    It should use the frame pointer only, if there is a frame pointer.
772    This is mandatory because of alloca; we also take advantage of it to
773    omit stack adjustments before returning.  */
774
775 #ifdef CRDS
776
777 static void
778 m68k_output_function_epilogue (stream, size)
779      FILE *stream;
780      HOST_WIDE_INT size;
781 {
782   register int regno;
783   register int mask, fmask;
784   register int nregs;
785   HOST_WIDE_INT offset, foffset, fpoffset;
786   extern char call_used_regs[];
787   HOST_WIDE_INT fsize = ((size) + 3) & -4;
788   int big = 0;
789
790   nregs = 0;  fmask = 0; fpoffset = 0;
791   for (regno = 16; regno < 24; regno++)
792     if (regs_ever_live[regno] && ! call_used_regs[regno])
793       {
794         nregs++;
795         fmask |= 1 << (23 - regno);
796       }
797
798   foffset = fpoffset + nregs * 12;
799   nregs = 0;  mask = 0;
800   if (frame_pointer_needed)
801     regs_ever_live[FRAME_POINTER_REGNUM] = 0;
802
803   for (regno = 0; regno < 16; regno++)
804     if (regs_ever_live[regno] && ! call_used_regs[regno])
805       {
806         nregs++;
807         mask |= 1 << regno;
808       }
809
810   offset = foffset + nregs * 4;
811   if (offset + fsize >= 0x8000
812       && frame_pointer_needed
813       && (mask || fmask || fpoffset))
814     {
815       fprintf (stream, "\tmovel $%d,a0\n", -fsize);
816       fsize = 0, big = 1;
817     }
818
819   if (exact_log2 (mask) >= 0)
820     {
821       if (big)
822         fprintf (stream, "\tmovel -%d(a6,a0.l),%s\n",
823                  offset + fsize, reg_names[exact_log2 (mask)]);
824       else if (! frame_pointer_needed)
825         fprintf (stream, "\tmovel (sp)+,%s\n",
826                  reg_names[exact_log2 (mask)]);
827       else
828         fprintf (stream, "\tmovel -%d(a6),%s\n",
829                  offset + fsize, reg_names[exact_log2 (mask)]);
830     }
831   else if (mask)
832     {
833       if (big)
834         fprintf (stream, "\tmovem -%d(a6,a0.l),$0x%x\n",
835                  offset + fsize, mask);
836       else if (! frame_pointer_needed)
837         fprintf (stream, "\tmovem (sp)+,$0x%x\n", mask);
838       else
839         fprintf (stream, "\tmovem -%d(a6),$0x%x\n",
840                  offset + fsize, mask);
841     }
842
843   if (fmask)
844     {
845       if (big)
846         fprintf (stream, "\tfmovem -%d(a6,a0.l),$0x%x\n",
847                  foffset + fsize, fmask);
848       else if (! frame_pointer_needed)
849         fprintf (stream, "\tfmovem (sp)+,$0x%x\n", fmask);
850       else
851         fprintf (stream, "\tfmovem -%d(a6),$0x%x\n",
852                  foffset + fsize, fmask);
853     }
854
855   if (fpoffset != 0)
856     for (regno = 55; regno >= 24; regno--)
857       if (regs_ever_live[regno] && ! call_used_regs[regno])
858         {
859           if (big)
860             fprintf(stream, "\tfpmoved -%d(a6,a0.l), %s\n",
861                     fpoffset + fsize, reg_names[regno]);
862           else if (! frame_pointer_needed)
863             fprintf(stream, "\tfpmoved (sp)+, %s\n",
864                     reg_names[regno]);
865           else
866             fprintf(stream, "\tfpmoved -%d(a6), %s\n",
867                     fpoffset + fsize, reg_names[regno]);
868           fpoffset -= 8;
869         }
870
871   if (frame_pointer_needed)
872     fprintf (stream, "\tunlk a6\n");
873   else if (fsize)
874     {
875       if (fsize + 4 < 0x8000)
876         fprintf (stream, "\tadd.w #%d,sp\n", fsize + 4);
877       else
878         fprintf (stream, "\tadd.l #%d,sp\n", fsize + 4);
879     }
880
881   if (current_function_pops_args)
882     fprintf (stream, "\trtd $%d\n", current_function_pops_args);
883   else
884     fprintf (stream, "\trts\n");
885 }
886
887 #else
888 #if defined (DPX2) && defined (MOTOROLA)
889
890 static void
891 m68k_output_function_epilogue (stream, size)
892      FILE *stream;
893      HOST_WIDE_INT size;
894 {
895   register int regno;
896   register int mask, fmask;
897   register int nregs;
898   HOST_WIDE_INT offset, foffset, fpoffset, first = 1;
899   extern char call_used_regs[];
900   HOST_WIDE_INT fsize = ((size) + 3) & -4;
901   int big = 0;
902   rtx insn = get_last_insn ();
903
904   /* If the last insn was a BARRIER, we don't have to write any code.  */
905   if (GET_CODE (insn) == NOTE)
906     insn = prev_nonnote_insn (insn);
907   if (insn && GET_CODE (insn) == BARRIER)
908     {
909       /* Output just a no-op so that debuggers don't get confused
910          about which function the pc is in at this address.  */
911       fprintf (stream, "\tnop\n");
912       return;
913     }
914
915   nregs = 0;  fmask = 0; fpoffset = 0;
916   for (regno = 16; regno < 24; regno++)
917     if (regs_ever_live[regno] && ! call_used_regs[regno])
918       {
919         nregs++;
920         fmask |= 1 << (23 - regno);
921       }
922
923   foffset = fpoffset + nregs * 12;
924   nregs = 0;  mask = 0;
925   if (frame_pointer_needed)
926     regs_ever_live[FRAME_POINTER_REGNUM] = 0;
927
928   for (regno = 0; regno < 16; regno++)
929     if (regs_ever_live[regno] && ! call_used_regs[regno])
930       {
931         nregs++;
932         mask |= 1 << regno;
933       }
934
935   offset = foffset + nregs * 4;
936   if (offset + fsize >= 0x8000
937       && frame_pointer_needed
938       && (mask || fmask || fpoffset))
939     {
940       fprintf (stream, "\tmove.l #%d,a0\n", -fsize);
941       fsize = 0, big = 1;
942     }
943
944   if (nregs <= 2)
945     {
946       /* Restore each separately in the same order moveml does.
947          Using two movel instructions instead of a single moveml
948          is about 15% faster for the 68020 and 68030 at no expense
949          in code size. */
950
951       int i;
952
953       /* Undo the work from above. */
954       for (i = 0; i< 16; i++)
955         if (mask & (1 << i))
956           {
957             if (big)
958               fprintf (stream, "\tmove.l -%d(%s,a0.l),%s\n",
959                        offset + fsize,
960                        reg_names[FRAME_POINTER_REGNUM],
961                        reg_names[i]);
962             else if (! frame_pointer_needed)
963               fprintf (stream, "\tmove.l (sp)+,%s\n",
964                        reg_names[i]);
965             else
966               fprintf (stream, "\tmove.l -%d(%s),%s\n",
967                        offset + fsize,
968                        reg_names[FRAME_POINTER_REGNUM],
969                        reg_names[i]);
970             offset = offset - 4;
971           }
972     }
973   else if (mask)
974     {
975       first = 1;
976       for (regno = 0; regno < 16; regno++)
977         if (mask & (1 << regno))
978           {
979             if (first && big)
980               {
981                 fprintf (stream, "\tmovem.l -%d(%s,a0.l),%s",
982                          offset + fsize,
983                          reg_names[FRAME_POINTER_REGNUM],
984                          reg_names[regno]);
985                 first = 0;
986               }
987             else if (first && ! frame_pointer_needed)
988               {
989                 fprintf (stream, "\tmovem.l (sp)+,%s",
990                          reg_names[regno]);
991                 first = 0;
992               }
993             else if (first)
994               {
995                 fprintf (stream, "\tmovem.l -%d(%s),%s",
996                          offset + fsize,
997                          reg_names[FRAME_POINTER_REGNUM],
998                          reg_names[regno]);
999                 first = 0;
1000               }
1001             else
1002               fprintf (stream, "/%s", reg_names[regno]);
1003           }
1004       fprintf (stream, "\n");
1005     }
1006
1007   if (fmask)
1008     {
1009       first = 1;
1010       for (regno = 16; regno < 24; regno++)
1011         if (fmask & (1 << (23 - regno)))
1012           {
1013             if (first && big)
1014               {
1015                 fprintf (stream, "\tfmovem.x -%d(%s,a0.l),%s",
1016                          foffset + fsize,
1017                          reg_names[FRAME_POINTER_REGNUM],
1018                          reg_names[regno]);
1019                 first = 0;
1020               }
1021             else if (first && ! frame_pointer_needed)
1022               {
1023                 fprintf (stream, "\tfmovem.x (sp)+,%s",
1024                          reg_names[regno]);
1025                 first = 0;
1026               }
1027             else if (first)
1028               {
1029                 fprintf (stream, "\tfmovem.x -%d(%s),%s",
1030                          foffset + fsize,
1031                          reg_names[FRAME_POINTER_REGNUM],
1032                          reg_names[regno]);
1033                 first = 0;
1034               }
1035             else
1036               fprintf (stream, "/%s", reg_names[regno]);
1037           }
1038       fprintf (stream, "\n");
1039     }
1040
1041   if (frame_pointer_needed)
1042     fprintf (stream, "\tunlk %s\n",
1043              reg_names[FRAME_POINTER_REGNUM]);
1044   else if (fsize)
1045     {
1046       if (fsize + 4 < 0x8000)
1047         fprintf (stream, "\tadd.w #%d,sp\n", fsize + 4);
1048       else
1049         fprintf (stream, "\tadd.l #%d,sp\n", fsize + 4);
1050     }
1051
1052   if (current_function_pops_args)
1053     fprintf (stream, "\trtd #%d\n", current_function_pops_args);
1054   else
1055     fprintf (stream, "\trts\n");
1056 }
1057
1058 #else
1059 #if defined (NEWS) && defined (MOTOROLA)
1060
1061 static void
1062 m68k_output_function_epilogue (stream, size)
1063      FILE *stream;
1064      HOST_WIDE_INT size;
1065 {
1066   register int regno;
1067   register int mask, fmask;
1068   register int nregs;
1069   HOST_WIDE_INT offset, foffset;
1070   extern char call_used_regs[];
1071   HOST_WIDE_INT fsize = ((size) + 3) & -4;
1072   int big = 0;
1073
1074   nregs = 0;  fmask = 0;
1075   for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++)
1076     if (regs_ever_live[regno] && ! call_used_regs[regno])
1077       {
1078         nregs++;
1079         fmask |= 1 << (23 - regno);
1080       }
1081
1082   foffset = nregs * 12;
1083   nregs = 0;  mask = 0;
1084   if (frame_pointer_needed)
1085     regs_ever_live[FRAME_POINTER_REGNUM] = 0;
1086
1087   for (regno = 0; regno < 16; regno++)
1088     if (regs_ever_live[regno] && ! call_used_regs[regno])
1089       {
1090         nregs++;
1091         mask |= 1 << regno;
1092       }
1093
1094   offset = foffset + nregs * 4;
1095   if (offset + fsize >= 0x8000
1096       && frame_pointer_needed
1097       && (mask || fmask))
1098     {
1099       fprintf (stream, "\tmove.l #%d,a0\n", -fsize);
1100       fsize = 0, big = 1;
1101     }
1102
1103   if (exact_log2 (mask) >= 0)
1104     {
1105       if (big)
1106         fprintf (stream, "\tmove.l (-%d,fp,a0.l),%s\n",
1107                  offset + fsize, reg_names[exact_log2 (mask)]);
1108       else if (! frame_pointer_needed)
1109         fprintf (stream, "\tmove.l (sp)+,%s\n",
1110                  reg_names[exact_log2 (mask)]);
1111       else
1112         fprintf (stream, "\tmove.l (-%d,fp),%s\n",
1113                  offset + fsize, reg_names[exact_log2 (mask)]);
1114     }
1115   else if (mask)
1116     {
1117       if (big)
1118         fprintf (stream, "\tmovem.l (-%d,fp,a0.l),#0x%x\n",
1119                  offset + fsize, mask);
1120       else if (! frame_pointer_needed)
1121         fprintf (stream, "\tmovem.l (sp)+,#0x%x\n", mask);
1122       else
1123         fprintf (stream, "\tmovem.l (-%d,fp),#0x%x\n",
1124                  offset + fsize, mask);
1125     }
1126
1127   if (fmask)
1128     {
1129       if (big)
1130         fprintf (stream, "\tfmovem.x (-%d,fp,a0.l),#0x%x\n",
1131                  foffset + fsize, fmask);
1132       else if (! frame_pointer_needed)
1133         fprintf (stream, "\tfmovem.x (sp)+,#0x%x\n", fmask);
1134       else
1135         fprintf (stream, "\tfmovem.x (-%d,fp),#0x%x\n",
1136                  foffset + fsize, fmask);
1137     }
1138
1139   if (frame_pointer_needed)
1140     fprintf (stream, "\tunlk fp\n");
1141   else if (fsize)
1142     {
1143       if (fsize + 4 < 0x8000)
1144         fprintf (stream, "\tadd.w #%d,sp\n", fsize + 4);
1145       else
1146         fprintf (stream, "\tadd.l #%d,sp\n", fsize + 4);
1147     }
1148
1149   if (current_function_pops_args)
1150     fprintf (stream, "\trtd #%d\n", current_function_pops_args);
1151   else
1152     fprintf (stream, "\trts\n");
1153 }
1154
1155 #else  /* !CRDS && ! (NEWS && MOTOROLA) && ! (DPX2 && MOTOROLA) */
1156
1157 static void
1158 m68k_output_function_epilogue (stream, size)
1159      FILE *stream;
1160      HOST_WIDE_INT size;
1161 {
1162   register int regno;
1163   register int mask, fmask;
1164   register int nregs;
1165   HOST_WIDE_INT offset, foffset, fpoffset;
1166   extern char call_used_regs[];
1167   HOST_WIDE_INT fsize = (size + 3) & -4;
1168   int big = 0;
1169   rtx insn = get_last_insn ();
1170   int restore_from_sp = 0;
1171   
1172   /* If the last insn was a BARRIER, we don't have to write any code.  */
1173   if (GET_CODE (insn) == NOTE)
1174     insn = prev_nonnote_insn (insn);
1175   if (insn && GET_CODE (insn) == BARRIER)
1176     {
1177       /* Output just a no-op so that debuggers don't get confused
1178          about which function the pc is in at this address.  */
1179       asm_fprintf (stream, "\tnop\n");
1180       return;
1181     }
1182
1183 #ifdef FUNCTION_BLOCK_PROFILER_EXIT
1184   if (profile_block_flag == 2)
1185     {
1186       FUNCTION_BLOCK_PROFILER_EXIT (stream);
1187     }
1188 #endif
1189
1190 #ifdef FUNCTION_EXTRA_EPILOGUE
1191   FUNCTION_EXTRA_EPILOGUE (stream, size);
1192 #endif
1193   nregs = 0;  fmask = 0; fpoffset = 0;
1194 #ifdef SUPPORT_SUN_FPA
1195   for (regno = 24 ; regno < 56 ; regno++)
1196     if (regs_ever_live[regno] && ! call_used_regs[regno])
1197       nregs++;
1198   fpoffset = nregs * 8;
1199 #endif
1200   nregs = 0;
1201   if (TARGET_68881)
1202     {
1203       for (regno = 16; regno < 24; regno++)
1204         if (regs_ever_live[regno] && ! call_used_regs[regno])
1205           {
1206             nregs++;
1207             fmask |= 1 << (23 - regno);
1208           }
1209     }
1210   foffset = fpoffset + nregs * 12;
1211   nregs = 0;  mask = 0;
1212   if (frame_pointer_needed)
1213     regs_ever_live[FRAME_POINTER_REGNUM] = 0;
1214   for (regno = 0; regno < 16; regno++)
1215     if (regs_ever_live[regno] && ! call_used_regs[regno])
1216       {
1217         nregs++;
1218         mask |= 1 << regno;
1219       }
1220   if (flag_pic && current_function_uses_pic_offset_table)
1221     {
1222       nregs++;
1223       mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
1224     }
1225   offset = foffset + nregs * 4;
1226   /* FIXME : leaf_function_p below is too strong.
1227      What we really need to know there is if there could be pending
1228      stack adjustment needed at that point. */
1229   restore_from_sp = ! frame_pointer_needed
1230              || (! current_function_calls_alloca && leaf_function_p ());
1231   if (offset + fsize >= 0x8000
1232       && ! restore_from_sp
1233       && (mask || fmask || fpoffset))
1234     {
1235 #ifdef MOTOROLA
1236       asm_fprintf (stream, "\t%Omove.l %0I%d,%Ra1\n", -fsize);
1237 #else
1238       asm_fprintf (stream, "\tmovel %0I%d,%Ra1\n", -fsize);
1239 #endif
1240       fsize = 0, big = 1;
1241     }
1242   if (TARGET_5200 || nregs <= 2)
1243     {
1244       /* Restore each separately in the same order moveml does.
1245          Using two movel instructions instead of a single moveml
1246          is about 15% faster for the 68020 and 68030 at no expense
1247          in code size. */
1248
1249       int i;
1250
1251       /* Undo the work from above. */
1252       for (i = 0; i< 16; i++)
1253         if (mask & (1 << i))
1254           {
1255             if (big)
1256               {
1257 #ifdef MOTOROLA
1258                 asm_fprintf (stream, "\t%Omove.l -%d(%s,%Ra1.l),%s\n",
1259                              offset + fsize,
1260                              reg_names[FRAME_POINTER_REGNUM],
1261                              reg_names[i]);
1262 #else
1263                 asm_fprintf (stream, "\tmovel %s@(-%d,%Ra1:l),%s\n",
1264                              reg_names[FRAME_POINTER_REGNUM],
1265                              offset + fsize, reg_names[i]);
1266 #endif
1267               }
1268             else if (restore_from_sp)
1269               {
1270 #ifdef MOTOROLA
1271                 asm_fprintf (stream, "\t%Omove.l (%Rsp)+,%s\n",
1272                              reg_names[i]);
1273 #else
1274                 asm_fprintf (stream, "\tmovel %Rsp@+,%s\n",
1275                              reg_names[i]);
1276 #endif
1277               }
1278             else
1279               {
1280 #ifdef MOTOROLA
1281                 asm_fprintf (stream, "\t%Omove.l -%d(%s),%s\n",
1282                              offset + fsize,
1283                              reg_names[FRAME_POINTER_REGNUM],
1284                              reg_names[i]);
1285 #else
1286                 asm_fprintf (stream, "\tmovel %s@(-%d),%s\n",
1287                              reg_names[FRAME_POINTER_REGNUM],
1288                              offset + fsize, reg_names[i]);
1289 #endif
1290               }
1291             offset = offset - 4;
1292           }
1293     }
1294   else if (mask)
1295     {
1296       if (big)
1297         {
1298 #ifdef MOTOROLA
1299           asm_fprintf (stream, "\tmovm.l -%d(%s,%Ra1.l),%0I0x%x\n",
1300                        offset + fsize,
1301                        reg_names[FRAME_POINTER_REGNUM],
1302                        mask);
1303 #else
1304           asm_fprintf (stream, "\tmoveml %s@(-%d,%Ra1:l),%0I0x%x\n",
1305                        reg_names[FRAME_POINTER_REGNUM],
1306                        offset + fsize, mask);
1307 #endif
1308         }
1309       else if (restore_from_sp)
1310         {
1311 #ifdef MOTOROLA
1312           asm_fprintf (stream, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask);
1313 #else
1314           asm_fprintf (stream, "\tmoveml %Rsp@+,%0I0x%x\n", mask);
1315 #endif
1316         }
1317       else
1318         {
1319 #ifdef MOTOROLA
1320           asm_fprintf (stream, "\tmovm.l -%d(%s),%0I0x%x\n",
1321                        offset + fsize,
1322                        reg_names[FRAME_POINTER_REGNUM],
1323                        mask);
1324 #else
1325           asm_fprintf (stream, "\tmoveml %s@(-%d),%0I0x%x\n",
1326                        reg_names[FRAME_POINTER_REGNUM],
1327                        offset + fsize, mask);
1328 #endif
1329         }
1330     }
1331   if (fmask)
1332     {
1333       if (big)
1334         {
1335 #ifdef MOTOROLA
1336           asm_fprintf (stream, "\tfmovm -%d(%s,%Ra1.l),%0I0x%x\n",
1337                        foffset + fsize,
1338                        reg_names[FRAME_POINTER_REGNUM],
1339                        fmask);
1340 #else
1341           asm_fprintf (stream, "\tfmovem %s@(-%d,%Ra1:l),%0I0x%x\n",
1342                        reg_names[FRAME_POINTER_REGNUM],
1343                        foffset + fsize, fmask);
1344 #endif
1345         }
1346       else if (restore_from_sp)
1347         {
1348 #ifdef MOTOROLA
1349           asm_fprintf (stream, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask);
1350 #else
1351           asm_fprintf (stream, "\tfmovem %Rsp@+,%0I0x%x\n", fmask);
1352 #endif
1353         }
1354       else
1355         {
1356 #ifdef MOTOROLA
1357           asm_fprintf (stream, "\tfmovm -%d(%s),%0I0x%x\n",
1358                        foffset + fsize,
1359                        reg_names[FRAME_POINTER_REGNUM],
1360                        fmask);
1361 #else
1362           asm_fprintf (stream, "\tfmovem %s@(-%d),%0I0x%x\n",
1363                        reg_names[FRAME_POINTER_REGNUM],
1364                        foffset + fsize, fmask);
1365 #endif
1366         }
1367     }
1368   if (fpoffset != 0)
1369     for (regno = 55; regno >= 24; regno--)
1370       if (regs_ever_live[regno] && ! call_used_regs[regno])
1371         {
1372           if (big)
1373             {
1374 #ifdef MOTOROLA
1375               asm_fprintf (stream, "\tfpmovd -%d(%s,%Ra1.l), %s\n",
1376                            fpoffset + fsize,
1377                            reg_names[FRAME_POINTER_REGNUM],
1378                            reg_names[regno]);
1379 #else
1380               asm_fprintf (stream, "\tfpmoved %s@(-%d,%Ra1:l), %s\n",
1381                            reg_names[FRAME_POINTER_REGNUM],
1382                            fpoffset + fsize, reg_names[regno]);
1383 #endif
1384             }
1385           else if (restore_from_sp)
1386             {
1387 #ifdef MOTOROLA
1388               asm_fprintf (stream, "\tfpmovd (%Rsp)+,%s\n",
1389                            reg_names[regno]);
1390 #else
1391               asm_fprintf (stream, "\tfpmoved %Rsp@+, %s\n",
1392                            reg_names[regno]);
1393 #endif
1394             }
1395           else
1396             {
1397 #ifdef MOTOROLA
1398               asm_fprintf (stream, "\tfpmovd -%d(%s), %s\n",
1399                            fpoffset + fsize,
1400                            reg_names[FRAME_POINTER_REGNUM],
1401                            reg_names[regno]);
1402 #else
1403               asm_fprintf (stream, "\tfpmoved %s@(-%d), %s\n",
1404                            reg_names[FRAME_POINTER_REGNUM],
1405                            fpoffset + fsize, reg_names[regno]);
1406 #endif
1407             }
1408           fpoffset -= 8;
1409         }
1410   if (frame_pointer_needed)
1411     fprintf (stream, "\tunlk %s\n",
1412              reg_names[FRAME_POINTER_REGNUM]);
1413   else if (fsize)
1414     {
1415 #ifndef NO_ADDSUB_Q
1416       if (fsize + 4 <= 8) 
1417         {
1418           if (!TARGET_5200)
1419             {
1420 #ifdef MOTOROLA
1421               asm_fprintf (stream, "\taddq.w %0I%d,%Rsp\n", fsize + 4);
1422 #else
1423               asm_fprintf (stream, "\taddqw %0I%d,%Rsp\n", fsize + 4);
1424 #endif
1425             }
1426           else
1427             {
1428 #ifdef MOTOROLA
1429               asm_fprintf (stream, "\taddq.l %0I%d,%Rsp\n", fsize + 4);
1430 #else
1431               asm_fprintf (stream, "\taddql %0I%d,%Rsp\n", fsize + 4);
1432 #endif
1433             }
1434         }
1435       else if (fsize + 4 <= 16 && TARGET_CPU32)
1436         {
1437           /* On the CPU32 it is faster to use two addqw instructions to
1438              add a small integer (8 < N <= 16) to a register. */
1439           /* asm_fprintf() cannot handle %. */
1440 #ifdef MOTOROLA
1441           asm_fprintf (stream, "\taddq.w %0I8,%Rsp\n\taddq.w %0I%d,%Rsp\n",
1442                        fsize + 4 - 8);
1443 #else
1444           asm_fprintf (stream, "\taddqw %0I8,%Rsp\n\taddqw %0I%d,%Rsp\n",
1445                        fsize + 4 - 8);
1446 #endif
1447         }
1448       else
1449 #endif /* not NO_ADDSUB_Q */
1450       if (fsize + 4 < 0x8000)
1451         {
1452           if (TARGET_68040)
1453             { 
1454               /* asm_fprintf() cannot handle %. */
1455 #ifdef MOTOROLA
1456               asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", fsize + 4);
1457 #else
1458               asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", fsize + 4);
1459 #endif
1460             }
1461           else
1462             {
1463 #ifdef MOTOROLA
1464               asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", fsize + 4);
1465 #else
1466               asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", fsize + 4);
1467 #endif
1468             }
1469         }
1470       else
1471         {
1472         /* asm_fprintf() cannot handle %. */
1473 #ifdef MOTOROLA
1474           asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", fsize + 4);
1475 #else
1476           asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", fsize + 4);
1477 #endif
1478         }
1479     }
1480   if (current_function_pops_args)
1481     asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args);
1482   else
1483     fprintf (stream, "\trts\n");
1484 }
1485
1486 #endif   /* ! (DPX2 && MOTOROLA)  */
1487 #endif   /* ! (NEWS && MOTOROLA)  */
1488 #endif   /* !CRDS  */
1489 \f
1490 /* Similar to general_operand, but exclude stack_pointer_rtx.  */
1491
1492 int
1493 not_sp_operand (op, mode)
1494      register rtx op;
1495      enum machine_mode mode;
1496 {
1497   return op != stack_pointer_rtx && general_operand (op, mode);
1498 }
1499
1500 /* Return TRUE if X is a valid comparison operator for the dbcc 
1501    instruction.  
1502
1503    Note it rejects floating point comparison operators.
1504    (In the future we could use Fdbcc).
1505
1506    It also rejects some comparisons when CC_NO_OVERFLOW is set.  */
1507    
1508 int
1509 valid_dbcc_comparison_p (x, mode)
1510      rtx x;
1511      enum machine_mode mode ATTRIBUTE_UNUSED;
1512 {
1513   switch (GET_CODE (x))
1514     {
1515       case EQ: case NE: case GTU: case LTU:
1516       case GEU: case LEU:
1517         return 1;
1518
1519       /* Reject some when CC_NO_OVERFLOW is set.  This may be over
1520          conservative */
1521       case GT: case LT: case GE: case LE:
1522         return ! (cc_prev_status.flags & CC_NO_OVERFLOW);
1523       default:
1524         return 0;
1525     }
1526 }
1527
1528 /* Return non-zero if flags are currently in the 68881 flag register.  */
1529 int
1530 flags_in_68881 ()
1531 {
1532   /* We could add support for these in the future */
1533   return cc_status.flags & CC_IN_68881;
1534 }
1535
1536 /* Output a dbCC; jCC sequence.  Note we do not handle the 
1537    floating point version of this sequence (Fdbcc).  We also
1538    do not handle alternative conditions when CC_NO_OVERFLOW is
1539    set.  It is assumed that valid_dbcc_comparison_p and flags_in_68881 will
1540    kick those out before we get here.  */
1541
1542 void
1543 output_dbcc_and_branch (operands)
1544      rtx *operands;
1545 {
1546   switch (GET_CODE (operands[3]))
1547     {
1548       case EQ:
1549 #ifdef MOTOROLA
1550         output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands);
1551 #else
1552         output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands);
1553 #endif
1554         break;
1555
1556       case NE:
1557 #ifdef MOTOROLA
1558         output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands);
1559 #else
1560         output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands);
1561 #endif
1562         break;
1563
1564       case GT:
1565 #ifdef MOTOROLA
1566         output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands);
1567 #else
1568         output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands);
1569 #endif
1570         break;
1571
1572       case GTU:
1573 #ifdef MOTOROLA
1574         output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands);
1575 #else
1576         output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands);
1577 #endif
1578         break;
1579
1580       case LT:
1581 #ifdef MOTOROLA
1582         output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands);
1583 #else
1584         output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands);
1585 #endif
1586         break;
1587
1588       case LTU:
1589 #ifdef MOTOROLA
1590         output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands);
1591 #else
1592         output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands);
1593 #endif
1594         break;
1595
1596       case GE:
1597 #ifdef MOTOROLA
1598         output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands);
1599 #else
1600         output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands);
1601 #endif
1602         break;
1603
1604       case GEU:
1605 #ifdef MOTOROLA
1606         output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands);
1607 #else
1608         output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands);
1609 #endif
1610         break;
1611
1612       case LE:
1613 #ifdef MOTOROLA
1614         output_asm_insn ("dble %0,%l1\n\tjble %l2", operands);
1615 #else
1616         output_asm_insn ("dble %0,%l1\n\tjle %l2", operands);
1617 #endif
1618         break;
1619
1620       case LEU:
1621 #ifdef MOTOROLA
1622         output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands);
1623 #else
1624         output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands);
1625 #endif
1626         break;
1627
1628       default:
1629         abort ();
1630     }
1631
1632   /* If the decrement is to be done in SImode, then we have
1633      to compensate for the fact that dbcc decrements in HImode. */
1634   switch (GET_MODE (operands[0]))
1635     {
1636       case SImode:
1637 #ifdef MOTOROLA
1638         output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands);
1639 #else
1640         output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands);
1641 #endif
1642         break;
1643
1644       case HImode:
1645         break;
1646
1647       default:
1648         abort ();
1649     }
1650 }
1651
1652 const char *
1653 output_scc_di(op, operand1, operand2, dest)
1654      rtx op;
1655      rtx operand1;
1656      rtx operand2;
1657      rtx dest;
1658 {
1659   rtx loperands[7];
1660   enum rtx_code op_code = GET_CODE (op);
1661
1662   /* This does not produce a usefull cc.  */
1663   CC_STATUS_INIT;
1664
1665   /* The m68k cmp.l instruction requires operand1 to be a reg as used
1666      below.  Swap the operands and change the op if these requirements
1667      are not fulfilled.  */
1668   if (GET_CODE (operand2) == REG && GET_CODE (operand1) != REG)
1669     {
1670       rtx tmp = operand1;
1671
1672       operand1 = operand2;
1673       operand2 = tmp;
1674       op_code = swap_condition (op_code);
1675     }
1676   loperands[0] = operand1;
1677   if (GET_CODE (operand1) == REG)
1678     loperands[1] = gen_rtx_REG (SImode, REGNO (operand1) + 1);
1679   else
1680     loperands[1] = adjust_address (operand1, SImode, 4);
1681   if (operand2 != const0_rtx)
1682     {
1683       loperands[2] = operand2;
1684       if (GET_CODE (operand2) == REG)
1685         loperands[3] = gen_rtx_REG (SImode, REGNO (operand2) + 1);
1686       else
1687         loperands[3] = adjust_address (operand2, SImode, 4);
1688     }
1689   loperands[4] = gen_label_rtx();
1690   if (operand2 != const0_rtx)
1691     {
1692 #ifdef MOTOROLA
1693 #ifdef SGS_CMP_ORDER
1694       output_asm_insn ("cmp%.l %0,%2\n\tjbne %l4\n\tcmp%.l %1,%3", loperands);
1695 #else
1696       output_asm_insn ("cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1", loperands);
1697 #endif
1698 #else
1699 #ifdef SGS_CMP_ORDER
1700       output_asm_insn ("cmp%.l %0,%2\n\tjne %l4\n\tcmp%.l %1,%3", loperands);
1701 #else
1702       output_asm_insn ("cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1", loperands);
1703 #endif
1704 #endif
1705     }
1706   else
1707     {
1708       if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (loperands[0]))
1709         output_asm_insn ("tst%.l %0", loperands);
1710       else
1711         {
1712 #ifdef SGS_CMP_ORDER
1713           output_asm_insn ("cmp%.w %0,%#0", loperands);
1714 #else
1715           output_asm_insn ("cmp%.w %#0,%0", loperands);
1716 #endif
1717         }
1718
1719 #ifdef MOTOROLA
1720       output_asm_insn ("jbne %l4", loperands);
1721 #else
1722       output_asm_insn ("jne %l4", loperands);
1723 #endif
1724
1725       if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (loperands[1]))
1726         output_asm_insn ("tst%.l %1", loperands);
1727       else
1728         {
1729 #ifdef SGS_CMP_ORDER
1730           output_asm_insn ("cmp%.w %1,%#0", loperands);
1731 #else
1732           output_asm_insn ("cmp%.w %#0,%1", loperands);
1733 #endif
1734         }
1735     }
1736
1737   loperands[5] = dest;
1738   
1739   switch (op_code)
1740     {
1741       case EQ:
1742         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1743                                     CODE_LABEL_NUMBER (loperands[4]));
1744         output_asm_insn ("seq %5", loperands);
1745         break;
1746
1747       case NE:
1748         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1749                                     CODE_LABEL_NUMBER (loperands[4]));
1750         output_asm_insn ("sne %5", loperands);
1751         break;
1752
1753       case GT:
1754         loperands[6] = gen_label_rtx();
1755 #ifdef MOTOROLA
1756         output_asm_insn ("shi %5\n\tjbra %l6", loperands);
1757 #else
1758         output_asm_insn ("shi %5\n\tjra %l6", loperands);
1759 #endif
1760         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1761                                     CODE_LABEL_NUMBER (loperands[4]));
1762         output_asm_insn ("sgt %5", loperands);
1763         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1764                                     CODE_LABEL_NUMBER (loperands[6]));
1765         break;
1766
1767       case GTU:
1768         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1769                                     CODE_LABEL_NUMBER (loperands[4]));
1770         output_asm_insn ("shi %5", loperands);
1771         break;
1772
1773       case LT:
1774         loperands[6] = gen_label_rtx();
1775 #ifdef MOTOROLA
1776         output_asm_insn ("scs %5\n\tjbra %l6", loperands);
1777 #else
1778         output_asm_insn ("scs %5\n\tjra %l6", loperands);
1779 #endif
1780         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1781                                     CODE_LABEL_NUMBER (loperands[4]));
1782         output_asm_insn ("slt %5", loperands);
1783         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1784                                     CODE_LABEL_NUMBER (loperands[6]));
1785         break;
1786
1787       case LTU:
1788         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1789                                     CODE_LABEL_NUMBER (loperands[4]));
1790         output_asm_insn ("scs %5", loperands);
1791         break;
1792
1793       case GE:
1794         loperands[6] = gen_label_rtx();
1795 #ifdef MOTOROLA
1796         output_asm_insn ("scc %5\n\tjbra %l6", loperands);
1797 #else
1798         output_asm_insn ("scc %5\n\tjra %l6", loperands);
1799 #endif
1800         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1801                                     CODE_LABEL_NUMBER (loperands[4]));
1802         output_asm_insn ("sge %5", loperands);
1803         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1804                                     CODE_LABEL_NUMBER (loperands[6]));
1805         break;
1806
1807       case GEU:
1808         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1809                                     CODE_LABEL_NUMBER (loperands[4]));
1810         output_asm_insn ("scc %5", loperands);
1811         break;
1812
1813       case LE:
1814         loperands[6] = gen_label_rtx();
1815 #ifdef MOTOROLA
1816         output_asm_insn ("sls %5\n\tjbra %l6", loperands);
1817 #else
1818         output_asm_insn ("sls %5\n\tjra %l6", loperands);
1819 #endif
1820         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1821                                     CODE_LABEL_NUMBER (loperands[4]));
1822         output_asm_insn ("sle %5", loperands);
1823         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1824                                     CODE_LABEL_NUMBER (loperands[6]));
1825         break;
1826
1827       case LEU:
1828         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1829                                     CODE_LABEL_NUMBER (loperands[4]));
1830         output_asm_insn ("sls %5", loperands);
1831         break;
1832
1833       default:
1834         abort ();
1835     }
1836   return "";
1837 }
1838
1839 const char *
1840 output_btst (operands, countop, dataop, insn, signpos)
1841      rtx *operands;
1842      rtx countop, dataop;
1843      rtx insn;
1844      int signpos;
1845 {
1846   operands[0] = countop;
1847   operands[1] = dataop;
1848
1849   if (GET_CODE (countop) == CONST_INT)
1850     {
1851       register int count = INTVAL (countop);
1852       /* If COUNT is bigger than size of storage unit in use,
1853          advance to the containing unit of same size.  */
1854       if (count > signpos)
1855         {
1856           int offset = (count & ~signpos) / 8;
1857           count = count & signpos;
1858           operands[1] = dataop = adjust_address (dataop, QImode, offset);
1859         }
1860       if (count == signpos)
1861         cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
1862       else
1863         cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
1864
1865       /* These three statements used to use next_insns_test_no...
1866          but it appears that this should do the same job.  */
1867       if (count == 31
1868           && next_insn_tests_no_inequality (insn))
1869         return "tst%.l %1";
1870       if (count == 15
1871           && next_insn_tests_no_inequality (insn))
1872         return "tst%.w %1";
1873       if (count == 7
1874           && next_insn_tests_no_inequality (insn))
1875         return "tst%.b %1";
1876
1877       cc_status.flags = CC_NOT_NEGATIVE;
1878     }
1879   return "btst %0,%1";
1880 }
1881 \f
1882 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
1883    reference and a constant.  */
1884
1885 int
1886 symbolic_operand (op, mode)
1887      register rtx op;
1888      enum machine_mode mode ATTRIBUTE_UNUSED;
1889 {
1890   switch (GET_CODE (op))
1891     {
1892     case SYMBOL_REF:
1893     case LABEL_REF:
1894       return 1;
1895
1896     case CONST:
1897       op = XEXP (op, 0);
1898       return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1899                || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1900               && GET_CODE (XEXP (op, 1)) == CONST_INT);
1901
1902 #if 0 /* Deleted, with corresponding change in m68k.h,
1903          so as to fit the specs.  No CONST_DOUBLE is ever symbolic.  */
1904     case CONST_DOUBLE:
1905       return GET_MODE (op) == mode;
1906 #endif
1907
1908     default:
1909       return 0;
1910     }
1911 }
1912 \f
1913 /* Check for sign_extend or zero_extend.  Used for bit-count operands. */
1914
1915 int
1916 extend_operator(x, mode)
1917      rtx x;
1918      enum machine_mode mode;
1919 {
1920     if (mode != VOIDmode && GET_MODE(x) != mode)
1921         return 0;
1922     switch (GET_CODE(x))
1923         {
1924         case SIGN_EXTEND :
1925         case ZERO_EXTEND :
1926             return 1;
1927         default :
1928             return 0;
1929         }
1930 }
1931
1932 \f
1933 /* Legitimize PIC addresses.  If the address is already
1934    position-independent, we return ORIG.  Newly generated
1935    position-independent addresses go to REG.  If we need more
1936    than one register, we lose.  
1937
1938    An address is legitimized by making an indirect reference
1939    through the Global Offset Table with the name of the symbol
1940    used as an offset.  
1941
1942    The assembler and linker are responsible for placing the 
1943    address of the symbol in the GOT.  The function prologue
1944    is responsible for initializing a5 to the starting address
1945    of the GOT.
1946
1947    The assembler is also responsible for translating a symbol name
1948    into a constant displacement from the start of the GOT.  
1949
1950    A quick example may make things a little clearer:
1951
1952    When not generating PIC code to store the value 12345 into _foo
1953    we would generate the following code:
1954
1955         movel #12345, _foo
1956
1957    When generating PIC two transformations are made.  First, the compiler
1958    loads the address of foo into a register.  So the first transformation makes:
1959
1960         lea     _foo, a0
1961         movel   #12345, a0@
1962
1963    The code in movsi will intercept the lea instruction and call this
1964    routine which will transform the instructions into:
1965
1966         movel   a5@(_foo:w), a0
1967         movel   #12345, a0@
1968    
1969
1970    That (in a nutshell) is how *all* symbol and label references are 
1971    handled.  */
1972
1973 rtx
1974 legitimize_pic_address (orig, mode, reg)
1975      rtx orig, reg;
1976      enum machine_mode mode ATTRIBUTE_UNUSED;
1977 {
1978   rtx pic_ref = orig;
1979
1980   /* First handle a simple SYMBOL_REF or LABEL_REF */
1981   if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
1982     {
1983       if (reg == 0)
1984         abort ();
1985
1986       pic_ref = gen_rtx_MEM (Pmode,
1987                              gen_rtx_PLUS (Pmode,
1988                                            pic_offset_table_rtx, orig));
1989       current_function_uses_pic_offset_table = 1;
1990       RTX_UNCHANGING_P (pic_ref) = 1;
1991       emit_move_insn (reg, pic_ref);
1992       return reg;
1993     }
1994   else if (GET_CODE (orig) == CONST)
1995     {
1996       rtx base;
1997
1998       /* Make sure this is CONST has not already been legitimized */
1999       if (GET_CODE (XEXP (orig, 0)) == PLUS
2000           && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
2001         return orig;
2002
2003       if (reg == 0)
2004         abort ();
2005
2006       /* legitimize both operands of the PLUS */
2007       if (GET_CODE (XEXP (orig, 0)) == PLUS)
2008         {
2009           base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
2010           orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
2011                                          base == reg ? 0 : reg);
2012         }
2013       else abort ();
2014
2015       if (GET_CODE (orig) == CONST_INT)
2016         return plus_constant (base, INTVAL (orig));
2017       pic_ref = gen_rtx_PLUS (Pmode, base, orig);
2018       /* Likewise, should we set special REG_NOTEs here?  */
2019     }
2020   return pic_ref;
2021 }
2022
2023 \f
2024 typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ } CONST_METHOD;
2025
2026 static CONST_METHOD const_method PARAMS ((rtx));
2027
2028 #define USE_MOVQ(i)     ((unsigned)((i) + 128) <= 255)
2029
2030 static CONST_METHOD
2031 const_method (constant)
2032      rtx constant;
2033 {
2034   int i;
2035   unsigned u;
2036
2037   i = INTVAL (constant);
2038   if (USE_MOVQ (i))
2039     return MOVQ;
2040
2041   /* The Coldfire doesn't have byte or word operations. */
2042   /* FIXME: This may not be useful for the m68060 either */
2043   if (!TARGET_5200) 
2044     {
2045       /* if -256 < N < 256 but N is not in range for a moveq
2046          N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */
2047       if (USE_MOVQ (i ^ 0xff))
2048         return NOTB;
2049       /* Likewise, try with not.w */
2050       if (USE_MOVQ (i ^ 0xffff))
2051         return NOTW;
2052       /* This is the only value where neg.w is useful */
2053       if (i == -65408)
2054         return NEGW;
2055       /* Try also with swap */
2056       u = i;
2057       if (USE_MOVQ ((u >> 16) | (u << 16)))
2058         return SWAP;
2059     }
2060   /* Otherwise, use move.l */
2061   return MOVL;
2062 }
2063
2064 int
2065 const_int_cost (constant)
2066      rtx constant;
2067 {
2068   switch (const_method (constant))
2069     {
2070       case MOVQ :
2071       /* Constants between -128 and 127 are cheap due to moveq */
2072         return 0;
2073       case NOTB :
2074       case NOTW :
2075       case NEGW :
2076       case SWAP :
2077       /* Constants easily generated by moveq + not.b/not.w/neg.w/swap  */
2078         return 1;
2079       case MOVL :
2080         return 2;
2081       default :
2082         abort ();
2083     }
2084 }
2085
2086 const char *
2087 output_move_const_into_data_reg (operands)
2088      rtx *operands;
2089 {
2090   int i;
2091
2092   i = INTVAL (operands[1]);
2093   switch (const_method (operands[1]))
2094     {
2095     case MOVQ :
2096 #if defined (MOTOROLA) && !defined (CRDS)
2097       return "moveq%.l %1,%0";
2098 #else
2099       return "moveq %1,%0";
2100 #endif
2101     case NOTB :
2102       operands[1] = GEN_INT (i ^ 0xff);
2103 #if defined (MOTOROLA) && !defined (CRDS)
2104       return "moveq%.l %1,%0\n\tnot%.b %0";
2105 #else
2106       return "moveq %1,%0\n\tnot%.b %0";
2107 #endif   
2108     case NOTW :
2109       operands[1] = GEN_INT (i ^ 0xffff);
2110 #if defined (MOTOROLA) && !defined (CRDS)
2111       return "moveq%.l %1,%0\n\tnot%.w %0";
2112 #else
2113       return "moveq %1,%0\n\tnot%.w %0";
2114 #endif   
2115     case NEGW :
2116 #if defined (MOTOROLA) && !defined (CRDS)
2117       return "moveq%.l %#-128,%0\n\tneg%.w %0";
2118 #else
2119       return "moveq %#-128,%0\n\tneg%.w %0";
2120 #endif   
2121     case SWAP :
2122       {
2123         unsigned u = i;
2124
2125         operands[1] = GEN_INT ((u << 16) | (u >> 16));
2126 #if defined (MOTOROLA) && !defined (CRDS)
2127         return "moveq%.l %1,%0\n\tswap %0";
2128 #else
2129         return "moveq %1,%0\n\tswap %0";
2130 #endif   
2131       }
2132     case MOVL :
2133         return "move%.l %1,%0";
2134     default :
2135         abort ();
2136     }
2137 }
2138
2139 const char *
2140 output_move_simode_const (operands)
2141      rtx *operands;
2142 {
2143   if (operands[1] == const0_rtx
2144       && (DATA_REG_P (operands[0])
2145           || GET_CODE (operands[0]) == MEM)
2146       /* clr insns on 68000 read before writing.
2147          This isn't so on the 68010, but we have no TARGET_68010.  */
2148       && ((TARGET_68020 || TARGET_5200)
2149           || !(GET_CODE (operands[0]) == MEM
2150                && MEM_VOLATILE_P (operands[0]))))
2151     return "clr%.l %0";
2152   else if (operands[1] == const0_rtx
2153            && ADDRESS_REG_P (operands[0]))
2154     return "sub%.l %0,%0";
2155   else if (DATA_REG_P (operands[0]))
2156     return output_move_const_into_data_reg (operands);
2157   else if (ADDRESS_REG_P (operands[0])
2158            && INTVAL (operands[1]) < 0x8000
2159            && INTVAL (operands[1]) >= -0x8000)
2160     return "move%.w %1,%0";
2161   else if (GET_CODE (operands[0]) == MEM
2162       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
2163       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
2164            && INTVAL (operands[1]) < 0x8000
2165            && INTVAL (operands[1]) >= -0x8000)
2166     return "pea %a1";
2167   return "move%.l %1,%0";
2168 }
2169
2170 const char *
2171 output_move_simode (operands)
2172      rtx *operands;
2173 {
2174   if (GET_CODE (operands[1]) == CONST_INT)
2175     return output_move_simode_const (operands);
2176   else if ((GET_CODE (operands[1]) == SYMBOL_REF
2177             || GET_CODE (operands[1]) == CONST)
2178            && push_operand (operands[0], SImode))
2179     return "pea %a1";
2180   else if ((GET_CODE (operands[1]) == SYMBOL_REF
2181             || GET_CODE (operands[1]) == CONST)
2182            && ADDRESS_REG_P (operands[0]))
2183     return "lea %a1,%0";
2184   return "move%.l %1,%0";
2185 }
2186
2187 const char *
2188 output_move_himode (operands)
2189      rtx *operands;
2190 {
2191  if (GET_CODE (operands[1]) == CONST_INT)
2192     {
2193       if (operands[1] == const0_rtx
2194           && (DATA_REG_P (operands[0])
2195               || GET_CODE (operands[0]) == MEM)
2196           /* clr insns on 68000 read before writing.
2197              This isn't so on the 68010, but we have no TARGET_68010.  */
2198           && ((TARGET_68020 || TARGET_5200)
2199               || !(GET_CODE (operands[0]) == MEM
2200                    && MEM_VOLATILE_P (operands[0]))))
2201         return "clr%.w %0";
2202       else if (operands[1] == const0_rtx
2203                && ADDRESS_REG_P (operands[0]))
2204         return "sub%.l %0,%0";
2205       else if (DATA_REG_P (operands[0])
2206                && INTVAL (operands[1]) < 128
2207                && INTVAL (operands[1]) >= -128)
2208         {
2209 #if defined(MOTOROLA) && !defined(CRDS)
2210           return "moveq%.l %1,%0";
2211 #else
2212           return "moveq %1,%0";
2213 #endif
2214         }
2215       else if (INTVAL (operands[1]) < 0x8000
2216                && INTVAL (operands[1]) >= -0x8000)
2217         return "move%.w %1,%0";
2218     }
2219   else if (CONSTANT_P (operands[1]))
2220     return "move%.l %1,%0";
2221 #ifndef SGS_NO_LI
2222   /* Recognize the insn before a tablejump, one that refers
2223      to a table of offsets.  Such an insn will need to refer
2224      to a label on the insn.  So output one.  Use the label-number
2225      of the table of offsets to generate this label.  This code,
2226      and similar code below, assumes that there will be at most one
2227      reference to each table.  */
2228   if (GET_CODE (operands[1]) == MEM
2229       && GET_CODE (XEXP (operands[1], 0)) == PLUS
2230       && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF
2231       && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS)
2232     {
2233       rtx labelref = XEXP (XEXP (operands[1], 0), 1);
2234 #if defined (MOTOROLA) && !defined (SGS_SWITCH_TABLES)
2235 #ifdef SGS
2236       asm_fprintf (asm_out_file, "\tset %LLI%d,.+2\n",
2237                    CODE_LABEL_NUMBER (XEXP (labelref, 0)));
2238 #else /* not SGS */
2239       asm_fprintf (asm_out_file, "\t.set %LLI%d,.+2\n",
2240                    CODE_LABEL_NUMBER (XEXP (labelref, 0)));
2241 #endif /* not SGS */
2242 #else /* SGS_SWITCH_TABLES or not MOTOROLA */
2243       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LI",
2244                                  CODE_LABEL_NUMBER (XEXP (labelref, 0)));
2245 #ifdef SGS_SWITCH_TABLES
2246       /* Set flag saying we need to define the symbol
2247          LD%n (with value L%n-LI%n) at the end of the switch table.  */
2248       switch_table_difference_label_flag = 1;
2249 #endif /* SGS_SWITCH_TABLES */
2250 #endif /* SGS_SWITCH_TABLES or not MOTOROLA */
2251     }
2252 #endif /* SGS_NO_LI */
2253   return "move%.w %1,%0";
2254 }
2255
2256 const char *
2257 output_move_qimode (operands)
2258      rtx *operands;
2259 {
2260   rtx xoperands[4];
2261
2262   /* This is probably useless, since it loses for pushing a struct
2263      of several bytes a byte at a time.  */
2264   /* 68k family always modifies the stack pointer by at least 2, even for
2265      byte pushes.  The 5200 (coldfire) does not do this.  */
2266   if (GET_CODE (operands[0]) == MEM
2267       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
2268       && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx
2269       && ! ADDRESS_REG_P (operands[1])
2270       && ! TARGET_5200)
2271     {
2272       xoperands[1] = operands[1];
2273       xoperands[2]
2274         = gen_rtx_MEM (QImode,
2275                        gen_rtx_PLUS (VOIDmode, stack_pointer_rtx, const1_rtx));
2276       /* Just pushing a byte puts it in the high byte of the halfword.  */
2277       /* We must put it in the low-order, high-numbered byte.  */
2278       if (!reg_mentioned_p (stack_pointer_rtx, operands[1]))
2279         {
2280           xoperands[3] = stack_pointer_rtx;
2281 #ifndef NO_ADDSUB_Q
2282           output_asm_insn ("subq%.l %#2,%3\n\tmove%.b %1,%2", xoperands);
2283 #else
2284           output_asm_insn ("sub%.l %#2,%3\n\tmove%.b %1,%2", xoperands);
2285 #endif
2286         }
2287       else
2288         output_asm_insn ("move%.b %1,%-\n\tmove%.b %@,%2", xoperands);
2289       return "";
2290     }
2291
2292   /* clr and st insns on 68000 read before writing.
2293      This isn't so on the 68010, but we have no TARGET_68010.  */
2294   if (!ADDRESS_REG_P (operands[0])
2295       && ((TARGET_68020 || TARGET_5200)
2296           || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
2297     {
2298       if (operands[1] == const0_rtx)
2299         return "clr%.b %0";
2300       if ((!TARGET_5200 || DATA_REG_P (operands[0]))
2301           && GET_CODE (operands[1]) == CONST_INT
2302           && (INTVAL (operands[1]) & 255) == 255)
2303         {
2304           CC_STATUS_INIT;
2305           return "st %0";
2306         }
2307     }
2308   if (GET_CODE (operands[1]) == CONST_INT
2309       && DATA_REG_P (operands[0])
2310       && INTVAL (operands[1]) < 128
2311       && INTVAL (operands[1]) >= -128)
2312     {
2313 #if defined(MOTOROLA) && !defined(CRDS)
2314       return "moveq%.l %1,%0";
2315 #else
2316       return "moveq %1,%0";
2317 #endif
2318     }
2319   if (operands[1] == const0_rtx && ADDRESS_REG_P (operands[0]))
2320     return "sub%.l %0,%0";
2321   if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
2322     return "move%.l %1,%0";
2323   /* 68k family (including the 5200 coldfire) does not support byte moves to
2324      from address registers.  */
2325   if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1]))
2326     return "move%.w %1,%0";
2327   return "move%.b %1,%0";
2328 }
2329
2330 const char *
2331 output_move_stricthi (operands)
2332      rtx *operands;
2333 {
2334   if (operands[1] == const0_rtx
2335       /* clr insns on 68000 read before writing.
2336          This isn't so on the 68010, but we have no TARGET_68010.  */
2337       && ((TARGET_68020 || TARGET_5200)
2338           || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
2339     return "clr%.w %0";
2340   return "move%.w %1,%0";
2341 }
2342
2343 const char *
2344 output_move_strictqi (operands)
2345      rtx *operands;
2346 {
2347   if (operands[1] == const0_rtx
2348       /* clr insns on 68000 read before writing.
2349          This isn't so on the 68010, but we have no TARGET_68010.  */
2350       && ((TARGET_68020 || TARGET_5200)
2351           || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
2352     return "clr%.b %0";
2353   return "move%.b %1,%0";
2354 }
2355
2356 /* Return the best assembler insn template
2357    for moving operands[1] into operands[0] as a fullword.  */
2358
2359 static const char *
2360 singlemove_string (operands)
2361      rtx *operands;
2362 {
2363 #ifdef SUPPORT_SUN_FPA
2364   if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
2365     return "fpmoves %1,%0";
2366 #endif
2367   if (GET_CODE (operands[1]) == CONST_INT)
2368     return output_move_simode_const (operands);
2369   return "move%.l %1,%0";
2370 }
2371
2372
2373 /* Output assembler code to perform a doubleword move insn
2374    with operands OPERANDS.  */
2375
2376 const char *
2377 output_move_double (operands)
2378      rtx *operands;
2379 {
2380   enum
2381     {
2382       REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP
2383     } optype0, optype1;
2384   rtx latehalf[2];
2385   rtx middlehalf[2];
2386   rtx xops[2];
2387   rtx addreg0 = 0, addreg1 = 0;
2388   int dest_overlapped_low = 0;
2389   int size = GET_MODE_SIZE (GET_MODE (operands[0]));
2390
2391   middlehalf[0] = 0;
2392   middlehalf[1] = 0;
2393
2394   /* First classify both operands.  */
2395
2396   if (REG_P (operands[0]))
2397     optype0 = REGOP;
2398   else if (offsettable_memref_p (operands[0]))
2399     optype0 = OFFSOP;
2400   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
2401     optype0 = POPOP;
2402   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
2403     optype0 = PUSHOP;
2404   else if (GET_CODE (operands[0]) == MEM)
2405     optype0 = MEMOP;
2406   else
2407     optype0 = RNDOP;
2408
2409   if (REG_P (operands[1]))
2410     optype1 = REGOP;
2411   else if (CONSTANT_P (operands[1]))
2412     optype1 = CNSTOP;
2413   else if (offsettable_memref_p (operands[1]))
2414     optype1 = OFFSOP;
2415   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
2416     optype1 = POPOP;
2417   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
2418     optype1 = PUSHOP;
2419   else if (GET_CODE (operands[1]) == MEM)
2420     optype1 = MEMOP;
2421   else
2422     optype1 = RNDOP;
2423
2424   /* Check for the cases that the operand constraints are not
2425      supposed to allow to happen.  Abort if we get one,
2426      because generating code for these cases is painful.  */
2427
2428   if (optype0 == RNDOP || optype1 == RNDOP)
2429     abort ();
2430
2431   /* If one operand is decrementing and one is incrementing
2432      decrement the former register explicitly
2433      and change that operand into ordinary indexing.  */
2434
2435   if (optype0 == PUSHOP && optype1 == POPOP)
2436     {
2437       operands[0] = XEXP (XEXP (operands[0], 0), 0);
2438       if (size == 12)
2439         output_asm_insn ("sub%.l %#12,%0", operands);
2440       else
2441         output_asm_insn ("subq%.l %#8,%0", operands);
2442       if (GET_MODE (operands[1]) == XFmode)
2443         operands[0] = gen_rtx_MEM (XFmode, operands[0]);
2444       else if (GET_MODE (operands[0]) == DFmode)
2445         operands[0] = gen_rtx_MEM (DFmode, operands[0]);
2446       else
2447         operands[0] = gen_rtx_MEM (DImode, operands[0]);
2448       optype0 = OFFSOP;
2449     }
2450   if (optype0 == POPOP && optype1 == PUSHOP)
2451     {
2452       operands[1] = XEXP (XEXP (operands[1], 0), 0);
2453       if (size == 12)
2454         output_asm_insn ("sub%.l %#12,%1", operands);
2455       else
2456         output_asm_insn ("subq%.l %#8,%1", operands);
2457       if (GET_MODE (operands[1]) == XFmode)
2458         operands[1] = gen_rtx_MEM (XFmode, operands[1]);
2459       else if (GET_MODE (operands[1]) == DFmode)
2460         operands[1] = gen_rtx_MEM (DFmode, operands[1]);
2461       else
2462         operands[1] = gen_rtx_MEM (DImode, operands[1]);
2463       optype1 = OFFSOP;
2464     }
2465
2466   /* If an operand is an unoffsettable memory ref, find a register
2467      we can increment temporarily to make it refer to the second word.  */
2468
2469   if (optype0 == MEMOP)
2470     addreg0 = find_addr_reg (XEXP (operands[0], 0));
2471
2472   if (optype1 == MEMOP)
2473     addreg1 = find_addr_reg (XEXP (operands[1], 0));
2474
2475   /* Ok, we can do one word at a time.
2476      Normally we do the low-numbered word first,
2477      but if either operand is autodecrementing then we
2478      do the high-numbered word first.
2479
2480      In either case, set up in LATEHALF the operands to use
2481      for the high-numbered word and in some cases alter the
2482      operands in OPERANDS to be suitable for the low-numbered word.  */
2483
2484   if (size == 12)
2485     {
2486       if (optype0 == REGOP)
2487         {
2488           latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
2489           middlehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
2490         }
2491       else if (optype0 == OFFSOP)
2492         {
2493           middlehalf[0] = adjust_address (operands[0], SImode, 4);
2494           latehalf[0] = adjust_address (operands[0], SImode, size - 4);
2495         }
2496       else
2497         {
2498           middlehalf[0] = operands[0];
2499           latehalf[0] = operands[0];
2500         }
2501
2502       if (optype1 == REGOP)
2503         {
2504           latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
2505           middlehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
2506         }
2507       else if (optype1 == OFFSOP)
2508         {
2509           middlehalf[1] = adjust_address (operands[1], SImode, 4);
2510           latehalf[1] = adjust_address (operands[1], SImode, size - 4);
2511         }
2512       else if (optype1 == CNSTOP)
2513         {
2514           if (GET_CODE (operands[1]) == CONST_DOUBLE)
2515             {
2516               REAL_VALUE_TYPE r;
2517               long l[3];
2518
2519               REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2520               REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
2521               operands[1] = GEN_INT (l[0]);
2522               middlehalf[1] = GEN_INT (l[1]);
2523               latehalf[1] = GEN_INT (l[2]);
2524             }
2525           else if (CONSTANT_P (operands[1]))
2526             {
2527               /* actually, no non-CONST_DOUBLE constant should ever
2528                  appear here.  */
2529               abort ();
2530               if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
2531                 latehalf[1] = constm1_rtx;
2532               else
2533                 latehalf[1] = const0_rtx;
2534             }
2535         }
2536       else
2537         {
2538           middlehalf[1] = operands[1];
2539           latehalf[1] = operands[1];
2540         }
2541     }
2542   else
2543     /* size is not 12: */
2544     {
2545       if (optype0 == REGOP)
2546         latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
2547       else if (optype0 == OFFSOP)
2548         latehalf[0] = adjust_address (operands[0], SImode, size - 4);
2549       else
2550         latehalf[0] = operands[0];
2551
2552       if (optype1 == REGOP)
2553         latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
2554       else if (optype1 == OFFSOP)
2555         latehalf[1] = adjust_address (operands[1], SImode, size - 4);
2556       else if (optype1 == CNSTOP)
2557         split_double (operands[1], &operands[1], &latehalf[1]);
2558       else
2559         latehalf[1] = operands[1];
2560     }
2561
2562   /* If insn is effectively movd N(sp),-(sp) then we will do the
2563      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
2564      for the low word as well, to compensate for the first decrement of sp.  */
2565   if (optype0 == PUSHOP
2566       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
2567       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
2568     operands[1] = middlehalf[1] = latehalf[1];
2569
2570   /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
2571      if the upper part of reg N does not appear in the MEM, arrange to
2572      emit the move late-half first.  Otherwise, compute the MEM address
2573      into the upper part of N and use that as a pointer to the memory
2574      operand.  */
2575   if (optype0 == REGOP
2576       && (optype1 == OFFSOP || optype1 == MEMOP))
2577     {
2578       rtx testlow = gen_rtx_REG (SImode, REGNO (operands[0]));
2579
2580       if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
2581           && reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
2582         {
2583           /* If both halves of dest are used in the src memory address,
2584              compute the address into latehalf of dest.
2585              Note that this can't happen if the dest is two data regs.  */
2586 compadr:
2587           xops[0] = latehalf[0];
2588           xops[1] = XEXP (operands[1], 0);
2589           output_asm_insn ("lea %a1,%0", xops);
2590           if (GET_MODE (operands[1]) == XFmode )
2591             {
2592               operands[1] = gen_rtx_MEM (XFmode, latehalf[0]);
2593               middlehalf[1] = adjust_address (operands[1], DImode, size - 8);
2594               latehalf[1] = adjust_address (operands[1], DImode, size - 4);
2595             }
2596           else
2597             {
2598               operands[1] = gen_rtx_MEM (DImode, latehalf[0]);
2599               latehalf[1] = adjust_address (operands[1], DImode, size - 4);
2600             }
2601         }
2602       else if (size == 12
2603                && reg_overlap_mentioned_p (middlehalf[0],
2604                                            XEXP (operands[1], 0)))
2605         {
2606           /* Check for two regs used by both source and dest.
2607              Note that this can't happen if the dest is all data regs.
2608              It can happen if the dest is d6, d7, a0.
2609              But in that case, latehalf is an addr reg, so
2610              the code at compadr does ok.  */
2611
2612           if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
2613               || reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
2614             goto compadr;
2615
2616           /* JRV says this can't happen: */
2617           if (addreg0 || addreg1)
2618             abort ();
2619
2620           /* Only the middle reg conflicts; simply put it last. */
2621           output_asm_insn (singlemove_string (operands), operands);
2622           output_asm_insn (singlemove_string (latehalf), latehalf);
2623           output_asm_insn (singlemove_string (middlehalf), middlehalf);
2624           return "";
2625         }
2626       else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)))
2627         /* If the low half of dest is mentioned in the source memory
2628            address, the arrange to emit the move late half first.  */
2629         dest_overlapped_low = 1;
2630     }
2631
2632   /* If one or both operands autodecrementing,
2633      do the two words, high-numbered first.  */
2634
2635   /* Likewise,  the first move would clobber the source of the second one,
2636      do them in the other order.  This happens only for registers;
2637      such overlap can't happen in memory unless the user explicitly
2638      sets it up, and that is an undefined circumstance.  */
2639
2640   if (optype0 == PUSHOP || optype1 == PUSHOP
2641       || (optype0 == REGOP && optype1 == REGOP
2642           && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1]))
2643               || REGNO (operands[0]) == REGNO (latehalf[1])))
2644       || dest_overlapped_low)
2645     {
2646       /* Make any unoffsettable addresses point at high-numbered word.  */
2647       if (addreg0)
2648         {
2649           if (size == 12)
2650             output_asm_insn ("addq%.l %#8,%0", &addreg0);
2651           else
2652             output_asm_insn ("addq%.l %#4,%0", &addreg0);
2653         }
2654       if (addreg1)
2655         {
2656           if (size == 12)
2657             output_asm_insn ("addq%.l %#8,%0", &addreg1);
2658           else
2659             output_asm_insn ("addq%.l %#4,%0", &addreg1);
2660         }
2661
2662       /* Do that word.  */
2663       output_asm_insn (singlemove_string (latehalf), latehalf);
2664
2665       /* Undo the adds we just did.  */
2666       if (addreg0)
2667         output_asm_insn ("subq%.l %#4,%0", &addreg0);
2668       if (addreg1)
2669         output_asm_insn ("subq%.l %#4,%0", &addreg1);
2670
2671       if (size == 12)
2672         {
2673           output_asm_insn (singlemove_string (middlehalf), middlehalf);
2674           if (addreg0)
2675             output_asm_insn ("subq%.l %#4,%0", &addreg0);
2676           if (addreg1)
2677             output_asm_insn ("subq%.l %#4,%0", &addreg1);
2678         }
2679
2680       /* Do low-numbered word.  */
2681       return singlemove_string (operands);
2682     }
2683
2684   /* Normal case: do the two words, low-numbered first.  */
2685
2686   output_asm_insn (singlemove_string (operands), operands);
2687
2688   /* Do the middle one of the three words for long double */
2689   if (size == 12)
2690     {
2691       if (addreg0)
2692         output_asm_insn ("addq%.l %#4,%0", &addreg0);
2693       if (addreg1)
2694         output_asm_insn ("addq%.l %#4,%0", &addreg1);
2695
2696       output_asm_insn (singlemove_string (middlehalf), middlehalf);
2697     }
2698
2699   /* Make any unoffsettable addresses point at high-numbered word.  */
2700   if (addreg0)
2701     output_asm_insn ("addq%.l %#4,%0", &addreg0);
2702   if (addreg1)
2703     output_asm_insn ("addq%.l %#4,%0", &addreg1);
2704
2705   /* Do that word.  */
2706   output_asm_insn (singlemove_string (latehalf), latehalf);
2707
2708   /* Undo the adds we just did.  */
2709   if (addreg0)
2710     {
2711       if (size == 12)
2712         output_asm_insn ("subq%.l %#8,%0", &addreg0);
2713       else
2714         output_asm_insn ("subq%.l %#4,%0", &addreg0);
2715     }
2716   if (addreg1)
2717     {
2718       if (size == 12)
2719         output_asm_insn ("subq%.l %#8,%0", &addreg1);
2720       else
2721         output_asm_insn ("subq%.l %#4,%0", &addreg1);
2722     }
2723
2724   return "";
2725 }
2726
2727 /* Return a REG that occurs in ADDR with coefficient 1.
2728    ADDR can be effectively incremented by incrementing REG.  */
2729
2730 static rtx
2731 find_addr_reg (addr)
2732      rtx addr;
2733 {
2734   while (GET_CODE (addr) == PLUS)
2735     {
2736       if (GET_CODE (XEXP (addr, 0)) == REG)
2737         addr = XEXP (addr, 0);
2738       else if (GET_CODE (XEXP (addr, 1)) == REG)
2739         addr = XEXP (addr, 1);
2740       else if (CONSTANT_P (XEXP (addr, 0)))
2741         addr = XEXP (addr, 1);
2742       else if (CONSTANT_P (XEXP (addr, 1)))
2743         addr = XEXP (addr, 0);
2744       else
2745         abort ();
2746     }
2747   if (GET_CODE (addr) == REG)
2748     return addr;
2749   abort ();
2750 }
2751
2752 /* Output assembler code to perform a 32 bit 3 operand add.  */
2753
2754 const char *
2755 output_addsi3 (operands)
2756      rtx *operands;
2757 {
2758   if (! operands_match_p (operands[0], operands[1]))
2759     {
2760       if (!ADDRESS_REG_P (operands[1]))
2761         {
2762           rtx tmp = operands[1];
2763
2764           operands[1] = operands[2];
2765           operands[2] = tmp;
2766         }
2767
2768       /* These insns can result from reloads to access
2769          stack slots over 64k from the frame pointer.  */
2770       if (GET_CODE (operands[2]) == CONST_INT
2771           && INTVAL (operands[2]) + 0x8000 >= (unsigned) 0x10000)
2772         return "move%.l %2,%0\n\tadd%.l %1,%0";
2773 #ifdef SGS
2774       if (GET_CODE (operands[2]) == REG)
2775         return "lea 0(%1,%2.l),%0";
2776       else
2777         return "lea %c2(%1),%0";
2778 #else /* not SGS */
2779 #ifdef MOTOROLA
2780       if (GET_CODE (operands[2]) == REG)
2781         return "lea (%1,%2.l),%0";
2782       else
2783         return "lea (%c2,%1),%0";
2784 #else /* not MOTOROLA (MIT syntax) */
2785       if (GET_CODE (operands[2]) == REG)
2786         return "lea %1@(0,%2:l),%0";
2787       else
2788         return "lea %1@(%c2),%0";
2789 #endif /* not MOTOROLA */
2790 #endif /* not SGS */
2791     }
2792   if (GET_CODE (operands[2]) == CONST_INT)
2793     {
2794 #ifndef NO_ADDSUB_Q
2795       if (INTVAL (operands[2]) > 0
2796           && INTVAL (operands[2]) <= 8)
2797         return "addq%.l %2,%0";
2798       if (INTVAL (operands[2]) < 0
2799           && INTVAL (operands[2]) >= -8)
2800         {
2801           operands[2] = GEN_INT (- INTVAL (operands[2]));
2802           return "subq%.l %2,%0";
2803         }
2804       /* On the CPU32 it is faster to use two addql instructions to
2805          add a small integer (8 < N <= 16) to a register.
2806          Likewise for subql. */
2807       if (TARGET_CPU32 && REG_P (operands[0]))
2808         {
2809           if (INTVAL (operands[2]) > 8
2810               && INTVAL (operands[2]) <= 16)
2811             {
2812               operands[2] = GEN_INT (INTVAL (operands[2]) - 8);
2813               return "addq%.l %#8,%0\n\taddq%.l %2,%0";
2814             }
2815           if (INTVAL (operands[2]) < -8
2816               && INTVAL (operands[2]) >= -16)
2817             {
2818               operands[2] = GEN_INT (- INTVAL (operands[2]) - 8);
2819               return "subq%.l %#8,%0\n\tsubq%.l %2,%0";
2820             }
2821         }
2822 #endif
2823       if (ADDRESS_REG_P (operands[0])
2824           && INTVAL (operands[2]) >= -0x8000
2825           && INTVAL (operands[2]) < 0x8000)
2826         {
2827           if (TARGET_68040)
2828             return "add%.w %2,%0";
2829           else
2830 #ifdef MOTOROLA  
2831             return "lea (%c2,%0),%0";
2832 #else
2833             return "lea %0@(%c2),%0";
2834 #endif
2835         }
2836     }
2837   return "add%.l %2,%0";
2838 }
2839 \f
2840 /* Store in cc_status the expressions that the condition codes will
2841    describe after execution of an instruction whose pattern is EXP.
2842    Do not alter them if the instruction would not alter the cc's.  */
2843
2844 /* On the 68000, all the insns to store in an address register fail to
2845    set the cc's.  However, in some cases these instructions can make it
2846    possibly invalid to use the saved cc's.  In those cases we clear out
2847    some or all of the saved cc's so they won't be used.  */
2848
2849 void
2850 notice_update_cc (exp, insn)
2851      rtx exp;
2852      rtx insn;
2853 {
2854   /* If the cc is being set from the fpa and the expression is not an
2855      explicit floating point test instruction (which has code to deal with
2856      this), reinit the CC.  */
2857   if (((cc_status.value1 && FPA_REG_P (cc_status.value1))
2858        || (cc_status.value2 && FPA_REG_P (cc_status.value2)))
2859       && !(GET_CODE (exp) == PARALLEL
2860            && GET_CODE (XVECEXP (exp, 0, 0)) == SET
2861            && XEXP (XVECEXP (exp, 0, 0), 0) == cc0_rtx))
2862     {
2863       CC_STATUS_INIT; 
2864     }
2865   else if (GET_CODE (exp) == SET)
2866     {
2867       if (GET_CODE (SET_SRC (exp)) == CALL)
2868         {
2869           CC_STATUS_INIT; 
2870         }
2871       else if (ADDRESS_REG_P (SET_DEST (exp)))
2872         {
2873           if (cc_status.value1 && modified_in_p (cc_status.value1, insn))
2874             cc_status.value1 = 0;
2875           if (cc_status.value2 && modified_in_p (cc_status.value2, insn))
2876             cc_status.value2 = 0; 
2877         }
2878       else if (!FP_REG_P (SET_DEST (exp))
2879                && SET_DEST (exp) != cc0_rtx
2880                && (FP_REG_P (SET_SRC (exp))
2881                    || GET_CODE (SET_SRC (exp)) == FIX
2882                    || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE
2883                    || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND))
2884         {
2885           CC_STATUS_INIT; 
2886         }
2887       /* A pair of move insns doesn't produce a useful overall cc.  */
2888       else if (!FP_REG_P (SET_DEST (exp))
2889                && !FP_REG_P (SET_SRC (exp))
2890                && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
2891                && (GET_CODE (SET_SRC (exp)) == REG
2892                    || GET_CODE (SET_SRC (exp)) == MEM
2893                    || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
2894         {
2895           CC_STATUS_INIT; 
2896         }
2897       else if (GET_CODE (SET_SRC (exp)) == CALL)
2898         {
2899           CC_STATUS_INIT; 
2900         }
2901       else if (XEXP (exp, 0) != pc_rtx)
2902         {
2903           cc_status.flags = 0;
2904           cc_status.value1 = XEXP (exp, 0);
2905           cc_status.value2 = XEXP (exp, 1);
2906         }
2907     }
2908   else if (GET_CODE (exp) == PARALLEL
2909            && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
2910     {
2911       if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0)))
2912         CC_STATUS_INIT;
2913       else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx)
2914         {
2915           cc_status.flags = 0;
2916           cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
2917           cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
2918         }
2919     }
2920   else
2921     CC_STATUS_INIT;
2922   if (cc_status.value2 != 0
2923       && ADDRESS_REG_P (cc_status.value2)
2924       && GET_MODE (cc_status.value2) == QImode)
2925     CC_STATUS_INIT;
2926   if (cc_status.value2 != 0
2927       && !(cc_status.value1 && FPA_REG_P (cc_status.value1)))
2928     switch (GET_CODE (cc_status.value2))
2929       {
2930       case PLUS: case MINUS: case MULT:
2931       case DIV: case UDIV: case MOD: case UMOD: case NEG:
2932 #if 0 /* These instructions always clear the overflow bit */
2933       case ASHIFT: case ASHIFTRT: case LSHIFTRT:
2934       case ROTATE: case ROTATERT:
2935 #endif
2936         if (GET_MODE (cc_status.value2) != VOIDmode)
2937           cc_status.flags |= CC_NO_OVERFLOW;
2938         break;
2939       case ZERO_EXTEND:
2940         /* (SET r1 (ZERO_EXTEND r2)) on this machine
2941            ends with a move insn moving r2 in r2's mode.
2942            Thus, the cc's are set for r2.
2943            This can set N bit spuriously. */
2944         cc_status.flags |= CC_NOT_NEGATIVE; 
2945
2946       default:
2947         break;
2948       }
2949   if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
2950       && cc_status.value2
2951       && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
2952     cc_status.value2 = 0;
2953   if (((cc_status.value1 && FP_REG_P (cc_status.value1))
2954        || (cc_status.value2 && FP_REG_P (cc_status.value2)))
2955       && !((cc_status.value1 && FPA_REG_P (cc_status.value1))
2956            || (cc_status.value2 && FPA_REG_P (cc_status.value2))))
2957     cc_status.flags = CC_IN_68881;
2958 }
2959 \f
2960 const char *
2961 output_move_const_double (operands)
2962      rtx *operands;
2963 {
2964 #ifdef SUPPORT_SUN_FPA
2965   if (TARGET_FPA && FPA_REG_P (operands[0]))
2966     {
2967       int code = standard_sun_fpa_constant_p (operands[1]);
2968
2969       if (code != 0)
2970         {
2971           static char buf[40];
2972
2973           sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff);
2974           return buf;
2975         }
2976       return "fpmove%.d %1,%0";
2977     }
2978   else
2979 #endif
2980     {
2981       int code = standard_68881_constant_p (operands[1]);
2982
2983       if (code != 0)
2984         {
2985           static char buf[40];
2986
2987           sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
2988           return buf;
2989         }
2990       return "fmove%.d %1,%0";
2991     }
2992 }
2993
2994 const char *
2995 output_move_const_single (operands)
2996      rtx *operands;
2997 {
2998 #ifdef SUPPORT_SUN_FPA
2999   if (TARGET_FPA)
3000     {
3001       int code = standard_sun_fpa_constant_p (operands[1]);
3002
3003       if (code != 0)
3004         {
3005           static char buf[40];
3006
3007           sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff);
3008           return buf;
3009         }
3010       return "fpmove%.s %1,%0";
3011     }
3012   else
3013 #endif /* defined SUPPORT_SUN_FPA */
3014     {
3015       int code = standard_68881_constant_p (operands[1]);
3016
3017       if (code != 0)
3018         {
3019           static char buf[40];
3020
3021           sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
3022           return buf;
3023         }
3024       return "fmove%.s %f1,%0";
3025     }
3026 }
3027
3028 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
3029    from the "fmovecr" instruction.
3030    The value, anded with 0xff, gives the code to use in fmovecr
3031    to get the desired constant.  */
3032
3033 /* This code has been fixed for cross-compilation. */
3034   
3035 static int inited_68881_table = 0;
3036
3037 static const char *const strings_68881[7] = {
3038   "0.0",
3039   "1.0",
3040   "10.0",
3041   "100.0",
3042   "10000.0",
3043   "1e8",
3044   "1e16"
3045   };
3046
3047 int codes_68881[7] = {
3048   0x0f,
3049   0x32,
3050   0x33,
3051   0x34,
3052   0x35,
3053   0x36,
3054   0x37
3055   };
3056
3057 REAL_VALUE_TYPE values_68881[7];
3058
3059 /* Set up values_68881 array by converting the decimal values
3060    strings_68881 to binary.   */
3061
3062 void
3063 init_68881_table ()
3064 {
3065   int i;
3066   REAL_VALUE_TYPE r;
3067   enum machine_mode mode;
3068
3069   mode = SFmode;
3070   for (i = 0; i < 7; i++)
3071     {
3072       if (i == 6)
3073         mode = DFmode;
3074       r = REAL_VALUE_ATOF (strings_68881[i], mode);
3075       values_68881[i] = r;
3076     }
3077   inited_68881_table = 1;
3078 }
3079
3080 int
3081 standard_68881_constant_p (x)
3082      rtx x;
3083 {
3084   REAL_VALUE_TYPE r;
3085   int i;
3086
3087 #ifdef NO_ASM_FMOVECR
3088   return 0;
3089 #endif
3090
3091   /* fmovecr must be emulated on the 68040 and 68060, so it shouldn't be
3092      used at all on those chips. */
3093   if (TARGET_68040 || TARGET_68060)
3094     return 0;
3095
3096 #ifndef REAL_ARITHMETIC
3097 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
3098   if (! flag_pretend_float)
3099     return 0;
3100 #endif
3101 #endif
3102
3103   if (! inited_68881_table)
3104     init_68881_table ();
3105
3106   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
3107
3108   /* Use REAL_VALUES_IDENTICAL instead of REAL_VALUES_EQUAL so that -0.0
3109      is rejected.  */
3110   for (i = 0; i < 6; i++)
3111     {
3112       if (REAL_VALUES_IDENTICAL (r, values_68881[i]))
3113         return (codes_68881[i]);
3114     }
3115   
3116   if (GET_MODE (x) == SFmode)
3117     return 0;
3118
3119   if (REAL_VALUES_EQUAL (r, values_68881[6]))
3120     return (codes_68881[6]);
3121
3122   /* larger powers of ten in the constants ram are not used
3123      because they are not equal to a `double' C constant.  */
3124   return 0;
3125 }
3126
3127 /* If X is a floating-point constant, return the logarithm of X base 2,
3128    or 0 if X is not a power of 2.  */
3129
3130 int
3131 floating_exact_log2 (x)
3132      rtx x;
3133 {
3134   REAL_VALUE_TYPE r, r1;
3135   int i;
3136
3137 #ifndef REAL_ARITHMETIC
3138 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
3139   if (! flag_pretend_float)
3140     return 0;
3141 #endif
3142 #endif
3143
3144   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
3145
3146   if (REAL_VALUES_LESS (r, dconst0))
3147     return 0;
3148
3149   r1 = dconst1;
3150   i = 0;
3151   while (REAL_VALUES_LESS (r1, r))
3152     {
3153       r1 = REAL_VALUE_LDEXP (dconst1, i);
3154       if (REAL_VALUES_EQUAL (r1, r))
3155         return i;
3156       i = i + 1;
3157     }
3158   return 0;
3159 }
3160 \f
3161 #ifdef SUPPORT_SUN_FPA
3162 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
3163    from the Sun FPA's constant RAM.
3164    The value returned, anded with 0x1ff, gives the code to use in fpmove
3165    to get the desired constant. */
3166
3167 static int inited_FPA_table = 0;
3168
3169 static const char *const strings_FPA[38] = {
3170 /* small rationals */
3171   "0.0",
3172   "1.0",
3173   "0.5",
3174   "-1.0",
3175   "2.0",
3176   "3.0",
3177   "4.0",
3178   "8.0",
3179   "0.25",
3180   "0.125",
3181   "10.0",
3182   "-0.5",
3183 /* Decimal equivalents of double precision values */
3184   "2.718281828459045091", /* D_E */
3185   "6.283185307179586477", /* 2 pi */
3186   "3.141592653589793116", /* D_PI */
3187   "1.570796326794896619", /* pi/2 */
3188   "1.414213562373095145", /* D_SQRT2 */
3189   "0.7071067811865475244", /* 1/sqrt(2) */
3190   "-1.570796326794896619", /* -pi/2 */
3191   "1.442695040888963387", /* D_LOG2ofE */
3192   "3.321928024887362182", /* D_LOG2of10 */
3193   "0.6931471805599452862", /* D_LOGEof2 */
3194   "2.302585092994045901", /* D_LOGEof10 */
3195   "0.3010299956639811980", /* D_LOG10of2 */
3196   "0.4342944819032518167", /* D_LOG10ofE */
3197 /* Decimal equivalents of single precision values */
3198   "2.718281745910644531", /* S_E */
3199   "6.283185307179586477", /* 2 pi */
3200   "3.141592741012573242", /* S_PI */
3201   "1.570796326794896619", /* pi/2 */
3202   "1.414213538169860840", /* S_SQRT2 */
3203   "0.7071067811865475244", /* 1/sqrt(2) */
3204   "-1.570796326794896619", /* -pi/2 */
3205   "1.442695021629333496", /* S_LOG2ofE */
3206   "3.321928024291992188", /* S_LOG2of10 */
3207   "0.6931471824645996094", /* S_LOGEof2 */
3208   "2.302585124969482442", /* S_LOGEof10 */
3209   "0.3010300099849700928", /* S_LOG10of2 */
3210   "0.4342944920063018799", /* S_LOG10ofE */
3211 };
3212
3213
3214 int codes_FPA[38] = {
3215 /* small rationals */
3216   0x200,
3217   0xe,
3218   0xf,
3219   0x10,
3220   0x11,
3221   0xb1,
3222   0x12,
3223   0x13,
3224   0x15,
3225   0x16,
3226   0x17,
3227   0x2e,
3228 /* double precision */
3229   0x8,
3230   0x9,
3231   0xa,
3232   0xb,
3233   0xc,
3234   0xd,
3235   0x27,
3236   0x28,
3237   0x29,
3238   0x2a,
3239   0x2b,
3240   0x2c,
3241   0x2d,
3242 /* single precision */
3243   0x8,
3244   0x9,
3245   0xa,
3246   0xb,
3247   0xc,
3248   0xd,
3249   0x27,
3250   0x28,
3251   0x29,
3252   0x2a,
3253   0x2b,
3254   0x2c,
3255   0x2d
3256   };
3257
3258 REAL_VALUE_TYPE values_FPA[38];
3259
3260 /* This code has been fixed for cross-compilation. */
3261
3262 void
3263 init_FPA_table ()
3264 {
3265   enum machine_mode mode;
3266   int i;
3267   REAL_VALUE_TYPE r;
3268
3269   mode = DFmode;
3270   for (i = 0; i < 38; i++)
3271     {
3272       if (i == 25)
3273         mode = SFmode;
3274       r = REAL_VALUE_ATOF (strings_FPA[i], mode);
3275       values_FPA[i] = r;
3276     }
3277   inited_FPA_table = 1;
3278 }
3279
3280
3281 int
3282 standard_sun_fpa_constant_p (x)
3283      rtx x;
3284 {
3285   REAL_VALUE_TYPE r;
3286   int i;
3287
3288 #ifndef REAL_ARITHMETIC
3289 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
3290   if (! flag_pretend_float)
3291     return 0;
3292 #endif
3293 #endif
3294
3295   if (! inited_FPA_table)
3296     init_FPA_table ();
3297
3298   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
3299
3300   for (i=0; i<12; i++)
3301     {
3302       if (REAL_VALUES_EQUAL (r, values_FPA[i]))
3303         return (codes_FPA[i]);
3304     }
3305
3306   if (GET_MODE (x) == SFmode)
3307     {
3308       for (i=25; i<38; i++)
3309         {
3310           if (REAL_VALUES_EQUAL (r, values_FPA[i]))
3311             return (codes_FPA[i]);
3312         }
3313     }
3314   else
3315     {
3316       for (i=12; i<25; i++)
3317         {
3318           if (REAL_VALUES_EQUAL (r, values_FPA[i]))
3319             return (codes_FPA[i]);
3320         }
3321     }
3322   return 0x0;
3323 }
3324 #endif /* define SUPPORT_SUN_FPA */
3325 \f
3326 /* A C compound statement to output to stdio stream STREAM the
3327    assembler syntax for an instruction operand X.  X is an RTL
3328    expression.
3329
3330    CODE is a value that can be used to specify one of several ways
3331    of printing the operand.  It is used when identical operands
3332    must be printed differently depending on the context.  CODE
3333    comes from the `%' specification that was used to request
3334    printing of the operand.  If the specification was just `%DIGIT'
3335    then CODE is 0; if the specification was `%LTR DIGIT' then CODE
3336    is the ASCII code for LTR.
3337
3338    If X is a register, this macro should print the register's name.
3339    The names can be found in an array `reg_names' whose type is
3340    `char *[]'.  `reg_names' is initialized from `REGISTER_NAMES'.
3341
3342    When the machine description has a specification `%PUNCT' (a `%'
3343    followed by a punctuation character), this macro is called with
3344    a null pointer for X and the punctuation character for CODE.
3345
3346    The m68k specific codes are:
3347
3348    '.' for dot needed in Motorola-style opcode names.
3349    '-' for an operand pushing on the stack:
3350        sp@-, -(sp) or -(%sp) depending on the style of syntax.
3351    '+' for an operand pushing on the stack:
3352        sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
3353    '@' for a reference to the top word on the stack:
3354        sp@, (sp) or (%sp) depending on the style of syntax.
3355    '#' for an immediate operand prefix (# in MIT and Motorola syntax
3356        but & in SGS syntax, $ in CRDS/UNOS syntax).
3357    '!' for the cc register (used in an `and to cc' insn).
3358    '$' for the letter `s' in an op code, but only on the 68040.
3359    '&' for the letter `d' in an op code, but only on the 68040.
3360    '/' for register prefix needed by longlong.h.
3361
3362    'b' for byte insn (no effect, on the Sun; this is for the ISI).
3363    'd' to force memory addressing to be absolute, not relative.
3364    'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
3365    'o' for operands to go directly to output_operand_address (bypassing
3366        print_operand_address--used only for SYMBOL_REFs under TARGET_PCREL)
3367    'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
3368        than directly).  Second part of 'y' below.
3369    'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
3370        or print pair of registers as rx:ry.
3371    'y' for a FPA insn (print pair of registers as rx:ry).  This also outputs
3372        CONST_DOUBLE's as SunFPA constant RAM registers if
3373        possible, so it should not be used except for the SunFPA.
3374
3375    */
3376
3377 void
3378 print_operand (file, op, letter)
3379      FILE *file;                /* file to write to */
3380      rtx op;                    /* operand to print */
3381      int letter;                /* %<letter> or 0 */
3382 {
3383 #ifdef SUPPORT_SUN_FPA
3384   int i;
3385 #endif
3386
3387   if (letter == '.')
3388     {
3389 #if defined (MOTOROLA) && !defined (CRDS)
3390       asm_fprintf (file, ".");
3391 #endif
3392     }
3393   else if (letter == '#')
3394     {
3395       asm_fprintf (file, "%0I");
3396     }
3397   else if (letter == '-')
3398     {
3399 #ifdef MOTOROLA
3400       asm_fprintf (file, "-(%Rsp)");
3401 #else
3402       asm_fprintf (file, "%Rsp@-");
3403 #endif
3404     }
3405   else if (letter == '+')
3406     {
3407 #ifdef MOTOROLA
3408       asm_fprintf (file, "(%Rsp)+");
3409 #else
3410       asm_fprintf (file, "%Rsp@+");
3411 #endif
3412     }
3413   else if (letter == '@')
3414     {
3415 #ifdef MOTOROLA
3416       asm_fprintf (file, "(%Rsp)");
3417 #else
3418       asm_fprintf (file, "%Rsp@");
3419 #endif
3420     }
3421   else if (letter == '!')
3422     {
3423       asm_fprintf (file, "%Rfpcr");
3424     }
3425   else if (letter == '$')
3426     {
3427       if (TARGET_68040_ONLY)
3428         {
3429           fprintf (file, "s");
3430         }
3431     }
3432   else if (letter == '&')
3433     {
3434       if (TARGET_68040_ONLY)
3435         {
3436           fprintf (file, "d");
3437         }
3438     }
3439   else if (letter == '/')
3440     {
3441       asm_fprintf (file, "%R");
3442     }
3443   else if (letter == 'o')
3444     {
3445       /* This is only for direct addresses with TARGET_PCREL */
3446       if (GET_CODE (op) != MEM || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
3447           || !TARGET_PCREL) 
3448         abort ();
3449       output_addr_const (file, XEXP (op, 0));
3450     }
3451   else if (GET_CODE (op) == REG)
3452     {
3453 #ifdef SUPPORT_SUN_FPA
3454       if (REGNO (op) < 16
3455           && (letter == 'y' || letter == 'x')
3456           && GET_MODE (op) == DFmode)
3457         {
3458           fprintf (file, "%s:%s", reg_names[REGNO (op)],
3459                    reg_names[REGNO (op)+1]);
3460         }
3461       else
3462 #endif
3463         {
3464           if (letter == 'R')
3465             /* Print out the second register name of a register pair.
3466                I.e., R (6) => 7.  */
3467             fputs (reg_names[REGNO (op) + 1], file);
3468           else
3469             fputs (reg_names[REGNO (op)], file);
3470         }
3471     }
3472   else if (GET_CODE (op) == MEM)
3473     {
3474       output_address (XEXP (op, 0));
3475       if (letter == 'd' && ! TARGET_68020
3476           && CONSTANT_ADDRESS_P (XEXP (op, 0))
3477           && !(GET_CODE (XEXP (op, 0)) == CONST_INT
3478                && INTVAL (XEXP (op, 0)) < 0x8000
3479                && INTVAL (XEXP (op, 0)) >= -0x8000))
3480         {
3481 #ifdef MOTOROLA
3482           fprintf (file, ".l");
3483 #else
3484           fprintf (file, ":l");
3485 #endif
3486         }
3487     }
3488 #ifdef SUPPORT_SUN_FPA
3489   else if ((letter == 'y' || letter == 'w')
3490            && GET_CODE (op) == CONST_DOUBLE
3491            && (i = standard_sun_fpa_constant_p (op)))
3492     {
3493       fprintf (file, "%%%d", i & 0x1ff);
3494     }
3495 #endif
3496   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
3497     {
3498       REAL_VALUE_TYPE r;
3499       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
3500       ASM_OUTPUT_FLOAT_OPERAND (letter, file, r);
3501     }
3502   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode)
3503     {
3504       REAL_VALUE_TYPE r;
3505       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
3506       ASM_OUTPUT_LONG_DOUBLE_OPERAND (file, r);
3507     }
3508   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
3509     {
3510       REAL_VALUE_TYPE r;
3511       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
3512       ASM_OUTPUT_DOUBLE_OPERAND (file, r);
3513     }
3514   else
3515     {
3516       /* Use `print_operand_address' instead of `output_addr_const'
3517          to ensure that we print relevant PIC stuff.  */
3518       asm_fprintf (file, "%0I");
3519       if (TARGET_PCREL
3520           && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST))
3521         print_operand_address (file, op);
3522       else
3523         output_addr_const (file, op);
3524     }
3525 }
3526
3527 \f
3528 /* A C compound statement to output to stdio stream STREAM the
3529    assembler syntax for an instruction operand that is a memory
3530    reference whose address is ADDR.  ADDR is an RTL expression.
3531
3532    Note that this contains a kludge that knows that the only reason
3533    we have an address (plus (label_ref...) (reg...)) when not generating
3534    PIC code is in the insn before a tablejump, and we know that m68k.md
3535    generates a label LInnn: on such an insn.
3536
3537    It is possible for PIC to generate a (plus (label_ref...) (reg...))
3538    and we handle that just like we would a (plus (symbol_ref...) (reg...)).
3539
3540    Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
3541    fails to assemble.  Luckily "Lnnn(pc,d0.l*2)" produces the results
3542    we want.  This difference can be accommodated by using an assembler
3543    define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
3544    string, as necessary.  This is accomplished via the ASM_OUTPUT_CASE_END
3545    macro.  See m68k/sgs.h for an example; for versions without the bug.
3546    Some assemblers refuse all the above solutions.  The workaround is to
3547    emit "K(pc,d0.l*2)" with K being a small constant known to give the
3548    right behaviour.
3549
3550    They also do not like things like "pea 1.w", so we simple leave off
3551    the .w on small constants. 
3552
3553    This routine is responsible for distinguishing between -fpic and -fPIC 
3554    style relocations in an address.  When generating -fpic code the
3555    offset is output in word mode (eg movel a5@(_foo:w), a0).  When generating
3556    -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
3557
3558 #ifndef ASM_OUTPUT_CASE_FETCH
3559 #ifdef MOTOROLA
3560 #ifdef SGS
3561 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
3562         asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
3563 #else
3564 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
3565         asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
3566 #endif
3567 #else
3568 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
3569         asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
3570 #endif
3571 #endif /* ASM_OUTPUT_CASE_FETCH */
3572
3573 void
3574 print_operand_address (file, addr)
3575      FILE *file;
3576      rtx addr;
3577 {
3578   register rtx reg1, reg2, breg, ireg;
3579   rtx offset;
3580
3581   switch (GET_CODE (addr))
3582     {
3583       case REG:
3584 #ifdef MOTOROLA
3585         fprintf (file, "(%s)", reg_names[REGNO (addr)]);
3586 #else
3587         fprintf (file, "%s@", reg_names[REGNO (addr)]);
3588 #endif
3589         break;
3590       case PRE_DEC:
3591 #ifdef MOTOROLA
3592         fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
3593 #else
3594         fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);
3595 #endif
3596         break;
3597       case POST_INC:
3598 #ifdef MOTOROLA
3599         fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
3600 #else
3601         fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);
3602 #endif
3603         break;
3604       case PLUS:
3605         reg1 = reg2 = ireg = breg = offset = 0;
3606         if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
3607           {
3608             offset = XEXP (addr, 0);
3609             addr = XEXP (addr, 1);
3610           }
3611         else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
3612           {
3613             offset = XEXP (addr, 1);
3614             addr = XEXP (addr, 0);
3615           }
3616         if (GET_CODE (addr) != PLUS)
3617           {
3618             ;
3619           }
3620         else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
3621           {
3622             reg1 = XEXP (addr, 0);
3623             addr = XEXP (addr, 1);
3624           }
3625         else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
3626           {
3627             reg1 = XEXP (addr, 1);
3628             addr = XEXP (addr, 0);
3629           }
3630         else if (GET_CODE (XEXP (addr, 0)) == MULT)
3631           {
3632             reg1 = XEXP (addr, 0);
3633             addr = XEXP (addr, 1);
3634           }
3635         else if (GET_CODE (XEXP (addr, 1)) == MULT)
3636           {
3637             reg1 = XEXP (addr, 1);
3638             addr = XEXP (addr, 0);
3639           }
3640         else if (GET_CODE (XEXP (addr, 0)) == REG)
3641           {
3642             reg1 = XEXP (addr, 0);
3643             addr = XEXP (addr, 1);
3644           }
3645         else if (GET_CODE (XEXP (addr, 1)) == REG)
3646           {
3647             reg1 = XEXP (addr, 1);
3648             addr = XEXP (addr, 0);
3649           }
3650         if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
3651             || GET_CODE (addr) == SIGN_EXTEND)
3652           {
3653             if (reg1 == 0)
3654               {
3655                 reg1 = addr;
3656               }
3657             else
3658               {
3659                 reg2 = addr;
3660               }
3661             addr = 0;
3662           }
3663 #if 0   /* for OLD_INDEXING */
3664         else if (GET_CODE (addr) == PLUS)
3665           {
3666             if (GET_CODE (XEXP (addr, 0)) == REG)
3667               {
3668                 reg2 = XEXP (addr, 0);
3669                 addr = XEXP (addr, 1);
3670               }
3671             else if (GET_CODE (XEXP (addr, 1)) == REG)
3672               {
3673                 reg2 = XEXP (addr, 1);
3674                 addr = XEXP (addr, 0);
3675               }
3676           }
3677 #endif
3678         if (offset != 0)
3679           {
3680             if (addr != 0)
3681               {
3682                 abort ();
3683               }
3684             addr = offset;
3685           }
3686         if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
3687                       || GET_CODE (reg1) == MULT))
3688             || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
3689           {
3690             breg = reg2;
3691             ireg = reg1;
3692           }
3693         else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
3694           {
3695             breg = reg1;
3696             ireg = reg2;
3697           }
3698         if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
3699             && ! (flag_pic && ireg == pic_offset_table_rtx))
3700           {
3701             int scale = 1;
3702             if (GET_CODE (ireg) == MULT)
3703               {
3704                 scale = INTVAL (XEXP (ireg, 1));
3705                 ireg = XEXP (ireg, 0);
3706               }
3707             if (GET_CODE (ireg) == SIGN_EXTEND)
3708               {
3709                 ASM_OUTPUT_CASE_FETCH (file,
3710                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
3711                              reg_names[REGNO (XEXP (ireg, 0))]);
3712                 fprintf (file, "w");
3713               }
3714             else
3715               {
3716                 ASM_OUTPUT_CASE_FETCH (file,
3717                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
3718                              reg_names[REGNO (ireg)]);
3719                 fprintf (file, "l");
3720               }
3721             if (scale != 1)
3722               {
3723 #ifdef MOTOROLA
3724                 fprintf (file, "*%d", scale);
3725 #else
3726                 fprintf (file, ":%d", scale);
3727 #endif
3728               }
3729             putc (')', file);
3730             break;
3731           }
3732         if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
3733             && ! (flag_pic && breg == pic_offset_table_rtx))
3734           {
3735             ASM_OUTPUT_CASE_FETCH (file,
3736                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
3737                          reg_names[REGNO (breg)]);
3738             fprintf (file, "l)");
3739             break;
3740           }
3741         if (ireg != 0 || breg != 0)
3742           {
3743             int scale = 1;
3744             if (breg == 0)
3745               {
3746                 abort ();
3747               }
3748             if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
3749               {
3750                 abort ();
3751               }
3752 #ifdef MOTOROLA
3753             if (addr != 0)
3754               {
3755                 output_addr_const (file, addr);
3756                 if (flag_pic && (breg == pic_offset_table_rtx))
3757                   {
3758                     fprintf (file, "@GOT");
3759                     if (flag_pic == 1)
3760                       fprintf (file, ".w");
3761                   }
3762               }
3763             fprintf (file, "(%s", reg_names[REGNO (breg)]);
3764             if (ireg != 0)
3765               {
3766                 putc (',', file);
3767               }
3768 #else
3769             fprintf (file, "%s@(", reg_names[REGNO (breg)]);
3770             if (addr != 0)
3771               {
3772                 output_addr_const (file, addr);
3773                 if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
3774                   fprintf (file, ":w");
3775                 if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
3776                   fprintf (file, ":l");
3777               }
3778             if (addr != 0 && ireg != 0)
3779               {
3780                 putc (',', file);
3781               }
3782 #endif
3783             if (ireg != 0 && GET_CODE (ireg) == MULT)
3784               {
3785                 scale = INTVAL (XEXP (ireg, 1));
3786                 ireg = XEXP (ireg, 0);
3787               }
3788             if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
3789               {
3790 #ifdef MOTOROLA
3791                 fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);
3792 #else
3793                 fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);
3794 #endif
3795               }
3796             else if (ireg != 0)
3797               {
3798 #ifdef MOTOROLA
3799                 fprintf (file, "%s.l", reg_names[REGNO (ireg)]);
3800 #else
3801                 fprintf (file, "%s:l", reg_names[REGNO (ireg)]);
3802 #endif
3803               }
3804             if (scale != 1)
3805               {
3806 #ifdef MOTOROLA
3807                 fprintf (file, "*%d", scale);
3808 #else
3809                 fprintf (file, ":%d", scale);
3810 #endif
3811               }
3812             putc (')', file);
3813             break;
3814           }
3815         else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
3816                  && ! (flag_pic && reg1 == pic_offset_table_rtx))       
3817           {
3818             ASM_OUTPUT_CASE_FETCH (file,
3819                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
3820                          reg_names[REGNO (reg1)]);
3821             fprintf (file, "l)");
3822             break;
3823           }
3824         /* FALL-THROUGH (is this really what we want?)  */
3825       default:
3826         if (GET_CODE (addr) == CONST_INT
3827             && INTVAL (addr) < 0x8000
3828             && INTVAL (addr) >= -0x8000)
3829           {
3830 #ifdef MOTOROLA
3831 #ifdef SGS
3832             /* Many SGS assemblers croak on size specifiers for constants. */
3833             fprintf (file, "%d", (int) INTVAL (addr));
3834 #else
3835             fprintf (file, "%d.w", (int) INTVAL (addr));
3836 #endif
3837 #else
3838             fprintf (file, "%d:w", (int) INTVAL (addr));
3839 #endif
3840           }
3841         else if (GET_CODE (addr) == CONST_INT)
3842           {
3843             fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr));
3844           }
3845         else if (TARGET_PCREL)
3846           {
3847             fputc ('(', file);
3848             output_addr_const (file, addr);
3849             if (flag_pic == 1)
3850               asm_fprintf (file, ":w,%Rpc)");
3851             else
3852               asm_fprintf (file, ":l,%Rpc)");
3853           }
3854         else
3855           {
3856             /* Special case for SYMBOL_REF if the symbol name ends in
3857                `.<letter>', this can be mistaken as a size suffix.  Put
3858                the name in parentheses.  */
3859             if (GET_CODE (addr) == SYMBOL_REF
3860                 && strlen (XSTR (addr, 0)) > 2
3861                 && XSTR (addr, 0)[strlen (XSTR (addr, 0)) - 2] == '.')
3862               {
3863                 putc ('(', file);
3864                 output_addr_const (file, addr);
3865                 putc (')', file);
3866               }
3867             else
3868               output_addr_const (file, addr);
3869           }
3870         break;
3871     }
3872 }
3873 \f
3874 /* Check for cases where a clr insns can be omitted from code using
3875    strict_low_part sets.  For example, the second clrl here is not needed:
3876    clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
3877
3878    MODE is the mode of this STRICT_LOW_PART set.  FIRST_INSN is the clear
3879    insn we are checking for redundancy.  TARGET is the register set by the
3880    clear insn.  */
3881
3882 int
3883 strict_low_part_peephole_ok (mode, first_insn, target)
3884      enum machine_mode mode;
3885      rtx first_insn;
3886      rtx target;
3887 {
3888   rtx p;
3889
3890   p = prev_nonnote_insn (first_insn);
3891
3892   while (p)
3893     {
3894       /* If it isn't an insn, then give up.  */
3895       if (GET_CODE (p) != INSN)
3896         return 0;
3897
3898       if (reg_set_p (target, p))
3899         {
3900           rtx set = single_set (p);
3901           rtx dest;
3902
3903           /* If it isn't an easy to recognize insn, then give up.  */
3904           if (! set)
3905             return 0;
3906
3907           dest = SET_DEST (set);
3908
3909           /* If this sets the entire target register to zero, then our
3910              first_insn is redundant.  */
3911           if (rtx_equal_p (dest, target)
3912               && SET_SRC (set) == const0_rtx)
3913             return 1;
3914           else if (GET_CODE (dest) == STRICT_LOW_PART
3915                    && GET_CODE (XEXP (dest, 0)) == REG
3916                    && REGNO (XEXP (dest, 0)) == REGNO (target)
3917                    && (GET_MODE_SIZE (GET_MODE (XEXP (dest, 0)))
3918                        <= GET_MODE_SIZE (mode)))
3919             /* This is a strict low part set which modifies less than
3920                we are using, so it is safe.  */
3921             ;
3922           else
3923             return 0;
3924         }
3925
3926       p = prev_nonnote_insn (p);
3927
3928     }
3929
3930   return 0;
3931 }
3932
3933 /* Accept integer operands in the range 0..0xffffffff.  We have to check the
3934    range carefully since this predicate is used in DImode contexts.  Also, we
3935    need some extra crud to make it work when hosted on 64-bit machines.  */
3936
3937 int
3938 const_uint32_operand (op, mode)
3939      rtx op;
3940      enum machine_mode mode;
3941 {
3942   /* It doesn't make sense to ask this question with a mode that is
3943      not larger than 32 bits.  */
3944   if (GET_MODE_BITSIZE (mode) <= 32)
3945     abort ();
3946
3947 #if HOST_BITS_PER_WIDE_INT > 32
3948   /* All allowed constants will fit a CONST_INT.  */
3949   return (GET_CODE (op) == CONST_INT
3950           && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
3951 #else
3952   return (GET_CODE (op) == CONST_INT
3953           || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
3954 #endif
3955 }
3956
3957 /* Accept integer operands in the range -0x80000000..0x7fffffff.  We have
3958    to check the range carefully since this predicate is used in DImode
3959    contexts.  */
3960
3961 int
3962 const_sint32_operand (op, mode)
3963      rtx op;
3964      enum machine_mode mode;
3965 {
3966   /* It doesn't make sense to ask this question with a mode that is
3967      not larger than 32 bits.  */
3968   if (GET_MODE_BITSIZE (mode) <= 32)
3969     abort ();
3970
3971   /* All allowed constants will fit a CONST_INT.  */
3972   return (GET_CODE (op) == CONST_INT
3973           && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
3974 }
3975
3976 /* Operand predicates for implementing asymmetric pc-relative addressing
3977    on m68k.  The m68k supports pc-relative addressing (mode 7, register 2)
3978    when used as a source operand, but not as a destintation operand.
3979
3980    We model this by restricting the meaning of the basic predicates
3981    (general_operand, memory_operand, etc) to forbid the use of this
3982    addressing mode, and then define the following predicates that permit
3983    this addressing mode.  These predicates can then be used for the
3984    source operands of the appropriate instructions.
3985
3986    n.b.  While it is theoretically possible to change all machine patterns
3987    to use this addressing more where permitted by the architecture,
3988    it has only been implemented for "common" cases: SImode, HImode, and
3989    QImode operands, and only for the principle operations that would
3990    require this addressing mode: data movement and simple integer operations.
3991
3992    In parallel with these new predicates, two new constraint letters
3993    were defined: 'S' and 'T'.  'S' is the -mpcrel analog of 'm'.
3994    'T' replaces 's' in the non-pcrel case.  It is a no-op in the pcrel case.
3995    In the pcrel case 's' is only valid in combination with 'a' registers.
3996    See addsi3, subsi3, cmpsi, and movsi patterns for a better understanding
3997    of how these constraints are used.
3998
3999    The use of these predicates is strictly optional, though patterns that
4000    don't will cause an extra reload register to be allocated where one
4001    was not necessary:
4002
4003         lea (abc:w,%pc),%a0     ; need to reload address
4004         moveq &1,%d1            ; since write to pc-relative space
4005         movel %d1,%a0@          ; is not allowed
4006         ...
4007         lea (abc:w,%pc),%a1     ; no need to reload address here
4008         movel %a1@,%d0          ; since "movel (abc:w,%pc),%d0" is ok
4009
4010    For more info, consult tiemann@cygnus.com.
4011
4012
4013    All of the ugliness with predicates and constraints is due to the
4014    simple fact that the m68k does not allow a pc-relative addressing
4015    mode as a destination.  gcc does not distinguish between source and
4016    destination addresses.  Hence, if we claim that pc-relative address
4017    modes are valid, e.g. GO_IF_LEGITIMATE_ADDRESS accepts them, then we
4018    end up with invalid code.  To get around this problem, we left
4019    pc-relative modes as invalid addresses, and then added special
4020    predicates and constraints to accept them.
4021
4022    A cleaner way to handle this is to modify gcc to distinguish
4023    between source and destination addresses.  We can then say that
4024    pc-relative is a valid source address but not a valid destination
4025    address, and hopefully avoid a lot of the predicate and constraint
4026    hackery.  Unfortunately, this would be a pretty big change.  It would
4027    be a useful change for a number of ports, but there aren't any current
4028    plans to undertake this.
4029
4030    ***************************************************************************/
4031
4032
4033 /* Special case of a general operand that's used as a source operand.
4034    Use this to permit reads from PC-relative memory when -mpcrel
4035    is specified.  */
4036
4037 int
4038 general_src_operand (op, mode)
4039      rtx op;
4040      enum machine_mode mode;
4041 {
4042   if (TARGET_PCREL
4043       && GET_CODE (op) == MEM
4044       && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
4045           || GET_CODE (XEXP (op, 0)) == LABEL_REF
4046           || GET_CODE (XEXP (op, 0)) == CONST))
4047     return 1;
4048   return general_operand (op, mode);
4049 }
4050
4051 /* Special case of a nonimmediate operand that's used as a source.
4052    Use this to permit reads from PC-relative memory when -mpcrel
4053    is specified.  */
4054
4055 int
4056 nonimmediate_src_operand (op, mode)
4057      rtx op;
4058      enum machine_mode mode;
4059 {
4060   if (TARGET_PCREL && GET_CODE (op) == MEM
4061       && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
4062           || GET_CODE (XEXP (op, 0)) == LABEL_REF
4063           || GET_CODE (XEXP (op, 0)) == CONST))
4064     return 1;
4065   return nonimmediate_operand (op, mode);
4066 }
4067
4068 /* Special case of a memory operand that's used as a source.
4069    Use this to permit reads from PC-relative memory when -mpcrel
4070    is specified.  */
4071
4072 int
4073 memory_src_operand (op, mode)
4074      rtx op;
4075      enum machine_mode mode;
4076 {
4077   if (TARGET_PCREL && GET_CODE (op) == MEM
4078       && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
4079           || GET_CODE (XEXP (op, 0)) == LABEL_REF
4080           || GET_CODE (XEXP (op, 0)) == CONST))
4081     return 1;
4082   return memory_operand (op, mode);
4083 }
4084
4085 /* Predicate that accepts only a pc-relative address.  This is needed
4086    because pc-relative addresses don't satisfy the predicate
4087    "general_src_operand".  */
4088
4089 int
4090 pcrel_address (op, mode)
4091      rtx op;
4092      enum machine_mode mode ATTRIBUTE_UNUSED;
4093 {
4094   return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF
4095           || GET_CODE (op) == CONST);
4096 }
4097
4098 const char *
4099 output_andsi3 (operands)
4100      rtx *operands;
4101 {
4102   int logval;
4103   if (GET_CODE (operands[2]) == CONST_INT
4104       && (INTVAL (operands[2]) | 0xffff) == 0xffffffff
4105       && (DATA_REG_P (operands[0])
4106           || offsettable_memref_p (operands[0]))
4107       && !TARGET_5200)
4108     {
4109       if (GET_CODE (operands[0]) != REG)
4110         operands[0] = adjust_address (operands[0], HImode, 2);
4111       operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
4112       /* Do not delete a following tstl %0 insn; that would be incorrect.  */
4113       CC_STATUS_INIT;
4114       if (operands[2] == const0_rtx)
4115         return "clr%.w %0";
4116       return "and%.w %2,%0";
4117     }
4118   if (GET_CODE (operands[2]) == CONST_INT
4119       && (logval = exact_log2 (~ INTVAL (operands[2]))) >= 0
4120       && (DATA_REG_P (operands[0])
4121           || offsettable_memref_p (operands[0])))
4122     {
4123       if (DATA_REG_P (operands[0]))
4124         {
4125           operands[1] = GEN_INT (logval);
4126         }
4127       else
4128         {
4129           operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
4130           operands[1] = GEN_INT (logval % 8);
4131         }
4132       /* This does not set condition codes in a standard way.  */
4133       CC_STATUS_INIT;
4134       return "bclr %1,%0";
4135     }
4136   return "and%.l %2,%0";
4137 }
4138
4139 const char *
4140 output_iorsi3 (operands)
4141      rtx *operands;
4142 {
4143   register int logval;
4144   if (GET_CODE (operands[2]) == CONST_INT
4145       && INTVAL (operands[2]) >> 16 == 0
4146       && (DATA_REG_P (operands[0])
4147           || offsettable_memref_p (operands[0]))
4148       && !TARGET_5200)
4149     {
4150       if (GET_CODE (operands[0]) != REG)
4151         operands[0] = adjust_address (operands[0], HImode, 2);
4152       /* Do not delete a following tstl %0 insn; that would be incorrect.  */
4153       CC_STATUS_INIT;
4154       if (INTVAL (operands[2]) == 0xffff)
4155         return "mov%.w %2,%0";
4156       return "or%.w %2,%0";
4157     }
4158   if (GET_CODE (operands[2]) == CONST_INT
4159       && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
4160       && (DATA_REG_P (operands[0])
4161           || offsettable_memref_p (operands[0])))
4162     {
4163       if (DATA_REG_P (operands[0]))
4164         operands[1] = GEN_INT (logval);
4165       else
4166         {
4167           operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
4168           operands[1] = GEN_INT (logval % 8);
4169         }
4170       CC_STATUS_INIT;
4171       return "bset %1,%0";
4172     }
4173   return "or%.l %2,%0";
4174 }
4175
4176 const char *
4177 output_xorsi3 (operands)
4178      rtx *operands;
4179 {
4180   register int logval;
4181   if (GET_CODE (operands[2]) == CONST_INT
4182       && INTVAL (operands[2]) >> 16 == 0
4183       && (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0]))
4184       && !TARGET_5200)
4185     {
4186       if (! DATA_REG_P (operands[0]))
4187         operands[0] = adjust_address (operands[0], HImode, 2);
4188       /* Do not delete a following tstl %0 insn; that would be incorrect.  */
4189       CC_STATUS_INIT;
4190       if (INTVAL (operands[2]) == 0xffff)
4191         return "not%.w %0";
4192       return "eor%.w %2,%0";
4193     }
4194   if (GET_CODE (operands[2]) == CONST_INT
4195       && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
4196       && (DATA_REG_P (operands[0])
4197           || offsettable_memref_p (operands[0])))
4198     {
4199       if (DATA_REG_P (operands[0]))
4200         operands[1] = GEN_INT (logval);
4201       else
4202         {
4203           operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
4204           operands[1] = GEN_INT (logval % 8);
4205         }
4206       CC_STATUS_INIT;
4207       return "bchg %1,%0";
4208     }
4209   return "eor%.l %2,%0";
4210 }