OSDN Git Service

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