OSDN Git Service

2b3022e156387641b3869b234d2d6dbe2ffddae3
[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
1955 /* Output assembler code to perform a 32 bit 3 operand add.  */
1956
1957 char *
1958 output_addsi3 (operands)
1959      rtx *operands;
1960 {
1961   if (! operands_match_p (operands[0], operands[1]))
1962     {
1963       if (!ADDRESS_REG_P (operands[1]))
1964         {
1965           rtx tmp = operands[1];
1966
1967           operands[1] = operands[2];
1968           operands[2] = tmp;
1969         }
1970
1971       /* These insns can result from reloads to access
1972          stack slots over 64k from the frame pointer.  */
1973       if (GET_CODE (operands[2]) == CONST_INT
1974           && INTVAL (operands[2]) + 0x8000 >= (unsigned) 0x10000)
1975         return "move%.l %2,%0\\;add%.l %1,%0";
1976 #ifdef SGS
1977       if (GET_CODE (operands[2]) == REG)
1978         return "lea 0(%1,%2.l),%0";
1979       else
1980         return "lea %c2(%1),%0";
1981 #else /* not SGS */
1982 #ifdef MOTOROLA
1983       if (GET_CODE (operands[2]) == REG)
1984         return "lea (%1,%2.l),%0";
1985       else
1986         return "lea (%c2,%1),%0";
1987 #else /* not MOTOROLA (MIT syntax) */
1988       if (GET_CODE (operands[2]) == REG)
1989         return "lea %1@(0,%2:l),%0";
1990       else
1991         return "lea %1@(%c2),%0";
1992 #endif /* not MOTOROLA */
1993 #endif /* not SGS */
1994     }
1995   if (GET_CODE (operands[2]) == CONST_INT)
1996     {
1997 #ifndef NO_ADDSUB_Q
1998       if (INTVAL (operands[2]) > 0
1999           && INTVAL (operands[2]) <= 8)
2000         return "addq%.l %2,%0";
2001       if (INTVAL (operands[2]) < 0
2002           && INTVAL (operands[2]) >= -8)
2003         {
2004           operands[2] = gen_rtx (CONST_INT, VOIDmode,
2005                                  - INTVAL (operands[2]));
2006           return "subq%.l %2,%0";
2007         }
2008       /* On the CPU32 it is faster to use two addql instructions to
2009          add a small integer (8 < N <= 16) to a register.
2010          Likewise for subql. */
2011       if (TARGET_CPU32 && REG_P (operands[0]))
2012         {
2013           if (INTVAL (operands[2]) > 8
2014               && INTVAL (operands[2]) <= 16)
2015             {
2016               operands[2] = gen_rtx (CONST_INT, VOIDmode, 
2017                                       INTVAL (operands[2]) - 8);
2018               return "addq%.l %#8,%0\\;addq%.l %2,%0";
2019             }
2020           if (INTVAL (operands[2]) < -8
2021               && INTVAL (operands[2]) >= -16)
2022             {
2023               operands[2] = gen_rtx (CONST_INT, VOIDmode,
2024                                       - INTVAL (operands[2]) - 8);
2025               return "subq%.l %#8,%0\\;subq%.l %2,%0";
2026             }
2027         }
2028 #endif
2029       if (ADDRESS_REG_P (operands[0])
2030           && INTVAL (operands[2]) >= -0x8000
2031           && INTVAL (operands[2]) < 0x8000)
2032         {
2033           if (TARGET_68040)
2034             return "add%.w %2,%0";
2035           else
2036 #ifdef MOTOROLA  
2037             return "lea (%c2,%0),%0";
2038 #else
2039             return "lea %0@(%c2),%0";
2040 #endif
2041         }
2042     }
2043   return "add%.l %2,%0";
2044 }
2045 \f
2046 /* Store in cc_status the expressions that the condition codes will
2047    describe after execution of an instruction whose pattern is EXP.
2048    Do not alter them if the instruction would not alter the cc's.  */
2049
2050 /* On the 68000, all the insns to store in an address register fail to
2051    set the cc's.  However, in some cases these instructions can make it
2052    possibly invalid to use the saved cc's.  In those cases we clear out
2053    some or all of the saved cc's so they won't be used.  */
2054
2055 notice_update_cc (exp, insn)
2056      rtx exp;
2057      rtx insn;
2058 {
2059   /* If the cc is being set from the fpa and the expression is not an
2060      explicit floating point test instruction (which has code to deal with
2061      this), reinit the CC.  */
2062   if (((cc_status.value1 && FPA_REG_P (cc_status.value1))
2063        || (cc_status.value2 && FPA_REG_P (cc_status.value2)))
2064       && !(GET_CODE (exp) == PARALLEL
2065            && GET_CODE (XVECEXP (exp, 0, 0)) == SET
2066            && XEXP (XVECEXP (exp, 0, 0), 0) == cc0_rtx))
2067     {
2068       CC_STATUS_INIT; 
2069     }
2070   else if (GET_CODE (exp) == SET)
2071     {
2072       if (GET_CODE (SET_SRC (exp)) == CALL)
2073         {
2074           CC_STATUS_INIT; 
2075         }
2076       else if (ADDRESS_REG_P (SET_DEST (exp)))
2077         {
2078           if (cc_status.value1
2079               && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
2080             cc_status.value1 = 0;
2081           if (cc_status.value2
2082               && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
2083             cc_status.value2 = 0; 
2084         }
2085       else if (!FP_REG_P (SET_DEST (exp))
2086                && SET_DEST (exp) != cc0_rtx
2087                && (FP_REG_P (SET_SRC (exp))
2088                    || GET_CODE (SET_SRC (exp)) == FIX
2089                    || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE
2090                    || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND))
2091         {
2092           CC_STATUS_INIT; 
2093         }
2094       /* A pair of move insns doesn't produce a useful overall cc.  */
2095       else if (!FP_REG_P (SET_DEST (exp))
2096                && !FP_REG_P (SET_SRC (exp))
2097                && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
2098                && (GET_CODE (SET_SRC (exp)) == REG
2099                    || GET_CODE (SET_SRC (exp)) == MEM
2100                    || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
2101         {
2102           CC_STATUS_INIT; 
2103         }
2104       else if (GET_CODE (SET_SRC (exp)) == CALL)
2105         {
2106           CC_STATUS_INIT; 
2107         }
2108       else if (XEXP (exp, 0) != pc_rtx)
2109         {
2110           cc_status.flags = 0;
2111           cc_status.value1 = XEXP (exp, 0);
2112           cc_status.value2 = XEXP (exp, 1);
2113         }
2114     }
2115   else if (GET_CODE (exp) == PARALLEL
2116            && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
2117     {
2118       if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0)))
2119         CC_STATUS_INIT;
2120       else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx)
2121         {
2122           cc_status.flags = 0;
2123           cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
2124           cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
2125         }
2126     }
2127   else
2128     CC_STATUS_INIT;
2129   if (cc_status.value2 != 0
2130       && ADDRESS_REG_P (cc_status.value2)
2131       && GET_MODE (cc_status.value2) == QImode)
2132     CC_STATUS_INIT;
2133   if (cc_status.value2 != 0
2134       && !(cc_status.value1 && FPA_REG_P (cc_status.value1)))
2135     switch (GET_CODE (cc_status.value2))
2136       {
2137       case PLUS: case MINUS: case MULT:
2138       case DIV: case UDIV: case MOD: case UMOD: case NEG:
2139 #if 0 /* These instructions always clear the overflow bit */
2140       case ASHIFT: case ASHIFTRT: case LSHIFTRT:
2141       case ROTATE: case ROTATERT:
2142 #endif
2143         if (GET_MODE (cc_status.value2) != VOIDmode)
2144           cc_status.flags |= CC_NO_OVERFLOW;
2145         break;
2146       case ZERO_EXTEND:
2147         /* (SET r1 (ZERO_EXTEND r2)) on this machine
2148            ends with a move insn moving r2 in r2's mode.
2149            Thus, the cc's are set for r2.
2150            This can set N bit spuriously. */
2151         cc_status.flags |= CC_NOT_NEGATIVE; 
2152       }
2153   if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
2154       && cc_status.value2
2155       && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
2156     cc_status.value2 = 0;
2157   if (((cc_status.value1 && FP_REG_P (cc_status.value1))
2158        || (cc_status.value2 && FP_REG_P (cc_status.value2)))
2159       && !((cc_status.value1 && FPA_REG_P (cc_status.value1))
2160            || (cc_status.value2 && FPA_REG_P (cc_status.value2))))
2161     cc_status.flags = CC_IN_68881;
2162 }
2163 \f
2164 char *
2165 output_move_const_double (operands)
2166      rtx *operands;
2167 {
2168 #ifdef SUPPORT_SUN_FPA
2169   if (TARGET_FPA && FPA_REG_P (operands[0]))
2170     {
2171       int code = standard_sun_fpa_constant_p (operands[1]);
2172
2173       if (code != 0)
2174         {
2175           static char buf[40];
2176
2177           sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff);
2178           return buf;
2179         }
2180       return "fpmove%.d %1,%0";
2181     }
2182   else
2183 #endif
2184     {
2185       int code = standard_68881_constant_p (operands[1]);
2186
2187       if (code != 0)
2188         {
2189           static char buf[40];
2190
2191           sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
2192           return buf;
2193         }
2194       return "fmove%.d %1,%0";
2195     }
2196 }
2197
2198 char *
2199 output_move_const_single (operands)
2200      rtx *operands;
2201 {
2202 #ifdef SUPPORT_SUN_FPA
2203   if (TARGET_FPA)
2204     {
2205       int code = standard_sun_fpa_constant_p (operands[1]);
2206
2207       if (code != 0)
2208         {
2209           static char buf[40];
2210
2211           sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff);
2212           return buf;
2213         }
2214       return "fpmove%.s %1,%0";
2215     }
2216   else
2217 #endif /* defined SUPPORT_SUN_FPA */
2218     {
2219       int code = standard_68881_constant_p (operands[1]);
2220
2221       if (code != 0)
2222         {
2223           static char buf[40];
2224
2225           sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
2226           return buf;
2227         }
2228       return "fmove%.s %f1,%0";
2229     }
2230 }
2231
2232 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
2233    from the "fmovecr" instruction.
2234    The value, anded with 0xff, gives the code to use in fmovecr
2235    to get the desired constant.  */
2236
2237 /* This code has been fixed for cross-compilation. */
2238   
2239 static int inited_68881_table = 0;
2240
2241 char *strings_68881[7] = {
2242   "0.0",
2243   "1.0",
2244   "10.0",
2245   "100.0",
2246   "10000.0",
2247   "1e8",
2248   "1e16"
2249   };
2250
2251 int codes_68881[7] = {
2252   0x0f,
2253   0x32,
2254   0x33,
2255   0x34,
2256   0x35,
2257   0x36,
2258   0x37
2259   };
2260
2261 REAL_VALUE_TYPE values_68881[7];
2262
2263 /* Set up values_68881 array by converting the decimal values
2264    strings_68881 to binary.   */
2265
2266 void
2267 init_68881_table ()
2268 {
2269   int i;
2270   REAL_VALUE_TYPE r;
2271   enum machine_mode mode;
2272
2273   mode = SFmode;
2274   for (i = 0; i < 7; i++)
2275     {
2276       if (i == 6)
2277         mode = DFmode;
2278       r = REAL_VALUE_ATOF (strings_68881[i], mode);
2279       values_68881[i] = r;
2280     }
2281   inited_68881_table = 1;
2282 }
2283
2284 int
2285 standard_68881_constant_p (x)
2286      rtx x;
2287 {
2288   REAL_VALUE_TYPE r;
2289   int i;
2290   enum machine_mode mode;
2291
2292 #ifdef NO_ASM_FMOVECR
2293   return 0;
2294 #endif
2295
2296   /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */
2297   if (TARGET_68040)
2298     return 0;
2299
2300 #ifndef REAL_ARITHMETIC
2301 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2302   if (! flag_pretend_float)
2303     return 0;
2304 #endif
2305 #endif
2306
2307   if (! inited_68881_table)
2308     init_68881_table ();
2309
2310   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2311
2312   for (i = 0; i < 6; i++)
2313     {
2314       if (REAL_VALUES_EQUAL (r, values_68881[i]))
2315         return (codes_68881[i]);
2316     }
2317   
2318   if (GET_MODE (x) == SFmode)
2319     return 0;
2320
2321   if (REAL_VALUES_EQUAL (r, values_68881[6]))
2322     return (codes_68881[6]);
2323
2324   /* larger powers of ten in the constants ram are not used
2325      because they are not equal to a `double' C constant.  */
2326   return 0;
2327 }
2328
2329 /* If X is a floating-point constant, return the logarithm of X base 2,
2330    or 0 if X is not a power of 2.  */
2331
2332 int
2333 floating_exact_log2 (x)
2334      rtx x;
2335 {
2336   REAL_VALUE_TYPE r, r1;
2337   int i;
2338
2339 #ifndef REAL_ARITHMETIC
2340 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2341   if (! flag_pretend_float)
2342     return 0;
2343 #endif
2344 #endif
2345
2346   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2347
2348   if (REAL_VALUES_LESS (r, dconst0))
2349     return 0;
2350
2351   r1 = dconst1;
2352   i = 0;
2353   while (REAL_VALUES_LESS (r1, r))
2354     {
2355       r1 = REAL_VALUE_LDEXP (dconst1, i);
2356       if (REAL_VALUES_EQUAL (r1, r))
2357         return i;
2358       i = i + 1;
2359     }
2360   return 0;
2361 }
2362 \f
2363 #ifdef SUPPORT_SUN_FPA
2364 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
2365    from the Sun FPA's constant RAM.
2366    The value returned, anded with 0x1ff, gives the code to use in fpmove
2367    to get the desired constant. */
2368
2369 static int inited_FPA_table = 0;
2370
2371 char *strings_FPA[38] = {
2372 /* small rationals */
2373   "0.0",
2374   "1.0",
2375   "0.5",
2376   "-1.0",
2377   "2.0",
2378   "3.0",
2379   "4.0",
2380   "8.0",
2381   "0.25",
2382   "0.125",
2383   "10.0",
2384   "-0.5",
2385 /* Decimal equivalents of double precision values */
2386   "2.718281828459045091", /* D_E */
2387   "6.283185307179586477", /* 2 pi */
2388   "3.141592653589793116", /* D_PI */
2389   "1.570796326794896619", /* pi/2 */
2390   "1.414213562373095145", /* D_SQRT2 */
2391   "0.7071067811865475244", /* 1/sqrt(2) */
2392   "-1.570796326794896619", /* -pi/2 */
2393   "1.442695040888963387", /* D_LOG2ofE */
2394   "3.321928024887362182", /* D_LOG2of10 */
2395   "0.6931471805599452862", /* D_LOGEof2 */
2396   "2.302585092994045901", /* D_LOGEof10 */
2397   "0.3010299956639811980", /* D_LOG10of2 */
2398   "0.4342944819032518167", /* D_LOG10ofE */
2399 /* Decimal equivalents of single precision values */
2400   "2.718281745910644531", /* S_E */
2401   "6.283185307179586477", /* 2 pi */
2402   "3.141592741012573242", /* S_PI */
2403   "1.570796326794896619", /* pi/2 */
2404   "1.414213538169860840", /* S_SQRT2 */
2405   "0.7071067811865475244", /* 1/sqrt(2) */
2406   "-1.570796326794896619", /* -pi/2 */
2407   "1.442695021629333496", /* S_LOG2ofE */
2408   "3.321928024291992188", /* S_LOG2of10 */
2409   "0.6931471824645996094", /* S_LOGEof2 */
2410   "2.302585124969482442", /* S_LOGEof10 */
2411   "0.3010300099849700928", /* S_LOG10of2 */
2412   "0.4342944920063018799", /* S_LOG10ofE */
2413 };
2414
2415
2416 int codes_FPA[38] = {
2417 /* small rationals */
2418   0x200,
2419   0xe,
2420   0xf,
2421   0x10,
2422   0x11,
2423   0xb1,
2424   0x12,
2425   0x13,
2426   0x15,
2427   0x16,
2428   0x17,
2429   0x2e,
2430 /* double precision */
2431   0x8,
2432   0x9,
2433   0xa,
2434   0xb,
2435   0xc,
2436   0xd,
2437   0x27,
2438   0x28,
2439   0x29,
2440   0x2a,
2441   0x2b,
2442   0x2c,
2443   0x2d,
2444 /* single precision */
2445   0x8,
2446   0x9,
2447   0xa,
2448   0xb,
2449   0xc,
2450   0xd,
2451   0x27,
2452   0x28,
2453   0x29,
2454   0x2a,
2455   0x2b,
2456   0x2c,
2457   0x2d
2458   };
2459
2460 REAL_VALUE_TYPE values_FPA[38];
2461
2462 /* This code has been fixed for cross-compilation. */
2463
2464 void
2465 init_FPA_table ()
2466 {
2467   enum machine_mode mode;
2468   int i;
2469   REAL_VALUE_TYPE r;
2470
2471   mode = DFmode;
2472   for (i = 0; i < 38; i++)
2473     {
2474       if (i == 25)
2475         mode = SFmode;
2476       r = REAL_VALUE_ATOF (strings_FPA[i], mode);
2477       values_FPA[i] = r;
2478     }
2479   inited_FPA_table = 1;
2480 }
2481
2482
2483 int
2484 standard_sun_fpa_constant_p (x)
2485      rtx x;
2486 {
2487   REAL_VALUE_TYPE r;
2488   int i;
2489
2490 #ifndef REAL_ARITHMETIC
2491 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2492   if (! flag_pretend_float)
2493     return 0;
2494 #endif
2495 #endif
2496
2497   if (! inited_FPA_table)
2498     init_FPA_table ();
2499
2500   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2501
2502   for (i=0; i<12; i++)
2503     {
2504       if (REAL_VALUES_EQUAL (r, values_FPA[i]))
2505         return (codes_FPA[i]);
2506     }
2507
2508   if (GET_MODE (x) == SFmode)
2509     {
2510       for (i=25; i<38; i++)
2511         {
2512           if (REAL_VALUES_EQUAL (r, values_FPA[i]))
2513             return (codes_FPA[i]);
2514         }
2515     }
2516   else
2517     {
2518       for (i=12; i<25; i++)
2519         {
2520           if (REAL_VALUES_EQUAL (r, values_FPA[i]))
2521             return (codes_FPA[i]);
2522         }
2523     }
2524   return 0x0;
2525 }
2526 #endif /* define SUPPORT_SUN_FPA */
2527 \f
2528 /* A C compound statement to output to stdio stream STREAM the
2529    assembler syntax for an instruction operand X.  X is an RTL
2530    expression.
2531
2532    CODE is a value that can be used to specify one of several ways
2533    of printing the operand.  It is used when identical operands
2534    must be printed differently depending on the context.  CODE
2535    comes from the `%' specification that was used to request
2536    printing of the operand.  If the specification was just `%DIGIT'
2537    then CODE is 0; if the specification was `%LTR DIGIT' then CODE
2538    is the ASCII code for LTR.
2539
2540    If X is a register, this macro should print the register's name.
2541    The names can be found in an array `reg_names' whose type is
2542    `char *[]'.  `reg_names' is initialized from `REGISTER_NAMES'.
2543
2544    When the machine description has a specification `%PUNCT' (a `%'
2545    followed by a punctuation character), this macro is called with
2546    a null pointer for X and the punctuation character for CODE.
2547
2548    The m68k specific codes are:
2549
2550    '.' for dot needed in Motorola-style opcode names.
2551    '-' for an operand pushing on the stack:
2552        sp@-, -(sp) or -(%sp) depending on the style of syntax.
2553    '+' for an operand pushing on the stack:
2554        sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
2555    '@' for a reference to the top word on the stack:
2556        sp@, (sp) or (%sp) depending on the style of syntax.
2557    '#' for an immediate operand prefix (# in MIT and Motorola syntax
2558        but & in SGS syntax, $ in CRDS/UNOS syntax).
2559    '!' for the cc register (used in an `and to cc' insn).
2560    '$' for the letter `s' in an op code, but only on the 68040.
2561    '&' for the letter `d' in an op code, but only on the 68040.
2562    '/' for register prefix needed by longlong.h.
2563
2564    'b' for byte insn (no effect, on the Sun; this is for the ISI).
2565    'd' to force memory addressing to be absolute, not relative.
2566    'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
2567    'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
2568        than directly).  Second part of 'y' below.
2569    'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
2570        or print pair of registers as rx:ry.
2571    'y' for a FPA insn (print pair of registers as rx:ry).  This also outputs
2572        CONST_DOUBLE's as SunFPA constant RAM registers if
2573        possible, so it should not be used except for the SunFPA.
2574
2575    */
2576
2577 void
2578 print_operand (file, op, letter)
2579      FILE *file;                /* file to write to */
2580      rtx op;                    /* operand to print */
2581      int letter;                /* %<letter> or 0 */
2582 {
2583   int i;
2584
2585   if (letter == '.')
2586     {
2587 #if defined (MOTOROLA) && !defined (CRDS)
2588       asm_fprintf (file, ".");
2589 #endif
2590     }
2591   else if (letter == '#')
2592     {
2593       asm_fprintf (file, "%0I");
2594     }
2595   else if (letter == '-')
2596     {
2597 #ifdef MOTOROLA
2598       asm_fprintf (file, "-(%Rsp)");
2599 #else
2600       asm_fprintf (file, "%Rsp@-");
2601 #endif
2602     }
2603   else if (letter == '+')
2604     {
2605 #ifdef MOTOROLA
2606       asm_fprintf (file, "(%Rsp)+");
2607 #else
2608       asm_fprintf (file, "%Rsp@+");
2609 #endif
2610     }
2611   else if (letter == '@')
2612     {
2613 #ifdef MOTOROLA
2614       asm_fprintf (file, "(%Rsp)");
2615 #else
2616       asm_fprintf (file, "%Rsp@");
2617 #endif
2618     }
2619   else if (letter == '!')
2620     {
2621       asm_fprintf (file, "%Rfpcr");
2622     }
2623   else if (letter == '$')
2624     {
2625       if (TARGET_68040_ONLY)
2626         {
2627           fprintf (file, "s");
2628         }
2629     }
2630   else if (letter == '&')
2631     {
2632       if (TARGET_68040_ONLY)
2633         {
2634           fprintf (file, "d");
2635         }
2636     }
2637   else if (letter == '/')
2638     {
2639       asm_fprintf (file, "%R");
2640     }
2641   else if (GET_CODE (op) == REG)
2642     {
2643 #ifdef SUPPORT_SUN_FPA
2644       if (REGNO (op) < 16
2645           && (letter == 'y' || letter == 'x')
2646           && GET_MODE (op) == DFmode)
2647         {
2648           fprintf (file, "%s:%s", reg_names[REGNO (op)],
2649                    reg_names[REGNO (op)+1]);
2650         }
2651       else
2652 #endif
2653         {
2654           if (letter == 'R')
2655             /* Print out the second register name of a register pair.
2656                I.e., R (6) => 7.  */
2657             fputs (reg_names[REGNO (op) + 1], file);
2658           else
2659             fputs (reg_names[REGNO (op)], file);
2660         }
2661     }
2662   else if (GET_CODE (op) == MEM)
2663     {
2664       output_address (XEXP (op, 0));
2665       if (letter == 'd' && ! TARGET_68020
2666           && CONSTANT_ADDRESS_P (XEXP (op, 0))
2667           && !(GET_CODE (XEXP (op, 0)) == CONST_INT
2668                && INTVAL (XEXP (op, 0)) < 0x8000
2669                && INTVAL (XEXP (op, 0)) >= -0x8000))
2670         {
2671 #ifdef MOTOROLA
2672           fprintf (file, ".l");
2673 #else
2674           fprintf (file, ":l");
2675 #endif
2676         }
2677     }
2678 #ifdef SUPPORT_SUN_FPA
2679   else if ((letter == 'y' || letter == 'w')
2680            && GET_CODE (op) == CONST_DOUBLE
2681            && (i = standard_sun_fpa_constant_p (op)))
2682     {
2683       fprintf (file, "%%%d", i & 0x1ff);
2684     }
2685 #endif
2686   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
2687     {
2688       REAL_VALUE_TYPE r;
2689       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2690       ASM_OUTPUT_FLOAT_OPERAND (letter, file, r);
2691     }
2692   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode)
2693     {
2694       REAL_VALUE_TYPE r;
2695       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2696       ASM_OUTPUT_LONG_DOUBLE_OPERAND (file, r);
2697     }
2698   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
2699     {
2700       REAL_VALUE_TYPE r;
2701       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2702       ASM_OUTPUT_DOUBLE_OPERAND (file, r);
2703     }
2704   else
2705     {
2706       asm_fprintf (file, "%0I"); output_addr_const (file, op);
2707     }
2708 }
2709
2710 \f
2711 /* A C compound statement to output to stdio stream STREAM the
2712    assembler syntax for an instruction operand that is a memory
2713    reference whose address is ADDR.  ADDR is an RTL expression.
2714
2715    Note that this contains a kludge that knows that the only reason
2716    we have an address (plus (label_ref...) (reg...)) when not generating
2717    PIC code is in the insn before a tablejump, and we know that m68k.md
2718    generates a label LInnn: on such an insn.
2719
2720    It is possible for PIC to generate a (plus (label_ref...) (reg...))
2721    and we handle that just like we would a (plus (symbol_ref...) (reg...)).
2722
2723    Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
2724    fails to assemble.  Luckily "Lnnn(pc,d0.l*2)" produces the results
2725    we want.  This difference can be accommodated by using an assembler
2726    define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
2727    string, as necessary.  This is accomplished via the ASM_OUTPUT_CASE_END
2728    macro.  See m68k/sgs.h for an example; for versions without the bug.
2729    Some assemblers refuse all the above solutions.  The workaround is to
2730    emit "K(pc,d0.l*2)" with K being a small constant known to give the
2731    right behaviour.
2732
2733    They also do not like things like "pea 1.w", so we simple leave off
2734    the .w on small constants. 
2735
2736    This routine is responsible for distinguishing between -fpic and -fPIC 
2737    style relocations in an address.  When generating -fpic code the
2738    offset is output in word mode (eg movel a5@(_foo:w), a0).  When generating
2739    -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
2740
2741 #ifndef ASM_OUTPUT_CASE_FETCH
2742 #ifdef MOTOROLA
2743 #ifdef SGS
2744 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2745         asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
2746 #else
2747 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2748         asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
2749 #endif
2750 #else
2751 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2752         asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
2753 #endif
2754 #endif /* ASM_OUTPUT_CASE_FETCH */
2755
2756 void
2757 print_operand_address (file, addr)
2758      FILE *file;
2759      rtx addr;
2760 {
2761   register rtx reg1, reg2, breg, ireg;
2762   rtx offset;
2763
2764   switch (GET_CODE (addr))
2765     {
2766       case REG:
2767 #ifdef MOTOROLA
2768         fprintf (file, "(%s)", reg_names[REGNO (addr)]);
2769 #else
2770         fprintf (file, "%s@", reg_names[REGNO (addr)]);
2771 #endif
2772         break;
2773       case PRE_DEC:
2774 #ifdef MOTOROLA
2775         fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
2776 #else
2777         fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);
2778 #endif
2779         break;
2780       case POST_INC:
2781 #ifdef MOTOROLA
2782         fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
2783 #else
2784         fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);
2785 #endif
2786         break;
2787       case PLUS:
2788         reg1 = reg2 = ireg = breg = offset = 0;
2789         if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
2790           {
2791             offset = XEXP (addr, 0);
2792             addr = XEXP (addr, 1);
2793           }
2794         else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
2795           {
2796             offset = XEXP (addr, 1);
2797             addr = XEXP (addr, 0);
2798           }
2799         if (GET_CODE (addr) != PLUS)
2800           {
2801             ;
2802           }
2803         else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
2804           {
2805             reg1 = XEXP (addr, 0);
2806             addr = XEXP (addr, 1);
2807           }
2808         else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
2809           {
2810             reg1 = XEXP (addr, 1);
2811             addr = XEXP (addr, 0);
2812           }
2813         else if (GET_CODE (XEXP (addr, 0)) == MULT)
2814           {
2815             reg1 = XEXP (addr, 0);
2816             addr = XEXP (addr, 1);
2817           }
2818         else if (GET_CODE (XEXP (addr, 1)) == MULT)
2819           {
2820             reg1 = XEXP (addr, 1);
2821             addr = XEXP (addr, 0);
2822           }
2823         else if (GET_CODE (XEXP (addr, 0)) == REG)
2824           {
2825             reg1 = XEXP (addr, 0);
2826             addr = XEXP (addr, 1);
2827           }
2828         else if (GET_CODE (XEXP (addr, 1)) == REG)
2829           {
2830             reg1 = XEXP (addr, 1);
2831             addr = XEXP (addr, 0);
2832           }
2833         if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
2834             || GET_CODE (addr) == SIGN_EXTEND)
2835           {
2836             if (reg1 == 0)
2837               {
2838                 reg1 = addr;
2839               }
2840             else
2841               {
2842                 reg2 = addr;
2843               }
2844             addr = 0;
2845           }
2846 #if 0   /* for OLD_INDEXING */
2847         else if (GET_CODE (addr) == PLUS)
2848           {
2849             if (GET_CODE (XEXP (addr, 0)) == REG)
2850               {
2851                 reg2 = XEXP (addr, 0);
2852                 addr = XEXP (addr, 1);
2853               }
2854             else if (GET_CODE (XEXP (addr, 1)) == REG)
2855               {
2856                 reg2 = XEXP (addr, 1);
2857                 addr = XEXP (addr, 0);
2858               }
2859           }
2860 #endif
2861         if (offset != 0)
2862           {
2863             if (addr != 0)
2864               {
2865                 abort ();
2866               }
2867             addr = offset;
2868           }
2869         if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
2870                       || GET_CODE (reg1) == MULT))
2871             || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
2872           {
2873             breg = reg2;
2874             ireg = reg1;
2875           }
2876         else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
2877           {
2878             breg = reg1;
2879             ireg = reg2;
2880           }
2881         if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
2882             && ! (flag_pic && ireg == pic_offset_table_rtx))
2883           {
2884             int scale = 1;
2885             if (GET_CODE (ireg) == MULT)
2886               {
2887                 scale = INTVAL (XEXP (ireg, 1));
2888                 ireg = XEXP (ireg, 0);
2889               }
2890             if (GET_CODE (ireg) == SIGN_EXTEND)
2891               {
2892                 ASM_OUTPUT_CASE_FETCH (file,
2893                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
2894                              reg_names[REGNO (XEXP (ireg, 0))]);
2895                 fprintf (file, "w");
2896               }
2897             else
2898               {
2899                 ASM_OUTPUT_CASE_FETCH (file,
2900                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
2901                              reg_names[REGNO (ireg)]);
2902                 fprintf (file, "l");
2903               }
2904             if (scale != 1)
2905               {
2906 #ifdef MOTOROLA
2907                 fprintf (file, "*%d", scale);
2908 #else
2909                 fprintf (file, ":%d", scale);
2910 #endif
2911               }
2912             putc (')', file);
2913             break;
2914           }
2915         if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
2916             && ! (flag_pic && breg == pic_offset_table_rtx))
2917           {
2918             ASM_OUTPUT_CASE_FETCH (file,
2919                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
2920                          reg_names[REGNO (breg)]);
2921             fprintf (file, "l)");
2922             break;
2923           }
2924         if (ireg != 0 || breg != 0)
2925           {
2926             int scale = 1;
2927             if (breg == 0)
2928               {
2929                 abort ();
2930               }
2931             if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
2932               {
2933                 abort ();
2934               }
2935 #ifdef MOTOROLA
2936             if (addr != 0)
2937               {
2938                 output_addr_const (file, addr);
2939                 if (flag_pic && (breg == pic_offset_table_rtx))
2940                   fprintf (file, "@GOT");
2941               }
2942             fprintf (file, "(%s", reg_names[REGNO (breg)]);
2943             if (ireg != 0)
2944               {
2945                 putc (',', file);
2946               }
2947 #else
2948             fprintf (file, "%s@(", reg_names[REGNO (breg)]);
2949             if (addr != 0)
2950               {
2951                 output_addr_const (file, addr);
2952                 if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
2953                   fprintf (file, ":w");
2954                 if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
2955                   fprintf (file, ":l");
2956               }
2957             if (addr != 0 && ireg != 0)
2958               {
2959                 putc (',', file);
2960               }
2961 #endif
2962             if (ireg != 0 && GET_CODE (ireg) == MULT)
2963               {
2964                 scale = INTVAL (XEXP (ireg, 1));
2965                 ireg = XEXP (ireg, 0);
2966               }
2967             if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
2968               {
2969 #ifdef MOTOROLA
2970                 fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);
2971 #else
2972                 fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);
2973 #endif
2974               }
2975             else if (ireg != 0)
2976               {
2977 #ifdef MOTOROLA
2978                 fprintf (file, "%s.l", reg_names[REGNO (ireg)]);
2979 #else
2980                 fprintf (file, "%s:l", reg_names[REGNO (ireg)]);
2981 #endif
2982               }
2983             if (scale != 1)
2984               {
2985 #ifdef MOTOROLA
2986                 fprintf (file, "*%d", scale);
2987 #else
2988                 fprintf (file, ":%d", scale);
2989 #endif
2990               }
2991             putc (')', file);
2992             break;
2993           }
2994         else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
2995                  && ! (flag_pic && reg1 == pic_offset_table_rtx))       
2996           {
2997             ASM_OUTPUT_CASE_FETCH (file,
2998                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
2999                          reg_names[REGNO (reg1)]);
3000             fprintf (file, "l)");
3001             break;
3002           }
3003         /* FALL-THROUGH (is this really what we want? */
3004       default:
3005         if (GET_CODE (addr) == CONST_INT
3006             && INTVAL (addr) < 0x8000
3007             && INTVAL (addr) >= -0x8000)
3008           {
3009 #ifdef MOTOROLA
3010 #ifdef SGS
3011             /* Many SGS assemblers croak on size specifiers for constants. */
3012             fprintf (file, "%d", INTVAL (addr));
3013 #else
3014             fprintf (file, "%d.w", INTVAL (addr));
3015 #endif
3016 #else
3017             fprintf (file, "%d:w", INTVAL (addr));
3018 #endif
3019           }
3020         else
3021           {
3022             output_addr_const (file, addr);
3023           }
3024         break;
3025     }
3026 }
3027 \f
3028 /* Check for cases where a clr insns can be omitted from code using
3029    strict_low_part sets.  For example, the second clrl here is not needed:
3030    clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
3031
3032    MODE is the mode of this STRICT_LOW_PART set.  FIRST_INSN is the clear
3033    insn we are checking for redundancy.  TARGET is the register set by the
3034    clear insn.  */
3035
3036 int
3037 strict_low_part_peephole_ok (mode, first_insn, target)
3038      enum machine_mode mode;
3039      rtx first_insn;
3040      rtx target;
3041 {
3042   rtx p;
3043
3044   p = prev_nonnote_insn (first_insn);
3045
3046   while (p)
3047     {
3048       /* If it isn't an insn, then give up.  */
3049       if (GET_CODE (p) != INSN)
3050         return 0;
3051
3052       if (reg_set_p (target, p))
3053         {
3054           rtx set = single_set (p);
3055           rtx dest;
3056
3057           /* If it isn't an easy to recognize insn, then give up.  */
3058           if (! set)
3059             return 0;
3060
3061           dest = SET_DEST (set);
3062
3063           /* If this sets the entire target register to zero, then our
3064              first_insn is redundant.  */
3065           if (rtx_equal_p (dest, target)
3066               && SET_SRC (set) == const0_rtx)
3067             return 1;
3068           else if (GET_CODE (dest) == STRICT_LOW_PART
3069                    && GET_CODE (XEXP (dest, 0)) == REG
3070                    && REGNO (XEXP (dest, 0)) == REGNO (target)
3071                    && (GET_MODE_SIZE (GET_MODE (XEXP (dest, 0)))
3072                        <= GET_MODE_SIZE (mode)))
3073             /* This is a strict low part set which modifies less than
3074                we are using, so it is safe.  */
3075             ;
3076           else
3077             return 0;
3078         }
3079
3080       p = prev_nonnote_insn (p);
3081
3082     }
3083
3084   return 0;
3085 }
3086
3087 /* Accept integer operands in the range 0..0xffffffff.  We have to check the
3088    range carefully since this predicate is used in DImode contexts.  Also, we
3089    need some extra crud to make it work when hosted on 64-bit machines.  */
3090
3091 int
3092 const_uint32_operand (op, mode)
3093      rtx op;
3094      enum machine_mode mode;
3095 {
3096 #if HOST_BITS_PER_WIDE_INT > 32
3097   /* All allowed constants will fit a CONST_INT.  */
3098   return (GET_CODE (op) == CONST_INT
3099           && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
3100 #else
3101   return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0)
3102           || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
3103 #endif
3104 }
3105
3106 /* Accept integer operands in the range -0x80000000..0x7fffffff.  We have
3107    to check the range carefully since this predicate is used in DImode
3108    contexts.  */
3109
3110 int
3111 const_sint32_operand (op, mode)
3112      rtx op;
3113      enum machine_mode mode;
3114 {
3115   /* All allowed constants will fit a CONST_INT.  */
3116   return (GET_CODE (op) == CONST_INT
3117           && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
3118 }