OSDN Git Service

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