OSDN Git Service

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