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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
1493    'b' for byte insn (no effect, on the Sun; this is for the ISI).
1494    'd' to force memory addressing to be absolute, not relative.
1495    'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
1496    'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
1497        than directly).  Second part of 'y' below.
1498    'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
1499        or print pair of registers as rx:ry.
1500    'y' for a FPA insn (print pair of registers as rx:ry).  This also outputs
1501        CONST_DOUBLE's as SunFPA constant RAM registers if
1502        possible, so it should not be used except for the SunFPA.
1503 
1504    */
1505 
1506 void
1507 print_operand (file, op, letter)
1508      FILE *file;		/* file to write to */
1509      rtx op;			/* operand to print */
1510      int letter;		/* %<letter> or 0 */
1511 {
1512   int i;
1513 
1514   if (letter == '.')
1515     {
1516 #ifdef MOTOROLA
1517       asm_fprintf (file, ".");
1518 #endif
1519     }
1520   else if (letter == '#')
1521     {
1522       asm_fprintf (file, "%0I");
1523     }
1524   else if (letter == '-')
1525     {
1526 #ifdef MOTOROLA
1527       asm_fprintf (file, "-(%Rsp)");
1528 #else
1529       asm_fprintf (file, "%Rsp@-");
1530 #endif
1531     }
1532   else if (letter == '+')
1533     {
1534 #ifdef MOTOROLA
1535       asm_fprintf (file, "(%Rsp)+");
1536 #else
1537       asm_fprintf (file, "%Rsp@+");
1538 #endif
1539     }
1540   else if (letter == '@')
1541     {
1542 #ifdef MOTOROLA
1543       asm_fprintf (file, "(%Rsp)");
1544 #else
1545       asm_fprintf (file, "%Rsp@");
1546 #endif
1547     }
1548   else if (letter == '!')
1549     {
1550       asm_fprintf (file, "%Rfpcr");
1551     }
1552   else if (letter == '$')
1553     {
1554       if (TARGET_68040_ONLY)
1555 	{
1556 	  fprintf (file, "s");
1557 	}
1558     }
1559   else if (letter == '&')
1560     {
1561       if (TARGET_68040_ONLY)
1562 	{
1563 	  fprintf (file, "d");
1564 	}
1565     }
1566   else if (GET_CODE (op) == REG)
1567     {
1568       if (REGNO (op) < 16
1569 	  && (letter == 'y' || letter == 'x')
1570 	  && GET_MODE (op) == DFmode)
1571 	{
1572 	  fprintf (file, "%s:%s", reg_names[REGNO (op)],
1573 		   reg_names[REGNO (op)+1]);
1574 	}
1575       else
1576 	{
1577 	  fprintf (file, "%s", reg_names[REGNO (op)]);
1578 	}
1579     }
1580   else if (GET_CODE (op) == MEM)
1581     {
1582       output_address (XEXP (op, 0));
1583       if (letter == 'd' && ! TARGET_68020
1584 	  && CONSTANT_ADDRESS_P (XEXP (op, 0))
1585 	  && !(GET_CODE (XEXP (op, 0)) == CONST_INT
1586 	       && INTVAL (XEXP (op, 0)) < 0x8000
1587 	       && INTVAL (XEXP (op, 0)) >= -0x8000))
1588 	{
1589 	  fprintf (file, ":l");
1590 	}
1591     }
1592 #ifdef SUPPORT_SUN_FPA
1593   else if ((letter == 'y' || letter == 'w')
1594 	   && GET_CODE (op) == CONST_DOUBLE
1595 	   && (i = standard_sun_fpa_constant_p (op)))
1596     {
1597       fprintf (file, "%%%d", i & 0x1ff);
1598     }
1599 #endif
1600   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
1601     {
1602       double d;
1603       union { float f; int i; } u1;
1604       REAL_VALUE_FROM_CONST_DOUBLE (d, op);
1605       u1.f = d;
1606       PRINT_OPERAND_PRINT_FLOAT (letter, file);
1607     }
1608   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) != DImode)
1609     {
1610       double d;
1611       REAL_VALUE_FROM_CONST_DOUBLE (d, op);
1612       ASM_OUTPUT_DOUBLE_OPERAND (file, d);
1613     }
1614   else
1615     {
1616       asm_fprintf (file, "%0I"); output_addr_const (file, op);
1617     }
1618 }
1619 
1620 
1621 /* A C compound statement to output to stdio stream STREAM the
1622    assembler syntax for an instruction operand that is a memory
1623    reference whose address is ADDR.  ADDR is an RTL expression.
1624 
1625    Note that this contains a kludge that knows that the only reason
1626    we have an address (plus (label_ref...) (reg...)) when not generating
1627    PIC code is in the insn before a tablejump, and we know that m68k.md
1628    generates a label LInnn: on such an insn.
1629 
1630    It is possible for PIC to generate a (plus (label_ref...) (reg...))
1631    and we handle that just like we would a (plus (symbol_ref...) (reg...)).
1632 
1633    Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
1634    fails to assemble.  Luckily "Lnnn(pc,d0.l*2)" produces the results
1635    we want.  This difference can be accommodated by using an assembler
1636    define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
1637    string, as necessary.  This is accomplished via the ASM_OUTPUT_CASE_END
1638    macro.  See m68ksgs.h for an example; for versions without the bug.
1639 
1640    They also do not like things like "pea 1.w", so we simple leave off
1641    the .w on small constants.
1642 
1643    This routine is responsible for distinguishing between -fpic and -fPIC
1644    style relocations in an address.  When generating -fpic code the
1645    offset is output in word mode (eg movel a5@(_foo:w), a0).  When generating
1646    -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
1647 
1648 void
1649 print_operand_address (file, addr)
1650      FILE *file;
1651      rtx addr;
1652 {
1653   register rtx reg1, reg2, breg, ireg;
1654   rtx offset;
1655 
1656   switch (GET_CODE (addr))
1657     {
1658       case REG:
1659 #ifdef MOTOROLA
1660 	fprintf (file, "(%s)", reg_names[REGNO (addr)]);
1661 #else
1662 	fprintf (file, "%s@", reg_names[REGNO (addr)]);
1663 #endif
1664 	break;
1665       case PRE_DEC:
1666 #ifdef MOTOROLA
1667 	fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
1668 #else
1669 	fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);
1670 #endif
1671 	break;
1672       case POST_INC:
1673 #ifdef MOTOROLA
1674 	fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
1675 #else
1676 	fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);
1677 #endif
1678 	break;
1679       case PLUS:
1680 	reg1 = reg2 = ireg = breg = offset = 0;
1681 	if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
1682 	  {
1683 	    offset = XEXP (addr, 0);
1684 	    addr = XEXP (addr, 1);
1685 	  }
1686 	else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
1687 	  {
1688 	    offset = XEXP (addr, 1);
1689 	    addr = XEXP (addr, 0);
1690 	  }
1691 	if (GET_CODE (addr) != PLUS)
1692 	  {
1693 	    ;
1694 	  }
1695 	else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
1696 	  {
1697 	    reg1 = XEXP (addr, 0);
1698 	    addr = XEXP (addr, 1);
1699 	  }
1700 	else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
1701 	  {
1702 	    reg1 = XEXP (addr, 1);
1703 	    addr = XEXP (addr, 0);
1704 	  }
1705 	else if (GET_CODE (XEXP (addr, 0)) == MULT)
1706 	  {
1707 	    reg1 = XEXP (addr, 0);
1708 	    addr = XEXP (addr, 1);
1709 	  }
1710 	else if (GET_CODE (XEXP (addr, 1)) == MULT)
1711 	  {
1712 	    reg1 = XEXP (addr, 1);
1713 	    addr = XEXP (addr, 0);
1714 	  }
1715 	else if (GET_CODE (XEXP (addr, 0)) == REG)
1716 	  {
1717 	    reg1 = XEXP (addr, 0);
1718 	    addr = XEXP (addr, 1);
1719 	  }
1720 	else if (GET_CODE (XEXP (addr, 1)) == REG)
1721 	  {
1722 	    reg1 = XEXP (addr, 1);
1723 	    addr = XEXP (addr, 0);
1724 	  }
1725 	if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
1726 	    || GET_CODE (addr) == SIGN_EXTEND)
1727 	  {
1728 	    if (reg1 == 0)
1729 	      {
1730 		reg1 = addr;
1731 	      }
1732 	    else
1733 	      {
1734 		reg2 = addr;
1735 	      }
1736 	    addr = 0;
1737 	  }
1738 #if 0	/* for OLD_INDEXING */
1739 	else if (GET_CODE (addr) == PLUS)
1740 	  {
1741 	    if (GET_CODE (XEXP (addr, 0)) == REG)
1742 	      {
1743 		reg2 = XEXP (addr, 0);
1744 		addr = XEXP (addr, 1);
1745 	      }
1746 	    else if (GET_CODE (XEXP (addr, 1)) == REG)
1747 	      {
1748 		reg2 = XEXP (addr, 1);
1749 		addr = XEXP (addr, 0);
1750 	      }
1751 	  }
1752 #endif
1753 	if (offset != 0)
1754 	  {
1755 	    if (addr != 0)
1756 	      {
1757 		abort ();
1758 	      }
1759 	    addr = offset;
1760 	  }
1761 	if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
1762 		      || GET_CODE (reg1) == MULT))
1763 	    || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
1764 	  {
1765 	    breg = reg2;
1766 	    ireg = reg1;
1767 	  }
1768 	else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
1769 	  {
1770 	    breg = reg1;
1771 	    ireg = reg2;
1772 	  }
1773 	if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
1774 	    && ! (flag_pic && ireg == pic_offset_table_rtx))
1775 	  {
1776 	    int scale = 1;
1777 	    if (GET_CODE (ireg) == MULT)
1778 	      {
1779 		scale = INTVAL (XEXP (ireg, 1));
1780 		ireg = XEXP (ireg, 0);
1781 	      }
1782 	    if (GET_CODE (ireg) == SIGN_EXTEND)
1783 	      {
1784 #ifdef MOTOROLA
1785 #ifdef SGS
1786 		asm_fprintf (file, "%LLD%d(%Rpc,%s.w",
1787 			     CODE_LABEL_NUMBER (XEXP (addr, 0)),
1788 			     reg_names[REGNO (XEXP (ireg, 0))]);
1789 #else
1790 		asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.w",
1791 			     CODE_LABEL_NUMBER (XEXP (addr, 0)),
1792 			     CODE_LABEL_NUMBER (XEXP (addr, 0)),
1793 			     reg_names[REGNO (XEXP (ireg, 0))]);
1794 #endif
1795 #else
1796 		asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:w",
1797 			     CODE_LABEL_NUMBER (XEXP (addr, 0)),
1798 			     CODE_LABEL_NUMBER (XEXP (addr, 0)),
1799 			     reg_names[REGNO (XEXP (ireg, 0))]);
1800 #endif
1801 	      }
1802 	    else
1803 	      {
1804 #ifdef MOTOROLA
1805 #ifdef SGS
1806 		asm_fprintf (file, "%LLD%d(%Rpc,%s.l",
1807 			     CODE_LABEL_NUMBER (XEXP (addr, 0)),
1808 			     reg_names[REGNO (ireg)]);
1809 #else
1810 		asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l",
1811 			     CODE_LABEL_NUMBER (XEXP (addr, 0)),
1812 			     CODE_LABEL_NUMBER (XEXP (addr, 0)),
1813 			     reg_names[REGNO (ireg)]);
1814 #endif
1815 #else
1816 		asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l",
1817 			     CODE_LABEL_NUMBER (XEXP (addr, 0)),
1818 			     CODE_LABEL_NUMBER (XEXP (addr, 0)),
1819 			     reg_names[REGNO (ireg)]);
1820 #endif
1821 	      }
1822 	    if (scale != 1)
1823 	      {
1824 #ifdef MOTOROLA
1825 		fprintf (file, "*%d", scale);
1826 #else
1827 		fprintf (file, ":%d", scale);
1828 #endif
1829 	      }
1830 	    putc (')', file);
1831 	    break;
1832 	  }
1833 	if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
1834 	    && ! (flag_pic && breg == pic_offset_table_rtx))
1835 	  {
1836 #ifdef MOTOROLA
1837 #ifdef SGS
1838 	    asm_fprintf (file, "%LLD%d(%Rpc,%s.l",
1839 			 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1840 			 reg_names[REGNO (breg)]);
1841 #else
1842 	    asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l",
1843 			 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1844 			 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1845 			 reg_names[REGNO (breg)]);
1846 #endif
1847 #else
1848 	    asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l",
1849 			 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1850 			 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1851 			 reg_names[REGNO (breg)]);
1852 #endif
1853 	    putc (')', file);
1854 	    break;
1855 	  }
1856 	if (ireg != 0 || breg != 0)
1857 	  {
1858 	    int scale = 1;
1859 	    if (breg == 0)
1860 	      {
1861 		abort ();
1862 	      }
1863 	    if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
1864 	      {
1865 		abort ();
1866 	      }
1867 #ifdef MOTOROLA
1868 	    if (addr != 0)
1869 	      {
1870 		output_addr_const (file, addr);
1871 	        if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
1872 	          fprintf (file, ".w");
1873 	        if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
1874 	          fprintf (file, ".l");
1875 	      }
1876 	    fprintf (file, "(%s", reg_names[REGNO (breg)]);
1877 	    if (ireg != 0)
1878 	      {
1879 		putc (',', file);
1880 	      }
1881 #else
1882 	    fprintf (file, "%s@(", reg_names[REGNO (breg)]);
1883 	    if (addr != 0)
1884 	      {
1885 		output_addr_const (file, addr);
1886 	        if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
1887 	          fprintf (file, ":w");
1888 	        if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
1889 	          fprintf (file, ":l");
1890 	      }
1891 	    if (addr != 0 && ireg != 0)
1892 	      {
1893 		putc (',', file);
1894 	      }
1895 #endif
1896 	    if (ireg != 0 && GET_CODE (ireg) == MULT)
1897 	      {
1898 		scale = INTVAL (XEXP (ireg, 1));
1899 		ireg = XEXP (ireg, 0);
1900 	      }
1901 	    if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
1902 	      {
1903 #ifdef MOTOROLA
1904 		fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);
1905 #else
1906 		fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);
1907 #endif
1908 	      }
1909 	    else if (ireg != 0)
1910 	      {
1911 #ifdef MOTOROLA
1912 		fprintf (file, "%s.l", reg_names[REGNO (ireg)]);
1913 #else
1914 		fprintf (file, "%s:l", reg_names[REGNO (ireg)]);
1915 #endif
1916 	      }
1917 	    if (scale != 1)
1918 	      {
1919 #ifdef MOTOROLA
1920 		fprintf (file, "*%d", scale);
1921 #else
1922 		fprintf (file, ":%d", scale);
1923 #endif
1924 	      }
1925 	    putc (')', file);
1926 	    break;
1927 	  }
1928 	else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
1929 		 && ! (flag_pic && reg1 == pic_offset_table_rtx))
1930 	  {
1931 #ifdef MOTOROLA
1932 #ifdef SGS
1933 	    asm_fprintf (file, "%LLD%d(%Rpc,%s.l)",
1934 			 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1935 			 reg_names[REGNO (reg1)]);
1936 #else
1937 	    asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l)",
1938 			 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1939 			 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1940 			 reg_names[REGNO (reg1)]);
1941 #endif
1942 #else
1943 	    asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l)",
1944 			 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1945 			 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1946 			 reg_names[REGNO (reg1)]);
1947 #endif
1948 	    break;
1949 	  }
1950 	/* FALL-THROUGH (is this really what we want? */
1951       default:
1952         if (GET_CODE (addr) == CONST_INT
1953 	    && INTVAL (addr) < 0x8000
1954 	    && INTVAL (addr) >= -0x8000)
1955 	  {
1956 #ifdef MOTOROLA
1957 #ifdef SGS
1958 	    /* Many SGS assemblers croak on size specifiers for constants. */
1959 	    fprintf (file, "%d", INTVAL (addr));
1960 #else
1961 	    fprintf (file, "%d.w", INTVAL (addr));
1962 #endif
1963 #else
1964 	    fprintf (file, "%d:w", INTVAL (addr));
1965 #endif
1966 	  }
1967 	else
1968 	  {
1969 	    output_addr_const (file, addr);
1970 	  }
1971 	break;
1972     }
1973 }
1974