OSDN Git Service

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