OSDN Git Service

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