OSDN Git Service

fixed typo
[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 xops[2];
888   rtx addreg0 = 0, addreg1 = 0;
889   int dest_overlapped_low = 0;
890   int size = GET_MODE_SIZE (GET_MODE (operands[0]));
891
892   middlehalf[0] = 0;
893   middlehalf[1] = 0;
894
895   /* First classify both operands.  */
896
897   if (REG_P (operands[0]))
898     optype0 = REGOP;
899   else if (offsettable_memref_p (operands[0]))
900     optype0 = OFFSOP;
901   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
902     optype0 = POPOP;
903   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
904     optype0 = PUSHOP;
905   else if (GET_CODE (operands[0]) == MEM)
906     optype0 = MEMOP;
907   else
908     optype0 = RNDOP;
909
910   if (REG_P (operands[1]))
911     optype1 = REGOP;
912   else if (CONSTANT_P (operands[1]))
913     optype1 = CNSTOP;
914   else if (offsettable_memref_p (operands[1]))
915     optype1 = OFFSOP;
916   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
917     optype1 = POPOP;
918   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
919     optype1 = PUSHOP;
920   else if (GET_CODE (operands[1]) == MEM)
921     optype1 = MEMOP;
922   else
923     optype1 = RNDOP;
924
925   /* Check for the cases that the operand constraints are not
926      supposed to allow to happen.  Abort if we get one,
927      because generating code for these cases is painful.  */
928
929   if (optype0 == RNDOP || optype1 == RNDOP)
930     abort ();
931
932   /* If one operand is decrementing and one is incrementing
933      decrement the former register explicitly
934      and change that operand into ordinary indexing.  */
935
936   if (optype0 == PUSHOP && optype1 == POPOP)
937     {
938       operands[0] = XEXP (XEXP (operands[0], 0), 0);
939       if (size == 12)
940         output_asm_insn ("sub%.l %#12,%0", operands);
941       else
942         output_asm_insn ("subq%.l %#8,%0", operands);
943       if (GET_MODE (operands[1]) == XFmode)
944         operands[0] = gen_rtx (MEM, XFmode, operands[0]);
945       else if (GET_MODE (operands[0]) == DFmode)
946         operands[0] = gen_rtx (MEM, DFmode, operands[0]);
947       else
948         operands[0] = gen_rtx (MEM, DImode, operands[0]);
949       optype0 = OFFSOP;
950     }
951   if (optype0 == POPOP && optype1 == PUSHOP)
952     {
953       operands[1] = XEXP (XEXP (operands[1], 0), 0);
954       if (size == 12)
955         output_asm_insn ("sub%.l %#12,%1", operands);
956       else
957         output_asm_insn ("subq%.l %#8,%1", operands);
958       if (GET_MODE (operands[1]) == XFmode)
959         operands[1] = gen_rtx (MEM, XFmode, operands[1]);
960       else if (GET_MODE (operands[1]) == DFmode)
961         operands[1] = gen_rtx (MEM, DFmode, operands[1]);
962       else
963         operands[1] = gen_rtx (MEM, DImode, operands[1]);
964       optype1 = OFFSOP;
965     }
966
967   /* If an operand is an unoffsettable memory ref, find a register
968      we can increment temporarily to make it refer to the second word.  */
969
970   if (optype0 == MEMOP)
971     addreg0 = find_addr_reg (XEXP (operands[0], 0));
972
973   if (optype1 == MEMOP)
974     addreg1 = find_addr_reg (XEXP (operands[1], 0));
975
976   /* Ok, we can do one word at a time.
977      Normally we do the low-numbered word first,
978      but if either operand is autodecrementing then we
979      do the high-numbered word first.
980
981      In either case, set up in LATEHALF the operands to use
982      for the high-numbered word and in some cases alter the
983      operands in OPERANDS to be suitable for the low-numbered word.  */
984
985   if (size == 12)
986     {
987       if (optype0 == REGOP)
988         {
989           latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
990           middlehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
991         }
992       else if (optype0 == OFFSOP)
993         {
994           middlehalf[0] = adj_offsettable_operand (operands[0], 4);
995           latehalf[0] = adj_offsettable_operand (operands[0], size - 4);
996         }
997       else
998         {
999           middlehalf[0] = operands[0];
1000           latehalf[0] = operands[0];
1001         }
1002
1003       if (optype1 == REGOP)
1004         {
1005           latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
1006           middlehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
1007         }
1008       else if (optype1 == OFFSOP)
1009         {
1010           middlehalf[1] = adj_offsettable_operand (operands[1], 4);
1011           latehalf[1] = adj_offsettable_operand (operands[1], size - 4);
1012         }
1013       else if (optype1 == CNSTOP)
1014         {
1015           if (GET_CODE (operands[1]) == CONST_DOUBLE)
1016             {
1017               REAL_VALUE_TYPE r;
1018               long l[3];
1019
1020               REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
1021               REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
1022               operands[1] = GEN_INT (l[0]);
1023               middlehalf[1] = GEN_INT (l[1]);
1024               latehalf[1] = GEN_INT (l[2]);
1025             }
1026           else if (CONSTANT_P (operands[1]))
1027             {
1028               /* actually, no non-CONST_DOUBLE constant should ever
1029                  appear here.  */
1030               abort ();
1031               if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
1032                 latehalf[1] = constm1_rtx;
1033               else
1034                 latehalf[1] = const0_rtx;
1035             }
1036         }
1037       else
1038         {
1039           middlehalf[1] = operands[1];
1040           latehalf[1] = operands[1];
1041         }
1042     }
1043   else
1044     /* size is not 12: */
1045     {
1046       if (optype0 == REGOP)
1047         latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1048       else if (optype0 == OFFSOP)
1049         latehalf[0] = adj_offsettable_operand (operands[0], size - 4);
1050       else
1051         latehalf[0] = operands[0];
1052
1053       if (optype1 == REGOP)
1054         latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
1055       else if (optype1 == OFFSOP)
1056         latehalf[1] = adj_offsettable_operand (operands[1], size - 4);
1057       else if (optype1 == CNSTOP)
1058         split_double (operands[1], &operands[1], &latehalf[1]);
1059       else
1060         latehalf[1] = operands[1];
1061     }
1062
1063   /* If insn is effectively movd N(sp),-(sp) then we will do the
1064      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
1065      for the low word as well, to compensate for the first decrement of sp.  */
1066   if (optype0 == PUSHOP
1067       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
1068       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
1069     operands[1] = latehalf[1];
1070
1071   /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
1072      if the upper part of reg N does not appear in the MEM, arrange to
1073      emit the move late-half first.  Otherwise, compute the MEM address
1074      into the upper part of N and use that as a pointer to the memory
1075      operand.  */
1076   if (optype0 == REGOP
1077       && (optype1 == OFFSOP || optype1 == MEMOP))
1078     {
1079       if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
1080           && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
1081         {
1082           /* If both halves of dest are used in the src memory address,
1083              compute the address into latehalf of dest.  */
1084 compadr:
1085           xops[0] = latehalf[0];
1086           xops[1] = XEXP (operands[1], 0);
1087           output_asm_insn ("lea%L0,%a1,%0", xops);
1088           if( GET_MODE (operands[1]) == XFmode )
1089             {
1090               operands[1] = gen_rtx (MEM, XFmode, latehalf[0]);
1091               middlehalf[1] = adj_offsettable_operand (operands[1], size-8);
1092               latehalf[1] = adj_offsettable_operand (operands[1], size-4);
1093             }
1094           else
1095             {
1096               operands[1] = gen_rtx (MEM, DImode, latehalf[0]);
1097               latehalf[1] = adj_offsettable_operand (operands[1], size-4);
1098             }
1099         }
1100       else if (size == 12
1101                  && reg_mentioned_p (middlehalf[0], XEXP (operands[1], 0)))
1102         {
1103           /* Check for two regs used by both source and dest. */
1104           if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
1105                 || reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
1106                 goto compadr;
1107
1108           /* JRV says this can't happen: */
1109           if (addreg0 || addreg1)
1110               abort();
1111
1112           /* Only the middle reg conflicts; simply put it last. */
1113           output_asm_insn (singlemove_string (operands), operands);
1114           output_asm_insn (singlemove_string (latehalf), latehalf);
1115           output_asm_insn (singlemove_string (middlehalf), middlehalf);
1116           return "";
1117         }
1118       else if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)))
1119         /* If the low half of dest is mentioned in the source memory
1120            address, the arrange to emit the move late half first.  */
1121         dest_overlapped_low = 1;
1122     }
1123
1124   /* If one or both operands autodecrementing,
1125      do the two words, high-numbered first.  */
1126
1127   /* Likewise,  the first move would clobber the source of the second one,
1128      do them in the other order.  This happens only for registers;
1129      such overlap can't happen in memory unless the user explicitly
1130      sets it up, and that is an undefined circumstance.  */
1131
1132   if (optype0 == PUSHOP || optype1 == PUSHOP
1133       || (optype0 == REGOP && optype1 == REGOP
1134           && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1]))
1135               || REGNO (operands[0]) == REGNO (latehalf[1])))
1136       || dest_overlapped_low)
1137     {
1138       /* Make any unoffsettable addresses point at high-numbered word.  */
1139       if (addreg0)
1140         {
1141           if (size == 12)
1142             output_asm_insn ("addql %#8,%0", &addreg0);
1143           else
1144             output_asm_insn ("addql %#4,%0", &addreg0);
1145         }
1146       if (addreg1)
1147         {
1148           if (size == 12)
1149             output_asm_insn ("addql %#8,%0", &addreg1);
1150           else
1151             output_asm_insn ("addql %#4,%0", &addreg1);
1152         }
1153
1154       /* Do that word.  */
1155       output_asm_insn (singlemove_string (latehalf), latehalf);
1156
1157       /* Undo the adds we just did.  */
1158       if (addreg0)
1159         output_asm_insn ("subql %#4,%0", &addreg0);
1160       if (addreg1)
1161         output_asm_insn ("subql %#4,%0", &addreg1);
1162
1163       if (size == 12)
1164         {
1165           output_asm_insn (singlemove_string (middlehalf), middlehalf);
1166           if (addreg0)
1167             output_asm_insn ("subql %#4,%0", &addreg0);
1168           if (addreg1)
1169             output_asm_insn ("subql %#4,%0", &addreg1);
1170         }
1171
1172       /* Do low-numbered word.  */
1173       return singlemove_string (operands);
1174     }
1175
1176   /* Normal case: do the two words, low-numbered first.  */
1177
1178   output_asm_insn (singlemove_string (operands), operands);
1179
1180   /* Do the middle one of the three words for long double */
1181   if (size == 12)
1182     {
1183       if (addreg0)
1184         output_asm_insn ("addql %#4,%0", &addreg0);
1185       if (addreg1)
1186         output_asm_insn ("addql %#4,%0", &addreg1);
1187
1188       output_asm_insn (singlemove_string (middlehalf), middlehalf);
1189     }
1190
1191   /* Make any unoffsettable addresses point at high-numbered word.  */
1192   if (addreg0)
1193     output_asm_insn ("addql %#4,%0", &addreg0);
1194   if (addreg1)
1195     output_asm_insn ("addql %#4,%0", &addreg1);
1196
1197   /* Do that word.  */
1198   output_asm_insn (singlemove_string (latehalf), latehalf);
1199
1200   /* Undo the adds we just did.  */
1201   if (addreg0)
1202     {
1203       if (size == 12)
1204         output_asm_insn ("subql %#8,%0", &addreg0);
1205       else
1206         output_asm_insn ("subql %#4,%0", &addreg0);
1207     }
1208   if (addreg1)
1209     {
1210       if (size == 12)
1211         output_asm_insn ("subql %#8,%0", &addreg1);
1212       else
1213         output_asm_insn ("subql %#4,%0", &addreg1);
1214     }
1215
1216   return "";
1217 }
1218
1219 /* Return a REG that occurs in ADDR with coefficient 1.
1220    ADDR can be effectively incremented by incrementing REG.  */
1221
1222 static rtx
1223 find_addr_reg (addr)
1224      rtx addr;
1225 {
1226   while (GET_CODE (addr) == PLUS)
1227     {
1228       if (GET_CODE (XEXP (addr, 0)) == REG)
1229         addr = XEXP (addr, 0);
1230       else if (GET_CODE (XEXP (addr, 1)) == REG)
1231         addr = XEXP (addr, 1);
1232       else if (CONSTANT_P (XEXP (addr, 0)))
1233         addr = XEXP (addr, 1);
1234       else if (CONSTANT_P (XEXP (addr, 1)))
1235         addr = XEXP (addr, 0);
1236       else
1237         abort ();
1238     }
1239   if (GET_CODE (addr) == REG)
1240     return addr;
1241   abort ();
1242 }
1243 \f
1244 /* Store in cc_status the expressions that the condition codes will
1245    describe after execution of an instruction whose pattern is EXP.
1246    Do not alter them if the instruction would not alter the cc's.  */
1247
1248 /* On the 68000, all the insns to store in an address register fail to
1249    set the cc's.  However, in some cases these instructions can make it
1250    possibly invalid to use the saved cc's.  In those cases we clear out
1251    some or all of the saved cc's so they won't be used.  */
1252
1253 notice_update_cc (exp, insn)
1254      rtx exp;
1255      rtx insn;
1256 {
1257   /* If the cc is being set from the fpa and the expression is not an
1258      explicit floating point test instruction (which has code to deal with
1259      this), reinit the CC.  */
1260   if (((cc_status.value1 && FPA_REG_P (cc_status.value1))
1261        || (cc_status.value2 && FPA_REG_P (cc_status.value2)))
1262       && !(GET_CODE (exp) == PARALLEL
1263            && GET_CODE (XVECEXP (exp, 0, 0)) == SET
1264            && XEXP (XVECEXP (exp, 0, 0), 0) == cc0_rtx))
1265     {
1266       CC_STATUS_INIT; 
1267     }
1268   else if (GET_CODE (exp) == SET)
1269     {
1270       if (GET_CODE (SET_SRC (exp)) == CALL)
1271         {
1272           CC_STATUS_INIT; 
1273         }
1274       else if (ADDRESS_REG_P (SET_DEST (exp)))
1275         {
1276           if (cc_status.value1
1277               && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
1278             cc_status.value1 = 0;
1279           if (cc_status.value2
1280               && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
1281             cc_status.value2 = 0; 
1282         }
1283       else if (!FP_REG_P (SET_DEST (exp))
1284                && SET_DEST (exp) != cc0_rtx
1285                && (FP_REG_P (SET_SRC (exp))
1286                    || GET_CODE (SET_SRC (exp)) == FIX
1287                    || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE
1288                    || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND))
1289         {
1290           CC_STATUS_INIT; 
1291         }
1292       /* A pair of move insns doesn't produce a useful overall cc.  */
1293       else if (!FP_REG_P (SET_DEST (exp))
1294                && !FP_REG_P (SET_SRC (exp))
1295                && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
1296                && (GET_CODE (SET_SRC (exp)) == REG
1297                    || GET_CODE (SET_SRC (exp)) == MEM
1298                    || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
1299         {
1300           CC_STATUS_INIT; 
1301         }
1302       else if (GET_CODE (SET_SRC (exp)) == CALL)
1303         {
1304           CC_STATUS_INIT; 
1305         }
1306       else if (XEXP (exp, 0) != pc_rtx)
1307         {
1308           cc_status.flags = 0;
1309           cc_status.value1 = XEXP (exp, 0);
1310           cc_status.value2 = XEXP (exp, 1);
1311         }
1312     }
1313   else if (GET_CODE (exp) == PARALLEL
1314            && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
1315     {
1316       if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0)))
1317         CC_STATUS_INIT;
1318       else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx)
1319         {
1320           cc_status.flags = 0;
1321           cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
1322           cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
1323         }
1324     }
1325   else
1326     CC_STATUS_INIT;
1327   if (cc_status.value2 != 0
1328       && ADDRESS_REG_P (cc_status.value2)
1329       && GET_MODE (cc_status.value2) == QImode)
1330     CC_STATUS_INIT;
1331   if (cc_status.value2 != 0
1332       && !(cc_status.value1 && FPA_REG_P (cc_status.value1)))
1333     switch (GET_CODE (cc_status.value2))
1334       {
1335       case PLUS: case MINUS: case MULT:
1336       case DIV: case UDIV: case MOD: case UMOD: case NEG:
1337       case ASHIFT: case LSHIFT: case ASHIFTRT: case LSHIFTRT:
1338       case ROTATE: case ROTATERT:
1339         if (GET_MODE (cc_status.value2) != VOIDmode)
1340           cc_status.flags |= CC_NO_OVERFLOW;
1341         break;
1342       case ZERO_EXTEND:
1343         /* (SET r1 (ZERO_EXTEND r2)) on this machine
1344            ends with a move insn moving r2 in r2's mode.
1345            Thus, the cc's are set for r2.
1346            This can set N bit spuriously. */
1347         cc_status.flags |= CC_NOT_NEGATIVE; 
1348       }
1349   if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1350       && cc_status.value2
1351       && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1352     cc_status.value2 = 0;
1353   if (((cc_status.value1 && FP_REG_P (cc_status.value1))
1354        || (cc_status.value2 && FP_REG_P (cc_status.value2)))
1355       && !((cc_status.value1 && FPA_REG_P (cc_status.value1))
1356            || (cc_status.value2 && FPA_REG_P (cc_status.value2))))
1357     cc_status.flags = CC_IN_68881;
1358 }
1359 \f
1360 char *
1361 output_move_const_double (operands)
1362      rtx *operands;
1363 {
1364 #ifdef SUPPORT_SUN_FPA
1365   if (TARGET_FPA && FPA_REG_P (operands[0]))
1366     {
1367       int code = standard_sun_fpa_constant_p (operands[1]);
1368
1369       if (code != 0)
1370         {
1371           static char buf[40];
1372
1373           sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff);
1374           return buf;
1375         }
1376       return "fpmove%.d %1,%0";
1377     }
1378   else
1379 #endif
1380     {
1381       int code = standard_68881_constant_p (operands[1]);
1382
1383       if (code != 0)
1384         {
1385           static char buf[40];
1386
1387           sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
1388           return buf;
1389         }
1390       return "fmove%.d %1,%0";
1391     }
1392 }
1393
1394 char *
1395 output_move_const_single (operands)
1396      rtx *operands;
1397 {
1398 #ifdef SUPPORT_SUN_FPA
1399   if (TARGET_FPA)
1400     {
1401       int code = standard_sun_fpa_constant_p (operands[1]);
1402
1403       if (code != 0)
1404         {
1405           static char buf[40];
1406
1407           sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff);
1408           return buf;
1409         }
1410       return "fpmove%.s %1,%0";
1411     }
1412   else
1413 #endif /* defined SUPPORT_SUN_FPA */
1414     {
1415       int code = standard_68881_constant_p (operands[1]);
1416
1417       if (code != 0)
1418         {
1419           static char buf[40];
1420
1421           sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
1422           return buf;
1423         }
1424       return "fmove%.s %f1,%0";
1425     }
1426 }
1427
1428 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1429    from the "fmovecr" instruction.
1430    The value, anded with 0xff, gives the code to use in fmovecr
1431    to get the desired constant.  */
1432
1433 /* This code has been fixed for cross-compilation. */
1434   
1435 static int inited_68881_table = 0;
1436
1437 char *strings_68881[7] = {
1438   "0.0",
1439   "1.0",
1440   "10.0",
1441   "100.0",
1442   "10000.0",
1443   "1e8",
1444   "1e16"
1445   };
1446
1447 int codes_68881[7] = {
1448   0x0f,
1449   0x32,
1450   0x33,
1451   0x34,
1452   0x35,
1453   0x36,
1454   0x37
1455   };
1456
1457 REAL_VALUE_TYPE values_68881[7];
1458
1459 /* Set up values_68881 array by converting the decimal values
1460    strings_68881 to binary.   */
1461
1462 void
1463 init_68881_table ()
1464 {
1465   int i;
1466   REAL_VALUE_TYPE r;
1467   enum machine_mode mode;
1468
1469   mode = DFmode;
1470   for (i = 0; i < 7; i++)
1471     {
1472       if (i == 6)
1473         mode = SFmode;
1474       r = REAL_VALUE_ATOF (strings_68881[i], mode);
1475       values_68881[i] = r;
1476     }
1477   inited_68881_table = 1;
1478 }
1479
1480 int
1481 standard_68881_constant_p (x)
1482      rtx x;
1483 {
1484   REAL_VALUE_TYPE r;
1485   int i;
1486   enum machine_mode mode;
1487
1488   /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */
1489   if (TARGET_68040)
1490     return 0;
1491
1492 #ifndef REAL_ARITHMETIC
1493 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1494   if (! flag_pretend_float)
1495     return 0;
1496 #endif
1497 #endif
1498
1499   if (! inited_68881_table)
1500     init_68881_table ();
1501
1502   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1503
1504   for (i = 0; i < 6; i++)
1505     {
1506       if (REAL_VALUES_EQUAL (r, values_68881[i]))
1507         return (codes_68881[i]);
1508     }
1509   
1510   if (GET_MODE (x) == SFmode)
1511     return 0;
1512
1513   if (REAL_VALUES_EQUAL (r, values_68881[6]))
1514     return (codes_68881[6]);
1515
1516   /* larger powers of ten in the constants ram are not used
1517      because they are not equal to a `double' C constant.  */
1518   return 0;
1519 }
1520
1521 /* If X is a floating-point constant, return the logarithm of X base 2,
1522    or 0 if X is not a power of 2.  */
1523
1524 int
1525 floating_exact_log2 (x)
1526      rtx x;
1527 {
1528   REAL_VALUE_TYPE r, r1;
1529   int i;
1530
1531 #ifndef REAL_ARITHMETIC
1532 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1533   if (! flag_pretend_float)
1534     return 0;
1535 #endif
1536 #endif
1537
1538   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1539
1540   if (REAL_VALUES_LESS (r, dconst0))
1541     return 0;
1542
1543   r1 = dconst1;
1544   i = 0;
1545   while (REAL_VALUES_LESS (r1, r))
1546     {
1547       r1 = REAL_VALUE_LDEXP (dconst1, i);
1548       if (REAL_VALUES_EQUAL (r1, r))
1549         return i;
1550       i = i + 1;
1551     }
1552   return 0;
1553 }
1554 \f
1555 #ifdef SUPPORT_SUN_FPA
1556 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1557    from the Sun FPA's constant RAM.
1558    The value returned, anded with 0x1ff, gives the code to use in fpmove
1559    to get the desired constant. */
1560
1561 static int inited_FPA_table = 0;
1562
1563 char *strings_FPA[38] = {
1564 /* small rationals */
1565   "0.0",
1566   "1.0",
1567   "0.5",
1568   "-1.0",
1569   "2.0",
1570   "3.0",
1571   "4.0",
1572   "8.0",
1573   "0.25",
1574   "0.125",
1575   "10.0",
1576   "-0.5",
1577 /* Decimal equivalents of double precision values */
1578   "2.718281828459045091", /* D_E */
1579   "6.283185307179586477", /* 2 pi */
1580   "3.141592653589793116", /* D_PI */
1581   "1.570796326794896619", /* pi/2 */
1582   "1.414213562373095145", /* D_SQRT2 */
1583   "0.7071067811865475244", /* 1/sqrt(2) */
1584   "-1.570796326794896619", /* -pi/2 */
1585   "1.442695040888963387", /* D_LOG2ofE */
1586   "3.321928024887362182", /* D_LOG2of10 */
1587   "0.6931471805599452862", /* D_LOGEof2 */
1588   "2.302585092994045901", /* D_LOGEof10 */
1589   "0.3010299956639811980", /* D_LOG10of2 */
1590   "0.4342944819032518167", /* D_LOG10ofE */
1591 /* Decimal equivalents of single precision values */
1592   "2.718281745910644531", /* S_E */
1593   "6.283185307179586477", /* 2 pi */
1594   "3.141592741012573242", /* S_PI */
1595   "1.570796326794896619", /* pi/2 */
1596   "1.414213538169860840", /* S_SQRT2 */
1597   "0.7071067811865475244", /* 1/sqrt(2) */
1598   "-1.570796326794896619", /* -pi/2 */
1599   "1.442695021629333496", /* S_LOG2ofE */
1600   "3.321928024291992188", /* S_LOG2of10 */
1601   "0.6931471824645996094", /* S_LOGEof2 */
1602   "2.302585124969482442", /* S_LOGEof10 */
1603   "0.3010300099849700928", /* S_LOG10of2 */
1604   "0.4342944920063018799", /* S_LOG10ofE */
1605 };
1606
1607
1608 int codes_FPA[38] = {
1609 /* small rationals */
1610   0x200,
1611   0xe,
1612   0xf,
1613   0x10,
1614   0x11,
1615   0xb1,
1616   0x12,
1617   0x13,
1618   0x15,
1619   0x16,
1620   0x17,
1621   0x2e,
1622 /* double precision */
1623   0x8,
1624   0x9,
1625   0xa,
1626   0xb,
1627   0xc,
1628   0xd,
1629   0x27,
1630   0x28,
1631   0x29,
1632   0x2a,
1633   0x2b,
1634   0x2c,
1635   0x2d,
1636 /* single precision */
1637   0x8,
1638   0x9,
1639   0xa,
1640   0xb,
1641   0xc,
1642   0xd,
1643   0x27,
1644   0x28,
1645   0x29,
1646   0x2a,
1647   0x2b,
1648   0x2c,
1649   0x2d
1650   };
1651
1652 REAL_VALUE_TYPE values_FPA[38];
1653
1654 /* This code has been fixed for cross-compilation. */
1655
1656 void
1657 init_FPA_table ()
1658 {
1659   enum machine_mode mode;
1660   int i;
1661   REAL_VALUE_TYPE r;
1662
1663   mode = DFmode;
1664   for (i = 0; i < 38; i++)
1665     {
1666       if (i == 25)
1667         mode = SFmode;
1668       r = REAL_VALUE_ATOF (strings_FPA[i], mode);
1669       values_FPA[i] = r;
1670     }
1671   inited_FPA_table = 1;
1672 }
1673
1674
1675 int
1676 standard_sun_fpa_constant_p (x)
1677      rtx x;
1678 {
1679   REAL_VALUE_TYPE r;
1680   int i;
1681
1682 #ifndef REAL_ARITHMETIC
1683 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1684   if (! flag_pretend_float)
1685     return 0;
1686 #endif
1687 #endif
1688
1689   if (! inited_FPA_table)
1690     init_FPA_table ();
1691
1692   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1693
1694   for (i=0; i<12; i++)
1695     {
1696       if (REAL_VALUES_EQUAL (r, values_FPA[i]))
1697         return (codes_FPA[i]);
1698     }
1699
1700   if (GET_MODE (x) == SFmode)
1701     {
1702       for (i=25; i<38; i++)
1703         {
1704           if (REAL_VALUES_EQUAL (r, values_FPA[i]))
1705             return (codes_FPA[i]);
1706         }
1707     }
1708   else
1709     {
1710       for (i=12; i<25; i++)
1711         {
1712           if (REAL_VALUES_EQUAL (r, values_FPA[i]))
1713             return (codes_FPA[i]);
1714         }
1715     }
1716   return 0x0;
1717 }
1718 #endif /* define SUPPORT_SUN_FPA */
1719 \f
1720 /* A C compound statement to output to stdio stream STREAM the
1721    assembler syntax for an instruction operand X.  X is an RTL
1722    expression.
1723
1724    CODE is a value that can be used to specify one of several ways
1725    of printing the operand.  It is used when identical operands
1726    must be printed differently depending on the context.  CODE
1727    comes from the `%' specification that was used to request
1728    printing of the operand.  If the specification was just `%DIGIT'
1729    then CODE is 0; if the specification was `%LTR DIGIT' then CODE
1730    is the ASCII code for LTR.
1731
1732    If X is a register, this macro should print the register's name.
1733    The names can be found in an array `reg_names' whose type is
1734    `char *[]'.  `reg_names' is initialized from `REGISTER_NAMES'.
1735
1736    When the machine description has a specification `%PUNCT' (a `%'
1737    followed by a punctuation character), this macro is called with
1738    a null pointer for X and the punctuation character for CODE.
1739
1740    The m68k specific codes are:
1741
1742    '.' for dot needed in Motorola-style opcode names.
1743    '-' for an operand pushing on the stack:
1744        sp@-, -(sp) or -(%sp) depending on the style of syntax.
1745    '+' for an operand pushing on the stack:
1746        sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
1747    '@' for a reference to the top word on the stack:
1748        sp@, (sp) or (%sp) depending on the style of syntax.
1749    '#' for an immediate operand prefix (# in MIT and Motorola syntax
1750        but & in SGS syntax).
1751    '!' for the cc register (used in an `and to cc' insn).
1752    '$' for the letter `s' in an op code, but only on the 68040.
1753    '&' for the letter `d' in an op code, but only on the 68040.
1754    '/' for register prefix needed by longlong.h.
1755
1756    'b' for byte insn (no effect, on the Sun; this is for the ISI).
1757    'd' to force memory addressing to be absolute, not relative.
1758    'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
1759    'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
1760        than directly).  Second part of 'y' below.
1761    'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
1762        or print pair of registers as rx:ry.
1763    'y' for a FPA insn (print pair of registers as rx:ry).  This also outputs
1764        CONST_DOUBLE's as SunFPA constant RAM registers if
1765        possible, so it should not be used except for the SunFPA.
1766
1767    */
1768
1769 void
1770 print_operand (file, op, letter)
1771      FILE *file;                /* file to write to */
1772      rtx op;                    /* operand to print */
1773      int letter;                /* %<letter> or 0 */
1774 {
1775   int i;
1776
1777   if (letter == '.')
1778     {
1779 #ifdef MOTOROLA
1780       asm_fprintf (file, ".");
1781 #endif
1782     }
1783   else if (letter == '#')
1784     {
1785       asm_fprintf (file, "%0I");
1786     }
1787   else if (letter == '-')
1788     {
1789 #ifdef MOTOROLA
1790       asm_fprintf (file, "-(%Rsp)");
1791 #else
1792       asm_fprintf (file, "%Rsp@-");
1793 #endif
1794     }
1795   else if (letter == '+')
1796     {
1797 #ifdef MOTOROLA
1798       asm_fprintf (file, "(%Rsp)+");
1799 #else
1800       asm_fprintf (file, "%Rsp@+");
1801 #endif
1802     }
1803   else if (letter == '@')
1804     {
1805 #ifdef MOTOROLA
1806       asm_fprintf (file, "(%Rsp)");
1807 #else
1808       asm_fprintf (file, "%Rsp@");
1809 #endif
1810     }
1811   else if (letter == '!')
1812     {
1813       asm_fprintf (file, "%Rfpcr");
1814     }
1815   else if (letter == '$')
1816     {
1817       if (TARGET_68040_ONLY)
1818         {
1819           fprintf (file, "s");
1820         }
1821     }
1822   else if (letter == '&')
1823     {
1824       if (TARGET_68040_ONLY)
1825         {
1826           fprintf (file, "d");
1827         }
1828     }
1829   else if (letter == '/')
1830     {
1831       asm_fprintf (file, "%R");
1832     }
1833   else if (GET_CODE (op) == REG)
1834     {
1835       if (REGNO (op) < 16
1836           && (letter == 'y' || letter == 'x')
1837           && GET_MODE (op) == DFmode)
1838         {
1839           fprintf (file, "%s:%s", reg_names[REGNO (op)],
1840                    reg_names[REGNO (op)+1]);
1841         }
1842       else
1843         {
1844           fprintf (file, "%s", reg_names[REGNO (op)]);
1845         }
1846     }
1847   else if (GET_CODE (op) == MEM)
1848     {
1849       output_address (XEXP (op, 0));
1850       if (letter == 'd' && ! TARGET_68020
1851           && CONSTANT_ADDRESS_P (XEXP (op, 0))
1852           && !(GET_CODE (XEXP (op, 0)) == CONST_INT
1853                && INTVAL (XEXP (op, 0)) < 0x8000
1854                && INTVAL (XEXP (op, 0)) >= -0x8000))
1855         {
1856           fprintf (file, ":l");
1857         }
1858     }
1859 #ifdef SUPPORT_SUN_FPA
1860   else if ((letter == 'y' || letter == 'w')
1861            && GET_CODE (op) == CONST_DOUBLE
1862            && (i = standard_sun_fpa_constant_p (op)))
1863     {
1864       fprintf (file, "%%%d", i & 0x1ff);
1865     }
1866 #endif
1867   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
1868     {
1869       REAL_VALUE_TYPE r;
1870       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
1871       ASM_OUTPUT_FLOAT_OPERAND (letter, file, r);
1872     }
1873   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode)
1874     {
1875       REAL_VALUE_TYPE r;
1876       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
1877       ASM_OUTPUT_LONG_DOUBLE_OPERAND (file, r);
1878     }
1879   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
1880     {
1881       REAL_VALUE_TYPE r;
1882       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
1883       ASM_OUTPUT_DOUBLE_OPERAND (file, r);
1884     }
1885   else
1886     {
1887       asm_fprintf (file, "%0I"); output_addr_const (file, op);
1888     }
1889 }
1890
1891 \f
1892 /* A C compound statement to output to stdio stream STREAM the
1893    assembler syntax for an instruction operand that is a memory
1894    reference whose address is ADDR.  ADDR is an RTL expression.
1895
1896    Note that this contains a kludge that knows that the only reason
1897    we have an address (plus (label_ref...) (reg...)) when not generating
1898    PIC code is in the insn before a tablejump, and we know that m68k.md
1899    generates a label LInnn: on such an insn.
1900
1901    It is possible for PIC to generate a (plus (label_ref...) (reg...))
1902    and we handle that just like we would a (plus (symbol_ref...) (reg...)).
1903
1904    Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
1905    fails to assemble.  Luckily "Lnnn(pc,d0.l*2)" produces the results
1906    we want.  This difference can be accommodated by using an assembler
1907    define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
1908    string, as necessary.  This is accomplished via the ASM_OUTPUT_CASE_END
1909    macro.  See m68k/sgs.h for an example; for versions without the bug.
1910
1911    They also do not like things like "pea 1.w", so we simple leave off
1912    the .w on small constants. 
1913
1914    This routine is responsible for distinguishing between -fpic and -fPIC 
1915    style relocations in an address.  When generating -fpic code the
1916    offset is output in word mode (eg movel a5@(_foo:w), a0).  When generating
1917    -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
1918
1919 void
1920 print_operand_address (file, addr)
1921      FILE *file;
1922      rtx addr;
1923 {
1924   register rtx reg1, reg2, breg, ireg;
1925   rtx offset;
1926
1927   switch (GET_CODE (addr))
1928     {
1929       case REG:
1930 #ifdef MOTOROLA
1931         fprintf (file, "(%s)", reg_names[REGNO (addr)]);
1932 #else
1933         fprintf (file, "%s@", reg_names[REGNO (addr)]);
1934 #endif
1935         break;
1936       case PRE_DEC:
1937 #ifdef MOTOROLA
1938         fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
1939 #else
1940         fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);
1941 #endif
1942         break;
1943       case POST_INC:
1944 #ifdef MOTOROLA
1945         fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
1946 #else
1947         fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);
1948 #endif
1949         break;
1950       case PLUS:
1951         reg1 = reg2 = ireg = breg = offset = 0;
1952         if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
1953           {
1954             offset = XEXP (addr, 0);
1955             addr = XEXP (addr, 1);
1956           }
1957         else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
1958           {
1959             offset = XEXP (addr, 1);
1960             addr = XEXP (addr, 0);
1961           }
1962         if (GET_CODE (addr) != PLUS)
1963           {
1964             ;
1965           }
1966         else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
1967           {
1968             reg1 = XEXP (addr, 0);
1969             addr = XEXP (addr, 1);
1970           }
1971         else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
1972           {
1973             reg1 = XEXP (addr, 1);
1974             addr = XEXP (addr, 0);
1975           }
1976         else if (GET_CODE (XEXP (addr, 0)) == MULT)
1977           {
1978             reg1 = XEXP (addr, 0);
1979             addr = XEXP (addr, 1);
1980           }
1981         else if (GET_CODE (XEXP (addr, 1)) == MULT)
1982           {
1983             reg1 = XEXP (addr, 1);
1984             addr = XEXP (addr, 0);
1985           }
1986         else if (GET_CODE (XEXP (addr, 0)) == REG)
1987           {
1988             reg1 = XEXP (addr, 0);
1989             addr = XEXP (addr, 1);
1990           }
1991         else if (GET_CODE (XEXP (addr, 1)) == REG)
1992           {
1993             reg1 = XEXP (addr, 1);
1994             addr = XEXP (addr, 0);
1995           }
1996         if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
1997             || GET_CODE (addr) == SIGN_EXTEND)
1998           {
1999             if (reg1 == 0)
2000               {
2001                 reg1 = addr;
2002               }
2003             else
2004               {
2005                 reg2 = addr;
2006               }
2007             addr = 0;
2008           }
2009 #if 0   /* for OLD_INDEXING */
2010         else if (GET_CODE (addr) == PLUS)
2011           {
2012             if (GET_CODE (XEXP (addr, 0)) == REG)
2013               {
2014                 reg2 = XEXP (addr, 0);
2015                 addr = XEXP (addr, 1);
2016               }
2017             else if (GET_CODE (XEXP (addr, 1)) == REG)
2018               {
2019                 reg2 = XEXP (addr, 1);
2020                 addr = XEXP (addr, 0);
2021               }
2022           }
2023 #endif
2024         if (offset != 0)
2025           {
2026             if (addr != 0)
2027               {
2028                 abort ();
2029               }
2030             addr = offset;
2031           }
2032         if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
2033                       || GET_CODE (reg1) == MULT))
2034             || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
2035           {
2036             breg = reg2;
2037             ireg = reg1;
2038           }
2039         else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
2040           {
2041             breg = reg1;
2042             ireg = reg2;
2043           }
2044         if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
2045             && ! (flag_pic && ireg == pic_offset_table_rtx))
2046           {
2047             int scale = 1;
2048             if (GET_CODE (ireg) == MULT)
2049               {
2050                 scale = INTVAL (XEXP (ireg, 1));
2051                 ireg = XEXP (ireg, 0);
2052               }
2053             if (GET_CODE (ireg) == SIGN_EXTEND)
2054               {
2055 #ifdef MOTOROLA
2056 #ifdef SGS
2057                 asm_fprintf (file, "%LLD%d(%Rpc,%s.w",
2058                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
2059                              reg_names[REGNO (XEXP (ireg, 0))]);
2060 #else
2061                 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.w",
2062                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
2063                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
2064                              reg_names[REGNO (XEXP (ireg, 0))]);
2065 #endif
2066 #else
2067                 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:w",
2068                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
2069                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
2070                              reg_names[REGNO (XEXP (ireg, 0))]);
2071 #endif
2072               }
2073             else
2074               {
2075 #ifdef MOTOROLA
2076 #ifdef SGS
2077                 asm_fprintf (file, "%LLD%d(%Rpc,%s.l",
2078                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
2079                              reg_names[REGNO (ireg)]);
2080 #else
2081                 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l",
2082                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
2083                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
2084                              reg_names[REGNO (ireg)]);
2085 #endif
2086 #else
2087                 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l",
2088                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
2089                              CODE_LABEL_NUMBER (XEXP (addr, 0)),
2090                              reg_names[REGNO (ireg)]);
2091 #endif
2092               }
2093             if (scale != 1)
2094               {
2095 #ifdef MOTOROLA
2096                 fprintf (file, "*%d", scale);
2097 #else
2098                 fprintf (file, ":%d", scale);
2099 #endif
2100               }
2101             putc (')', file);
2102             break;
2103           }
2104         if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
2105             && ! (flag_pic && breg == pic_offset_table_rtx))
2106           {
2107 #ifdef MOTOROLA
2108 #ifdef SGS
2109             asm_fprintf (file, "%LLD%d(%Rpc,%s.l",
2110                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
2111                          reg_names[REGNO (breg)]);
2112 #else
2113             asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l",
2114                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
2115                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
2116                          reg_names[REGNO (breg)]);
2117 #endif
2118 #else
2119             asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l",
2120                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
2121                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
2122                          reg_names[REGNO (breg)]);
2123 #endif
2124             putc (')', file);
2125             break;
2126           }
2127         if (ireg != 0 || breg != 0)
2128           {
2129             int scale = 1;
2130             if (breg == 0)
2131               {
2132                 abort ();
2133               }
2134             if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
2135               {
2136                 abort ();
2137               }
2138 #ifdef MOTOROLA
2139             if (addr != 0)
2140               {
2141                 output_addr_const (file, addr);
2142                 if (flag_pic && (breg == pic_offset_table_rtx))
2143                   fprintf (file, "@GOT");
2144               }
2145             fprintf (file, "(%s", reg_names[REGNO (breg)]);
2146             if (ireg != 0)
2147               {
2148                 putc (',', file);
2149               }
2150 #else
2151             fprintf (file, "%s@(", reg_names[REGNO (breg)]);
2152             if (addr != 0)
2153               {
2154                 output_addr_const (file, addr);
2155                 if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
2156                   fprintf (file, ":w");
2157                 if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
2158                   fprintf (file, ":l");
2159               }
2160             if (addr != 0 && ireg != 0)
2161               {
2162                 putc (',', file);
2163               }
2164 #endif
2165             if (ireg != 0 && GET_CODE (ireg) == MULT)
2166               {
2167                 scale = INTVAL (XEXP (ireg, 1));
2168                 ireg = XEXP (ireg, 0);
2169               }
2170             if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
2171               {
2172 #ifdef MOTOROLA
2173                 fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);
2174 #else
2175                 fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);
2176 #endif
2177               }
2178             else if (ireg != 0)
2179               {
2180 #ifdef MOTOROLA
2181                 fprintf (file, "%s.l", reg_names[REGNO (ireg)]);
2182 #else
2183                 fprintf (file, "%s:l", reg_names[REGNO (ireg)]);
2184 #endif
2185               }
2186             if (scale != 1)
2187               {
2188 #ifdef MOTOROLA
2189                 fprintf (file, "*%d", scale);
2190 #else
2191                 fprintf (file, ":%d", scale);
2192 #endif
2193               }
2194             putc (')', file);
2195             break;
2196           }
2197         else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
2198                  && ! (flag_pic && reg1 == pic_offset_table_rtx))       
2199           {
2200 #ifdef MOTOROLA
2201 #ifdef SGS
2202             asm_fprintf (file, "%LLD%d(%Rpc,%s.l)",
2203                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
2204                          reg_names[REGNO (reg1)]);
2205 #else
2206             asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l)",
2207                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
2208                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
2209                          reg_names[REGNO (reg1)]);
2210 #endif
2211 #else
2212             asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l)",
2213                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
2214                          CODE_LABEL_NUMBER (XEXP (addr, 0)),
2215                          reg_names[REGNO (reg1)]);
2216 #endif
2217             break;
2218           }
2219         /* FALL-THROUGH (is this really what we want? */
2220       default:
2221         if (GET_CODE (addr) == CONST_INT
2222             && INTVAL (addr) < 0x8000
2223             && INTVAL (addr) >= -0x8000)
2224           {
2225 #ifdef MOTOROLA
2226 #ifdef SGS
2227             /* Many SGS assemblers croak on size specifiers for constants. */
2228             fprintf (file, "%d", INTVAL (addr));
2229 #else
2230             fprintf (file, "%d.w", INTVAL (addr));
2231 #endif
2232 #else
2233             fprintf (file, "%d:w", INTVAL (addr));
2234 #endif
2235           }
2236         else
2237           {
2238             output_addr_const (file, addr);
2239           }
2240         break;
2241     }
2242 }
2243 \f
2244 /* Check for cases where a clr insns can be omitted from code using
2245    strict_low_part sets.  For example, the second clrl here is not needed:
2246    clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
2247
2248    MODE is the mode of this STRICT_LOW_PART set.  FIRST_INSN is the clear
2249    insn we are checking for redundancy.  TARGET is the register set by the
2250    clear insn.  */
2251
2252 int
2253 strict_low_part_peephole_ok (mode, first_insn, target)
2254      enum machine_mode mode;
2255      rtx first_insn;
2256      rtx target;
2257 {
2258   rtx p;
2259
2260   p = prev_nonnote_insn (first_insn);
2261
2262   while (p)
2263     {
2264       /* If it isn't an insn, then give up.  */
2265       if (GET_CODE (p) != INSN)
2266         return 0;
2267
2268       if (reg_set_p (target, p))
2269         {
2270           rtx set = single_set (p);
2271           rtx dest;
2272
2273           /* If it isn't an easy to recognize insn, then give up.  */
2274           if (! set)
2275             return 0;
2276
2277           dest = SET_DEST (set);
2278
2279           /* If this sets the entire target register to zero, then our
2280              first_insn is redundant.  */
2281           if (rtx_equal_p (dest, target)
2282               && SET_SRC (set) == const0_rtx)
2283             return 1;
2284           else if (GET_CODE (dest) == STRICT_LOW_PART
2285                    && GET_CODE (XEXP (dest, 0)) == REG
2286                    && REGNO (XEXP (dest, 0)) == REGNO (target)
2287                    && (GET_MODE_SIZE (GET_MODE (XEXP (dest, 0)))
2288                        <= GET_MODE_SIZE (mode)))
2289             /* This is a strict low part set which modifies less than
2290                we are using, so it is safe.  */
2291             ;
2292           else
2293             return 0;
2294         }
2295
2296       p = prev_nonnote_insn (p);
2297
2298     }
2299
2300   return 0;
2301 }
2302 \f
2303 /* Trampoline code for the function entry.  */
2304 extern struct bc_seg *trampoline;
2305
2306 /* Emit the machine-code interface trampoline at the beginning of a byte
2307    coded function.  The argument is a label name of the interpreter
2308    bytecode callinfo structure; the return value is a label name for
2309    the beginning of the actual bytecode.  */
2310 char *
2311 bc_emit_trampoline (callinfo)
2312   char *callinfo;
2313 {
2314   short insn;
2315   int zero = 0;
2316   char mylab[256];
2317   static int n;
2318
2319   sprintf (mylab, "*LB%d", n++);
2320
2321   /* Push a reference to the callinfo structure.  */
2322   insn = 0x4879;                /* pea xxx.L */
2323   seg_data (trampoline, (char *) &insn, sizeof insn);
2324   seg_refsym (trampoline, callinfo, 0);
2325
2326   /* Call __interp, pop arguments, and return.  */
2327   insn = 0x4EB9;                /* jsr xxx.L  */
2328   seg_data (trampoline, (char *) &insn, sizeof insn);
2329   seg_refsym (trampoline, "__callint", 0);
2330   insn = 0x588F;                /* addql #4, sp */
2331   seg_data (trampoline, (char *) &insn, sizeof insn);
2332   insn = 0x4E75;                /* rts */
2333   seg_data (trampoline, (char *) &insn, sizeof insn);
2334   seg_defsym (bytecode, mylab);
2335   return sym_lookup (mylab)->name;
2336 }