OSDN Git Service

(ENDFILE_SPEC): Add missing `%s'.
[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 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21
22 /* Some output-actions in m68k.md need these.  */
23 #include <stdio.h>
24 #include "config.h"
25 #include "rtl.h"
26 #include "regs.h"
27 #include "hard-reg-set.h"
28 #include "real.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "insn-flags.h"
32 #include "output.h"
33 #include "insn-attr.h"
34
35 /* Needed for use_return_insn.  */
36 #include "flags.h"
37
38 #ifdef SUPPORT_SUN_FPA
39
40 /* Index into this array by (register number >> 3) to find the
41    smallest class which contains that register.  */
42 enum reg_class regno_reg_class[]
43   = { DATA_REGS, ADDR_REGS, FP_REGS,
44       LO_FPA_REGS, LO_FPA_REGS, FPA_REGS, FPA_REGS };
45
46 #endif /* defined SUPPORT_SUN_FPA */
47
48 /* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
49    if SGS_SWITCH_TABLE.  */
50 int switch_table_difference_label_flag;
51
52 static rtx find_addr_reg ();
53 rtx legitimize_pic_address ();
54 \f
55
56 /* Emit a (use pic_offset_table_rtx) if we used PIC relocation in the 
57    function at any time during the compilation process.  In the future 
58    we should try and eliminate the USE if we can easily determine that 
59    all PIC references were deleted from the current function.  That would 
60    save an address register */
61    
62 void
63 finalize_pic ()
64 {
65   if (flag_pic && current_function_uses_pic_offset_table)
66     {
67       rtx insn = gen_rtx (USE, VOIDmode, pic_offset_table_rtx);
68       emit_insn_after (insn, get_insns ());
69       emit_insn (insn);
70     }
71 }
72
73 \f
74 /* This function generates the assembly code for function entry.
75    STREAM is a stdio stream to output the code to.
76    SIZE is an int: how many units of temporary storage to allocate.
77    Refer to the array `regs_ever_live' to determine which registers
78    to save; `regs_ever_live[I]' is nonzero if register number I
79    is ever used in the function.  This function is responsible for
80    knowing which registers should not be saved even if used.  */
81
82
83 /* Note that the order of the bit mask for fmovem is the opposite
84    of the order for movem!  */
85
86
87 void
88 output_function_prologue (stream, size)
89      FILE *stream;
90      int size;
91 {
92   register int regno;
93   register int mask = 0;
94   int num_saved_regs = 0;
95   extern char call_used_regs[];
96   int fsize = (size + 3) & -4;
97   
98
99   if (frame_pointer_needed)
100     {
101       if (fsize == 0 && TARGET_68040)
102         {
103         /* on the 68040, pea + move is faster than link.w 0 */
104 #ifdef MOTOROLA
105           asm_fprintf (stream, "\tpea (%s)\n\tmove.l %s,%s\n",
106                reg_names[FRAME_POINTER_REGNUM], reg_names[STACK_POINTER_REGNUM],
107                reg_names[FRAME_POINTER_REGNUM]);
108 #else
109           asm_fprintf (stream, "\tpea %s@\n\tmovel %s,%s\n",
110                reg_names[FRAME_POINTER_REGNUM], reg_names[STACK_POINTER_REGNUM],
111                reg_names[FRAME_POINTER_REGNUM]);
112 #endif
113         }
114       else if (fsize < 0x8000)
115         {
116 #ifdef MOTOROLA
117           asm_fprintf (stream, "\tlink.w %s,%0I%d\n",
118                        reg_names[FRAME_POINTER_REGNUM], -fsize);
119 #else
120           asm_fprintf (stream, "\tlink %s,%0I%d\n",
121                        reg_names[FRAME_POINTER_REGNUM], -fsize);
122 #endif
123         }
124       else if (TARGET_68020)
125         {
126 #ifdef MOTOROLA
127           asm_fprintf (stream, "\tlink.l %s,%0I%d\n",
128                        reg_names[FRAME_POINTER_REGNUM], -fsize);
129 #else
130           asm_fprintf (stream, "\tlink %s,%0I%d\n",
131                        reg_names[FRAME_POINTER_REGNUM], -fsize);
132 #endif
133         }
134       else
135         {
136       /* Adding negative number is faster on the 68040.  */
137 #ifdef MOTOROLA
138           asm_fprintf (stream, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
139                        reg_names[FRAME_POINTER_REGNUM], -fsize);
140 #else
141           asm_fprintf (stream, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
142                        reg_names[FRAME_POINTER_REGNUM], -fsize);
143 #endif
144         }
145     }
146   else if (fsize)
147     {
148       /* Adding negative number is faster on the 68040.  */
149       if (fsize + 4 < 0x8000)
150         {
151         /* asm_fprintf() cannot handle %. */
152 #ifdef MOTOROLA
153           asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - (fsize + 4));
154 #else
155           asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", - (fsize + 4));
156 #endif
157         }
158       else
159         {
160         /* asm_fprintf() cannot handle %. */
161 #ifdef MOTOROLA
162           asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", - (fsize + 4));
163 #else
164           asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", - (fsize + 4));
165 #endif
166         }
167     }
168 #ifdef SUPPORT_SUN_FPA
169   for (regno = 24; regno < 56; regno++)
170     if (regs_ever_live[regno] && ! call_used_regs[regno])
171       {
172 #ifdef MOTOROLA
173         asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n",
174                      reg_names[regno]);
175 #else
176         asm_fprintf (stream, "\tfpmoved %s,%Rsp@-\n",
177                      reg_names[regno]);
178 #endif
179       }
180 #endif
181   for (regno = 16; regno < 24; regno++)
182     if (regs_ever_live[regno] && ! call_used_regs[regno])
183        mask |= 1 << (regno - 16);
184   if ((mask & 0xff) != 0)
185     {
186 #ifdef MOTOROLA
187       asm_fprintf (stream, "\tfmovm %0I0x%x,-(%Rsp)\n", mask & 0xff);
188 #else
189       asm_fprintf (stream, "\tfmovem %0I0x%x,%Rsp@-\n", mask & 0xff);
190 #endif
191     }
192   mask = 0;
193   for (regno = 0; regno < 16; regno++)
194     if (regs_ever_live[regno] && ! call_used_regs[regno])
195       {
196         mask |= 1 << (15 - regno);
197         num_saved_regs++;
198       }
199   if (frame_pointer_needed)
200     {
201       mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));
202       num_saved_regs--;
203     }
204
205 #if NEED_PROBE
206   fprintf (stream, "\ttstl sp@(%d)\n", NEED_PROBE - num_saved_regs * 4);
207 #endif
208
209   if (num_saved_regs <= 2)
210     {
211       /* Store each separately in the same order moveml uses.
212          Using two movel instructions instead of a single moveml
213          is about 15% faster for the 68020 and 68030 at no expense
214          in code size */
215
216       int i;
217
218       /* Undo the work from above. */
219       for (i = 0; i< 16; i++)
220         if (mask & (1 << i))
221           asm_fprintf (stream,
222 #ifdef MOTOROLA
223                        "\t%Omove.l %s,-(%Rsp)\n",
224 #else
225                        "\tmovel %s,%Rsp@-\n",
226 #endif
227                        reg_names[15 - i]);
228     }
229   else if (mask)
230     {
231 #ifdef MOTOROLA
232       asm_fprintf (stream, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask);
233 #else
234       asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@-\n", mask);
235 #endif
236     }
237   if (flag_pic && current_function_uses_pic_offset_table)
238     {
239 #ifdef MOTOROLA
240       asm_fprintf (stream, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
241                    reg_names[PIC_OFFSET_TABLE_REGNUM]);
242 #else
243       asm_fprintf (stream, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
244                    reg_names[PIC_OFFSET_TABLE_REGNUM]);
245       asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n",
246                    reg_names[PIC_OFFSET_TABLE_REGNUM],
247                    reg_names[PIC_OFFSET_TABLE_REGNUM]);
248 #endif
249     }
250 }
251 \f
252 /* Return true if this function's epilogue can be output as RTL.  */
253
254 int
255 use_return_insn ()
256 {
257   int regno;
258
259   if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)
260     return 0;
261   
262   /* Copied from output_function_epilogue ().  We should probably create a
263      separate layout routine to perform the common work.  */
264   
265   for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++)
266     if (regs_ever_live[regno] && ! call_used_regs[regno])
267       return 0;
268   
269   return 1;
270 }
271
272 /* This function generates the assembly code for function exit,
273    on machines that need it.  Args are same as for FUNCTION_PROLOGUE.
274
275    The function epilogue should not depend on the current stack pointer!
276    It should use the frame pointer only, if there is a frame pointer.
277    This is mandatory because of alloca; we also take advantage of it to
278    omit stack adjustments before returning.  */
279
280 void
281 output_function_epilogue (stream, size)
282      FILE *stream;
283      int size;
284 {
285   register int regno;
286   register int mask, fmask;
287   register int nregs;
288   int offset, foffset, fpoffset;
289   extern char call_used_regs[];
290   int fsize = (size + 3) & -4;
291   int big = 0;
292   rtx insn = get_last_insn ();
293   int restore_from_sp = 0;
294   
295   /* If the last insn was a BARRIER, we don't have to write any code.  */
296   if (GET_CODE (insn) == NOTE)
297     insn = prev_nonnote_insn (insn);
298   if (insn && GET_CODE (insn) == BARRIER)
299     {
300       /* Output just a no-op so that debuggers don't get confused
301          about which function the pc is in at this address.  */
302       asm_fprintf (stream, "\tnop\n");
303       return;
304     }
305
306 #ifdef FUNCTION_BLOCK_PROFILER_EXIT
307   if (profile_block_flag == 2)
308     {
309       FUNCTION_BLOCK_PROFILER_EXIT (stream);
310     }
311 #endif
312
313 #ifdef FUNCTION_EXTRA_EPILOGUE
314   FUNCTION_EXTRA_EPILOGUE (stream, size);
315 #endif
316   nregs = 0;  fmask = 0; fpoffset = 0;
317 #ifdef SUPPORT_SUN_FPA
318   for (regno = 24 ; regno < 56 ; regno++)
319     if (regs_ever_live[regno] && ! call_used_regs[regno])
320       nregs++;
321   fpoffset = nregs * 8;
322 #endif
323   nregs = 0;
324   for (regno = 16; regno < 24; regno++)
325     if (regs_ever_live[regno] && ! call_used_regs[regno])
326       {
327         nregs++;
328         fmask |= 1 << (23 - regno);
329       }
330   foffset = fpoffset + nregs * 12;
331   nregs = 0;  mask = 0;
332   if (frame_pointer_needed)
333     regs_ever_live[FRAME_POINTER_REGNUM] = 0;
334   for (regno = 0; regno < 16; regno++)
335     if (regs_ever_live[regno] && ! call_used_regs[regno])
336       {
337         nregs++;
338         mask |= 1 << regno;
339       }
340   offset = foffset + nregs * 4;
341   restore_from_sp = ! frame_pointer_needed
342              || (! current_function_calls_alloca && leaf_function_p ());
343   if (offset + fsize >= 0x8000
344       && ! restore_from_sp
345       && (mask || fmask || fpoffset))
346     {
347 #ifdef MOTOROLA
348       asm_fprintf (stream, "\t%Omove.l %0I%d,%Ra1\n", -fsize);
349 #else
350       asm_fprintf (stream, "\tmovel %0I%d,%Ra1\n", -fsize);
351 #endif
352       fsize = 0, big = 1;
353     }
354   if (nregs <= 2)
355     {
356       /* Restore each separately in the same order moveml does.
357          Using two movel instructions instead of a single moveml
358          is about 15% faster for the 68020 and 68030 at no expense
359          in code size. */
360
361       int i;
362
363       /* Undo the work from above. */
364       for (i = 0; i< 16; i++)
365         if (mask & (1 << i))
366           {
367             if (big)
368               {
369 #ifdef MOTOROLA
370                 asm_fprintf (stream, "\t%Omove.l -%d(%s,%Ra1.l),%s\n",
371                              offset + fsize,
372                              reg_names[FRAME_POINTER_REGNUM],
373                              reg_names[i]);
374 #else
375                 asm_fprintf (stream, "\tmovel %s@(-%d,%Ra1:l),%s\n",
376                              reg_names[FRAME_POINTER_REGNUM],
377                              offset + fsize, reg_names[i]);
378 #endif
379               }
380             else if (restore_from_sp)
381               {
382 #ifdef MOTOROLA
383                 asm_fprintf (stream, "\t%Omove.l (%Rsp)+,%s\n",
384                              reg_names[i]);
385 #else
386                 asm_fprintf (stream, "\tmovel %Rsp@+,%s\n",
387                              reg_names[i]);
388 #endif
389               }
390             else
391               {
392 #ifdef MOTOROLA
393                 asm_fprintf (stream, "\t%Omove.l -%d(%s),%s\n",
394                              offset + fsize,
395                              reg_names[FRAME_POINTER_REGNUM],
396                              reg_names[i]);
397 #else
398                 asm_fprintf (stream, "\tmovel %s@(-%d),%s\n",
399                              reg_names[FRAME_POINTER_REGNUM],
400                              offset + fsize, reg_names[i]);
401 #endif
402               }
403             offset = offset - 4;
404           }
405     }
406   else if (mask)
407     {
408       if (big)
409         {
410 #ifdef MOTOROLA
411           asm_fprintf (stream, "\tmovm.l -%d(%s,%Ra1.l),%0I0x%x\n",
412                        offset + fsize,
413                        reg_names[FRAME_POINTER_REGNUM],
414                        mask);
415 #else
416           asm_fprintf (stream, "\tmoveml %s@(-%d,%Ra1:l),%0I0x%x\n",
417                        reg_names[FRAME_POINTER_REGNUM],
418                        offset + fsize, mask);
419 #endif
420         }
421       else if (restore_from_sp)
422         {
423 #ifdef MOTOROLA
424           asm_fprintf (stream, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask);
425 #else
426           asm_fprintf (stream, "\tmoveml %Rsp@+,%0I0x%x\n", mask);
427 #endif
428         }
429       else
430         {
431 #ifdef MOTOROLA
432           asm_fprintf (stream, "\tmovm.l -%d(%s),%0I0x%x\n",
433                        offset + fsize,
434                        reg_names[FRAME_POINTER_REGNUM],
435                        mask);
436 #else
437           asm_fprintf (stream, "\tmoveml %s@(-%d),%0I0x%x\n",
438                        reg_names[FRAME_POINTER_REGNUM],
439                        offset + fsize, mask);
440 #endif
441         }
442     }
443   if (fmask)
444     {
445       if (big)
446         {
447 #ifdef MOTOROLA
448           asm_fprintf (stream, "\tfmovm -%d(%s,%Ra1.l),%0I0x%x\n",
449                        foffset + fsize,
450                        reg_names[FRAME_POINTER_REGNUM],
451                        fmask);
452 #else
453           asm_fprintf (stream, "\tfmovem %s@(-%d,%Ra1:l),%0I0x%x\n",
454                        reg_names[FRAME_POINTER_REGNUM],
455                        foffset + fsize, fmask);
456 #endif
457         }
458       else if (restore_from_sp)
459         {
460 #ifdef MOTOROLA
461           asm_fprintf (stream, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask);
462 #else
463           asm_fprintf (stream, "\tfmovem %Rsp@+,%0I0x%x\n", fmask);
464 #endif
465         }
466       else
467         {
468 #ifdef MOTOROLA
469           asm_fprintf (stream, "\tfmovm -%d(%s),%0I0x%x\n",
470                        foffset + fsize,
471                        reg_names[FRAME_POINTER_REGNUM],
472                        fmask);
473 #else
474           asm_fprintf (stream, "\tfmovem %s@(-%d),%0I0x%x\n",
475                        reg_names[FRAME_POINTER_REGNUM],
476                        foffset + fsize, fmask);
477 #endif
478         }
479     }
480   if (fpoffset != 0)
481     for (regno = 55; regno >= 24; regno--)
482       if (regs_ever_live[regno] && ! call_used_regs[regno])
483         {
484           if (big)
485             {
486 #ifdef MOTOROLA
487               asm_fprintf (stream, "\tfpmovd -%d(%s,%Ra1.l), %s\n",
488                            fpoffset + fsize,
489                            reg_names[FRAME_POINTER_REGNUM],
490                            reg_names[regno]);
491 #else
492               asm_fprintf (stream, "\tfpmoved %s@(-%d,%Ra1:l), %s\n",
493                            reg_names[FRAME_POINTER_REGNUM],
494                            fpoffset + fsize, reg_names[regno]);
495 #endif
496             }
497           else if (restore_from_sp)
498             {
499 #ifdef MOTOROLA
500               asm_fprintf (stream, "\tfpmovd (%Rsp)+,%s\n",
501                            reg_names[regno]);
502 #else
503               asm_fprintf (stream, "\tfpmoved %Rsp@+, %s\n",
504                            reg_names[regno]);
505 #endif
506             }
507           else
508             {
509 #ifdef MOTOROLA
510               asm_fprintf (stream, "\tfpmovd -%d(%s), %s\n",
511                            fpoffset + fsize,
512                            reg_names[FRAME_POINTER_REGNUM],
513                            reg_names[regno]);
514 #else
515               asm_fprintf (stream, "\tfpmoved %s@(-%d), %s\n",
516                            reg_names[FRAME_POINTER_REGNUM],
517                            fpoffset + fsize, reg_names[regno]);
518 #endif
519             }
520           fpoffset -= 8;
521         }
522   if (frame_pointer_needed)
523     fprintf (stream, "\tunlk %s\n",
524              reg_names[FRAME_POINTER_REGNUM]);
525   else if (fsize)
526     {
527       if (fsize + 4 < 0x8000)
528         {
529         /* asm_fprintf() cannot handle %. */
530 #ifdef MOTOROLA
531           asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", fsize + 4);
532 #else
533           asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", fsize + 4);
534 #endif
535         }
536       else
537         {
538         /* asm_fprintf() cannot handle %. */
539 #ifdef MOTOROLA
540           asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", fsize + 4);
541 #else
542           asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", fsize + 4);
543 #endif
544         }
545     }
546   if (current_function_pops_args)
547     asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args);
548   else
549     fprintf (stream, "\trts\n");
550 }
551 \f
552 /* Similar to general_operand, but exclude stack_pointer_rtx.  */
553
554 int
555 not_sp_operand (op, mode)
556      register rtx op;
557      enum machine_mode mode;
558 {
559   return op != stack_pointer_rtx && general_operand (op, mode);
560 }
561
562 /* Return TRUE if X is a valid comparison operator for the dbcc 
563    instruction.  
564
565    Note it rejects floating point comparison operators.
566    (In the future we could use Fdbcc).
567
568    It also rejects some comparisons when CC_NO_OVERFLOW is set.  */
569    
570 int
571 valid_dbcc_comparison_p (x, mode)
572      rtx x;
573      enum machine_mode mode;
574 {
575   switch (GET_CODE (x))
576     {
577       case EQ: case NE: case GTU: case LTU:
578       case GEU: case LEU:
579         return 1;
580
581       /* Reject some when CC_NO_OVERFLOW is set.  This may be over
582          conservative */
583       case GT: case LT: case GE: case LE:
584         return ! (cc_prev_status.flags & CC_NO_OVERFLOW);
585       default:
586         return 0;
587     }
588 }
589
590 /* Return non-zero if flags are currently in the 68881 flag register.  */
591 int
592 flags_in_68881 ()
593 {
594   /* We could add support for these in the future */
595   return cc_status.flags & CC_IN_68881;
596 }
597
598 /* Output a dbCC; jCC sequence.  Note we do not handle the 
599    floating point version of this sequence (Fdbcc).  We also
600    do not handle alternative conditions when CC_NO_OVERFLOW is
601    set.  It is assumed that valid_dbcc_comparison_p and flags_in_68881 will
602    kick those out before we get here.  */
603
604 output_dbcc_and_branch (operands)
605      rtx *operands;
606 {
607   switch (GET_CODE (operands[3]))
608     {
609       case EQ:
610 #ifdef MOTOROLA
611         output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands);
612 #else
613         output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands);
614 #endif
615         break;
616
617       case NE:
618 #ifdef MOTOROLA
619         output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands);
620 #else
621         output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands);
622 #endif
623         break;
624
625       case GT:
626 #ifdef MOTOROLA
627         output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands);
628 #else
629         output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands);
630 #endif
631         break;
632
633       case GTU:
634 #ifdef MOTOROLA
635         output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands);
636 #else
637         output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands);
638 #endif
639         break;
640
641       case LT:
642 #ifdef MOTOROLA
643         output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands);
644 #else
645         output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands);
646 #endif
647         break;
648
649       case LTU:
650 #ifdef MOTOROLA
651         output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands);
652 #else
653         output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands);
654 #endif
655         break;
656
657       case GE:
658 #ifdef MOTOROLA
659         output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands);
660 #else
661         output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands);
662 #endif
663         break;
664
665       case GEU:
666 #ifdef MOTOROLA
667         output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands);
668 #else
669         output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands);
670 #endif
671         break;
672
673       case LE:
674 #ifdef MOTOROLA
675         output_asm_insn ("dble %0,%l1\n\tjble %l2", operands);
676 #else
677         output_asm_insn ("dble %0,%l1\n\tjle %l2", operands);
678 #endif
679         break;
680
681       case LEU:
682 #ifdef MOTOROLA
683         output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands);
684 #else
685         output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands);
686 #endif
687         break;
688
689       default:
690         abort ();
691     }
692
693   /* If the decrement is to be done in SImode, then we have
694      to compensate for the fact that dbcc decrements in HImode. */
695   switch (GET_MODE (operands[0]))
696     {
697       case SImode:
698 #ifdef MOTOROLA
699         output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands);
700 #else
701         output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands);
702 #endif
703         break;
704
705       case HImode:
706         break;
707
708       default:
709         abort ();
710     }
711 }
712
713 char *
714 output_scc_di(op, operand1, operand2, dest)
715      rtx op;
716      rtx operand1;
717      rtx operand2;
718      rtx dest;
719 {
720   rtx loperands[7];
721   enum rtx_code op_code = GET_CODE (op);
722
723   /* The m68k cmp.l instruction requires operand1 to be a reg as used
724      below.  Swap the operands and change the op if these requirements
725      are not fulfilled.  */
726   if (GET_CODE (operand2) == REG && GET_CODE (operand1) != REG)
727     {
728       rtx tmp = operand1;
729
730       operand1 = operand2;
731       operand2 = tmp;
732       op_code = swap_condition (op_code);
733     }
734   loperands[0] = operand1;
735   if (GET_CODE (operand1) == REG)
736     loperands[1] = gen_rtx (REG, SImode, REGNO (operand1) + 1);
737   else
738     loperands[1] = adj_offsettable_operand (operand1, 4);
739   if (operand2 != const0_rtx)
740     {
741       loperands[2] = operand2;
742       if (GET_CODE (operand2) == REG)
743         loperands[3] = gen_rtx (REG, SImode, REGNO (operand2) + 1);
744       else
745         loperands[3] = adj_offsettable_operand (operand2, 4);
746     }
747   loperands[4] = gen_label_rtx();
748   if (operand2 != const0_rtx)
749 #ifdef MOTOROLA
750 #ifdef SGS_CMP_ORDER
751     output_asm_insn ("cmp%.l %0,%2\n\tjbne %l4\n\tcmp%.l %1,%3", loperands);
752 #else
753     output_asm_insn ("cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1", loperands);
754 #endif
755 #else
756 #ifdef SGS_CMP_ORDER
757     output_asm_insn ("cmp%.l %0,%2\n\tjne %l4\n\tcmp%.l %1,%3", loperands);
758 #else
759     output_asm_insn ("cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1", loperands);
760 #endif
761 #endif
762   else
763 #ifdef MOTOROLA
764     output_asm_insn ("tst%.l %0\n\tjbne %l4\n\ttst%.l %1", loperands);
765 #else
766     output_asm_insn ("tst%.l %0\n\tjne %l4\n\ttst%.l %1", loperands);
767 #endif
768   loperands[5] = dest;
769   
770   switch (op_code)
771     {
772       case EQ:
773         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
774                                     CODE_LABEL_NUMBER (loperands[4]));
775         output_asm_insn ("seq %5", loperands);
776         break;
777
778       case NE:
779         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
780                                     CODE_LABEL_NUMBER (loperands[4]));
781         output_asm_insn ("sne %5", loperands);
782         break;
783
784       case GT:
785         loperands[6] = gen_label_rtx();
786 #ifdef MOTOROLA
787         output_asm_insn ("shi %5\n\tjbra %l6", loperands);
788 #else
789         output_asm_insn ("shi %5\n\tjra %l6", loperands);
790 #endif
791         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
792                                     CODE_LABEL_NUMBER (loperands[4]));
793         output_asm_insn ("sgt %5", loperands);
794         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
795                                     CODE_LABEL_NUMBER (loperands[6]));
796         break;
797
798       case GTU:
799         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
800                                     CODE_LABEL_NUMBER (loperands[4]));
801         output_asm_insn ("shi %5", loperands);
802         break;
803
804       case LT:
805         loperands[6] = gen_label_rtx();
806 #ifdef MOTOROLA
807         output_asm_insn ("scs %5\n\tjbra %l6", loperands);
808 #else
809         output_asm_insn ("scs %5\n\tjra %l6", loperands);
810 #endif
811         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
812                                     CODE_LABEL_NUMBER (loperands[4]));
813         output_asm_insn ("slt %5", loperands);
814         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
815                                     CODE_LABEL_NUMBER (loperands[6]));
816         break;
817
818       case LTU:
819         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
820                                     CODE_LABEL_NUMBER (loperands[4]));
821         output_asm_insn ("scs %5", loperands);
822         break;
823
824       case GE:
825         loperands[6] = gen_label_rtx();
826 #ifdef MOTOROLA
827         output_asm_insn ("scc %5\n\tjbra %l6", loperands);
828 #else
829         output_asm_insn ("scc %5\n\tjra %l6", loperands);
830 #endif
831         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
832                                     CODE_LABEL_NUMBER (loperands[4]));
833         output_asm_insn ("sge %5", loperands);
834         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
835                                     CODE_LABEL_NUMBER (loperands[6]));
836         break;
837
838       case GEU:
839         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
840                                     CODE_LABEL_NUMBER (loperands[4]));
841         output_asm_insn ("scc %5", loperands);
842         break;
843
844       case LE:
845         loperands[6] = gen_label_rtx();
846 #ifdef MOTOROLA
847         output_asm_insn ("sls %5\n\tjbra %l6", loperands);
848 #else
849         output_asm_insn ("sls %5\n\tjra %l6", loperands);
850 #endif
851         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
852                                     CODE_LABEL_NUMBER (loperands[4]));
853         output_asm_insn ("sle %5", loperands);
854         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
855                                     CODE_LABEL_NUMBER (loperands[6]));
856         break;
857
858       case LEU:
859         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
860                                     CODE_LABEL_NUMBER (loperands[4]));
861         output_asm_insn ("sls %5", loperands);
862         break;
863
864       default:
865         abort ();
866     }
867   return "";
868 }
869
870 char *
871 output_btst (operands, countop, dataop, insn, signpos)
872      rtx *operands;
873      rtx countop, dataop;
874      rtx insn;
875      int signpos;
876 {
877   operands[0] = countop;
878   operands[1] = dataop;
879
880   if (GET_CODE (countop) == CONST_INT)
881     {
882       register int count = INTVAL (countop);
883       /* If COUNT is bigger than size of storage unit in use,
884          advance to the containing unit of same size.  */
885       if (count > signpos)
886         {
887           int offset = (count & ~signpos) / 8;
888           count = count & signpos;
889           operands[1] = dataop = adj_offsettable_operand (dataop, offset);
890         }
891       if (count == signpos)
892         cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
893       else
894         cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
895
896       /* These three statements used to use next_insns_test_no...
897          but it appears that this should do the same job.  */
898       if (count == 31
899           && next_insn_tests_no_inequality (insn))
900         return "tst%.l %1";
901       if (count == 15
902           && next_insn_tests_no_inequality (insn))
903         return "tst%.w %1";
904       if (count == 7
905           && next_insn_tests_no_inequality (insn))
906         return "tst%.b %1";
907
908       cc_status.flags = CC_NOT_NEGATIVE;
909     }
910   return "btst %0,%1";
911 }
912 \f
913 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
914    reference and a constant.  */
915
916 int
917 symbolic_operand (op, mode)
918      register rtx op;
919      enum machine_mode mode;
920 {
921   switch (GET_CODE (op))
922     {
923     case SYMBOL_REF:
924     case LABEL_REF:
925       return 1;
926
927     case CONST:
928       op = XEXP (op, 0);
929       return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
930                || GET_CODE (XEXP (op, 0)) == LABEL_REF)
931               && GET_CODE (XEXP (op, 1)) == CONST_INT);
932
933 #if 0 /* Deleted, with corresponding change in m68k.h,
934          so as to fit the specs.  No CONST_DOUBLE is ever symbolic.  */
935     case CONST_DOUBLE:
936       return GET_MODE (op) == mode;
937 #endif
938
939     default:
940       return 0;
941     }
942 }
943 \f
944 /* Check for sign_extend or zero_extend.  Used for bit-count operands. */
945
946 int
947 extend_operator(x, mode)
948      rtx x;
949      enum machine_mode mode;
950 {
951     if (mode != VOIDmode && GET_MODE(x) != mode)
952         return 0;
953     switch (GET_CODE(x))
954         {
955         case SIGN_EXTEND :
956         case ZERO_EXTEND :
957             return 1;
958         default :
959             return 0;
960         }
961 }
962
963 \f
964 /* Legitimize PIC addresses.  If the address is already
965    position-independent, we return ORIG.  Newly generated
966    position-independent addresses go to REG.  If we need more
967    than one register, we lose.  
968
969    An address is legitimized by making an indirect reference
970    through the Global Offset Table with the name of the symbol
971    used as an offset.  
972
973    The assembler and linker are responsible for placing the 
974    address of the symbol in the GOT.  The function prologue
975    is responsible for initializing a5 to the starting address
976    of the GOT.
977
978    The assembler is also responsible for translating a symbol name
979    into a constant displacement from the start of the GOT.  
980
981    A quick example may make things a little clearer:
982
983    When not generating PIC code to store the value 12345 into _foo
984    we would generate the following code:
985
986         movel #12345, _foo
987
988    When generating PIC two transformations are made.  First, the compiler
989    loads the address of foo into a register.  So the first transformation makes:
990
991         lea     _foo, a0
992         movel   #12345, a0@
993
994    The code in movsi will intercept the lea instruction and call this
995    routine which will transform the instructions into:
996
997         movel   a5@(_foo:w), a0
998         movel   #12345, a0@
999    
1000
1001    That (in a nutshell) is how *all* symbol and label references are 
1002    handled.  */
1003
1004 rtx
1005 legitimize_pic_address (orig, mode, reg)
1006      rtx orig, reg;
1007      enum machine_mode mode;
1008 {
1009   rtx pic_ref = orig;
1010
1011   /* First handle a simple SYMBOL_REF or LABEL_REF */
1012   if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
1013     {
1014       if (reg == 0)
1015         abort ();
1016
1017       pic_ref = gen_rtx (MEM, Pmode,
1018                          gen_rtx (PLUS, Pmode,
1019                                   pic_offset_table_rtx, orig));
1020       current_function_uses_pic_offset_table = 1;
1021       RTX_UNCHANGING_P (pic_ref) = 1;
1022       emit_move_insn (reg, pic_ref);
1023       return reg;
1024     }
1025   else if (GET_CODE (orig) == CONST)
1026     {
1027       rtx base, offset;
1028
1029       /* Make sure this is CONST has not already been legitimized */
1030       if (GET_CODE (XEXP (orig, 0)) == PLUS
1031           && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
1032         return orig;
1033
1034       if (reg == 0)
1035         abort ();
1036
1037       /* legitimize both operands of the PLUS */
1038       if (GET_CODE (XEXP (orig, 0)) == PLUS)
1039         {
1040           base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
1041           orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
1042                                          base == reg ? 0 : reg);
1043         }
1044       else abort ();
1045
1046       if (GET_CODE (orig) == CONST_INT)
1047         return plus_constant_for_output (base, INTVAL (orig));
1048       pic_ref = gen_rtx (PLUS, Pmode, base, orig);
1049       /* Likewise, should we set special REG_NOTEs here?  */
1050     }
1051   return pic_ref;
1052 }
1053
1054 \f
1055 typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ } CONST_METHOD;
1056
1057 #define USE_MOVQ(i)     ((unsigned)((i) + 128) <= 255)
1058
1059 CONST_METHOD
1060 const_method (constant)
1061      rtx constant;
1062 {
1063   int i;
1064   unsigned u;
1065
1066   i = INTVAL (constant);
1067   if (USE_MOVQ (i))
1068     return MOVQ;
1069   /* if -256 < N < 256 but N is not in range for a moveq
1070      N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */
1071   if (USE_MOVQ (i ^ 0xff))
1072     return NOTB;
1073   /* Likewise, try with not.w */
1074   if (USE_MOVQ (i ^ 0xffff))
1075     return NOTW;
1076   /* This is the only value where neg.w is useful */
1077   if (i == -65408)
1078     return NEGW;
1079   /* Try also with swap */
1080   u = i;
1081   if (USE_MOVQ ((u >> 16) | (u << 16)))
1082     return SWAP;
1083   /* Otherwise, use move.l */
1084   return MOVL;
1085 }
1086
1087 const_int_cost (constant)
1088      rtx constant;
1089 {
1090   switch (const_method (constant))
1091     {
1092       case MOVQ :
1093       /* Constants between -128 and 127 are cheap due to moveq */
1094         return 0;
1095       case NOTB :
1096       case NOTW :
1097       case NEGW :
1098       case SWAP :
1099       /* Constants easily generated by moveq + not.b/not.w/neg.w/swap  */
1100         return 1;
1101       case MOVL :
1102         return 2;
1103       default :
1104         abort ();
1105     }
1106 }
1107
1108 char *
1109 output_move_const_into_data_reg (operands)
1110      rtx *operands;
1111 {
1112   int i;
1113
1114   i = INTVAL (operands[1]);
1115   switch (const_method (operands[1]))
1116     {
1117     case MOVQ :
1118 #if defined (MOTOROLA) && !defined (CRDS)
1119       return "moveq%.l %1,%0";
1120 #else
1121       return "moveq %1,%0";
1122 #endif
1123     case NOTB :
1124       operands[1] = gen_rtx (CONST_INT, VOIDmode, i ^ 0xff);
1125 #if defined (MOTOROLA) && !defined (CRDS)
1126       return "moveq%.l %1,%0\n\tnot%.b %0";
1127 #else
1128       return "moveq %1,%0\n\tnot%.b %0";
1129 #endif   
1130     case NOTW :
1131       operands[1] = gen_rtx (CONST_INT, VOIDmode, i ^ 0xffff);
1132 #if defined (MOTOROLA) && !defined (CRDS)
1133       return "moveq%.l %1,%0\n\tnot%.w %0";
1134 #else
1135       return "moveq %1,%0\n\tnot%.w %0";
1136 #endif   
1137     case NEGW :
1138 #if defined (MOTOROLA) && !defined (CRDS)
1139       return "moveq%.l %#-128,%0\n\tneg%.w %0";
1140 #else
1141       return "moveq %#-128,%0\n\tneg%.w %0";
1142 #endif   
1143     case SWAP :
1144       {
1145         unsigned u = i;
1146
1147         operands[1] = gen_rtx (CONST_INT, VOIDmode, (u << 16) | (u >> 16));
1148 #if defined (MOTOROLA) && !defined (CRDS)
1149         return "moveq%.l %1,%0\n\tswap %0";
1150 #else
1151         return "moveq %1,%0\n\tswap %0";
1152 #endif   
1153       }
1154     case MOVL :
1155         return "move%.l %1,%0";
1156     default :
1157         abort ();
1158     }
1159 }
1160
1161 char *
1162 output_move_simode_const (operands)
1163      rtx *operands;
1164 {
1165   if (operands[1] == const0_rtx
1166       && (DATA_REG_P (operands[0])
1167           || GET_CODE (operands[0]) == MEM)
1168       /* clr insns on 68000 read before writing.
1169          This isn't so on the 68010, but we have no alternative for it.  */
1170       && (TARGET_68020
1171           || !(GET_CODE (operands[0]) == MEM
1172                && MEM_VOLATILE_P (operands[0]))))
1173     return "clr%.l %0";
1174   else if (DATA_REG_P (operands[0]))
1175     return output_move_const_into_data_reg (operands);
1176   else if (ADDRESS_REG_P (operands[0])
1177            && INTVAL (operands[1]) < 0x8000
1178            && INTVAL (operands[1]) >= -0x8000)
1179     return "move%.w %1,%0";
1180   else if (GET_CODE (operands[0]) == MEM
1181       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
1182       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
1183            && INTVAL (operands[1]) < 0x8000
1184            && INTVAL (operands[1]) >= -0x8000)
1185     return "pea %a1";
1186   return "move%.l %1,%0";
1187 }
1188
1189 /* Return the best assembler insn template
1190    for moving operands[1] into operands[0] as a fullword.  */
1191
1192 static char *
1193 singlemove_string (operands)
1194      rtx *operands;
1195 {
1196 #ifdef SUPPORT_SUN_FPA
1197   if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
1198     return "fpmoves %1,%0";
1199 #endif
1200   if (GET_CODE (operands[1]) == CONST_INT)
1201     return output_move_simode_const (operands);
1202   return "move%.l %1,%0";
1203 }
1204
1205
1206 /* Output assembler code to perform a doubleword move insn
1207    with operands OPERANDS.  */
1208
1209 char *
1210 output_move_double (operands)
1211      rtx *operands;
1212 {
1213   enum
1214     {
1215       REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP
1216     } optype0, optype1;
1217   rtx latehalf[2];
1218   rtx middlehalf[2];
1219   rtx xops[2];
1220   rtx addreg0 = 0, addreg1 = 0;
1221   int dest_overlapped_low = 0;
1222   int size = GET_MODE_SIZE (GET_MODE (operands[0]));
1223
1224   middlehalf[0] = 0;
1225   middlehalf[1] = 0;
1226
1227   /* First classify both operands.  */
1228
1229   if (REG_P (operands[0]))
1230     optype0 = REGOP;
1231   else if (offsettable_memref_p (operands[0]))
1232     optype0 = OFFSOP;
1233   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
1234     optype0 = POPOP;
1235   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
1236     optype0 = PUSHOP;
1237   else if (GET_CODE (operands[0]) == MEM)
1238     optype0 = MEMOP;
1239   else
1240     optype0 = RNDOP;
1241
1242   if (REG_P (operands[1]))
1243     optype1 = REGOP;
1244   else if (CONSTANT_P (operands[1]))
1245     optype1 = CNSTOP;
1246   else if (offsettable_memref_p (operands[1]))
1247     optype1 = OFFSOP;
1248   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
1249     optype1 = POPOP;
1250   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
1251     optype1 = PUSHOP;
1252   else if (GET_CODE (operands[1]) == MEM)
1253     optype1 = MEMOP;
1254   else
1255     optype1 = RNDOP;
1256
1257   /* Check for the cases that the operand constraints are not
1258      supposed to allow to happen.  Abort if we get one,
1259      because generating code for these cases is painful.  */
1260
1261   if (optype0 == RNDOP || optype1 == RNDOP)
1262     abort ();
1263
1264   /* If one operand is decrementing and one is incrementing
1265      decrement the former register explicitly
1266      and change that operand into ordinary indexing.  */
1267
1268   if (optype0 == PUSHOP && optype1 == POPOP)
1269     {
1270       operands[0] = XEXP (XEXP (operands[0], 0), 0);
1271       if (size == 12)
1272         output_asm_insn ("sub%.l %#12,%0", operands);
1273       else
1274         output_asm_insn ("subq%.l %#8,%0", operands);
1275       if (GET_MODE (operands[1]) == XFmode)
1276         operands[0] = gen_rtx (MEM, XFmode, operands[0]);
1277       else if (GET_MODE (operands[0]) == DFmode)
1278         operands[0] = gen_rtx (MEM, DFmode, operands[0]);
1279       else
1280         operands[0] = gen_rtx (MEM, DImode, operands[0]);
1281       optype0 = OFFSOP;
1282     }
1283   if (optype0 == POPOP && optype1 == PUSHOP)
1284     {
1285       operands[1] = XEXP (XEXP (operands[1], 0), 0);
1286       if (size == 12)
1287         output_asm_insn ("sub%.l %#12,%1", operands);
1288       else
1289         output_asm_insn ("subq%.l %#8,%1", operands);
1290       if (GET_MODE (operands[1]) == XFmode)
1291         operands[1] = gen_rtx (MEM, XFmode, operands[1]);
1292       else if (GET_MODE (operands[1]) == DFmode)
1293         operands[1] = gen_rtx (MEM, DFmode, operands[1]);
1294       else
1295         operands[1] = gen_rtx (MEM, DImode, operands[1]);
1296       optype1 = OFFSOP;
1297     }
1298
1299   /* If an operand is an unoffsettable memory ref, find a register
1300      we can increment temporarily to make it refer to the second word.  */
1301
1302   if (optype0 == MEMOP)
1303     addreg0 = find_addr_reg (XEXP (operands[0], 0));
1304
1305   if (optype1 == MEMOP)
1306     addreg1 = find_addr_reg (XEXP (operands[1], 0));
1307
1308   /* Ok, we can do one word at a time.
1309      Normally we do the low-numbered word first,
1310      but if either operand is autodecrementing then we
1311      do the high-numbered word first.
1312
1313      In either case, set up in LATEHALF the operands to use
1314      for the high-numbered word and in some cases alter the
1315      operands in OPERANDS to be suitable for the low-numbered word.  */
1316
1317   if (size == 12)
1318     {
1319       if (optype0 == REGOP)
1320         {
1321           latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
1322           middlehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1323         }
1324       else if (optype0 == OFFSOP)
1325         {
1326           middlehalf[0] = adj_offsettable_operand (operands[0], 4);
1327           latehalf[0] = adj_offsettable_operand (operands[0], size - 4);
1328         }
1329       else
1330         {
1331           middlehalf[0] = operands[0];
1332           latehalf[0] = operands[0];
1333         }
1334
1335       if (optype1 == REGOP)
1336         {
1337           latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
1338           middlehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
1339         }
1340       else if (optype1 == OFFSOP)
1341         {
1342           middlehalf[1] = adj_offsettable_operand (operands[1], 4);
1343           latehalf[1] = adj_offsettable_operand (operands[1], size - 4);
1344         }
1345       else if (optype1 == CNSTOP)
1346         {
1347           if (GET_CODE (operands[1]) == CONST_DOUBLE)
1348             {
1349               REAL_VALUE_TYPE r;
1350               long l[3];
1351
1352               REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
1353               REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
1354               operands[1] = GEN_INT (l[0]);
1355               middlehalf[1] = GEN_INT (l[1]);
1356               latehalf[1] = GEN_INT (l[2]);
1357             }
1358           else if (CONSTANT_P (operands[1]))
1359             {
1360               /* actually, no non-CONST_DOUBLE constant should ever
1361                  appear here.  */
1362               abort ();
1363               if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
1364                 latehalf[1] = constm1_rtx;
1365               else
1366                 latehalf[1] = const0_rtx;
1367             }
1368         }
1369       else
1370         {
1371           middlehalf[1] = operands[1];
1372           latehalf[1] = operands[1];
1373         }
1374     }
1375   else
1376     /* size is not 12: */
1377     {
1378       if (optype0 == REGOP)
1379         latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1380       else if (optype0 == OFFSOP)
1381         latehalf[0] = adj_offsettable_operand (operands[0], size - 4);
1382       else
1383         latehalf[0] = operands[0];
1384
1385       if (optype1 == REGOP)
1386         latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
1387       else if (optype1 == OFFSOP)
1388         latehalf[1] = adj_offsettable_operand (operands[1], size - 4);
1389       else if (optype1 == CNSTOP)
1390         split_double (operands[1], &operands[1], &latehalf[1]);
1391       else
1392         latehalf[1] = operands[1];
1393     }
1394
1395   /* If insn is effectively movd N(sp),-(sp) then we will do the
1396      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
1397      for the low word as well, to compensate for the first decrement of sp.  */
1398   if (optype0 == PUSHOP
1399       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
1400       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
1401     operands[1] = middlehalf[1] = latehalf[1];
1402
1403   /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
1404      if the upper part of reg N does not appear in the MEM, arrange to
1405      emit the move late-half first.  Otherwise, compute the MEM address
1406      into the upper part of N and use that as a pointer to the memory
1407      operand.  */
1408   if (optype0 == REGOP
1409       && (optype1 == OFFSOP || optype1 == MEMOP))
1410     {
1411       rtx testlow = gen_rtx (REG, SImode, REGNO (operands[0]));
1412
1413       if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
1414           && reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
1415         {
1416           /* If both halves of dest are used in the src memory address,
1417              compute the address into latehalf of dest.
1418              Note that this can't happen if the dest is two data regs.  */
1419 compadr:
1420           xops[0] = latehalf[0];
1421           xops[1] = XEXP (operands[1], 0);
1422           output_asm_insn ("lea %a1,%0", xops);
1423           if( GET_MODE (operands[1]) == XFmode )
1424             {
1425               operands[1] = gen_rtx (MEM, XFmode, latehalf[0]);
1426               middlehalf[1] = adj_offsettable_operand (operands[1], size-8);
1427               latehalf[1] = adj_offsettable_operand (operands[1], size-4);
1428             }
1429           else
1430             {
1431               operands[1] = gen_rtx (MEM, DImode, latehalf[0]);
1432               latehalf[1] = adj_offsettable_operand (operands[1], size-4);
1433             }
1434         }
1435       else if (size == 12
1436                && reg_overlap_mentioned_p (middlehalf[0],
1437                                            XEXP (operands[1], 0)))
1438         {
1439           /* Check for two regs used by both source and dest.
1440              Note that this can't happen if the dest is all data regs.
1441              It can happen if the dest is d6, d7, a0.
1442              But in that case, latehalf is an addr reg, so
1443              the code at compadr does ok.  */
1444
1445           if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
1446               || reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
1447             goto compadr;
1448
1449           /* JRV says this can't happen: */
1450           if (addreg0 || addreg1)
1451             abort ();
1452
1453           /* Only the middle reg conflicts; simply put it last. */
1454           output_asm_insn (singlemove_string (operands), operands);
1455           output_asm_insn (singlemove_string (latehalf), latehalf);
1456           output_asm_insn (singlemove_string (middlehalf), middlehalf);
1457           return "";
1458         }
1459       else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)))
1460         /* If the low half of dest is mentioned in the source memory
1461            address, the arrange to emit the move late half first.  */
1462         dest_overlapped_low = 1;
1463     }
1464
1465   /* If one or both operands autodecrementing,
1466      do the two words, high-numbered first.  */
1467
1468   /* Likewise,  the first move would clobber the source of the second one,
1469      do them in the other order.  This happens only for registers;
1470      such overlap can't happen in memory unless the user explicitly
1471      sets it up, and that is an undefined circumstance.  */
1472
1473   if (optype0 == PUSHOP || optype1 == PUSHOP
1474       || (optype0 == REGOP && optype1 == REGOP
1475           && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1]))
1476               || REGNO (operands[0]) == REGNO (latehalf[1])))
1477       || dest_overlapped_low)
1478     {
1479       /* Make any unoffsettable addresses point at high-numbered word.  */
1480       if (addreg0)
1481         {
1482           if (size == 12)
1483             output_asm_insn ("addq%.l %#8,%0", &addreg0);
1484           else
1485             output_asm_insn ("addq%.l %#4,%0", &addreg0);
1486         }
1487       if (addreg1)
1488         {
1489           if (size == 12)
1490             output_asm_insn ("addq%.l %#8,%0", &addreg1);
1491           else
1492             output_asm_insn ("addq%.l %#4,%0", &addreg1);
1493         }
1494
1495       /* Do that word.  */
1496       output_asm_insn (singlemove_string (latehalf), latehalf);
1497
1498       /* Undo the adds we just did.  */
1499       if (addreg0)
1500         output_asm_insn ("subq%.l %#4,%0", &addreg0);
1501       if (addreg1)
1502         output_asm_insn ("subq%.l %#4,%0", &addreg1);
1503
1504       if (size == 12)
1505         {
1506           output_asm_insn (singlemove_string (middlehalf), middlehalf);
1507           if (addreg0)
1508             output_asm_insn ("subq%.l %#4,%0", &addreg0);
1509           if (addreg1)
1510             output_asm_insn ("subq%.l %#4,%0", &addreg1);
1511         }
1512
1513       /* Do low-numbered word.  */
1514       return singlemove_string (operands);
1515     }
1516
1517   /* Normal case: do the two words, low-numbered first.  */
1518
1519   output_asm_insn (singlemove_string (operands), operands);
1520
1521   /* Do the middle one of the three words for long double */
1522   if (size == 12)
1523     {
1524       if (addreg0)
1525         output_asm_insn ("addq%.l %#4,%0", &addreg0);
1526       if (addreg1)
1527         output_asm_insn ("addq%.l %#4,%0", &addreg1);
1528
1529       output_asm_insn (singlemove_string (middlehalf), middlehalf);
1530     }
1531
1532   /* Make any unoffsettable addresses point at high-numbered word.  */
1533   if (addreg0)
1534     output_asm_insn ("addq%.l %#4,%0", &addreg0);
1535   if (addreg1)
1536     output_asm_insn ("addq%.l %#4,%0", &addreg1);
1537
1538   /* Do that word.  */
1539   output_asm_insn (singlemove_string (latehalf), latehalf);
1540
1541   /* Undo the adds we just did.  */
1542   if (addreg0)
1543     {
1544       if (size == 12)
1545         output_asm_insn ("subq%.l %#8,%0", &addreg0);
1546       else
1547         output_asm_insn ("subq%.l %#4,%0", &addreg0);
1548     }
1549   if (addreg1)
1550     {
1551       if (size == 12)
1552         output_asm_insn ("subq%.l %#8,%0", &addreg1);
1553       else
1554         output_asm_insn ("subq%.l %#4,%0", &addreg1);
1555     }
1556
1557   return "";
1558 }
1559
1560 /* Return a REG that occurs in ADDR with coefficient 1.
1561    ADDR can be effectively incremented by incrementing REG.  */
1562
1563 static rtx
1564 find_addr_reg (addr)
1565      rtx addr;
1566 {
1567   while (GET_CODE (addr) == PLUS)
1568     {
1569       if (GET_CODE (XEXP (addr, 0)) == REG)
1570         addr = XEXP (addr, 0);
1571       else if (GET_CODE (XEXP (addr, 1)) == REG)
1572         addr = XEXP (addr, 1);
1573       else if (CONSTANT_P (XEXP (addr, 0)))
1574         addr = XEXP (addr, 1);
1575       else if (CONSTANT_P (XEXP (addr, 1)))
1576         addr = XEXP (addr, 0);
1577       else
1578         abort ();
1579     }
1580   if (GET_CODE (addr) == REG)
1581     return addr;
1582   abort ();
1583 }
1584 \f
1585 /* Store in cc_status the expressions that the condition codes will
1586    describe after execution of an instruction whose pattern is EXP.
1587    Do not alter them if the instruction would not alter the cc's.  */
1588
1589 /* On the 68000, all the insns to store in an address register fail to
1590    set the cc's.  However, in some cases these instructions can make it
1591    possibly invalid to use the saved cc's.  In those cases we clear out
1592    some or all of the saved cc's so they won't be used.  */
1593
1594 notice_update_cc (exp, insn)
1595      rtx exp;
1596      rtx insn;
1597 {
1598   /* If the cc is being set from the fpa and the expression is not an
1599      explicit floating point test instruction (which has code to deal with
1600      this), reinit the CC.  */
1601   if (((cc_status.value1 && FPA_REG_P (cc_status.value1))
1602        || (cc_status.value2 && FPA_REG_P (cc_status.value2)))
1603       && !(GET_CODE (exp) == PARALLEL
1604            && GET_CODE (XVECEXP (exp, 0, 0)) == SET
1605            && XEXP (XVECEXP (exp, 0, 0), 0) == cc0_rtx))
1606     {
1607       CC_STATUS_INIT; 
1608     }
1609   else if (GET_CODE (exp) == SET)
1610     {
1611       if (GET_CODE (SET_SRC (exp)) == CALL)
1612         {
1613           CC_STATUS_INIT; 
1614         }
1615       else if (ADDRESS_REG_P (SET_DEST (exp)))
1616         {
1617           if (cc_status.value1
1618               && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
1619             cc_status.value1 = 0;
1620           if (cc_status.value2
1621               && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
1622             cc_status.value2 = 0; 
1623         }
1624       else if (!FP_REG_P (SET_DEST (exp))
1625                && SET_DEST (exp) != cc0_rtx
1626                && (FP_REG_P (SET_SRC (exp))
1627                    || GET_CODE (SET_SRC (exp)) == FIX
1628                    || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE
1629                    || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND))
1630         {
1631           CC_STATUS_INIT; 
1632         }
1633       /* A pair of move insns doesn't produce a useful overall cc.  */
1634       else if (!FP_REG_P (SET_DEST (exp))
1635                && !FP_REG_P (SET_SRC (exp))
1636                && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
1637                && (GET_CODE (SET_SRC (exp)) == REG
1638                    || GET_CODE (SET_SRC (exp)) == MEM
1639                    || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
1640         {
1641           CC_STATUS_INIT; 
1642         }
1643       else if (GET_CODE (SET_SRC (exp)) == CALL)
1644         {
1645           CC_STATUS_INIT; 
1646         }
1647       else if (XEXP (exp, 0) != pc_rtx)
1648         {
1649           cc_status.flags = 0;
1650           cc_status.value1 = XEXP (exp, 0);
1651           cc_status.value2 = XEXP (exp, 1);
1652         }
1653     }
1654   else if (GET_CODE (exp) == PARALLEL
1655            && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
1656     {
1657       if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0)))
1658         CC_STATUS_INIT;
1659       else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx)
1660         {
1661           cc_status.flags = 0;
1662           cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
1663           cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
1664         }
1665     }
1666   else
1667     CC_STATUS_INIT;
1668   if (cc_status.value2 != 0
1669       && ADDRESS_REG_P (cc_status.value2)
1670       && GET_MODE (cc_status.value2) == QImode)
1671     CC_STATUS_INIT;
1672   if (cc_status.value2 != 0
1673       && !(cc_status.value1 && FPA_REG_P (cc_status.value1)))
1674     switch (GET_CODE (cc_status.value2))
1675       {
1676       case PLUS: case MINUS: case MULT:
1677       case DIV: case UDIV: case MOD: case UMOD: case NEG:
1678 #if 0 /* These instructions always clear the overflow bit */
1679       case ASHIFT: case ASHIFTRT: case LSHIFTRT:
1680       case ROTATE: case ROTATERT:
1681 #endif
1682         if (GET_MODE (cc_status.value2) != VOIDmode)
1683           cc_status.flags |= CC_NO_OVERFLOW;
1684         break;
1685       case ZERO_EXTEND:
1686         /* (SET r1 (ZERO_EXTEND r2)) on this machine
1687            ends with a move insn moving r2 in r2's mode.
1688            Thus, the cc's are set for r2.
1689            This can set N bit spuriously. */
1690         cc_status.flags |= CC_NOT_NEGATIVE; 
1691       }
1692   if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1693       && cc_status.value2
1694       && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1695     cc_status.value2 = 0;
1696   if (((cc_status.value1 && FP_REG_P (cc_status.value1))
1697        || (cc_status.value2 && FP_REG_P (cc_status.value2)))
1698       && !((cc_status.value1 && FPA_REG_P (cc_status.value1))
1699            || (cc_status.value2 && FPA_REG_P (cc_status.value2))))
1700     cc_status.flags = CC_IN_68881;
1701 }
1702 \f
1703 char *
1704 output_move_const_double (operands)
1705      rtx *operands;
1706 {
1707 #ifdef SUPPORT_SUN_FPA
1708   if (TARGET_FPA && FPA_REG_P (operands[0]))
1709     {
1710       int code = standard_sun_fpa_constant_p (operands[1]);
1711
1712       if (code != 0)
1713         {
1714           static char buf[40];
1715
1716           sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff);
1717           return buf;
1718         }
1719       return "fpmove%.d %1,%0";
1720     }
1721   else
1722 #endif
1723     {
1724       int code = standard_68881_constant_p (operands[1]);
1725
1726       if (code != 0)
1727         {
1728           static char buf[40];
1729
1730           sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
1731           return buf;
1732         }
1733       return "fmove%.d %1,%0";
1734     }
1735 }
1736
1737 char *
1738 output_move_const_single (operands)
1739      rtx *operands;
1740 {
1741 #ifdef SUPPORT_SUN_FPA
1742   if (TARGET_FPA)
1743     {
1744       int code = standard_sun_fpa_constant_p (operands[1]);
1745
1746       if (code != 0)
1747         {
1748           static char buf[40];
1749
1750           sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff);
1751           return buf;
1752         }
1753       return "fpmove%.s %1,%0";
1754     }
1755   else
1756 #endif /* defined SUPPORT_SUN_FPA */
1757     {
1758       int code = standard_68881_constant_p (operands[1]);
1759
1760       if (code != 0)
1761         {
1762           static char buf[40];
1763
1764           sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
1765           return buf;
1766         }
1767       return "fmove%.s %f1,%0";
1768     }
1769 }
1770
1771 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1772    from the "fmovecr" instruction.
1773    The value, anded with 0xff, gives the code to use in fmovecr
1774    to get the desired constant.  */
1775
1776 /* This code has been fixed for cross-compilation. */
1777   
1778 static int inited_68881_table = 0;
1779
1780 char *strings_68881[7] = {
1781   "0.0",
1782   "1.0",
1783   "10.0",
1784   "100.0",
1785   "10000.0",
1786   "1e8",
1787   "1e16"
1788   };
1789
1790 int codes_68881[7] = {
1791   0x0f,
1792   0x32,
1793   0x33,
1794   0x34,
1795   0x35,
1796   0x36,
1797   0x37
1798   };
1799
1800 REAL_VALUE_TYPE values_68881[7];
1801
1802 /* Set up values_68881 array by converting the decimal values
1803    strings_68881 to binary.   */
1804
1805 void
1806 init_68881_table ()
1807 {
1808   int i;
1809   REAL_VALUE_TYPE r;
1810   enum machine_mode mode;
1811
1812   mode = SFmode;
1813   for (i = 0; i < 7; i++)
1814     {
1815       if (i == 6)
1816         mode = DFmode;
1817       r = REAL_VALUE_ATOF (strings_68881[i], mode);
1818       values_68881[i] = r;
1819     }
1820   inited_68881_table = 1;
1821 }
1822
1823 int
1824 standard_68881_constant_p (x)
1825      rtx x;
1826 {
1827   REAL_VALUE_TYPE r;
1828   int i;
1829   enum machine_mode mode;
1830
1831 #ifdef NO_ASM_FMOVECR
1832   return 0;
1833 #endif
1834
1835   /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */
1836   if (TARGET_68040)
1837     return 0;
1838
1839 #ifndef REAL_ARITHMETIC
1840 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1841   if (! flag_pretend_float)
1842     return 0;
1843 #endif
1844 #endif
1845
1846   if (! inited_68881_table)
1847     init_68881_table ();
1848
1849   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1850
1851   for (i = 0; i < 6; i++)
1852     {
1853       if (REAL_VALUES_EQUAL (r, values_68881[i]))
1854         return (codes_68881[i]);
1855     }
1856   
1857   if (GET_MODE (x) == SFmode)
1858     return 0;
1859
1860   if (REAL_VALUES_EQUAL (r, values_68881[6]))
1861     return (codes_68881[6]);
1862
1863   /* larger powers of ten in the constants ram are not used
1864      because they are not equal to a `double' C constant.  */
1865   return 0;
1866 }
1867
1868 /* If X is a floating-point constant, return the logarithm of X base 2,
1869    or 0 if X is not a power of 2.  */
1870
1871 int
1872 floating_exact_log2 (x)
1873      rtx x;
1874 {
1875   REAL_VALUE_TYPE r, r1;
1876   int i;
1877
1878 #ifndef REAL_ARITHMETIC
1879 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1880   if (! flag_pretend_float)
1881     return 0;
1882 #endif
1883 #endif
1884
1885   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1886
1887   if (REAL_VALUES_LESS (r, dconst0))
1888     return 0;
1889
1890   r1 = dconst1;
1891   i = 0;
1892   while (REAL_VALUES_LESS (r1, r))
1893     {
1894       r1 = REAL_VALUE_LDEXP (dconst1, i);
1895       if (REAL_VALUES_EQUAL (r1, r))
1896         return i;
1897       i = i + 1;
1898     }
1899   return 0;
1900 }
1901 \f
1902 #ifdef SUPPORT_SUN_FPA
1903 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1904    from the Sun FPA's constant RAM.
1905    The value returned, anded with 0x1ff, gives the code to use in fpmove
1906    to get the desired constant. */
1907
1908 static int inited_FPA_table = 0;
1909
1910 char *strings_FPA[38] = {
1911 /* small rationals */
1912   "0.0",
1913   "1.0",
1914   "0.5",
1915   "-1.0",
1916   "2.0",
1917   "3.0",
1918   "4.0",
1919   "8.0",
1920   "0.25",
1921   "0.125",
1922   "10.0",
1923   "-0.5",
1924 /* Decimal equivalents of double precision values */
1925   "2.718281828459045091", /* D_E */
1926   "6.283185307179586477", /* 2 pi */
1927   "3.141592653589793116", /* D_PI */
1928   "1.570796326794896619", /* pi/2 */
1929   "1.414213562373095145", /* D_SQRT2 */
1930   "0.7071067811865475244", /* 1/sqrt(2) */
1931   "-1.570796326794896619", /* -pi/2 */
1932   "1.442695040888963387", /* D_LOG2ofE */
1933   "3.321928024887362182", /* D_LOG2of10 */
1934   "0.6931471805599452862", /* D_LOGEof2 */
1935   "2.302585092994045901", /* D_LOGEof10 */
1936   "0.3010299956639811980", /* D_LOG10of2 */
1937   "0.4342944819032518167", /* D_LOG10ofE */
1938 /* Decimal equivalents of single precision values */
1939   "2.718281745910644531", /* S_E */
1940   "6.283185307179586477", /* 2 pi */
1941   "3.141592741012573242", /* S_PI */
1942   "1.570796326794896619", /* pi/2 */
1943   "1.414213538169860840", /* S_SQRT2 */
1944   "0.7071067811865475244", /* 1/sqrt(2) */
1945   "-1.570796326794896619", /* -pi/2 */
1946   "1.442695021629333496", /* S_LOG2ofE */
1947   "3.321928024291992188", /* S_LOG2of10 */
1948   "0.6931471824645996094", /* S_LOGEof2 */
1949   "2.302585124969482442", /* S_LOGEof10 */
1950   "0.3010300099849700928", /* S_LOG10of2 */
1951   "0.4342944920063018799", /* S_LOG10ofE */
1952 };
1953
1954
1955 int codes_FPA[38] = {
1956 /* small rationals */
1957   0x200,
1958   0xe,
1959   0xf,
1960   0x10,
1961   0x11,
1962   0xb1,
1963   0x12,
1964   0x13,
1965   0x15,
1966   0x16,
1967   0x17,
1968   0x2e,
1969 /* double precision */
1970   0x8,
1971   0x9,
1972   0xa,
1973   0xb,
1974   0xc,
1975   0xd,
1976   0x27,
1977   0x28,
1978   0x29,
1979   0x2a,
1980   0x2b,
1981   0x2c,
1982   0x2d,
1983 /* single precision */
1984   0x8,
1985   0x9,
1986   0xa,
1987   0xb,
1988   0xc,
1989   0xd,
1990   0x27,
1991   0x28,
1992   0x29,
1993   0x2a,
1994   0x2b,
1995   0x2c,
1996   0x2d
1997   };
1998
1999 REAL_VALUE_TYPE values_FPA[38];
2000
2001 /* This code has been fixed for cross-compilation. */
2002
2003 void
2004 init_FPA_table ()
2005 {
2006   enum machine_mode mode;
2007   int i;
2008   REAL_VALUE_TYPE r;
2009
2010   mode = DFmode;
2011   for (i = 0; i < 38; i++)
2012     {
2013       if (i == 25)
2014         mode = SFmode;
2015       r = REAL_VALUE_ATOF (strings_FPA[i], mode);
2016       values_FPA[i] = r;
2017     }
2018   inited_FPA_table = 1;
2019 }
2020
2021
2022 int
2023 standard_sun_fpa_constant_p (x)
2024      rtx x;
2025 {
2026   REAL_VALUE_TYPE r;
2027   int i;
2028
2029 #ifndef REAL_ARITHMETIC
2030 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2031   if (! flag_pretend_float)
2032     return 0;
2033 #endif
2034 #endif
2035
2036   if (! inited_FPA_table)
2037     init_FPA_table ();
2038
2039   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2040
2041   for (i=0; i<12; i++)
2042     {
2043       if (REAL_VALUES_EQUAL (r, values_FPA[i]))
2044         return (codes_FPA[i]);
2045     }
2046
2047   if (GET_MODE (x) == SFmode)
2048     {
2049       for (i=25; i<38; i++)
2050         {
2051           if (REAL_VALUES_EQUAL (r, values_FPA[i]))
2052             return (codes_FPA[i]);
2053         }
2054     }
2055   else
2056     {
2057       for (i=12; i<25; i++)
2058         {
2059           if (REAL_VALUES_EQUAL (r, values_FPA[i]))
2060             return (codes_FPA[i]);
2061         }
2062     }
2063   return 0x0;
2064 }
2065 #endif /* define SUPPORT_SUN_FPA */
2066 \f
2067 /* A C compound statement to output to stdio stream STREAM the
2068    assembler syntax for an instruction operand X.  X is an RTL
2069    expression.
2070
2071    CODE is a value that can be used to specify one of several ways
2072    of printing the operand.  It is used when identical operands
2073    must be printed differently depending on the context.  CODE
2074    comes from the `%' specification that was used to request
2075    printing of the operand.  If the specification was just `%DIGIT'
2076    then CODE is 0; if the specification was `%LTR DIGIT' then CODE
2077    is the ASCII code for LTR.
2078
2079    If X is a register, this macro should print the register's name.
2080    The names can be found in an array `reg_names' whose type is
2081    `char *[]'.  `reg_names' is initialized from `REGISTER_NAMES'.
2082
2083    When the machine description has a specification `%PUNCT' (a `%'
2084    followed by a punctuation character), this macro is called with
2085    a null pointer for X and the punctuation character for CODE.
2086
2087    The m68k specific codes are:
2088
2089    '.' for dot needed in Motorola-style opcode names.
2090    '-' for an operand pushing on the stack:
2091        sp@-, -(sp) or -(%sp) depending on the style of syntax.
2092    '+' for an operand pushing on the stack:
2093        sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
2094    '@' for a reference to the top word on the stack:
2095        sp@, (sp) or (%sp) depending on the style of syntax.
2096    '#' for an immediate operand prefix (# in MIT and Motorola syntax
2097        but & in SGS syntax).
2098    '!' for the cc register (used in an `and to cc' insn).
2099    '$' for the letter `s' in an op code, but only on the 68040.
2100    '&' for the letter `d' in an op code, but only on the 68040.
2101    '/' for register prefix needed by longlong.h.
2102
2103    'b' for byte insn (no effect, on the Sun; this is for the ISI).
2104    'd' to force memory addressing to be absolute, not relative.
2105    'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
2106    'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
2107        than directly).  Second part of 'y' below.
2108    'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
2109        or print pair of registers as rx:ry.
2110    'y' for a FPA insn (print pair of registers as rx:ry).  This also outputs
2111        CONST_DOUBLE's as SunFPA constant RAM registers if
2112        possible, so it should not be used except for the SunFPA.
2113
2114    */
2115
2116 void
2117 print_operand (file, op, letter)
2118      FILE *file;                /* file to write to */
2119      rtx op;                    /* operand to print */
2120      int letter;                /* %<letter> or 0 */
2121 {
2122   int i;
2123
2124   if (letter == '.')
2125     {
2126 #ifdef MOTOROLA
2127       asm_fprintf (file, ".");
2128 #endif
2129     }
2130   else if (letter == '#')
2131     {
2132       asm_fprintf (file, "%0I");
2133     }
2134   else if (letter == '-')
2135     {
2136 #ifdef MOTOROLA
2137       asm_fprintf (file, "-(%Rsp)");
2138 #else
2139       asm_fprintf (file, "%Rsp@-");
2140 #endif
2141     }
2142   else if (letter == '+')
2143     {
2144 #ifdef MOTOROLA
2145       asm_fprintf (file, "(%Rsp)+");
2146 #else
2147       asm_fprintf (file, "%Rsp@+");
2148 #endif
2149     }
2150   else if (letter == '@')
2151     {
2152 #ifdef MOTOROLA
2153       asm_fprintf (file, "(%Rsp)");
2154 #else
2155       asm_fprintf (file, "%Rsp@");
2156 #endif
2157     }
2158   else if (letter == '!')
2159     {
2160       asm_fprintf (file, "%Rfpcr");
2161     }
2162   else if (letter == '$')
2163     {
2164       if (TARGET_68040_ONLY)
2165         {
2166           fprintf (file, "s");
2167         }
2168     }
2169   else if (letter == '&')
2170     {
2171       if (TARGET_68040_ONLY)
2172         {
2173           fprintf (file, "d");
2174         }
2175     }
2176   else if (letter == '/')
2177     {
2178       asm_fprintf (file, "%R");
2179     }
2180   else if (GET_CODE (op) == REG)
2181     {
2182 #ifdef SUPPORT_SUN_FPA
2183       if (REGNO (op) < 16
2184           && (letter == 'y' || letter == 'x')
2185           && GET_MODE (op) == DFmode)
2186         {
2187           fprintf (file, "%s:%s", reg_names[REGNO (op)],
2188                    reg_names[REGNO (op)+1]);
2189         }
2190       else
2191 #endif
2192         {
2193           if (letter == 'R')
2194             /* Print out the second register name of a register pair.
2195                I.e., R (6) => 7.  */
2196             fputs (reg_names[REGNO (op) + 1], file);
2197           else
2198             fputs (reg_names[REGNO (op)], file);
2199         }
2200     }
2201   else if (GET_CODE (op) == MEM)
2202     {
2203       output_address (XEXP (op, 0));
2204       if (letter == 'd' && ! TARGET_68020
2205           && CONSTANT_ADDRESS_P (XEXP (op, 0))
2206           && !(GET_CODE (XEXP (op, 0)) == CONST_INT
2207                && INTVAL (XEXP (op, 0)) < 0x8000
2208                && INTVAL (XEXP (op, 0)) >= -0x8000))
2209         {
2210 #ifdef MOTOROLA
2211           fprintf (file, ".l");
2212 #else
2213           fprintf (file, ":l");
2214 #endif
2215         }
2216     }
2217 #ifdef SUPPORT_SUN_FPA
2218   else if ((letter == 'y' || letter == 'w')
2219            && GET_CODE (op) == CONST_DOUBLE
2220            && (i = standard_sun_fpa_constant_p (op)))
2221     {
2222       fprintf (file, "%%%d", i & 0x1ff);
2223     }
2224 #endif
2225   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
2226     {
2227       REAL_VALUE_TYPE r;
2228       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2229       ASM_OUTPUT_FLOAT_OPERAND (letter, file, r);
2230     }
2231   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode)
2232     {
2233       REAL_VALUE_TYPE r;
2234       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2235       ASM_OUTPUT_LONG_DOUBLE_OPERAND (file, r);
2236     }
2237   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
2238     {
2239       REAL_VALUE_TYPE r;
2240       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2241       ASM_OUTPUT_DOUBLE_OPERAND (file, r);
2242     }
2243   else
2244     {
2245       asm_fprintf (file, "%0I"); output_addr_const (file, op);
2246     }
2247 }
2248
2249 \f
2250 /* A C compound statement to output to stdio stream STREAM the
2251    assembler syntax for an instruction operand that is a memory
2252    reference whose address is ADDR.  ADDR is an RTL expression.
2253
2254    Note that this contains a kludge that knows that the only reason
2255    we have an address (plus (label_ref...) (reg...)) when not generating
2256    PIC code is in the insn before a tablejump, and we know that m68k.md
2257    generates a label LInnn: on such an insn.
2258
2259    It is possible for PIC to generate a (plus (label_ref...) (reg...))
2260    and we handle that just like we would a (plus (symbol_ref...) (reg...)).
2261
2262    Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
2263    fails to assemble.  Luckily "Lnnn(pc,d0.l*2)" produces the results
2264    we want.  This difference can be accommodated by using an assembler
2265    define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
2266    string, as necessary.  This is accomplished via the ASM_OUTPUT_CASE_END
2267    macro.  See m68k/sgs.h for an example; for versions without the bug.
2268    Some assemblers refuse all the above solutions.  The workaround is to
2269    emit "K(pc,d0.l*2)" with K being a small constant known to give the
2270    right behaviour.
2271
2272    They also do not like things like "pea 1.w", so we simple leave off
2273    the .w on small constants. 
2274
2275    This routine is responsible for distinguishing between -fpic and -fPIC 
2276    style relocations in an address.  When generating -fpic code the
2277    offset is output in word mode (eg movel a5@(_foo:w), a0).  When generating
2278    -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
2279
2280 #ifndef ASM_OUTPUT_CASE_FETCH
2281 #ifdef MOTOROLA
2282 #ifdef SGS
2283 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2284         asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
2285 #else
2286 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2287         asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
2288 #endif
2289 #else
2290 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2291         asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
2292 #endif
2293 #endif /* ASM_OUTPUT_CASE_FETCH */
2294
2295 void
2296 print_operand_address (file, addr)
2297      FILE *file;
2298      rtx addr;
2299 {
2300   register rtx reg1, reg2, breg, ireg;
2301   rtx offset;
2302
2303   switch (GET_CODE (addr))
2304     {
2305       case REG:
2306 #ifdef MOTOROLA
2307         fprintf (file, "(%s)", reg_names[REGNO (addr)]);
2308 #else
2309         fprintf (file, "%s@", reg_names[REGNO (addr)]);
2310 #endif
2311         break;
2312       case PRE_DEC:
2313 #ifdef MOTOROLA
2314         fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
2315 #else
2316         fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);
2317 #endif
2318         break;
2319       case POST_INC:
2320 #ifdef MOTOROLA
2321         fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
2322 #else
2323         fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);
2324 #endif
2325         break;
2326       case PLUS:
2327         reg1 = reg2 = ireg = breg = offset = 0;
2328         if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
2329           {
2330             offset = XEXP (addr, 0);
2331             addr = XEXP (addr, 1);
2332           }
2333         else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
2334           {
2335             offset = XEXP (addr, 1);
2336             addr = XEXP (addr, 0);
2337           }
2338         if (GET_CODE (addr) != PLUS)
2339           {
2340             ;
2341           }
2342         else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
2343           {
2344             reg1 = XEXP (addr, 0);
2345             addr = XEXP (addr, 1);
2346           }
2347         else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
2348           {
2349             reg1 = XEXP (addr, 1);
2350             addr = XEXP (addr, 0);
2351           }
2352         else if (GET_CODE (XEXP (addr, 0)) == MULT)
2353           {
2354             reg1 = XEXP (addr, 0);
2355             addr = XEXP (addr, 1);
2356           }
2357         else if (GET_CODE (XEXP (addr, 1)) == MULT)
2358           {
2359             reg1 = XEXP (addr, 1);
2360             addr = XEXP (addr, 0);
2361           }
2362         else if (GET_CODE (XEXP (addr, 0)) == REG)
2363           {
2364             reg1 = XEXP (addr, 0);
2365             addr = XEXP (addr, 1);
2366           }
2367         else if (GET_CODE (XEXP (addr, 1)) == REG)
2368           {
2369             reg1 = XEXP (addr, 1);
2370             addr = XEXP (addr, 0);
2371           }
2372         if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
2373             || GET_CODE (addr) == SIGN_EXTEND)
2374           {
2375             if (reg1 == 0)
2376               {
2377                 reg1 = addr;
2378               }
2379             else
2380               {
2381                 reg2 = addr;
2382               }
2383             addr = 0;
2384           }
2385 #if 0   /* for OLD_INDEXING */
2386         else if (GET_CODE (addr) == PLUS)
2387           {
2388             if (GET_CODE (XEXP (addr, 0)) == REG)
2389               {
2390                 reg2 = XEXP (addr, 0);
2391                 addr = XEXP (addr, 1);
2392               }
2393             else if (GET_CODE (XEXP (addr, 1)) == REG)
2394               {
2395                 reg2 = XEXP (addr, 1);
2396                 addr = XEXP (addr, 0);
2397               }
2398           }
2399 #endif
2400         if (offset != 0)
2401           {
2402             if (addr != 0)
2403               {
2404                 abort ();
2405               }
2406             addr = offset;
2407           }
2408         if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
2409                       || GET_CODE (reg1) == MULT))
2410             || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
2411           {
2412             breg = reg2;
2413             ireg = reg1;
2414           }
2415         else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
2416           {
2417             breg = reg1;
2418             ireg = reg2;
2419           }
2420         if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
2421             && ! (flag_pic && ireg == pic_offset_table_rtx))
2422           {
2423             int scale = 1;
2424             if (GET_CODE (ireg) == MULT)
2425               {
2426                 scale = INTVAL (XEXP (ireg, 1));
2427                 ireg = XEXP (ireg, 0);
2428               }
2429             if (GET_CODE (ireg) == SIGN_EXTEND)
2430               {
2431                 ASM_OUTPUT_CASE_FETCH (file,
2432                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
2433                              reg_names[REGNO (XEXP (ireg, 0))]);
2434                 fprintf (file, "w");
2435               }
2436             else
2437               {
2438                 ASM_OUTPUT_CASE_FETCH (file,
2439                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
2440                              reg_names[REGNO (ireg)]);
2441                 fprintf (file, "l");
2442               }
2443             if (scale != 1)
2444               {
2445 #ifdef MOTOROLA
2446                 fprintf (file, "*%d", scale);
2447 #else
2448                 fprintf (file, ":%d", scale);
2449 #endif
2450               }
2451             putc (')', file);
2452             break;
2453           }
2454         if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
2455             && ! (flag_pic && breg == pic_offset_table_rtx))
2456           {
2457             ASM_OUTPUT_CASE_FETCH (file,
2458                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
2459                          reg_names[REGNO (breg)]);
2460             fprintf (file, "l)");
2461             break;
2462           }
2463         if (ireg != 0 || breg != 0)
2464           {
2465             int scale = 1;
2466             if (breg == 0)
2467               {
2468                 abort ();
2469               }
2470             if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
2471               {
2472                 abort ();
2473               }
2474 #ifdef MOTOROLA
2475             if (addr != 0)
2476               {
2477                 output_addr_const (file, addr);
2478                 if (flag_pic && (breg == pic_offset_table_rtx))
2479                   fprintf (file, "@GOT");
2480               }
2481             fprintf (file, "(%s", reg_names[REGNO (breg)]);
2482             if (ireg != 0)
2483               {
2484                 putc (',', file);
2485               }
2486 #else
2487             fprintf (file, "%s@(", reg_names[REGNO (breg)]);
2488             if (addr != 0)
2489               {
2490                 output_addr_const (file, addr);
2491                 if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
2492                   fprintf (file, ":w");
2493                 if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
2494                   fprintf (file, ":l");
2495               }
2496             if (addr != 0 && ireg != 0)
2497               {
2498                 putc (',', file);
2499               }
2500 #endif
2501             if (ireg != 0 && GET_CODE (ireg) == MULT)
2502               {
2503                 scale = INTVAL (XEXP (ireg, 1));
2504                 ireg = XEXP (ireg, 0);
2505               }
2506             if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
2507               {
2508 #ifdef MOTOROLA
2509                 fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);
2510 #else
2511                 fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);
2512 #endif
2513               }
2514             else if (ireg != 0)
2515               {
2516 #ifdef MOTOROLA
2517                 fprintf (file, "%s.l", reg_names[REGNO (ireg)]);
2518 #else
2519                 fprintf (file, "%s:l", reg_names[REGNO (ireg)]);
2520 #endif
2521               }
2522             if (scale != 1)
2523               {
2524 #ifdef MOTOROLA
2525                 fprintf (file, "*%d", scale);
2526 #else
2527                 fprintf (file, ":%d", scale);
2528 #endif
2529               }
2530             putc (')', file);
2531             break;
2532           }
2533         else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
2534                  && ! (flag_pic && reg1 == pic_offset_table_rtx))       
2535           {
2536             ASM_OUTPUT_CASE_FETCH (file,
2537                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
2538                          reg_names[REGNO (reg1)]);
2539             fprintf (file, "l)");
2540             break;
2541           }
2542         /* FALL-THROUGH (is this really what we want? */
2543       default:
2544         if (GET_CODE (addr) == CONST_INT
2545             && INTVAL (addr) < 0x8000
2546             && INTVAL (addr) >= -0x8000)
2547           {
2548 #ifdef MOTOROLA
2549 #ifdef SGS
2550             /* Many SGS assemblers croak on size specifiers for constants. */
2551             fprintf (file, "%d", INTVAL (addr));
2552 #else
2553             fprintf (file, "%d.w", INTVAL (addr));
2554 #endif
2555 #else
2556             fprintf (file, "%d:w", INTVAL (addr));
2557 #endif
2558           }
2559         else
2560           {
2561             output_addr_const (file, addr);
2562           }
2563         break;
2564     }
2565 }
2566 \f
2567 /* Check for cases where a clr insns can be omitted from code using
2568    strict_low_part sets.  For example, the second clrl here is not needed:
2569    clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
2570
2571    MODE is the mode of this STRICT_LOW_PART set.  FIRST_INSN is the clear
2572    insn we are checking for redundancy.  TARGET is the register set by the
2573    clear insn.  */
2574
2575 int
2576 strict_low_part_peephole_ok (mode, first_insn, target)
2577      enum machine_mode mode;
2578      rtx first_insn;
2579      rtx target;
2580 {
2581   rtx p;
2582
2583   p = prev_nonnote_insn (first_insn);
2584
2585   while (p)
2586     {
2587       /* If it isn't an insn, then give up.  */
2588       if (GET_CODE (p) != INSN)
2589         return 0;
2590
2591       if (reg_set_p (target, p))
2592         {
2593           rtx set = single_set (p);
2594           rtx dest;
2595
2596           /* If it isn't an easy to recognize insn, then give up.  */
2597           if (! set)
2598             return 0;
2599
2600           dest = SET_DEST (set);
2601
2602           /* If this sets the entire target register to zero, then our
2603              first_insn is redundant.  */
2604           if (rtx_equal_p (dest, target)
2605               && SET_SRC (set) == const0_rtx)
2606             return 1;
2607           else if (GET_CODE (dest) == STRICT_LOW_PART
2608                    && GET_CODE (XEXP (dest, 0)) == REG
2609                    && REGNO (XEXP (dest, 0)) == REGNO (target)
2610                    && (GET_MODE_SIZE (GET_MODE (XEXP (dest, 0)))
2611                        <= GET_MODE_SIZE (mode)))
2612             /* This is a strict low part set which modifies less than
2613                we are using, so it is safe.  */
2614             ;
2615           else
2616             return 0;
2617         }
2618
2619       p = prev_nonnote_insn (p);
2620
2621     }
2622
2623   return 0;
2624 }
2625
2626 /* Accept integer operands in the range 0..0xffffffff.  We have to check the
2627    range carefully since this predicate is used in DImode contexts.  Also, we
2628    need some extra crud to make it work when hosted on 64-bit machines.  */
2629
2630 int
2631 const_uint32_operand (op, mode)
2632      rtx op;
2633      enum machine_mode mode;
2634 {
2635 #if HOST_BITS_PER_WIDE_INT > 32
2636   /* All allowed constants will fit a CONST_INT.  */
2637   return (GET_CODE (op) == CONST_INT
2638           && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
2639 #else
2640   return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0)
2641           || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
2642 #endif
2643 }
2644
2645 /* Accept integer operands in the range -0x80000000..0x7fffffff.  We have
2646    to check the range carefully since this predicate is used in DImode
2647    contexts.  */
2648
2649 int
2650 const_sint32_operand (op, mode)
2651      rtx op;
2652      enum machine_mode mode;
2653 {
2654   /* All allowed constants will fit a CONST_INT.  */
2655   return (GET_CODE (op) == CONST_INT
2656           && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
2657 }