OSDN Git Service

f0c171414ef88eec5f85290d20a693732d14954d
[pf3gnuchains/gcc-fork.git] / gcc / config / m68k / m68k.c
1 /* Subroutines for insn-output.c for Motorola 68000 family.
2    Copyright (C) 1987, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21
22 /* Some output-actions in m68k.md need these.  */
23 #include <stdio.h>
24 #include "config.h"
25 #include "rtl.h"
26 #include "regs.h"
27 #include "hard-reg-set.h"
28 #include "real.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "insn-flags.h"
32 #include "output.h"
33 #include "insn-attr.h"
34
35 /* Needed for use_return_insn.  */
36 #include "flags.h"
37
38 #ifdef SUPPORT_SUN_FPA
39
40 /* Index into this array by (register number >> 3) to find the
41    smallest class which contains that register.  */
42 enum reg_class regno_reg_class[]
43   = { DATA_REGS, ADDR_REGS, FP_REGS,
44       LO_FPA_REGS, LO_FPA_REGS, FPA_REGS, FPA_REGS };
45
46 #endif /* defined SUPPORT_SUN_FPA */
47
48 /* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
49    if SGS_SWITCH_TABLE.  */
50 int switch_table_difference_label_flag;
51
52 static rtx find_addr_reg ();
53 rtx legitimize_pic_address ();
54 \f
55
56 /* Alignment to use for loops and jumps */
57 /* Specify power of two alignment used for loops. */
58 char *m68k_align_loops_string;
59 /* Specify power of two alignment used for non-loop jumps. */
60 char *m68k_align_jumps_string;
61 /* Specify power of two alignment used for functions. */
62 char *m68k_align_funcs_string;
63
64 /* Specify power of two alignment used for loops. */
65 int m68k_align_loops;
66 /* Specify power of two alignment used for non-loop jumps. */
67 int m68k_align_jumps;
68 /* Specify power of two alignment used for functions. */
69 int m68k_align_funcs;
70
71 /* Nonzero if the last compare/test insn had FP operands.  The
72    sCC expanders peek at this to determine what to do for the
73    68060, which has no fsCC instructions.  */
74 int m68k_last_compare_had_fp_operands;
75
76 /* Sometimes certain combinations of command options do not make
77    sense on a particular target machine.  You can define a macro
78    `OVERRIDE_OPTIONS' to take account of this.  This macro, if
79    defined, is executed once just after all the command options have
80    been parsed.
81
82    Don't use this macro to turn on various extra optimizations for
83    `-O'.  That is what `OPTIMIZATION_OPTIONS' is for.  */
84
85 void
86 override_options ()
87 {
88   int def_align;
89
90   def_align = 1;
91
92   /* Validate -malign-loops= value, or provide default */
93   if (m68k_align_loops_string)
94     {
95       m68k_align_loops = atoi (m68k_align_loops_string);
96       if (m68k_align_loops < 1 || m68k_align_loops > MAX_CODE_ALIGN)
97         fatal ("-malign-loops=%d is not between 1 and %d",
98                m68k_align_loops, MAX_CODE_ALIGN);
99     }
100   else
101     m68k_align_loops = def_align;
102
103   /* Validate -malign-jumps= value, or provide default */
104   if (m68k_align_jumps_string)
105     {
106       m68k_align_jumps = atoi (m68k_align_jumps_string);
107       if (m68k_align_jumps < 1 || m68k_align_jumps > MAX_CODE_ALIGN)
108         fatal ("-malign-jumps=%d is not between 1 and %d",
109                m68k_align_jumps, MAX_CODE_ALIGN);
110     }
111   else
112     m68k_align_jumps = def_align;
113
114   /* Validate -malign-functions= value, or provide default */
115   if (m68k_align_funcs_string)
116     {
117       m68k_align_funcs = atoi (m68k_align_funcs_string);
118       if (m68k_align_funcs < 1 || m68k_align_funcs > MAX_CODE_ALIGN)
119         fatal ("-malign-functions=%d is not between 1 and %d",
120                m68k_align_funcs, MAX_CODE_ALIGN);
121     }
122   else
123     m68k_align_funcs = def_align;
124 }
125 \f
126 /* Emit a (use pic_offset_table_rtx) if we used PIC relocation in the 
127    function at any time during the compilation process.  In the future 
128    we should try and eliminate the USE if we can easily determine that 
129    all PIC references were deleted from the current function.  That would 
130    save an address register */
131    
132 void
133 finalize_pic ()
134 {
135   if (flag_pic && current_function_uses_pic_offset_table)
136     {
137       rtx insn = gen_rtx (USE, VOIDmode, pic_offset_table_rtx);
138       emit_insn_after (insn, get_insns ());
139       emit_insn (insn);
140     }
141 }
142
143 \f
144 /* This function generates the assembly code for function entry.
145    STREAM is a stdio stream to output the code to.
146    SIZE is an int: how many units of temporary storage to allocate.
147    Refer to the array `regs_ever_live' to determine which registers
148    to save; `regs_ever_live[I]' is nonzero if register number I
149    is ever used in the function.  This function is responsible for
150    knowing which registers should not be saved even if used.  */
151
152
153 /* Note that the order of the bit mask for fmovem is the opposite
154    of the order for movem!  */
155
156
157 void
158 output_function_prologue (stream, size)
159      FILE *stream;
160      int size;
161 {
162   register int regno;
163   register int mask = 0;
164   int num_saved_regs = 0;
165   extern char call_used_regs[];
166   int fsize = (size + 3) & -4;
167   
168
169   if (frame_pointer_needed)
170     {
171       if (fsize == 0 && TARGET_68040)
172         {
173         /* on the 68040, pea + move is faster than link.w 0 */
174 #ifdef MOTOROLA
175           asm_fprintf (stream, "\tpea (%s)\n\tmove.l %s,%s\n",
176                reg_names[FRAME_POINTER_REGNUM], reg_names[STACK_POINTER_REGNUM],
177                reg_names[FRAME_POINTER_REGNUM]);
178 #else
179           asm_fprintf (stream, "\tpea %s@\n\tmovel %s,%s\n",
180                reg_names[FRAME_POINTER_REGNUM], reg_names[STACK_POINTER_REGNUM],
181                reg_names[FRAME_POINTER_REGNUM]);
182 #endif
183         }
184       else if (fsize < 0x8000)
185         {
186 #ifdef MOTOROLA
187           asm_fprintf (stream, "\tlink.w %s,%0I%d\n",
188                        reg_names[FRAME_POINTER_REGNUM], -fsize);
189 #else
190           asm_fprintf (stream, "\tlink %s,%0I%d\n",
191                        reg_names[FRAME_POINTER_REGNUM], -fsize);
192 #endif
193         }
194       else if (TARGET_68020)
195         {
196 #ifdef MOTOROLA
197           asm_fprintf (stream, "\tlink.l %s,%0I%d\n",
198                        reg_names[FRAME_POINTER_REGNUM], -fsize);
199 #else
200           asm_fprintf (stream, "\tlink %s,%0I%d\n",
201                        reg_names[FRAME_POINTER_REGNUM], -fsize);
202 #endif
203         }
204       else
205         {
206       /* Adding negative number is faster on the 68040.  */
207 #ifdef MOTOROLA
208           asm_fprintf (stream, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
209                        reg_names[FRAME_POINTER_REGNUM], -fsize);
210 #else
211           asm_fprintf (stream, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
212                        reg_names[FRAME_POINTER_REGNUM], -fsize);
213 #endif
214         }
215     }
216   else if (fsize)
217     {
218       if (fsize + 4 < 0x8000)
219         {
220 #ifdef NO_ADDSUB_Q
221           if (fsize + 4 <= 8)
222             {
223               if (!TARGET_5200)
224                 {
225                   /* asm_fprintf() cannot handle %. */
226 #ifdef MOTOROLA
227                   asm_fprintf (stream, "\tsubq.w %OI%d,%Rsp\n", fsize + 4);
228 #else
229                   asm_fprintf (stream, "\tsubqw %OI%d,%Rsp\n", fsize + 4);
230 #endif
231                 }
232               else
233                 {
234                   /* asm_fprintf() cannot handle %. */
235 #ifdef MOTOROLA
236                   asm_fprintf (stream, "\tsubq.l %OI%d,%Rsp\n", fsize + 4);
237 #else
238                   asm_fprintf (stream, "\tsubql %OI%d,%Rsp\n", fsize + 4);
239 #endif
240                 }
241             }
242           else if (fsize + 4 <= 16 && TARGET_CPU32)
243             {
244               /* On the CPU32 it is faster to use two subqw instructions to
245                  subtract a small integer (8 < N <= 16) to a register. */
246               /* asm_fprintf() cannot handle %. */
247 #ifdef MOTOROLA
248               asm_fprintf (stream, "\tsubq.w %OI8,%Rsp\n\tsubq.w %OI%d,%Rsp\n",
249                            fsize + 4);
250 #else
251               asm_fprintf (stream, "\tsubqw %OI8,%Rsp\n\tsubqw %OI%d,%Rsp\n",
252                            fsize + 4);
253 #endif
254             }
255           else 
256 #endif /* NO_ADDSUB_Q */
257           if (TARGET_68040)
258             {
259               /* Adding negative number is faster on the 68040.  */
260               /* asm_fprintf() cannot handle %. */
261 #ifdef MOTOROLA
262               asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - (fsize + 4));
263 #else
264               asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", - (fsize + 4));
265 #endif
266             }
267           else
268             {
269 #ifdef MOTOROLA
270               asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", - (fsize + 4));
271 #else
272               asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", - (fsize + 4));
273 #endif
274             }
275         }
276       else
277         {
278         /* asm_fprintf() cannot handle %. */
279 #ifdef MOTOROLA
280           asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", - (fsize + 4));
281 #else
282           asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", - (fsize + 4));
283 #endif
284         }
285     }
286 #ifdef SUPPORT_SUN_FPA
287   for (regno = 24; regno < 56; regno++)
288     if (regs_ever_live[regno] && ! call_used_regs[regno])
289       {
290 #ifdef MOTOROLA
291         asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n",
292                      reg_names[regno]);
293 #else
294         asm_fprintf (stream, "\tfpmoved %s,%Rsp@-\n",
295                      reg_names[regno]);
296 #endif
297       }
298 #endif
299   if (TARGET_68881)
300     {
301       for (regno = 16; regno < 24; regno++)
302         if (regs_ever_live[regno] && ! call_used_regs[regno])
303            mask |= 1 << (regno - 16);
304       if ((mask & 0xff) != 0)
305         {
306 #ifdef MOTOROLA
307           asm_fprintf (stream, "\tfmovm %0I0x%x,-(%Rsp)\n", mask & 0xff);
308 #else
309           asm_fprintf (stream, "\tfmovem %0I0x%x,%Rsp@-\n", mask & 0xff);
310 #endif
311         }
312       mask = 0;
313     }
314   for (regno = 0; regno < 16; regno++)
315     if (regs_ever_live[regno] && ! call_used_regs[regno])
316       {
317         mask |= 1 << (15 - regno);
318         num_saved_regs++;
319       }
320   if (frame_pointer_needed)
321     {
322       mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));
323       num_saved_regs--;
324     }
325
326 #if NEED_PROBE
327 #ifdef MOTOROLA
328 #ifdef CRDS
329   asm_fprintf (stream, "\ttstl %d(%Rsp)\n", NEED_PROBE - num_saved_regs * 4);
330 #else
331   asm_fprintf (stream, "\ttst.l %d(%Rsp)\n", NEED_PROBE - num_saved_regs * 4);
332 #endif
333 #else
334   asm_fprintf (stream, "\ttstl %Rsp@(%d)\n", NEED_PROBE - num_saved_regs * 4);
335 #endif
336 #endif
337
338   if (num_saved_regs <= 2)
339     {
340       /* Store each separately in the same order moveml uses.
341          Using two movel instructions instead of a single moveml
342          is about 15% faster for the 68020 and 68030 at no expense
343          in code size */
344
345       int i;
346
347       /* Undo the work from above. */
348       for (i = 0; i< 16; i++)
349         if (mask & (1 << i))
350           asm_fprintf (stream,
351 #ifdef MOTOROLA
352                        "\t%Omove.l %s,-(%Rsp)\n",
353 #else
354                        "\tmovel %s,%Rsp@-\n",
355 #endif
356                        reg_names[15 - i]);
357     }
358   else if (mask)
359     {
360       if (TARGET_5200)
361         {
362           /* The coldfire does not support the predecrement form of the 
363              movml instruction, so we must adjust the stack pointer and
364              then use the plain address register indirect mode.  We also
365              have to invert the register save mask to use the new mode.
366
367              FIXME: if num_saved_regs was calculated earlier, we could
368              combine the stack pointer adjustment with any adjustment
369              done when the initial stack frame is created.  This would
370              save an instruction */
371              
372           int newmask = 0;
373           int i;
374
375           for (i = 0; i < 16; i++)
376             if (mask & (1 << i))
377                 newmask |= (1 << (15-i));
378
379 #ifdef MOTOROLA
380           asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", -num_saved_regs*4);
381           asm_fprintf (stream, "\tmovm.l %0I0x%x,(%Rsp)\n", newmask);
382 #else
383           asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", -num_saved_regs*4);
384           asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@\n", newmask);
385 #endif
386         }
387       else
388         {
389 #ifdef MOTOROLA
390           asm_fprintf (stream, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask);
391 #else
392           asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@-\n", mask);
393 #endif
394         }
395     }
396   if (flag_pic && current_function_uses_pic_offset_table)
397     {
398 #ifdef MOTOROLA
399       asm_fprintf (stream, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
400                    reg_names[PIC_OFFSET_TABLE_REGNUM]);
401 #else
402       asm_fprintf (stream, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
403                    reg_names[PIC_OFFSET_TABLE_REGNUM]);
404       asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n",
405                    reg_names[PIC_OFFSET_TABLE_REGNUM],
406                    reg_names[PIC_OFFSET_TABLE_REGNUM]);
407 #endif
408     }
409 }
410 \f
411 /* Return true if this function's epilogue can be output as RTL.  */
412
413 int
414 use_return_insn ()
415 {
416   int regno;
417
418   if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)
419     return 0;
420   
421   /* Copied from output_function_epilogue ().  We should probably create a
422      separate layout routine to perform the common work.  */
423   
424   for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++)
425     if (regs_ever_live[regno] && ! call_used_regs[regno])
426       return 0;
427   
428   return 1;
429 }
430
431 /* This function generates the assembly code for function exit,
432    on machines that need it.  Args are same as for FUNCTION_PROLOGUE.
433
434    The function epilogue should not depend on the current stack pointer!
435    It should use the frame pointer only, if there is a frame pointer.
436    This is mandatory because of alloca; we also take advantage of it to
437    omit stack adjustments before returning.  */
438
439 void
440 output_function_epilogue (stream, size)
441      FILE *stream;
442      int size;
443 {
444   register int regno;
445   register int mask, fmask;
446   register int nregs;
447   int offset, foffset, fpoffset;
448   extern char call_used_regs[];
449   int fsize = (size + 3) & -4;
450   int big = 0;
451   rtx insn = get_last_insn ();
452   int restore_from_sp = 0;
453   
454   /* If the last insn was a BARRIER, we don't have to write any code.  */
455   if (GET_CODE (insn) == NOTE)
456     insn = prev_nonnote_insn (insn);
457   if (insn && GET_CODE (insn) == BARRIER)
458     {
459       /* Output just a no-op so that debuggers don't get confused
460          about which function the pc is in at this address.  */
461       asm_fprintf (stream, "\tnop\n");
462       return;
463     }
464
465 #ifdef FUNCTION_BLOCK_PROFILER_EXIT
466   if (profile_block_flag == 2)
467     {
468       FUNCTION_BLOCK_PROFILER_EXIT (stream);
469     }
470 #endif
471
472 #ifdef FUNCTION_EXTRA_EPILOGUE
473   FUNCTION_EXTRA_EPILOGUE (stream, size);
474 #endif
475   nregs = 0;  fmask = 0; fpoffset = 0;
476 #ifdef SUPPORT_SUN_FPA
477   for (regno = 24 ; regno < 56 ; regno++)
478     if (regs_ever_live[regno] && ! call_used_regs[regno])
479       nregs++;
480   fpoffset = nregs * 8;
481 #endif
482   nregs = 0;
483   if (TARGET_68881)
484     {
485       for (regno = 16; regno < 24; regno++)
486         if (regs_ever_live[regno] && ! call_used_regs[regno])
487           {
488             nregs++;
489             fmask |= 1 << (23 - regno);
490           }
491     }
492   foffset = fpoffset + nregs * 12;
493   nregs = 0;  mask = 0;
494   if (frame_pointer_needed)
495     regs_ever_live[FRAME_POINTER_REGNUM] = 0;
496   for (regno = 0; regno < 16; regno++)
497     if (regs_ever_live[regno] && ! call_used_regs[regno])
498       {
499         nregs++;
500         mask |= 1 << regno;
501       }
502   offset = foffset + nregs * 4;
503   /* FIXME : leaf_function_p below is too strong.
504      What we really need to know there is if there could be pending
505      stack adjustment needed at that point. */
506   restore_from_sp = ! frame_pointer_needed
507              || (! current_function_calls_alloca && leaf_function_p ());
508   if (offset + fsize >= 0x8000
509       && ! restore_from_sp
510       && (mask || fmask || fpoffset))
511     {
512 #ifdef MOTOROLA
513       asm_fprintf (stream, "\t%Omove.l %0I%d,%Ra1\n", -fsize);
514 #else
515       asm_fprintf (stream, "\tmovel %0I%d,%Ra1\n", -fsize);
516 #endif
517       fsize = 0, big = 1;
518     }
519   if (TARGET_5200 || nregs <= 2)
520     {
521       /* Restore each separately in the same order moveml does.
522          Using two movel instructions instead of a single moveml
523          is about 15% faster for the 68020 and 68030 at no expense
524          in code size. */
525
526       int i;
527
528       /* Undo the work from above. */
529       for (i = 0; i< 16; i++)
530         if (mask & (1 << i))
531           {
532             if (big)
533               {
534 #ifdef MOTOROLA
535                 asm_fprintf (stream, "\t%Omove.l -%d(%s,%Ra1.l),%s\n",
536                              offset + fsize,
537                              reg_names[FRAME_POINTER_REGNUM],
538                              reg_names[i]);
539 #else
540                 asm_fprintf (stream, "\tmovel %s@(-%d,%Ra1:l),%s\n",
541                              reg_names[FRAME_POINTER_REGNUM],
542                              offset + fsize, reg_names[i]);
543 #endif
544               }
545             else if (restore_from_sp)
546               {
547 #ifdef MOTOROLA
548                 asm_fprintf (stream, "\t%Omove.l (%Rsp)+,%s\n",
549                              reg_names[i]);
550 #else
551                 asm_fprintf (stream, "\tmovel %Rsp@+,%s\n",
552                              reg_names[i]);
553 #endif
554               }
555             else
556               {
557 #ifdef MOTOROLA
558                 asm_fprintf (stream, "\t%Omove.l -%d(%s),%s\n",
559                              offset + fsize,
560                              reg_names[FRAME_POINTER_REGNUM],
561                              reg_names[i]);
562 #else
563                 asm_fprintf (stream, "\tmovel %s@(-%d),%s\n",
564                              reg_names[FRAME_POINTER_REGNUM],
565                              offset + fsize, reg_names[i]);
566 #endif
567               }
568             offset = offset - 4;
569           }
570     }
571   else if (mask)
572     {
573       if (big)
574         {
575 #ifdef MOTOROLA
576           asm_fprintf (stream, "\tmovm.l -%d(%s,%Ra1.l),%0I0x%x\n",
577                        offset + fsize,
578                        reg_names[FRAME_POINTER_REGNUM],
579                        mask);
580 #else
581           asm_fprintf (stream, "\tmoveml %s@(-%d,%Ra1:l),%0I0x%x\n",
582                        reg_names[FRAME_POINTER_REGNUM],
583                        offset + fsize, mask);
584 #endif
585         }
586       else if (restore_from_sp)
587         {
588 #ifdef MOTOROLA
589           asm_fprintf (stream, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask);
590 #else
591           asm_fprintf (stream, "\tmoveml %Rsp@+,%0I0x%x\n", mask);
592 #endif
593         }
594       else
595         {
596 #ifdef MOTOROLA
597           asm_fprintf (stream, "\tmovm.l -%d(%s),%0I0x%x\n",
598                        offset + fsize,
599                        reg_names[FRAME_POINTER_REGNUM],
600                        mask);
601 #else
602           asm_fprintf (stream, "\tmoveml %s@(-%d),%0I0x%x\n",
603                        reg_names[FRAME_POINTER_REGNUM],
604                        offset + fsize, mask);
605 #endif
606         }
607     }
608   if (fmask)
609     {
610       if (big)
611         {
612 #ifdef MOTOROLA
613           asm_fprintf (stream, "\tfmovm -%d(%s,%Ra1.l),%0I0x%x\n",
614                        foffset + fsize,
615                        reg_names[FRAME_POINTER_REGNUM],
616                        fmask);
617 #else
618           asm_fprintf (stream, "\tfmovem %s@(-%d,%Ra1:l),%0I0x%x\n",
619                        reg_names[FRAME_POINTER_REGNUM],
620                        foffset + fsize, fmask);
621 #endif
622         }
623       else if (restore_from_sp)
624         {
625 #ifdef MOTOROLA
626           asm_fprintf (stream, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask);
627 #else
628           asm_fprintf (stream, "\tfmovem %Rsp@+,%0I0x%x\n", fmask);
629 #endif
630         }
631       else
632         {
633 #ifdef MOTOROLA
634           asm_fprintf (stream, "\tfmovm -%d(%s),%0I0x%x\n",
635                        foffset + fsize,
636                        reg_names[FRAME_POINTER_REGNUM],
637                        fmask);
638 #else
639           asm_fprintf (stream, "\tfmovem %s@(-%d),%0I0x%x\n",
640                        reg_names[FRAME_POINTER_REGNUM],
641                        foffset + fsize, fmask);
642 #endif
643         }
644     }
645   if (fpoffset != 0)
646     for (regno = 55; regno >= 24; regno--)
647       if (regs_ever_live[regno] && ! call_used_regs[regno])
648         {
649           if (big)
650             {
651 #ifdef MOTOROLA
652               asm_fprintf (stream, "\tfpmovd -%d(%s,%Ra1.l), %s\n",
653                            fpoffset + fsize,
654                            reg_names[FRAME_POINTER_REGNUM],
655                            reg_names[regno]);
656 #else
657               asm_fprintf (stream, "\tfpmoved %s@(-%d,%Ra1:l), %s\n",
658                            reg_names[FRAME_POINTER_REGNUM],
659                            fpoffset + fsize, reg_names[regno]);
660 #endif
661             }
662           else if (restore_from_sp)
663             {
664 #ifdef MOTOROLA
665               asm_fprintf (stream, "\tfpmovd (%Rsp)+,%s\n",
666                            reg_names[regno]);
667 #else
668               asm_fprintf (stream, "\tfpmoved %Rsp@+, %s\n",
669                            reg_names[regno]);
670 #endif
671             }
672           else
673             {
674 #ifdef MOTOROLA
675               asm_fprintf (stream, "\tfpmovd -%d(%s), %s\n",
676                            fpoffset + fsize,
677                            reg_names[FRAME_POINTER_REGNUM],
678                            reg_names[regno]);
679 #else
680               asm_fprintf (stream, "\tfpmoved %s@(-%d), %s\n",
681                            reg_names[FRAME_POINTER_REGNUM],
682                            fpoffset + fsize, reg_names[regno]);
683 #endif
684             }
685           fpoffset -= 8;
686         }
687   if (frame_pointer_needed)
688     fprintf (stream, "\tunlk %s\n",
689              reg_names[FRAME_POINTER_REGNUM]);
690   else if (fsize)
691     {
692 #ifdef NO_ADDSUB_Q
693       if (fsize + 4 <= 8) 
694         {
695           if (!TARGET_5200)
696             {
697 #ifdef MOTOROLA
698               asm_fprintf (stream, "\taddq.w %OI%d,%Rsp\n", fsize + 4);
699 #else
700               asm_fprintf (stream, "\taddqw %OI%d,%Rsp\n", fsize + 4);
701 #endif
702             }
703           else
704             {
705 #ifdef MOTOROLA
706               asm_fprintf (stream, "\taddq.l %OI%d,%Rsp\n", fsize + 4);
707 #else
708               asm_fprintf (stream, "\taddql %OI%d,%Rsp\n", fsize + 4);
709 #endif
710             }
711         }
712       else if (fsize + 4 <= 16 && TARGET_CPU32)
713         {
714           /* On the CPU32 it is faster to use two addqw instructions to
715              add a small integer (8 < N <= 16) to a register. */
716           /* asm_fprintf() cannot handle %. */
717 #ifdef MOTOROLA
718           asm_fprintf (stream, "\taddq.w %OI8,%Rsp\n\taddq.w %OI%d,%Rsp\n",
719                        fsize + 4);
720 #else
721           asm_fprintf (stream, "\taddqw %OI8,%Rsp\n\taddqw %OI%d,%Rsp\n",
722                        fsize + 4);
723 #endif
724         }
725       else
726 #endif /* NO_ADDSUB_Q */
727       if (fsize + 4 < 0x8000)
728         {
729           if (TARGET_68040)
730             { 
731               /* asm_fprintf() cannot handle %. */
732 #ifdef MOTOROLA
733               asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", fsize + 4);
734 #else
735               asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", fsize + 4);
736 #endif
737             }
738           else
739             {
740 #ifdef MOTOROLA
741               asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", fsize + 4);
742 #else
743               asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", fsize + 4);
744 #endif
745             }
746         }
747       else
748         {
749         /* asm_fprintf() cannot handle %. */
750 #ifdef MOTOROLA
751           asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", fsize + 4);
752 #else
753           asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", fsize + 4);
754 #endif
755         }
756     }
757   if (current_function_pops_args)
758     asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args);
759   else
760     fprintf (stream, "\trts\n");
761 }
762 \f
763 /* Similar to general_operand, but exclude stack_pointer_rtx.  */
764
765 int
766 not_sp_operand (op, mode)
767      register rtx op;
768      enum machine_mode mode;
769 {
770   return op != stack_pointer_rtx && general_operand (op, mode);
771 }
772
773 /* Return TRUE if X is a valid comparison operator for the dbcc 
774    instruction.  
775
776    Note it rejects floating point comparison operators.
777    (In the future we could use Fdbcc).
778
779    It also rejects some comparisons when CC_NO_OVERFLOW is set.  */
780    
781 int
782 valid_dbcc_comparison_p (x, mode)
783      rtx x;
784      enum machine_mode mode;
785 {
786   switch (GET_CODE (x))
787     {
788       case EQ: case NE: case GTU: case LTU:
789       case GEU: case LEU:
790         return 1;
791
792       /* Reject some when CC_NO_OVERFLOW is set.  This may be over
793          conservative */
794       case GT: case LT: case GE: case LE:
795         return ! (cc_prev_status.flags & CC_NO_OVERFLOW);
796       default:
797         return 0;
798     }
799 }
800
801 /* Return non-zero if flags are currently in the 68881 flag register.  */
802 int
803 flags_in_68881 ()
804 {
805   /* We could add support for these in the future */
806   return cc_status.flags & CC_IN_68881;
807 }
808
809 /* Output a dbCC; jCC sequence.  Note we do not handle the 
810    floating point version of this sequence (Fdbcc).  We also
811    do not handle alternative conditions when CC_NO_OVERFLOW is
812    set.  It is assumed that valid_dbcc_comparison_p and flags_in_68881 will
813    kick those out before we get here.  */
814
815 output_dbcc_and_branch (operands)
816      rtx *operands;
817 {
818   switch (GET_CODE (operands[3]))
819     {
820       case EQ:
821 #ifdef MOTOROLA
822         output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands);
823 #else
824         output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands);
825 #endif
826         break;
827
828       case NE:
829 #ifdef MOTOROLA
830         output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands);
831 #else
832         output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands);
833 #endif
834         break;
835
836       case GT:
837 #ifdef MOTOROLA
838         output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands);
839 #else
840         output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands);
841 #endif
842         break;
843
844       case GTU:
845 #ifdef MOTOROLA
846         output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands);
847 #else
848         output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands);
849 #endif
850         break;
851
852       case LT:
853 #ifdef MOTOROLA
854         output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands);
855 #else
856         output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands);
857 #endif
858         break;
859
860       case LTU:
861 #ifdef MOTOROLA
862         output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands);
863 #else
864         output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands);
865 #endif
866         break;
867
868       case GE:
869 #ifdef MOTOROLA
870         output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands);
871 #else
872         output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands);
873 #endif
874         break;
875
876       case GEU:
877 #ifdef MOTOROLA
878         output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands);
879 #else
880         output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands);
881 #endif
882         break;
883
884       case LE:
885 #ifdef MOTOROLA
886         output_asm_insn ("dble %0,%l1\n\tjble %l2", operands);
887 #else
888         output_asm_insn ("dble %0,%l1\n\tjle %l2", operands);
889 #endif
890         break;
891
892       case LEU:
893 #ifdef MOTOROLA
894         output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands);
895 #else
896         output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands);
897 #endif
898         break;
899
900       default:
901         abort ();
902     }
903
904   /* If the decrement is to be done in SImode, then we have
905      to compensate for the fact that dbcc decrements in HImode. */
906   switch (GET_MODE (operands[0]))
907     {
908       case SImode:
909 #ifdef MOTOROLA
910         output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands);
911 #else
912         output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands);
913 #endif
914         break;
915
916       case HImode:
917         break;
918
919       default:
920         abort ();
921     }
922 }
923
924 char *
925 output_scc_di(op, operand1, operand2, dest)
926      rtx op;
927      rtx operand1;
928      rtx operand2;
929      rtx dest;
930 {
931   rtx loperands[7];
932   enum rtx_code op_code = GET_CODE (op);
933
934   /* This does not produce a usefull cc.  */
935   CC_STATUS_INIT;
936
937   /* The m68k cmp.l instruction requires operand1 to be a reg as used
938      below.  Swap the operands and change the op if these requirements
939      are not fulfilled.  */
940   if (GET_CODE (operand2) == REG && GET_CODE (operand1) != REG)
941     {
942       rtx tmp = operand1;
943
944       operand1 = operand2;
945       operand2 = tmp;
946       op_code = swap_condition (op_code);
947     }
948   loperands[0] = operand1;
949   if (GET_CODE (operand1) == REG)
950     loperands[1] = gen_rtx (REG, SImode, REGNO (operand1) + 1);
951   else
952     loperands[1] = adj_offsettable_operand (operand1, 4);
953   if (operand2 != const0_rtx)
954     {
955       loperands[2] = operand2;
956       if (GET_CODE (operand2) == REG)
957         loperands[3] = gen_rtx (REG, SImode, REGNO (operand2) + 1);
958       else
959         loperands[3] = adj_offsettable_operand (operand2, 4);
960     }
961   loperands[4] = gen_label_rtx();
962   if (operand2 != const0_rtx)
963 #ifdef MOTOROLA
964 #ifdef SGS_CMP_ORDER
965     output_asm_insn ("cmp%.l %0,%2\n\tjbne %l4\n\tcmp%.l %1,%3", loperands);
966 #else
967     output_asm_insn ("cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1", loperands);
968 #endif
969 #else
970 #ifdef SGS_CMP_ORDER
971     output_asm_insn ("cmp%.l %0,%2\n\tjne %l4\n\tcmp%.l %1,%3", loperands);
972 #else
973     output_asm_insn ("cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1", loperands);
974 #endif
975 #endif
976   else
977 #ifdef MOTOROLA
978     output_asm_insn ("tst%.l %0\n\tjbne %l4\n\ttst%.l %1", loperands);
979 #else
980     output_asm_insn ("tst%.l %0\n\tjne %l4\n\ttst%.l %1", loperands);
981 #endif
982   loperands[5] = dest;
983   
984   switch (op_code)
985     {
986       case EQ:
987         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
988                                     CODE_LABEL_NUMBER (loperands[4]));
989         output_asm_insn ("seq %5", loperands);
990         break;
991
992       case NE:
993         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
994                                     CODE_LABEL_NUMBER (loperands[4]));
995         output_asm_insn ("sne %5", loperands);
996         break;
997
998       case GT:
999         loperands[6] = gen_label_rtx();
1000 #ifdef MOTOROLA
1001         output_asm_insn ("shi %5\n\tjbra %l6", loperands);
1002 #else
1003         output_asm_insn ("shi %5\n\tjra %l6", loperands);
1004 #endif
1005         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1006                                     CODE_LABEL_NUMBER (loperands[4]));
1007         output_asm_insn ("sgt %5", loperands);
1008         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1009                                     CODE_LABEL_NUMBER (loperands[6]));
1010         break;
1011
1012       case GTU:
1013         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1014                                     CODE_LABEL_NUMBER (loperands[4]));
1015         output_asm_insn ("shi %5", loperands);
1016         break;
1017
1018       case LT:
1019         loperands[6] = gen_label_rtx();
1020 #ifdef MOTOROLA
1021         output_asm_insn ("scs %5\n\tjbra %l6", loperands);
1022 #else
1023         output_asm_insn ("scs %5\n\tjra %l6", loperands);
1024 #endif
1025         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1026                                     CODE_LABEL_NUMBER (loperands[4]));
1027         output_asm_insn ("slt %5", loperands);
1028         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1029                                     CODE_LABEL_NUMBER (loperands[6]));
1030         break;
1031
1032       case LTU:
1033         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1034                                     CODE_LABEL_NUMBER (loperands[4]));
1035         output_asm_insn ("scs %5", loperands);
1036         break;
1037
1038       case GE:
1039         loperands[6] = gen_label_rtx();
1040 #ifdef MOTOROLA
1041         output_asm_insn ("scc %5\n\tjbra %l6", loperands);
1042 #else
1043         output_asm_insn ("scc %5\n\tjra %l6", loperands);
1044 #endif
1045         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1046                                     CODE_LABEL_NUMBER (loperands[4]));
1047         output_asm_insn ("sge %5", loperands);
1048         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1049                                     CODE_LABEL_NUMBER (loperands[6]));
1050         break;
1051
1052       case GEU:
1053         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1054                                     CODE_LABEL_NUMBER (loperands[4]));
1055         output_asm_insn ("scc %5", loperands);
1056         break;
1057
1058       case LE:
1059         loperands[6] = gen_label_rtx();
1060 #ifdef MOTOROLA
1061         output_asm_insn ("sls %5\n\tjbra %l6", loperands);
1062 #else
1063         output_asm_insn ("sls %5\n\tjra %l6", loperands);
1064 #endif
1065         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1066                                     CODE_LABEL_NUMBER (loperands[4]));
1067         output_asm_insn ("sle %5", loperands);
1068         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1069                                     CODE_LABEL_NUMBER (loperands[6]));
1070         break;
1071
1072       case LEU:
1073         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1074                                     CODE_LABEL_NUMBER (loperands[4]));
1075         output_asm_insn ("sls %5", loperands);
1076         break;
1077
1078       default:
1079         abort ();
1080     }
1081   return "";
1082 }
1083
1084 char *
1085 output_btst (operands, countop, dataop, insn, signpos)
1086      rtx *operands;
1087      rtx countop, dataop;
1088      rtx insn;
1089      int signpos;
1090 {
1091   operands[0] = countop;
1092   operands[1] = dataop;
1093
1094   if (GET_CODE (countop) == CONST_INT)
1095     {
1096       register int count = INTVAL (countop);
1097       /* If COUNT is bigger than size of storage unit in use,
1098          advance to the containing unit of same size.  */
1099       if (count > signpos)
1100         {
1101           int offset = (count & ~signpos) / 8;
1102           count = count & signpos;
1103           operands[1] = dataop = adj_offsettable_operand (dataop, offset);
1104         }
1105       if (count == signpos)
1106         cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
1107       else
1108         cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
1109
1110       /* These three statements used to use next_insns_test_no...
1111          but it appears that this should do the same job.  */
1112       if (count == 31
1113           && next_insn_tests_no_inequality (insn))
1114         return "tst%.l %1";
1115       if (count == 15
1116           && next_insn_tests_no_inequality (insn))
1117         return "tst%.w %1";
1118       if (count == 7
1119           && next_insn_tests_no_inequality (insn))
1120         return "tst%.b %1";
1121
1122       cc_status.flags = CC_NOT_NEGATIVE;
1123     }
1124   return "btst %0,%1";
1125 }
1126 \f
1127 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
1128    reference and a constant.  */
1129
1130 int
1131 symbolic_operand (op, mode)
1132      register rtx op;
1133      enum machine_mode mode;
1134 {
1135   switch (GET_CODE (op))
1136     {
1137     case SYMBOL_REF:
1138     case LABEL_REF:
1139       return 1;
1140
1141     case CONST:
1142       op = XEXP (op, 0);
1143       return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1144                || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1145               && GET_CODE (XEXP (op, 1)) == CONST_INT);
1146
1147 #if 0 /* Deleted, with corresponding change in m68k.h,
1148          so as to fit the specs.  No CONST_DOUBLE is ever symbolic.  */
1149     case CONST_DOUBLE:
1150       return GET_MODE (op) == mode;
1151 #endif
1152
1153     default:
1154       return 0;
1155     }
1156 }
1157 \f
1158 /* Check for sign_extend or zero_extend.  Used for bit-count operands. */
1159
1160 int
1161 extend_operator(x, mode)
1162      rtx x;
1163      enum machine_mode mode;
1164 {
1165     if (mode != VOIDmode && GET_MODE(x) != mode)
1166         return 0;
1167     switch (GET_CODE(x))
1168         {
1169         case SIGN_EXTEND :
1170         case ZERO_EXTEND :
1171             return 1;
1172         default :
1173             return 0;
1174         }
1175 }
1176
1177 \f
1178 /* Legitimize PIC addresses.  If the address is already
1179    position-independent, we return ORIG.  Newly generated
1180    position-independent addresses go to REG.  If we need more
1181    than one register, we lose.  
1182
1183    An address is legitimized by making an indirect reference
1184    through the Global Offset Table with the name of the symbol
1185    used as an offset.  
1186
1187    The assembler and linker are responsible for placing the 
1188    address of the symbol in the GOT.  The function prologue
1189    is responsible for initializing a5 to the starting address
1190    of the GOT.
1191
1192    The assembler is also responsible for translating a symbol name
1193    into a constant displacement from the start of the GOT.  
1194
1195    A quick example may make things a little clearer:
1196
1197    When not generating PIC code to store the value 12345 into _foo
1198    we would generate the following code:
1199
1200         movel #12345, _foo
1201
1202    When generating PIC two transformations are made.  First, the compiler
1203    loads the address of foo into a register.  So the first transformation makes:
1204
1205         lea     _foo, a0
1206         movel   #12345, a0@
1207
1208    The code in movsi will intercept the lea instruction and call this
1209    routine which will transform the instructions into:
1210
1211         movel   a5@(_foo:w), a0
1212         movel   #12345, a0@
1213    
1214
1215    That (in a nutshell) is how *all* symbol and label references are 
1216    handled.  */
1217
1218 rtx
1219 legitimize_pic_address (orig, mode, reg)
1220      rtx orig, reg;
1221      enum machine_mode mode;
1222 {
1223   rtx pic_ref = orig;
1224
1225   /* First handle a simple SYMBOL_REF or LABEL_REF */
1226   if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
1227     {
1228       if (reg == 0)
1229         abort ();
1230
1231       pic_ref = gen_rtx (MEM, Pmode,
1232                          gen_rtx (PLUS, Pmode,
1233                                   pic_offset_table_rtx, orig));
1234       current_function_uses_pic_offset_table = 1;
1235       RTX_UNCHANGING_P (pic_ref) = 1;
1236       emit_move_insn (reg, pic_ref);
1237       return reg;
1238     }
1239   else if (GET_CODE (orig) == CONST)
1240     {
1241       rtx base, offset;
1242
1243       /* Make sure this is CONST has not already been legitimized */
1244       if (GET_CODE (XEXP (orig, 0)) == PLUS
1245           && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
1246         return orig;
1247
1248       if (reg == 0)
1249         abort ();
1250
1251       /* legitimize both operands of the PLUS */
1252       if (GET_CODE (XEXP (orig, 0)) == PLUS)
1253         {
1254           base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
1255           orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
1256                                          base == reg ? 0 : reg);
1257         }
1258       else abort ();
1259
1260       if (GET_CODE (orig) == CONST_INT)
1261         return plus_constant_for_output (base, INTVAL (orig));
1262       pic_ref = gen_rtx (PLUS, Pmode, base, orig);
1263       /* Likewise, should we set special REG_NOTEs here?  */
1264     }
1265   return pic_ref;
1266 }
1267
1268 \f
1269 typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ } CONST_METHOD;
1270
1271 #define USE_MOVQ(i)     ((unsigned)((i) + 128) <= 255)
1272
1273 CONST_METHOD
1274 const_method (constant)
1275      rtx constant;
1276 {
1277   int i;
1278   unsigned u;
1279
1280   i = INTVAL (constant);
1281   if (USE_MOVQ (i))
1282     return MOVQ;
1283
1284   /* The Coldfire doesn't have byte or word operations. */
1285   /* FIXME: This may not be useful for the m68060 either */
1286   if (!TARGET_5200) 
1287     {
1288       /* if -256 < N < 256 but N is not in range for a moveq
1289          N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */
1290       if (USE_MOVQ (i ^ 0xff))
1291         return NOTB;
1292       /* Likewise, try with not.w */
1293       if (USE_MOVQ (i ^ 0xffff))
1294         return NOTW;
1295       /* This is the only value where neg.w is useful */
1296       if (i == -65408)
1297         return NEGW;
1298       /* Try also with swap */
1299       u = i;
1300       if (USE_MOVQ ((u >> 16) | (u << 16)))
1301         return SWAP;
1302     }
1303   /* Otherwise, use move.l */
1304   return MOVL;
1305 }
1306
1307 const_int_cost (constant)
1308      rtx constant;
1309 {
1310   switch (const_method (constant))
1311     {
1312       case MOVQ :
1313       /* Constants between -128 and 127 are cheap due to moveq */
1314         return 0;
1315       case NOTB :
1316       case NOTW :
1317       case NEGW :
1318       case SWAP :
1319       /* Constants easily generated by moveq + not.b/not.w/neg.w/swap  */
1320         return 1;
1321       case MOVL :
1322         return 2;
1323       default :
1324         abort ();
1325     }
1326 }
1327
1328 char *
1329 output_move_const_into_data_reg (operands)
1330      rtx *operands;
1331 {
1332   int i;
1333
1334   i = INTVAL (operands[1]);
1335   switch (const_method (operands[1]))
1336     {
1337     case MOVQ :
1338 #if defined (MOTOROLA) && !defined (CRDS)
1339       return "moveq%.l %1,%0";
1340 #else
1341       return "moveq %1,%0";
1342 #endif
1343     case NOTB :
1344       operands[1] = gen_rtx (CONST_INT, VOIDmode, i ^ 0xff);
1345 #if defined (MOTOROLA) && !defined (CRDS)
1346       return "moveq%.l %1,%0\n\tnot%.b %0";
1347 #else
1348       return "moveq %1,%0\n\tnot%.b %0";
1349 #endif   
1350     case NOTW :
1351       operands[1] = gen_rtx (CONST_INT, VOIDmode, i ^ 0xffff);
1352 #if defined (MOTOROLA) && !defined (CRDS)
1353       return "moveq%.l %1,%0\n\tnot%.w %0";
1354 #else
1355       return "moveq %1,%0\n\tnot%.w %0";
1356 #endif   
1357     case NEGW :
1358 #if defined (MOTOROLA) && !defined (CRDS)
1359       return "moveq%.l %#-128,%0\n\tneg%.w %0";
1360 #else
1361       return "moveq %#-128,%0\n\tneg%.w %0";
1362 #endif   
1363     case SWAP :
1364       {
1365         unsigned u = i;
1366
1367         operands[1] = gen_rtx (CONST_INT, VOIDmode, (u << 16) | (u >> 16));
1368 #if defined (MOTOROLA) && !defined (CRDS)
1369         return "moveq%.l %1,%0\n\tswap %0";
1370 #else
1371         return "moveq %1,%0\n\tswap %0";
1372 #endif   
1373       }
1374     case MOVL :
1375         return "move%.l %1,%0";
1376     default :
1377         abort ();
1378     }
1379 }
1380
1381 char *
1382 output_move_simode_const (operands)
1383      rtx *operands;
1384 {
1385   if (operands[1] == const0_rtx
1386       && (DATA_REG_P (operands[0])
1387           || GET_CODE (operands[0]) == MEM)
1388       /* clr insns on 68000 read before writing.
1389          This isn't so on the 68010, but we have no TARGET_68010.  */
1390       && ((TARGET_68020 || TARGET_5200)
1391           || !(GET_CODE (operands[0]) == MEM
1392                && MEM_VOLATILE_P (operands[0]))))
1393     return "clr%.l %0";
1394   else if (DATA_REG_P (operands[0]))
1395     return output_move_const_into_data_reg (operands);
1396   else if (ADDRESS_REG_P (operands[0])
1397            && INTVAL (operands[1]) < 0x8000
1398            && INTVAL (operands[1]) >= -0x8000)
1399     return "move%.w %1,%0";
1400   else if (GET_CODE (operands[0]) == MEM
1401       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
1402       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
1403            && INTVAL (operands[1]) < 0x8000
1404            && INTVAL (operands[1]) >= -0x8000)
1405     return "pea %a1";
1406   return "move%.l %1,%0";
1407 }
1408
1409 char *
1410 output_move_simode (operands)
1411      rtx *operands;
1412 {
1413   if (GET_CODE (operands[1]) == CONST_INT)
1414     return output_move_simode_const (operands);
1415   else if ((GET_CODE (operands[1]) == SYMBOL_REF
1416             || GET_CODE (operands[1]) == CONST)
1417            && push_operand (operands[0], SImode))
1418     return "pea %a1";
1419   else if ((GET_CODE (operands[1]) == SYMBOL_REF
1420             || GET_CODE (operands[1]) == CONST)
1421            && ADDRESS_REG_P (operands[0]))
1422     return "lea %a1,%0";
1423   return "move%.l %1,%0";
1424 }
1425
1426 char *
1427 output_move_himode (operands)
1428      rtx *operands;
1429 {
1430  if (GET_CODE (operands[1]) == CONST_INT)
1431     {
1432       if (operands[1] == const0_rtx
1433           && (DATA_REG_P (operands[0])
1434               || GET_CODE (operands[0]) == MEM)
1435           /* clr insns on 68000 read before writing.
1436              This isn't so on the 68010, but we have no TARGET_68010.  */
1437           && ((TARGET_68020 || TARGET_5200)
1438               || !(GET_CODE (operands[0]) == MEM
1439                    && MEM_VOLATILE_P (operands[0]))))
1440         return "clr%.w %0";
1441       else if (DATA_REG_P (operands[0])
1442                && INTVAL (operands[1]) < 128
1443                && INTVAL (operands[1]) >= -128)
1444         {
1445 #if defined(MOTOROLA) && !defined(CRDS)
1446           return "moveq%.l %1,%0";
1447 #else
1448           return "moveq %1,%0";
1449 #endif
1450         }
1451       else if (INTVAL (operands[1]) < 0x8000
1452                && INTVAL (operands[1]) >= -0x8000)
1453         return "move%.w %1,%0";
1454     }
1455   else if (CONSTANT_P (operands[1]))
1456     return "move%.l %1,%0";
1457 #ifndef SGS_NO_LI
1458   /* Recognize the insn before a tablejump, one that refers
1459      to a table of offsets.  Such an insn will need to refer
1460      to a label on the insn.  So output one.  Use the label-number
1461      of the table of offsets to generate this label.  This code,
1462      and similar code below, assumes that there will be at most one
1463      reference to each table.  */
1464   if (GET_CODE (operands[1]) == MEM
1465       && GET_CODE (XEXP (operands[1], 0)) == PLUS
1466       && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF
1467       && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS)
1468     {
1469       rtx labelref = XEXP (XEXP (operands[1], 0), 1);
1470 #if defined (MOTOROLA) && !defined (SGS_SWITCH_TABLES)
1471 #ifdef SGS
1472       asm_fprintf (asm_out_file, "\tset %LLI%d,.+2\n",
1473                    CODE_LABEL_NUMBER (XEXP (labelref, 0)));
1474 #else /* not SGS */
1475       asm_fprintf (asm_out_file, "\t.set %LLI%d,.+2\n",
1476                    CODE_LABEL_NUMBER (XEXP (labelref, 0)));
1477 #endif /* not SGS */
1478 #else /* SGS_SWITCH_TABLES or not MOTOROLA */
1479       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LI",
1480                                  CODE_LABEL_NUMBER (XEXP (labelref, 0)));
1481 #ifdef SGS_SWITCH_TABLES
1482       /* Set flag saying we need to define the symbol
1483          LD%n (with value L%n-LI%n) at the end of the switch table.  */
1484       switch_table_difference_label_flag = 1;
1485 #endif /* SGS_SWITCH_TABLES */
1486 #endif /* SGS_SWITCH_TABLES or not MOTOROLA */
1487     }
1488 #endif /* SGS_NO_LI */
1489   return "move%.w %1,%0";
1490 }
1491
1492 char *
1493 output_move_qimode (operands)
1494      rtx *operands;
1495 {
1496   rtx xoperands[4];
1497
1498   /* This is probably useless, since it loses for pushing a struct
1499      of several bytes a byte at a time.  */
1500   if (GET_CODE (operands[0]) == MEM
1501       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
1502       && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx
1503       && ! ADDRESS_REG_P (operands[1]))
1504     {
1505       xoperands[1] = operands[1];
1506       xoperands[2]
1507         = gen_rtx (MEM, QImode,
1508                    gen_rtx (PLUS, VOIDmode, stack_pointer_rtx, const1_rtx));
1509       /* Just pushing a byte puts it in the high byte of the halfword.  */
1510       /* We must put it in the low-order, high-numbered byte.  */
1511       if (!reg_mentioned_p (stack_pointer_rtx, operands[1]))
1512         {
1513           xoperands[3] = stack_pointer_rtx;
1514 #ifndef NO_ADDSUB_Q
1515           output_asm_insn ("subq%.l %#2,%3\n\tmove%.b %1,%2", xoperands);
1516 #else
1517           output_asm_insn ("sub%.l %#2,%3\n\tmove%.b %1,%2", xoperands);
1518 #endif
1519         }
1520       else
1521         output_asm_insn ("move%.b %1,%-\n\tmove%.b %@,%2", xoperands);
1522       return "";
1523     }
1524
1525   /* clr and st insns on 68000 read before writing.
1526      This isn't so on the 68010, but we have no TARGET_68010.  */
1527   if (!ADDRESS_REG_P (operands[0])
1528       && ((TARGET_68020 || TARGET_5200)
1529           || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
1530     {
1531       if (operands[1] == const0_rtx)
1532         return "clr%.b %0";
1533       if ((!TARGET_5200 || DATA_REG_P (operands[0]))
1534           && GET_CODE (operands[1]) == CONST_INT
1535           && (INTVAL (operands[1]) & 255) == 255)
1536         {
1537           CC_STATUS_INIT;
1538           return "st %0";
1539         }
1540     }
1541   if (GET_CODE (operands[1]) == CONST_INT
1542       && DATA_REG_P (operands[0])
1543       && INTVAL (operands[1]) < 128
1544       && INTVAL (operands[1]) >= -128)
1545     {
1546 #if defined(MOTOROLA) && !defined(CRDS)
1547       return "moveq%.l %1,%0";
1548 #else
1549       return "moveq %1,%0";
1550 #endif
1551     }
1552   if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
1553     return "move%.l %1,%0";
1554   if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1]))
1555     return "move%.w %1,%0";
1556   return "move%.b %1,%0";
1557 }
1558
1559 /* Return the best assembler insn template
1560    for moving operands[1] into operands[0] as a fullword.  */
1561
1562 static char *
1563 singlemove_string (operands)
1564      rtx *operands;
1565 {
1566 #ifdef SUPPORT_SUN_FPA
1567   if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
1568     return "fpmoves %1,%0";
1569 #endif
1570   if (GET_CODE (operands[1]) == CONST_INT)
1571     return output_move_simode_const (operands);
1572   return "move%.l %1,%0";
1573 }
1574
1575
1576 /* Output assembler code to perform a doubleword move insn
1577    with operands OPERANDS.  */
1578
1579 char *
1580 output_move_double (operands)
1581      rtx *operands;
1582 {
1583   enum
1584     {
1585       REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP
1586     } optype0, optype1;
1587   rtx latehalf[2];
1588   rtx middlehalf[2];
1589   rtx xops[2];
1590   rtx addreg0 = 0, addreg1 = 0;
1591   int dest_overlapped_low = 0;
1592   int size = GET_MODE_SIZE (GET_MODE (operands[0]));
1593
1594   middlehalf[0] = 0;
1595   middlehalf[1] = 0;
1596
1597   /* First classify both operands.  */
1598
1599   if (REG_P (operands[0]))
1600     optype0 = REGOP;
1601   else if (offsettable_memref_p (operands[0]))
1602     optype0 = OFFSOP;
1603   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
1604     optype0 = POPOP;
1605   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
1606     optype0 = PUSHOP;
1607   else if (GET_CODE (operands[0]) == MEM)
1608     optype0 = MEMOP;
1609   else
1610     optype0 = RNDOP;
1611
1612   if (REG_P (operands[1]))
1613     optype1 = REGOP;
1614   else if (CONSTANT_P (operands[1]))
1615     optype1 = CNSTOP;
1616   else if (offsettable_memref_p (operands[1]))
1617     optype1 = OFFSOP;
1618   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
1619     optype1 = POPOP;
1620   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
1621     optype1 = PUSHOP;
1622   else if (GET_CODE (operands[1]) == MEM)
1623     optype1 = MEMOP;
1624   else
1625     optype1 = RNDOP;
1626
1627   /* Check for the cases that the operand constraints are not
1628      supposed to allow to happen.  Abort if we get one,
1629      because generating code for these cases is painful.  */
1630
1631   if (optype0 == RNDOP || optype1 == RNDOP)
1632     abort ();
1633
1634   /* If one operand is decrementing and one is incrementing
1635      decrement the former register explicitly
1636      and change that operand into ordinary indexing.  */
1637
1638   if (optype0 == PUSHOP && optype1 == POPOP)
1639     {
1640       operands[0] = XEXP (XEXP (operands[0], 0), 0);
1641       if (size == 12)
1642         output_asm_insn ("sub%.l %#12,%0", operands);
1643       else
1644         output_asm_insn ("subq%.l %#8,%0", operands);
1645       if (GET_MODE (operands[1]) == XFmode)
1646         operands[0] = gen_rtx (MEM, XFmode, operands[0]);
1647       else if (GET_MODE (operands[0]) == DFmode)
1648         operands[0] = gen_rtx (MEM, DFmode, operands[0]);
1649       else
1650         operands[0] = gen_rtx (MEM, DImode, operands[0]);
1651       optype0 = OFFSOP;
1652     }
1653   if (optype0 == POPOP && optype1 == PUSHOP)
1654     {
1655       operands[1] = XEXP (XEXP (operands[1], 0), 0);
1656       if (size == 12)
1657         output_asm_insn ("sub%.l %#12,%1", operands);
1658       else
1659         output_asm_insn ("subq%.l %#8,%1", operands);
1660       if (GET_MODE (operands[1]) == XFmode)
1661         operands[1] = gen_rtx (MEM, XFmode, operands[1]);
1662       else if (GET_MODE (operands[1]) == DFmode)
1663         operands[1] = gen_rtx (MEM, DFmode, operands[1]);
1664       else
1665         operands[1] = gen_rtx (MEM, DImode, operands[1]);
1666       optype1 = OFFSOP;
1667     }
1668
1669   /* If an operand is an unoffsettable memory ref, find a register
1670      we can increment temporarily to make it refer to the second word.  */
1671
1672   if (optype0 == MEMOP)
1673     addreg0 = find_addr_reg (XEXP (operands[0], 0));
1674
1675   if (optype1 == MEMOP)
1676     addreg1 = find_addr_reg (XEXP (operands[1], 0));
1677
1678   /* Ok, we can do one word at a time.
1679      Normally we do the low-numbered word first,
1680      but if either operand is autodecrementing then we
1681      do the high-numbered word first.
1682
1683      In either case, set up in LATEHALF the operands to use
1684      for the high-numbered word and in some cases alter the
1685      operands in OPERANDS to be suitable for the low-numbered word.  */
1686
1687   if (size == 12)
1688     {
1689       if (optype0 == REGOP)
1690         {
1691           latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
1692           middlehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1693         }
1694       else if (optype0 == OFFSOP)
1695         {
1696           middlehalf[0] = adj_offsettable_operand (operands[0], 4);
1697           latehalf[0] = adj_offsettable_operand (operands[0], size - 4);
1698         }
1699       else
1700         {
1701           middlehalf[0] = operands[0];
1702           latehalf[0] = operands[0];
1703         }
1704
1705       if (optype1 == REGOP)
1706         {
1707           latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
1708           middlehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
1709         }
1710       else if (optype1 == OFFSOP)
1711         {
1712           middlehalf[1] = adj_offsettable_operand (operands[1], 4);
1713           latehalf[1] = adj_offsettable_operand (operands[1], size - 4);
1714         }
1715       else if (optype1 == CNSTOP)
1716         {
1717           if (GET_CODE (operands[1]) == CONST_DOUBLE)
1718             {
1719               REAL_VALUE_TYPE r;
1720               long l[3];
1721
1722               REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
1723               REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
1724               operands[1] = GEN_INT (l[0]);
1725               middlehalf[1] = GEN_INT (l[1]);
1726               latehalf[1] = GEN_INT (l[2]);
1727             }
1728           else if (CONSTANT_P (operands[1]))
1729             {
1730               /* actually, no non-CONST_DOUBLE constant should ever
1731                  appear here.  */
1732               abort ();
1733               if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
1734                 latehalf[1] = constm1_rtx;
1735               else
1736                 latehalf[1] = const0_rtx;
1737             }
1738         }
1739       else
1740         {
1741           middlehalf[1] = operands[1];
1742           latehalf[1] = operands[1];
1743         }
1744     }
1745   else
1746     /* size is not 12: */
1747     {
1748       if (optype0 == REGOP)
1749         latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1750       else if (optype0 == OFFSOP)
1751         latehalf[0] = adj_offsettable_operand (operands[0], size - 4);
1752       else
1753         latehalf[0] = operands[0];
1754
1755       if (optype1 == REGOP)
1756         latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
1757       else if (optype1 == OFFSOP)
1758         latehalf[1] = adj_offsettable_operand (operands[1], size - 4);
1759       else if (optype1 == CNSTOP)
1760         split_double (operands[1], &operands[1], &latehalf[1]);
1761       else
1762         latehalf[1] = operands[1];
1763     }
1764
1765   /* If insn is effectively movd N(sp),-(sp) then we will do the
1766      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
1767      for the low word as well, to compensate for the first decrement of sp.  */
1768   if (optype0 == PUSHOP
1769       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
1770       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
1771     operands[1] = middlehalf[1] = latehalf[1];
1772
1773   /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
1774      if the upper part of reg N does not appear in the MEM, arrange to
1775      emit the move late-half first.  Otherwise, compute the MEM address
1776      into the upper part of N and use that as a pointer to the memory
1777      operand.  */
1778   if (optype0 == REGOP
1779       && (optype1 == OFFSOP || optype1 == MEMOP))
1780     {
1781       rtx testlow = gen_rtx (REG, SImode, REGNO (operands[0]));
1782
1783       if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
1784           && reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
1785         {
1786           /* If both halves of dest are used in the src memory address,
1787              compute the address into latehalf of dest.
1788              Note that this can't happen if the dest is two data regs.  */
1789 compadr:
1790           xops[0] = latehalf[0];
1791           xops[1] = XEXP (operands[1], 0);
1792           output_asm_insn ("lea %a1,%0", xops);
1793           if( GET_MODE (operands[1]) == XFmode )
1794             {
1795               operands[1] = gen_rtx (MEM, XFmode, latehalf[0]);
1796               middlehalf[1] = adj_offsettable_operand (operands[1], size-8);
1797               latehalf[1] = adj_offsettable_operand (operands[1], size-4);
1798             }
1799           else
1800             {
1801               operands[1] = gen_rtx (MEM, DImode, latehalf[0]);
1802               latehalf[1] = adj_offsettable_operand (operands[1], size-4);
1803             }
1804         }
1805       else if (size == 12
1806                && reg_overlap_mentioned_p (middlehalf[0],
1807                                            XEXP (operands[1], 0)))
1808         {
1809           /* Check for two regs used by both source and dest.
1810              Note that this can't happen if the dest is all data regs.
1811              It can happen if the dest is d6, d7, a0.
1812              But in that case, latehalf is an addr reg, so
1813              the code at compadr does ok.  */
1814
1815           if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
1816               || reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
1817             goto compadr;
1818
1819           /* JRV says this can't happen: */
1820           if (addreg0 || addreg1)
1821             abort ();
1822
1823           /* Only the middle reg conflicts; simply put it last. */
1824           output_asm_insn (singlemove_string (operands), operands);
1825           output_asm_insn (singlemove_string (latehalf), latehalf);
1826           output_asm_insn (singlemove_string (middlehalf), middlehalf);
1827           return "";
1828         }
1829       else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)))
1830         /* If the low half of dest is mentioned in the source memory
1831            address, the arrange to emit the move late half first.  */
1832         dest_overlapped_low = 1;
1833     }
1834
1835   /* If one or both operands autodecrementing,
1836      do the two words, high-numbered first.  */
1837
1838   /* Likewise,  the first move would clobber the source of the second one,
1839      do them in the other order.  This happens only for registers;
1840      such overlap can't happen in memory unless the user explicitly
1841      sets it up, and that is an undefined circumstance.  */
1842
1843   if (optype0 == PUSHOP || optype1 == PUSHOP
1844       || (optype0 == REGOP && optype1 == REGOP
1845           && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1]))
1846               || REGNO (operands[0]) == REGNO (latehalf[1])))
1847       || dest_overlapped_low)
1848     {
1849       /* Make any unoffsettable addresses point at high-numbered word.  */
1850       if (addreg0)
1851         {
1852           if (size == 12)
1853             output_asm_insn ("addq%.l %#8,%0", &addreg0);
1854           else
1855             output_asm_insn ("addq%.l %#4,%0", &addreg0);
1856         }
1857       if (addreg1)
1858         {
1859           if (size == 12)
1860             output_asm_insn ("addq%.l %#8,%0", &addreg1);
1861           else
1862             output_asm_insn ("addq%.l %#4,%0", &addreg1);
1863         }
1864
1865       /* Do that word.  */
1866       output_asm_insn (singlemove_string (latehalf), latehalf);
1867
1868       /* Undo the adds we just did.  */
1869       if (addreg0)
1870         output_asm_insn ("subq%.l %#4,%0", &addreg0);
1871       if (addreg1)
1872         output_asm_insn ("subq%.l %#4,%0", &addreg1);
1873
1874       if (size == 12)
1875         {
1876           output_asm_insn (singlemove_string (middlehalf), middlehalf);
1877           if (addreg0)
1878             output_asm_insn ("subq%.l %#4,%0", &addreg0);
1879           if (addreg1)
1880             output_asm_insn ("subq%.l %#4,%0", &addreg1);
1881         }
1882
1883       /* Do low-numbered word.  */
1884       return singlemove_string (operands);
1885     }
1886
1887   /* Normal case: do the two words, low-numbered first.  */
1888
1889   output_asm_insn (singlemove_string (operands), operands);
1890
1891   /* Do the middle one of the three words for long double */
1892   if (size == 12)
1893     {
1894       if (addreg0)
1895         output_asm_insn ("addq%.l %#4,%0", &addreg0);
1896       if (addreg1)
1897         output_asm_insn ("addq%.l %#4,%0", &addreg1);
1898
1899       output_asm_insn (singlemove_string (middlehalf), middlehalf);
1900     }
1901
1902   /* Make any unoffsettable addresses point at high-numbered word.  */
1903   if (addreg0)
1904     output_asm_insn ("addq%.l %#4,%0", &addreg0);
1905   if (addreg1)
1906     output_asm_insn ("addq%.l %#4,%0", &addreg1);
1907
1908   /* Do that word.  */
1909   output_asm_insn (singlemove_string (latehalf), latehalf);
1910
1911   /* Undo the adds we just did.  */
1912   if (addreg0)
1913     {
1914       if (size == 12)
1915         output_asm_insn ("subq%.l %#8,%0", &addreg0);
1916       else
1917         output_asm_insn ("subq%.l %#4,%0", &addreg0);
1918     }
1919   if (addreg1)
1920     {
1921       if (size == 12)
1922         output_asm_insn ("subq%.l %#8,%0", &addreg1);
1923       else
1924         output_asm_insn ("subq%.l %#4,%0", &addreg1);
1925     }
1926
1927   return "";
1928 }
1929
1930 /* Return a REG that occurs in ADDR with coefficient 1.
1931    ADDR can be effectively incremented by incrementing REG.  */
1932
1933 static rtx
1934 find_addr_reg (addr)
1935      rtx addr;
1936 {
1937   while (GET_CODE (addr) == PLUS)
1938     {
1939       if (GET_CODE (XEXP (addr, 0)) == REG)
1940         addr = XEXP (addr, 0);
1941       else if (GET_CODE (XEXP (addr, 1)) == REG)
1942         addr = XEXP (addr, 1);
1943       else if (CONSTANT_P (XEXP (addr, 0)))
1944         addr = XEXP (addr, 1);
1945       else if (CONSTANT_P (XEXP (addr, 1)))
1946         addr = XEXP (addr, 0);
1947       else
1948         abort ();
1949     }
1950   if (GET_CODE (addr) == REG)
1951     return addr;
1952   abort ();
1953 }
1954 \f
1955 /* Store in cc_status the expressions that the condition codes will
1956    describe after execution of an instruction whose pattern is EXP.
1957    Do not alter them if the instruction would not alter the cc's.  */
1958
1959 /* On the 68000, all the insns to store in an address register fail to
1960    set the cc's.  However, in some cases these instructions can make it
1961    possibly invalid to use the saved cc's.  In those cases we clear out
1962    some or all of the saved cc's so they won't be used.  */
1963
1964 notice_update_cc (exp, insn)
1965      rtx exp;
1966      rtx insn;
1967 {
1968   /* If the cc is being set from the fpa and the expression is not an
1969      explicit floating point test instruction (which has code to deal with
1970      this), reinit the CC.  */
1971   if (((cc_status.value1 && FPA_REG_P (cc_status.value1))
1972        || (cc_status.value2 && FPA_REG_P (cc_status.value2)))
1973       && !(GET_CODE (exp) == PARALLEL
1974            && GET_CODE (XVECEXP (exp, 0, 0)) == SET
1975            && XEXP (XVECEXP (exp, 0, 0), 0) == cc0_rtx))
1976     {
1977       CC_STATUS_INIT; 
1978     }
1979   else if (GET_CODE (exp) == SET)
1980     {
1981       if (GET_CODE (SET_SRC (exp)) == CALL)
1982         {
1983           CC_STATUS_INIT; 
1984         }
1985       else if (ADDRESS_REG_P (SET_DEST (exp)))
1986         {
1987           if (cc_status.value1
1988               && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
1989             cc_status.value1 = 0;
1990           if (cc_status.value2
1991               && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
1992             cc_status.value2 = 0; 
1993         }
1994       else if (!FP_REG_P (SET_DEST (exp))
1995                && SET_DEST (exp) != cc0_rtx
1996                && (FP_REG_P (SET_SRC (exp))
1997                    || GET_CODE (SET_SRC (exp)) == FIX
1998                    || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE
1999                    || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND))
2000         {
2001           CC_STATUS_INIT; 
2002         }
2003       /* A pair of move insns doesn't produce a useful overall cc.  */
2004       else if (!FP_REG_P (SET_DEST (exp))
2005                && !FP_REG_P (SET_SRC (exp))
2006                && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
2007                && (GET_CODE (SET_SRC (exp)) == REG
2008                    || GET_CODE (SET_SRC (exp)) == MEM
2009                    || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
2010         {
2011           CC_STATUS_INIT; 
2012         }
2013       else if (GET_CODE (SET_SRC (exp)) == CALL)
2014         {
2015           CC_STATUS_INIT; 
2016         }
2017       else if (XEXP (exp, 0) != pc_rtx)
2018         {
2019           cc_status.flags = 0;
2020           cc_status.value1 = XEXP (exp, 0);
2021           cc_status.value2 = XEXP (exp, 1);
2022         }
2023     }
2024   else if (GET_CODE (exp) == PARALLEL
2025            && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
2026     {
2027       if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0)))
2028         CC_STATUS_INIT;
2029       else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx)
2030         {
2031           cc_status.flags = 0;
2032           cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
2033           cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
2034         }
2035     }
2036   else
2037     CC_STATUS_INIT;
2038   if (cc_status.value2 != 0
2039       && ADDRESS_REG_P (cc_status.value2)
2040       && GET_MODE (cc_status.value2) == QImode)
2041     CC_STATUS_INIT;
2042   if (cc_status.value2 != 0
2043       && !(cc_status.value1 && FPA_REG_P (cc_status.value1)))
2044     switch (GET_CODE (cc_status.value2))
2045       {
2046       case PLUS: case MINUS: case MULT:
2047       case DIV: case UDIV: case MOD: case UMOD: case NEG:
2048 #if 0 /* These instructions always clear the overflow bit */
2049       case ASHIFT: case ASHIFTRT: case LSHIFTRT:
2050       case ROTATE: case ROTATERT:
2051 #endif
2052         if (GET_MODE (cc_status.value2) != VOIDmode)
2053           cc_status.flags |= CC_NO_OVERFLOW;
2054         break;
2055       case ZERO_EXTEND:
2056         /* (SET r1 (ZERO_EXTEND r2)) on this machine
2057            ends with a move insn moving r2 in r2's mode.
2058            Thus, the cc's are set for r2.
2059            This can set N bit spuriously. */
2060         cc_status.flags |= CC_NOT_NEGATIVE; 
2061       }
2062   if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
2063       && cc_status.value2
2064       && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
2065     cc_status.value2 = 0;
2066   if (((cc_status.value1 && FP_REG_P (cc_status.value1))
2067        || (cc_status.value2 && FP_REG_P (cc_status.value2)))
2068       && !((cc_status.value1 && FPA_REG_P (cc_status.value1))
2069            || (cc_status.value2 && FPA_REG_P (cc_status.value2))))
2070     cc_status.flags = CC_IN_68881;
2071 }
2072 \f
2073 char *
2074 output_move_const_double (operands)
2075      rtx *operands;
2076 {
2077 #ifdef SUPPORT_SUN_FPA
2078   if (TARGET_FPA && FPA_REG_P (operands[0]))
2079     {
2080       int code = standard_sun_fpa_constant_p (operands[1]);
2081
2082       if (code != 0)
2083         {
2084           static char buf[40];
2085
2086           sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff);
2087           return buf;
2088         }
2089       return "fpmove%.d %1,%0";
2090     }
2091   else
2092 #endif
2093     {
2094       int code = standard_68881_constant_p (operands[1]);
2095
2096       if (code != 0)
2097         {
2098           static char buf[40];
2099
2100           sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
2101           return buf;
2102         }
2103       return "fmove%.d %1,%0";
2104     }
2105 }
2106
2107 char *
2108 output_move_const_single (operands)
2109      rtx *operands;
2110 {
2111 #ifdef SUPPORT_SUN_FPA
2112   if (TARGET_FPA)
2113     {
2114       int code = standard_sun_fpa_constant_p (operands[1]);
2115
2116       if (code != 0)
2117         {
2118           static char buf[40];
2119
2120           sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff);
2121           return buf;
2122         }
2123       return "fpmove%.s %1,%0";
2124     }
2125   else
2126 #endif /* defined SUPPORT_SUN_FPA */
2127     {
2128       int code = standard_68881_constant_p (operands[1]);
2129
2130       if (code != 0)
2131         {
2132           static char buf[40];
2133
2134           sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
2135           return buf;
2136         }
2137       return "fmove%.s %f1,%0";
2138     }
2139 }
2140
2141 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
2142    from the "fmovecr" instruction.
2143    The value, anded with 0xff, gives the code to use in fmovecr
2144    to get the desired constant.  */
2145
2146 /* This code has been fixed for cross-compilation. */
2147   
2148 static int inited_68881_table = 0;
2149
2150 char *strings_68881[7] = {
2151   "0.0",
2152   "1.0",
2153   "10.0",
2154   "100.0",
2155   "10000.0",
2156   "1e8",
2157   "1e16"
2158   };
2159
2160 int codes_68881[7] = {
2161   0x0f,
2162   0x32,
2163   0x33,
2164   0x34,
2165   0x35,
2166   0x36,
2167   0x37
2168   };
2169
2170 REAL_VALUE_TYPE values_68881[7];
2171
2172 /* Set up values_68881 array by converting the decimal values
2173    strings_68881 to binary.   */
2174
2175 void
2176 init_68881_table ()
2177 {
2178   int i;
2179   REAL_VALUE_TYPE r;
2180   enum machine_mode mode;
2181
2182   mode = SFmode;
2183   for (i = 0; i < 7; i++)
2184     {
2185       if (i == 6)
2186         mode = DFmode;
2187       r = REAL_VALUE_ATOF (strings_68881[i], mode);
2188       values_68881[i] = r;
2189     }
2190   inited_68881_table = 1;
2191 }
2192
2193 int
2194 standard_68881_constant_p (x)
2195      rtx x;
2196 {
2197   REAL_VALUE_TYPE r;
2198   int i;
2199   enum machine_mode mode;
2200
2201 #ifdef NO_ASM_FMOVECR
2202   return 0;
2203 #endif
2204
2205   /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */
2206   if (TARGET_68040)
2207     return 0;
2208
2209 #ifndef REAL_ARITHMETIC
2210 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2211   if (! flag_pretend_float)
2212     return 0;
2213 #endif
2214 #endif
2215
2216   if (! inited_68881_table)
2217     init_68881_table ();
2218
2219   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2220
2221   for (i = 0; i < 6; i++)
2222     {
2223       if (REAL_VALUES_EQUAL (r, values_68881[i]))
2224         return (codes_68881[i]);
2225     }
2226   
2227   if (GET_MODE (x) == SFmode)
2228     return 0;
2229
2230   if (REAL_VALUES_EQUAL (r, values_68881[6]))
2231     return (codes_68881[6]);
2232
2233   /* larger powers of ten in the constants ram are not used
2234      because they are not equal to a `double' C constant.  */
2235   return 0;
2236 }
2237
2238 /* If X is a floating-point constant, return the logarithm of X base 2,
2239    or 0 if X is not a power of 2.  */
2240
2241 int
2242 floating_exact_log2 (x)
2243      rtx x;
2244 {
2245   REAL_VALUE_TYPE r, r1;
2246   int i;
2247
2248 #ifndef REAL_ARITHMETIC
2249 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2250   if (! flag_pretend_float)
2251     return 0;
2252 #endif
2253 #endif
2254
2255   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2256
2257   if (REAL_VALUES_LESS (r, dconst0))
2258     return 0;
2259
2260   r1 = dconst1;
2261   i = 0;
2262   while (REAL_VALUES_LESS (r1, r))
2263     {
2264       r1 = REAL_VALUE_LDEXP (dconst1, i);
2265       if (REAL_VALUES_EQUAL (r1, r))
2266         return i;
2267       i = i + 1;
2268     }
2269   return 0;
2270 }
2271 \f
2272 #ifdef SUPPORT_SUN_FPA
2273 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
2274    from the Sun FPA's constant RAM.
2275    The value returned, anded with 0x1ff, gives the code to use in fpmove
2276    to get the desired constant. */
2277
2278 static int inited_FPA_table = 0;
2279
2280 char *strings_FPA[38] = {
2281 /* small rationals */
2282   "0.0",
2283   "1.0",
2284   "0.5",
2285   "-1.0",
2286   "2.0",
2287   "3.0",
2288   "4.0",
2289   "8.0",
2290   "0.25",
2291   "0.125",
2292   "10.0",
2293   "-0.5",
2294 /* Decimal equivalents of double precision values */
2295   "2.718281828459045091", /* D_E */
2296   "6.283185307179586477", /* 2 pi */
2297   "3.141592653589793116", /* D_PI */
2298   "1.570796326794896619", /* pi/2 */
2299   "1.414213562373095145", /* D_SQRT2 */
2300   "0.7071067811865475244", /* 1/sqrt(2) */
2301   "-1.570796326794896619", /* -pi/2 */
2302   "1.442695040888963387", /* D_LOG2ofE */
2303   "3.321928024887362182", /* D_LOG2of10 */
2304   "0.6931471805599452862", /* D_LOGEof2 */
2305   "2.302585092994045901", /* D_LOGEof10 */
2306   "0.3010299956639811980", /* D_LOG10of2 */
2307   "0.4342944819032518167", /* D_LOG10ofE */
2308 /* Decimal equivalents of single precision values */
2309   "2.718281745910644531", /* S_E */
2310   "6.283185307179586477", /* 2 pi */
2311   "3.141592741012573242", /* S_PI */
2312   "1.570796326794896619", /* pi/2 */
2313   "1.414213538169860840", /* S_SQRT2 */
2314   "0.7071067811865475244", /* 1/sqrt(2) */
2315   "-1.570796326794896619", /* -pi/2 */
2316   "1.442695021629333496", /* S_LOG2ofE */
2317   "3.321928024291992188", /* S_LOG2of10 */
2318   "0.6931471824645996094", /* S_LOGEof2 */
2319   "2.302585124969482442", /* S_LOGEof10 */
2320   "0.3010300099849700928", /* S_LOG10of2 */
2321   "0.4342944920063018799", /* S_LOG10ofE */
2322 };
2323
2324
2325 int codes_FPA[38] = {
2326 /* small rationals */
2327   0x200,
2328   0xe,
2329   0xf,
2330   0x10,
2331   0x11,
2332   0xb1,
2333   0x12,
2334   0x13,
2335   0x15,
2336   0x16,
2337   0x17,
2338   0x2e,
2339 /* double precision */
2340   0x8,
2341   0x9,
2342   0xa,
2343   0xb,
2344   0xc,
2345   0xd,
2346   0x27,
2347   0x28,
2348   0x29,
2349   0x2a,
2350   0x2b,
2351   0x2c,
2352   0x2d,
2353 /* single precision */
2354   0x8,
2355   0x9,
2356   0xa,
2357   0xb,
2358   0xc,
2359   0xd,
2360   0x27,
2361   0x28,
2362   0x29,
2363   0x2a,
2364   0x2b,
2365   0x2c,
2366   0x2d
2367   };
2368
2369 REAL_VALUE_TYPE values_FPA[38];
2370
2371 /* This code has been fixed for cross-compilation. */
2372
2373 void
2374 init_FPA_table ()
2375 {
2376   enum machine_mode mode;
2377   int i;
2378   REAL_VALUE_TYPE r;
2379
2380   mode = DFmode;
2381   for (i = 0; i < 38; i++)
2382     {
2383       if (i == 25)
2384         mode = SFmode;
2385       r = REAL_VALUE_ATOF (strings_FPA[i], mode);
2386       values_FPA[i] = r;
2387     }
2388   inited_FPA_table = 1;
2389 }
2390
2391
2392 int
2393 standard_sun_fpa_constant_p (x)
2394      rtx x;
2395 {
2396   REAL_VALUE_TYPE r;
2397   int i;
2398
2399 #ifndef REAL_ARITHMETIC
2400 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2401   if (! flag_pretend_float)
2402     return 0;
2403 #endif
2404 #endif
2405
2406   if (! inited_FPA_table)
2407     init_FPA_table ();
2408
2409   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2410
2411   for (i=0; i<12; i++)
2412     {
2413       if (REAL_VALUES_EQUAL (r, values_FPA[i]))
2414         return (codes_FPA[i]);
2415     }
2416
2417   if (GET_MODE (x) == SFmode)
2418     {
2419       for (i=25; i<38; i++)
2420         {
2421           if (REAL_VALUES_EQUAL (r, values_FPA[i]))
2422             return (codes_FPA[i]);
2423         }
2424     }
2425   else
2426     {
2427       for (i=12; i<25; i++)
2428         {
2429           if (REAL_VALUES_EQUAL (r, values_FPA[i]))
2430             return (codes_FPA[i]);
2431         }
2432     }
2433   return 0x0;
2434 }
2435 #endif /* define SUPPORT_SUN_FPA */
2436 \f
2437 /* A C compound statement to output to stdio stream STREAM the
2438    assembler syntax for an instruction operand X.  X is an RTL
2439    expression.
2440
2441    CODE is a value that can be used to specify one of several ways
2442    of printing the operand.  It is used when identical operands
2443    must be printed differently depending on the context.  CODE
2444    comes from the `%' specification that was used to request
2445    printing of the operand.  If the specification was just `%DIGIT'
2446    then CODE is 0; if the specification was `%LTR DIGIT' then CODE
2447    is the ASCII code for LTR.
2448
2449    If X is a register, this macro should print the register's name.
2450    The names can be found in an array `reg_names' whose type is
2451    `char *[]'.  `reg_names' is initialized from `REGISTER_NAMES'.
2452
2453    When the machine description has a specification `%PUNCT' (a `%'
2454    followed by a punctuation character), this macro is called with
2455    a null pointer for X and the punctuation character for CODE.
2456
2457    The m68k specific codes are:
2458
2459    '.' for dot needed in Motorola-style opcode names.
2460    '-' for an operand pushing on the stack:
2461        sp@-, -(sp) or -(%sp) depending on the style of syntax.
2462    '+' for an operand pushing on the stack:
2463        sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
2464    '@' for a reference to the top word on the stack:
2465        sp@, (sp) or (%sp) depending on the style of syntax.
2466    '#' for an immediate operand prefix (# in MIT and Motorola syntax
2467        but & in SGS syntax, $ in CRDS/UNOS syntax).
2468    '!' for the cc register (used in an `and to cc' insn).
2469    '$' for the letter `s' in an op code, but only on the 68040.
2470    '&' for the letter `d' in an op code, but only on the 68040.
2471    '/' for register prefix needed by longlong.h.
2472
2473    'b' for byte insn (no effect, on the Sun; this is for the ISI).
2474    'd' to force memory addressing to be absolute, not relative.
2475    'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
2476    'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
2477        than directly).  Second part of 'y' below.
2478    'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
2479        or print pair of registers as rx:ry.
2480    'y' for a FPA insn (print pair of registers as rx:ry).  This also outputs
2481        CONST_DOUBLE's as SunFPA constant RAM registers if
2482        possible, so it should not be used except for the SunFPA.
2483
2484    */
2485
2486 void
2487 print_operand (file, op, letter)
2488      FILE *file;                /* file to write to */
2489      rtx op;                    /* operand to print */
2490      int letter;                /* %<letter> or 0 */
2491 {
2492   int i;
2493
2494   if (letter == '.')
2495     {
2496 #if defined (MOTOROLA) && !defined (CRDS)
2497       asm_fprintf (file, ".");
2498 #endif
2499     }
2500   else if (letter == '#')
2501     {
2502       asm_fprintf (file, "%0I");
2503     }
2504   else if (letter == '-')
2505     {
2506 #ifdef MOTOROLA
2507       asm_fprintf (file, "-(%Rsp)");
2508 #else
2509       asm_fprintf (file, "%Rsp@-");
2510 #endif
2511     }
2512   else if (letter == '+')
2513     {
2514 #ifdef MOTOROLA
2515       asm_fprintf (file, "(%Rsp)+");
2516 #else
2517       asm_fprintf (file, "%Rsp@+");
2518 #endif
2519     }
2520   else if (letter == '@')
2521     {
2522 #ifdef MOTOROLA
2523       asm_fprintf (file, "(%Rsp)");
2524 #else
2525       asm_fprintf (file, "%Rsp@");
2526 #endif
2527     }
2528   else if (letter == '!')
2529     {
2530       asm_fprintf (file, "%Rfpcr");
2531     }
2532   else if (letter == '$')
2533     {
2534       if (TARGET_68040_ONLY)
2535         {
2536           fprintf (file, "s");
2537         }
2538     }
2539   else if (letter == '&')
2540     {
2541       if (TARGET_68040_ONLY)
2542         {
2543           fprintf (file, "d");
2544         }
2545     }
2546   else if (letter == '/')
2547     {
2548       asm_fprintf (file, "%R");
2549     }
2550   else if (GET_CODE (op) == REG)
2551     {
2552 #ifdef SUPPORT_SUN_FPA
2553       if (REGNO (op) < 16
2554           && (letter == 'y' || letter == 'x')
2555           && GET_MODE (op) == DFmode)
2556         {
2557           fprintf (file, "%s:%s", reg_names[REGNO (op)],
2558                    reg_names[REGNO (op)+1]);
2559         }
2560       else
2561 #endif
2562         {
2563           if (letter == 'R')
2564             /* Print out the second register name of a register pair.
2565                I.e., R (6) => 7.  */
2566             fputs (reg_names[REGNO (op) + 1], file);
2567           else
2568             fputs (reg_names[REGNO (op)], file);
2569         }
2570     }
2571   else if (GET_CODE (op) == MEM)
2572     {
2573       output_address (XEXP (op, 0));
2574       if (letter == 'd' && ! TARGET_68020
2575           && CONSTANT_ADDRESS_P (XEXP (op, 0))
2576           && !(GET_CODE (XEXP (op, 0)) == CONST_INT
2577                && INTVAL (XEXP (op, 0)) < 0x8000
2578                && INTVAL (XEXP (op, 0)) >= -0x8000))
2579         {
2580 #ifdef MOTOROLA
2581           fprintf (file, ".l");
2582 #else
2583           fprintf (file, ":l");
2584 #endif
2585         }
2586     }
2587 #ifdef SUPPORT_SUN_FPA
2588   else if ((letter == 'y' || letter == 'w')
2589            && GET_CODE (op) == CONST_DOUBLE
2590            && (i = standard_sun_fpa_constant_p (op)))
2591     {
2592       fprintf (file, "%%%d", i & 0x1ff);
2593     }
2594 #endif
2595   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
2596     {
2597       REAL_VALUE_TYPE r;
2598       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2599       ASM_OUTPUT_FLOAT_OPERAND (letter, file, r);
2600     }
2601   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode)
2602     {
2603       REAL_VALUE_TYPE r;
2604       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2605       ASM_OUTPUT_LONG_DOUBLE_OPERAND (file, r);
2606     }
2607   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
2608     {
2609       REAL_VALUE_TYPE r;
2610       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2611       ASM_OUTPUT_DOUBLE_OPERAND (file, r);
2612     }
2613   else
2614     {
2615       asm_fprintf (file, "%0I"); output_addr_const (file, op);
2616     }
2617 }
2618
2619 \f
2620 /* A C compound statement to output to stdio stream STREAM the
2621    assembler syntax for an instruction operand that is a memory
2622    reference whose address is ADDR.  ADDR is an RTL expression.
2623
2624    Note that this contains a kludge that knows that the only reason
2625    we have an address (plus (label_ref...) (reg...)) when not generating
2626    PIC code is in the insn before a tablejump, and we know that m68k.md
2627    generates a label LInnn: on such an insn.
2628
2629    It is possible for PIC to generate a (plus (label_ref...) (reg...))
2630    and we handle that just like we would a (plus (symbol_ref...) (reg...)).
2631
2632    Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
2633    fails to assemble.  Luckily "Lnnn(pc,d0.l*2)" produces the results
2634    we want.  This difference can be accommodated by using an assembler
2635    define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
2636    string, as necessary.  This is accomplished via the ASM_OUTPUT_CASE_END
2637    macro.  See m68k/sgs.h for an example; for versions without the bug.
2638    Some assemblers refuse all the above solutions.  The workaround is to
2639    emit "K(pc,d0.l*2)" with K being a small constant known to give the
2640    right behaviour.
2641
2642    They also do not like things like "pea 1.w", so we simple leave off
2643    the .w on small constants. 
2644
2645    This routine is responsible for distinguishing between -fpic and -fPIC 
2646    style relocations in an address.  When generating -fpic code the
2647    offset is output in word mode (eg movel a5@(_foo:w), a0).  When generating
2648    -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
2649
2650 #ifndef ASM_OUTPUT_CASE_FETCH
2651 #ifdef MOTOROLA
2652 #ifdef SGS
2653 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2654         asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
2655 #else
2656 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2657         asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
2658 #endif
2659 #else
2660 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2661         asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
2662 #endif
2663 #endif /* ASM_OUTPUT_CASE_FETCH */
2664
2665 void
2666 print_operand_address (file, addr)
2667      FILE *file;
2668      rtx addr;
2669 {
2670   register rtx reg1, reg2, breg, ireg;
2671   rtx offset;
2672
2673   switch (GET_CODE (addr))
2674     {
2675       case REG:
2676 #ifdef MOTOROLA
2677         fprintf (file, "(%s)", reg_names[REGNO (addr)]);
2678 #else
2679         fprintf (file, "%s@", reg_names[REGNO (addr)]);
2680 #endif
2681         break;
2682       case PRE_DEC:
2683 #ifdef MOTOROLA
2684         fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
2685 #else
2686         fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);
2687 #endif
2688         break;
2689       case POST_INC:
2690 #ifdef MOTOROLA
2691         fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
2692 #else
2693         fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);
2694 #endif
2695         break;
2696       case PLUS:
2697         reg1 = reg2 = ireg = breg = offset = 0;
2698         if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
2699           {
2700             offset = XEXP (addr, 0);
2701             addr = XEXP (addr, 1);
2702           }
2703         else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
2704           {
2705             offset = XEXP (addr, 1);
2706             addr = XEXP (addr, 0);
2707           }
2708         if (GET_CODE (addr) != PLUS)
2709           {
2710             ;
2711           }
2712         else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
2713           {
2714             reg1 = XEXP (addr, 0);
2715             addr = XEXP (addr, 1);
2716           }
2717         else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
2718           {
2719             reg1 = XEXP (addr, 1);
2720             addr = XEXP (addr, 0);
2721           }
2722         else if (GET_CODE (XEXP (addr, 0)) == MULT)
2723           {
2724             reg1 = XEXP (addr, 0);
2725             addr = XEXP (addr, 1);
2726           }
2727         else if (GET_CODE (XEXP (addr, 1)) == MULT)
2728           {
2729             reg1 = XEXP (addr, 1);
2730             addr = XEXP (addr, 0);
2731           }
2732         else if (GET_CODE (XEXP (addr, 0)) == REG)
2733           {
2734             reg1 = XEXP (addr, 0);
2735             addr = XEXP (addr, 1);
2736           }
2737         else if (GET_CODE (XEXP (addr, 1)) == REG)
2738           {
2739             reg1 = XEXP (addr, 1);
2740             addr = XEXP (addr, 0);
2741           }
2742         if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
2743             || GET_CODE (addr) == SIGN_EXTEND)
2744           {
2745             if (reg1 == 0)
2746               {
2747                 reg1 = addr;
2748               }
2749             else
2750               {
2751                 reg2 = addr;
2752               }
2753             addr = 0;
2754           }
2755 #if 0   /* for OLD_INDEXING */
2756         else if (GET_CODE (addr) == PLUS)
2757           {
2758             if (GET_CODE (XEXP (addr, 0)) == REG)
2759               {
2760                 reg2 = XEXP (addr, 0);
2761                 addr = XEXP (addr, 1);
2762               }
2763             else if (GET_CODE (XEXP (addr, 1)) == REG)
2764               {
2765                 reg2 = XEXP (addr, 1);
2766                 addr = XEXP (addr, 0);
2767               }
2768           }
2769 #endif
2770         if (offset != 0)
2771           {
2772             if (addr != 0)
2773               {
2774                 abort ();
2775               }
2776             addr = offset;
2777           }
2778         if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
2779                       || GET_CODE (reg1) == MULT))
2780             || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
2781           {
2782             breg = reg2;
2783             ireg = reg1;
2784           }
2785         else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
2786           {
2787             breg = reg1;
2788             ireg = reg2;
2789           }
2790         if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
2791             && ! (flag_pic && ireg == pic_offset_table_rtx))
2792           {
2793             int scale = 1;
2794             if (GET_CODE (ireg) == MULT)
2795               {
2796                 scale = INTVAL (XEXP (ireg, 1));
2797                 ireg = XEXP (ireg, 0);
2798               }
2799             if (GET_CODE (ireg) == SIGN_EXTEND)
2800               {
2801                 ASM_OUTPUT_CASE_FETCH (file,
2802                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
2803                              reg_names[REGNO (XEXP (ireg, 0))]);
2804                 fprintf (file, "w");
2805               }
2806             else
2807               {
2808                 ASM_OUTPUT_CASE_FETCH (file,
2809                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
2810                              reg_names[REGNO (ireg)]);
2811                 fprintf (file, "l");
2812               }
2813             if (scale != 1)
2814               {
2815 #ifdef MOTOROLA
2816                 fprintf (file, "*%d", scale);
2817 #else
2818                 fprintf (file, ":%d", scale);
2819 #endif
2820               }
2821             putc (')', file);
2822             break;
2823           }
2824         if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
2825             && ! (flag_pic && breg == pic_offset_table_rtx))
2826           {
2827             ASM_OUTPUT_CASE_FETCH (file,
2828                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
2829                          reg_names[REGNO (breg)]);
2830             fprintf (file, "l)");
2831             break;
2832           }
2833         if (ireg != 0 || breg != 0)
2834           {
2835             int scale = 1;
2836             if (breg == 0)
2837               {
2838                 abort ();
2839               }
2840             if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
2841               {
2842                 abort ();
2843               }
2844 #ifdef MOTOROLA
2845             if (addr != 0)
2846               {
2847                 output_addr_const (file, addr);
2848                 if (flag_pic && (breg == pic_offset_table_rtx))
2849                   fprintf (file, "@GOT");
2850               }
2851             fprintf (file, "(%s", reg_names[REGNO (breg)]);
2852             if (ireg != 0)
2853               {
2854                 putc (',', file);
2855               }
2856 #else
2857             fprintf (file, "%s@(", reg_names[REGNO (breg)]);
2858             if (addr != 0)
2859               {
2860                 output_addr_const (file, addr);
2861                 if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
2862                   fprintf (file, ":w");
2863                 if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
2864                   fprintf (file, ":l");
2865               }
2866             if (addr != 0 && ireg != 0)
2867               {
2868                 putc (',', file);
2869               }
2870 #endif
2871             if (ireg != 0 && GET_CODE (ireg) == MULT)
2872               {
2873                 scale = INTVAL (XEXP (ireg, 1));
2874                 ireg = XEXP (ireg, 0);
2875               }
2876             if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
2877               {
2878 #ifdef MOTOROLA
2879                 fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);
2880 #else
2881                 fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);
2882 #endif
2883               }
2884             else if (ireg != 0)
2885               {
2886 #ifdef MOTOROLA
2887                 fprintf (file, "%s.l", reg_names[REGNO (ireg)]);
2888 #else
2889                 fprintf (file, "%s:l", reg_names[REGNO (ireg)]);
2890 #endif
2891               }
2892             if (scale != 1)
2893               {
2894 #ifdef MOTOROLA
2895                 fprintf (file, "*%d", scale);
2896 #else
2897                 fprintf (file, ":%d", scale);
2898 #endif
2899               }
2900             putc (')', file);
2901             break;
2902           }
2903         else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
2904                  && ! (flag_pic && reg1 == pic_offset_table_rtx))       
2905           {
2906             ASM_OUTPUT_CASE_FETCH (file,
2907                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
2908                          reg_names[REGNO (reg1)]);
2909             fprintf (file, "l)");
2910             break;
2911           }
2912         /* FALL-THROUGH (is this really what we want? */
2913       default:
2914         if (GET_CODE (addr) == CONST_INT
2915             && INTVAL (addr) < 0x8000
2916             && INTVAL (addr) >= -0x8000)
2917           {
2918 #ifdef MOTOROLA
2919 #ifdef SGS
2920             /* Many SGS assemblers croak on size specifiers for constants. */
2921             fprintf (file, "%d", INTVAL (addr));
2922 #else
2923             fprintf (file, "%d.w", INTVAL (addr));
2924 #endif
2925 #else
2926             fprintf (file, "%d:w", INTVAL (addr));
2927 #endif
2928           }
2929         else
2930           {
2931             output_addr_const (file, addr);
2932           }
2933         break;
2934     }
2935 }
2936 \f
2937 /* Check for cases where a clr insns can be omitted from code using
2938    strict_low_part sets.  For example, the second clrl here is not needed:
2939    clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
2940
2941    MODE is the mode of this STRICT_LOW_PART set.  FIRST_INSN is the clear
2942    insn we are checking for redundancy.  TARGET is the register set by the
2943    clear insn.  */
2944
2945 int
2946 strict_low_part_peephole_ok (mode, first_insn, target)
2947      enum machine_mode mode;
2948      rtx first_insn;
2949      rtx target;
2950 {
2951   rtx p;
2952
2953   p = prev_nonnote_insn (first_insn);
2954
2955   while (p)
2956     {
2957       /* If it isn't an insn, then give up.  */
2958       if (GET_CODE (p) != INSN)
2959         return 0;
2960
2961       if (reg_set_p (target, p))
2962         {
2963           rtx set = single_set (p);
2964           rtx dest;
2965
2966           /* If it isn't an easy to recognize insn, then give up.  */
2967           if (! set)
2968             return 0;
2969
2970           dest = SET_DEST (set);
2971
2972           /* If this sets the entire target register to zero, then our
2973              first_insn is redundant.  */
2974           if (rtx_equal_p (dest, target)
2975               && SET_SRC (set) == const0_rtx)
2976             return 1;
2977           else if (GET_CODE (dest) == STRICT_LOW_PART
2978                    && GET_CODE (XEXP (dest, 0)) == REG
2979                    && REGNO (XEXP (dest, 0)) == REGNO (target)
2980                    && (GET_MODE_SIZE (GET_MODE (XEXP (dest, 0)))
2981                        <= GET_MODE_SIZE (mode)))
2982             /* This is a strict low part set which modifies less than
2983                we are using, so it is safe.  */
2984             ;
2985           else
2986             return 0;
2987         }
2988
2989       p = prev_nonnote_insn (p);
2990
2991     }
2992
2993   return 0;
2994 }
2995
2996 /* Accept integer operands in the range 0..0xffffffff.  We have to check the
2997    range carefully since this predicate is used in DImode contexts.  Also, we
2998    need some extra crud to make it work when hosted on 64-bit machines.  */
2999
3000 int
3001 const_uint32_operand (op, mode)
3002      rtx op;
3003      enum machine_mode mode;
3004 {
3005 #if HOST_BITS_PER_WIDE_INT > 32
3006   /* All allowed constants will fit a CONST_INT.  */
3007   return (GET_CODE (op) == CONST_INT
3008           && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
3009 #else
3010   return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0)
3011           || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
3012 #endif
3013 }
3014
3015 /* Accept integer operands in the range -0x80000000..0x7fffffff.  We have
3016    to check the range carefully since this predicate is used in DImode
3017    contexts.  */
3018
3019 int
3020 const_sint32_operand (op, mode)
3021      rtx op;
3022      enum machine_mode mode;
3023 {
3024   /* All allowed constants will fit a CONST_INT.  */
3025   return (GET_CODE (op) == CONST_INT
3026           && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
3027 }