OSDN Git Service

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