OSDN Git Service

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