OSDN Git Service

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