xref: /openbsd-src/gnu/usr.bin/gcc/gcc/config/m68k/m68k.c (revision 4e43c760ad4cd5f644ec700462679d05749498d8)
1 /* Subroutines for insn-output.c for Motorola 68000 family.
2    Copyright (C) 1987, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003
3    Free Software Foundation, Inc.
4 
5 This file is part of GNU CC.
6 
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11 
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21 
22 #include "config.h"
23 #include "system.h"
24 #include "tree.h"
25 #include "rtl.h"
26 #include "function.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "real.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "output.h"
33 #include "insn-attr.h"
34 #include "recog.h"
35 #include "toplev.h"
36 #include "expr.h"
37 #include "reload.h"
38 #include "tm_p.h"
39 #include "target.h"
40 #include "target-def.h"
41 #include "debug.h"
42 
43 /* Needed for use_return_insn.  */
44 #include "flags.h"
45 
46 #ifdef SUPPORT_SUN_FPA
47 
48 /* Index into this array by (register number >> 3) to find the
49    smallest class which contains that register.  */
50 const enum reg_class regno_reg_class[]
51   = { DATA_REGS, ADDR_REGS, FP_REGS,
52       LO_FPA_REGS, LO_FPA_REGS, FPA_REGS, FPA_REGS };
53 
54 #endif /* defined SUPPORT_SUN_FPA */
55 
56 /* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
57    if SGS_SWITCH_TABLE.  */
58 int switch_table_difference_label_flag;
59 
60 static rtx find_addr_reg PARAMS ((rtx));
61 static const char *singlemove_string PARAMS ((rtx *));
62 static void m68k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
63 static void m68k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
64 static void m68k_coff_asm_named_section PARAMS ((const char *, unsigned int));
65 #ifdef CTOR_LIST_BEGIN
66 static void m68k_svr3_asm_out_constructor PARAMS ((rtx, int));
67 #endif
68 static void m68k_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
69 					  HOST_WIDE_INT, tree));
70 static int m68k_save_reg PARAMS ((unsigned int));
71 
72 
73 /* Alignment to use for loops and jumps */
74 /* Specify power of two alignment used for loops.  */
75 const char *m68k_align_loops_string;
76 /* Specify power of two alignment used for non-loop jumps.  */
77 const char *m68k_align_jumps_string;
78 /* Specify power of two alignment used for functions.  */
79 const char *m68k_align_funcs_string;
80 
81 /* Specify power of two alignment used for loops.  */
82 int m68k_align_loops;
83 /* Specify power of two alignment used for non-loop jumps.  */
84 int m68k_align_jumps;
85 /* Specify power of two alignment used for functions.  */
86 int m68k_align_funcs;
87 
88 /* Nonzero if the last compare/test insn had FP operands.  The
89    sCC expanders peek at this to determine what to do for the
90    68060, which has no fsCC instructions.  */
91 int m68k_last_compare_had_fp_operands;
92 
93 /* Initialize the GCC target structure.  */
94 
95 #if INT_OP_GROUP == INT_OP_DOT_WORD
96 #undef TARGET_ASM_ALIGNED_HI_OP
97 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
98 #endif
99 
100 #if INT_OP_GROUP == INT_OP_NO_DOT
101 #undef TARGET_ASM_BYTE_OP
102 #define TARGET_ASM_BYTE_OP "\tbyte\t"
103 #undef TARGET_ASM_ALIGNED_HI_OP
104 #define TARGET_ASM_ALIGNED_HI_OP "\tshort\t"
105 #undef TARGET_ASM_ALIGNED_SI_OP
106 #define TARGET_ASM_ALIGNED_SI_OP "\tlong\t"
107 #endif
108 
109 #if INT_OP_GROUP == INT_OP_DC
110 #undef TARGET_ASM_BYTE_OP
111 #define TARGET_ASM_BYTE_OP "\tdc.b\t"
112 #undef TARGET_ASM_ALIGNED_HI_OP
113 #define TARGET_ASM_ALIGNED_HI_OP "\tdc.w\t"
114 #undef TARGET_ASM_ALIGNED_SI_OP
115 #define TARGET_ASM_ALIGNED_SI_OP "\tdc.l\t"
116 #endif
117 
118 #undef TARGET_ASM_UNALIGNED_HI_OP
119 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
120 #undef TARGET_ASM_UNALIGNED_SI_OP
121 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
122 
123 #undef TARGET_ASM_FUNCTION_PROLOGUE
124 #define TARGET_ASM_FUNCTION_PROLOGUE m68k_output_function_prologue
125 #undef TARGET_ASM_FUNCTION_EPILOGUE
126 #define TARGET_ASM_FUNCTION_EPILOGUE m68k_output_function_epilogue
127 
128 #undef TARGET_ASM_OUTPUT_MI_THUNK
129 #define TARGET_ASM_OUTPUT_MI_THUNK m68k_output_mi_thunk
130 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
131 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
132 
133 struct gcc_target targetm = TARGET_INITIALIZER;
134 
135 /* Sometimes certain combinations of command options do not make
136    sense on a particular target machine.  You can define a macro
137    `OVERRIDE_OPTIONS' to take account of this.  This macro, if
138    defined, is executed once just after all the command options have
139    been parsed.
140 
141    Don't use this macro to turn on various extra optimizations for
142    `-O'.  That is what `OPTIMIZATION_OPTIONS' is for.  */
143 
144 void
override_options()145 override_options ()
146 {
147   int def_align;
148   int i;
149 
150   def_align = 1;
151 
152   /* Validate -malign-loops= value, or provide default */
153   m68k_align_loops = def_align;
154   if (m68k_align_loops_string)
155     {
156       i = atoi (m68k_align_loops_string);
157       if (i < 1 || i > MAX_CODE_ALIGN)
158 	error ("-malign-loops=%d is not between 1 and %d", i, MAX_CODE_ALIGN);
159       else
160 	m68k_align_loops = i;
161     }
162 
163   /* Validate -malign-jumps= value, or provide default */
164   m68k_align_jumps = def_align;
165   if (m68k_align_jumps_string)
166     {
167       i = atoi (m68k_align_jumps_string);
168       if (i < 1 || i > MAX_CODE_ALIGN)
169 	error ("-malign-jumps=%d is not between 1 and %d", i, MAX_CODE_ALIGN);
170       else
171 	m68k_align_jumps = i;
172     }
173 
174   /* Validate -malign-functions= value, or provide default */
175   m68k_align_funcs = def_align;
176   if (m68k_align_funcs_string)
177     {
178       i = atoi (m68k_align_funcs_string);
179       if (i < 1 || i > MAX_CODE_ALIGN)
180 	error ("-malign-functions=%d is not between 1 and %d",
181 	       i, MAX_CODE_ALIGN);
182       else
183 	m68k_align_funcs = i;
184     }
185 
186   /* -fPIC uses 32-bit pc-relative displacements, which don't exist
187      until the 68020.  */
188   if (! TARGET_68020 && flag_pic == 2)
189     error("-fPIC is not currently supported on the 68000 or 68010\n");
190 
191   /* ??? A historic way of turning on pic, or is this intended to
192      be an embedded thing that doesn't have the same name binding
193      significance that it does on hosted ELF systems?  */
194   if (TARGET_PCREL && flag_pic == 0)
195     flag_pic = 1;
196 
197   /* Turn off function cse if we are doing PIC.  We always want function call
198      to be done as `bsr foo@PLTPC', so it will force the assembler to create
199      the PLT entry for `foo'. Doing function cse will cause the address of
200      `foo' to be loaded into a register, which is exactly what we want to
201      avoid when we are doing PIC on svr4 m68k.  */
202   if (flag_pic)
203     flag_no_function_cse = 1;
204 
205   SUBTARGET_OVERRIDE_OPTIONS;
206 
207   /* Tell the compiler which flavor of XFmode we're using.  */
208   real_format_for_mode[XFmode - QFmode] = &ieee_extended_motorola_format;
209 }
210 
211 /* Return 1 if we need to save REGNO.  */
212 static int
m68k_save_reg(regno)213 m68k_save_reg (regno)
214      unsigned int regno;
215 {
216   if (flag_pic && current_function_uses_pic_offset_table
217       && regno == PIC_OFFSET_TABLE_REGNUM)
218     return 1;
219 
220   if (current_function_calls_eh_return)
221     {
222       unsigned int i;
223       for (i = 0; ; i++)
224 	{
225 	  unsigned int test = EH_RETURN_DATA_REGNO (i);
226 	  if (test == INVALID_REGNUM)
227 	    break;
228 	  if (test == regno)
229 	    return 1;
230 	}
231     }
232 
233   return (regs_ever_live[regno]
234 	  && !call_used_regs[regno]
235 	  && !fixed_regs[regno]
236 	  && !(regno == FRAME_POINTER_REGNUM && frame_pointer_needed));
237 }
238 
239 /* This function generates the assembly code for function entry.
240    STREAM is a stdio stream to output the code to.
241    SIZE is an int: how many units of temporary storage to allocate.
242    Refer to the array `regs_ever_live' to determine which registers
243    to save; `regs_ever_live[I]' is nonzero if register number I
244    is ever used in the function.  This function is responsible for
245    knowing which registers should not be saved even if used.  */
246 
247 
248 /* Note that the order of the bit mask for fmovem is the opposite
249    of the order for movem!  */
250 
251 #ifdef CRDS
252 
253 static void
m68k_output_function_prologue(stream,size)254 m68k_output_function_prologue (stream, size)
255      FILE *stream;
256      HOST_WIDE_INT size;
257 {
258   register int regno;
259   register int mask = 0;
260   HOST_WIDE_INT fsize = ((size) + 3) & -4;
261 
262   /* unos stack probe */
263   if (fsize > 30000)
264     {
265       fprintf (stream, "\tmovel sp,a0\n");
266       fprintf (stream, "\taddl $-%d,a0\n", 2048 + fsize);
267       fprintf (stream, "\ttstb (a0)\n");
268     }
269   else
270     fprintf (stream, "\ttstb -%d(sp)\n", 2048 + fsize);
271 
272   if (frame_pointer_needed)
273     {
274       if (TARGET_68020 || fsize < 0x8000)
275 	fprintf (stream, "\tlink a6,$%d\n", -fsize);
276       else
277 	fprintf (stream, "\tlink a6,$0\n\tsubl $%d,sp\n", fsize);
278     }
279   else if (fsize)
280     {
281       /* Adding negative number is faster on the 68040.  */
282       if (fsize + 4 < 0x8000)
283 	fprintf (stream, "\tadd.w $%d,sp\n", - (fsize + 4));
284       else
285 	fprintf (stream, "\tadd.l $%d,sp\n", - (fsize + 4));
286     }
287 
288   for (regno = 16; regno < 24; regno++)
289     if (m68k_save_reg (regno))
290       mask |= 1 << (regno - 16);
291 
292   if ((mask & 0xff) != 0)
293     fprintf (stream, "\tfmovem $0x%x,-(sp)\n", mask & 0xff);
294 
295   mask = 0;
296   for (regno = 0; regno < 16; regno++)
297     if (m68k_save_reg (regno))
298       mask |= 1 << (15 - regno);
299 
300   if (exact_log2 (mask) >= 0)
301     fprintf (stream, "\tmovel %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]);
302   else if (mask)
303     fprintf (stream, "\tmovem $0x%x,-(sp)\n", mask);
304 }
305 
306 #else  /* !CRDS */
307 
308 static void
m68k_output_function_prologue(stream,size)309 m68k_output_function_prologue (stream, size)
310      FILE *stream;
311      HOST_WIDE_INT size;
312 {
313   register int regno;
314   register int mask = 0;
315   int num_saved_regs = 0;
316   HOST_WIDE_INT fsize = (size + 3) & -4;
317   HOST_WIDE_INT cfa_offset = INCOMING_FRAME_SP_OFFSET;
318   HOST_WIDE_INT cfa_store_offset = cfa_offset;
319 
320   /* If the stack limit is a symbol, we can check it here,
321      before actually allocating the space.  */
322   if (current_function_limit_stack
323       && GET_CODE (stack_limit_rtx) == SYMBOL_REF)
324     {
325 #if defined (MOTOROLA)
326       asm_fprintf (stream, "\tcmp.l %0I%s+%d,%Rsp\n\ttrapcs\n",
327 		   XSTR (stack_limit_rtx, 0), fsize + 4);
328 #else
329       asm_fprintf (stream, "\tcmpl %0I%s+%d,%Rsp\n\ttrapcs\n",
330 		   XSTR (stack_limit_rtx, 0), fsize + 4);
331 #endif
332     }
333 
334   if (frame_pointer_needed)
335     {
336       if (fsize == 0 && TARGET_68040)
337 	{
338 	/* on the 68040, pea + move is faster than link.w 0 */
339 #ifdef MOTOROLA
340 	  fprintf (stream, "\tpea (%s)\n\tmove.l %s,%s\n",
341 		   reg_names[FRAME_POINTER_REGNUM],
342 		   reg_names[STACK_POINTER_REGNUM],
343 		   reg_names[FRAME_POINTER_REGNUM]);
344 #else
345 	  fprintf (stream, "\tpea %s@\n\tmovel %s,%s\n",
346 		   reg_names[FRAME_POINTER_REGNUM],
347 		   reg_names[STACK_POINTER_REGNUM],
348 		   reg_names[FRAME_POINTER_REGNUM]);
349 #endif
350 	}
351       else if (fsize < 0x8000)
352 	{
353 #ifdef MOTOROLA
354 	  asm_fprintf (stream, "\tlink.w %s,%0I%d\n",
355 		       reg_names[FRAME_POINTER_REGNUM], -fsize);
356 #else
357 	  asm_fprintf (stream, "\tlink %s,%0I%d\n",
358 		       reg_names[FRAME_POINTER_REGNUM], -fsize);
359 #endif
360 	}
361       else if (TARGET_68020)
362 	{
363 #ifdef MOTOROLA
364 	  asm_fprintf (stream, "\tlink.l %s,%0I%d\n",
365 		       reg_names[FRAME_POINTER_REGNUM], -fsize);
366 #else
367 	  asm_fprintf (stream, "\tlink %s,%0I%d\n",
368 		       reg_names[FRAME_POINTER_REGNUM], -fsize);
369 #endif
370 	}
371       else
372 	{
373       /* Adding negative number is faster on the 68040.  */
374 #ifdef MOTOROLA
375 	  asm_fprintf (stream, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
376 		       reg_names[FRAME_POINTER_REGNUM], -fsize);
377 #else
378 	  asm_fprintf (stream, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
379 		       reg_names[FRAME_POINTER_REGNUM], -fsize);
380 #endif
381 	}
382       if (dwarf2out_do_frame ())
383 	{
384 	  char *l;
385           l = (char *) dwarf2out_cfi_label ();
386 	  cfa_store_offset += 4;
387 	  cfa_offset = cfa_store_offset;
388 	  dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, -cfa_store_offset);
389 	  dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, cfa_offset);
390 	  cfa_store_offset += fsize;
391 	}
392     }
393   else if (fsize)
394     {
395       if (fsize + 4 < 0x8000)
396 	{
397 #ifndef NO_ADDSUB_Q
398 	  if (fsize + 4 <= 8)
399 	    {
400 	      if (!TARGET_5200)
401 		{
402 		  /* asm_fprintf() cannot handle %.  */
403 #ifdef MOTOROLA
404 		  asm_fprintf (stream, "\tsubq.w %0I%d,%Rsp\n", fsize + 4);
405 #else
406 		  asm_fprintf (stream, "\tsubqw %0I%d,%Rsp\n", fsize + 4);
407 #endif
408 		}
409 	      else
410 		{
411 		  /* asm_fprintf() cannot handle %.  */
412 #ifdef MOTOROLA
413 		  asm_fprintf (stream, "\tsubq.l %0I%d,%Rsp\n", fsize + 4);
414 #else
415 		  asm_fprintf (stream, "\tsubql %0I%d,%Rsp\n", fsize + 4);
416 #endif
417 		}
418 	    }
419 	  else if (fsize + 4 <= 16 && TARGET_CPU32)
420 	    {
421 	      /* On the CPU32 it is faster to use two subqw instructions to
422 		 subtract a small integer (8 < N <= 16) to a register.  */
423 	      /* asm_fprintf() cannot handle %.  */
424 #ifdef MOTOROLA
425 	      asm_fprintf (stream, "\tsubq.w %0I8,%Rsp\n\tsubq.w %0I%d,%Rsp\n",
426 			   fsize + 4 - 8);
427 #else
428 	      asm_fprintf (stream, "\tsubqw %0I8,%Rsp\n\tsubqw %0I%d,%Rsp\n",
429 			   fsize + 4 - 8);
430 #endif
431 	    }
432 	  else
433 #endif /* not NO_ADDSUB_Q */
434 	  if (TARGET_68040)
435 	    {
436 	      /* Adding negative number is faster on the 68040.  */
437 	      /* asm_fprintf() cannot handle %.  */
438 #ifdef MOTOROLA
439 	      asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - (fsize + 4));
440 #else
441 	      asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", - (fsize + 4));
442 #endif
443 	    }
444 	  else
445 	    {
446 #ifdef MOTOROLA
447 	      asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", - (fsize + 4));
448 #else
449 	      asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", - (fsize + 4));
450 #endif
451 	    }
452 	}
453       else
454 	{
455 	/* asm_fprintf() cannot handle %.  */
456 #ifdef MOTOROLA
457 	  asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", - (fsize + 4));
458 #else
459 	  asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", - (fsize + 4));
460 #endif
461 	}
462       if (dwarf2out_do_frame ())
463 	{
464 	  cfa_store_offset += fsize + 4;
465 	  cfa_offset = cfa_store_offset;
466 	  dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset);
467 	}
468     }
469 #ifdef SUPPORT_SUN_FPA
470   for (regno = 24; regno < 56; regno++)
471     if (m68k_save_reg (regno))
472       {
473 #ifdef MOTOROLA
474 	asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n",
475 		     reg_names[regno]);
476 #else
477 	asm_fprintf (stream, "\tfpmoved %s,%Rsp@-\n",
478 		     reg_names[regno]);
479 #endif
480 	if (dwarf2out_do_frame ())
481 	  {
482 	    char *l = dwarf2out_cfi_label ();
483 
484 	    cfa_store_offset += 8;
485 	    if (! frame_pointer_needed)
486 	      {
487 		cfa_offset = cfa_store_offset;
488 		dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
489 	      }
490 	    dwarf2out_reg_save (l, regno, -cfa_store_offset);
491 	  }
492       }
493 #endif
494   if (TARGET_68881)
495     {
496       for (regno = 16; regno < 24; regno++)
497 	if (m68k_save_reg (regno))
498 	  {
499 	    mask |= 1 << (regno - 16);
500 	    num_saved_regs++;
501 	  }
502       if ((mask & 0xff) != 0)
503 	{
504 #ifdef MOTOROLA
505 	  asm_fprintf (stream, "\tfmovm %0I0x%x,-(%Rsp)\n", mask & 0xff);
506 #else
507 	  asm_fprintf (stream, "\tfmovem %0I0x%x,%Rsp@-\n", mask & 0xff);
508 #endif
509 	  if (dwarf2out_do_frame ())
510 	    {
511 	      char *l = (char *) dwarf2out_cfi_label ();
512 	      int n_regs;
513 
514 	      cfa_store_offset += num_saved_regs * 12;
515 	      if (! frame_pointer_needed)
516 		{
517 		  cfa_offset = cfa_store_offset;
518 		  dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
519 		}
520 	      for (regno = 16, n_regs = 0; regno < 24; regno++)
521 		if (mask & (1 << (regno - 16)))
522 		  dwarf2out_reg_save (l, regno,
523 				      -cfa_store_offset + n_regs++ * 12);
524 	    }
525 	}
526       mask = 0;
527       num_saved_regs = 0;
528     }
529   for (regno = 0; regno < 16; regno++)
530     if (m68k_save_reg (regno))
531       {
532         mask |= 1 << (15 - regno);
533         num_saved_regs++;
534       }
535 
536 #if NEED_PROBE
537 #ifdef MOTOROLA
538   asm_fprintf (stream, "\ttst.l %d(%Rsp)\n", NEED_PROBE - num_saved_regs * 4);
539 #else
540   asm_fprintf (stream, "\ttstl %Rsp@(%d)\n", NEED_PROBE - num_saved_regs * 4);
541 #endif
542 #endif
543 
544   /* If the stack limit is not a symbol, check it here.
545      This has the disadvantage that it may be too late...  */
546   if (current_function_limit_stack)
547     {
548       if (REG_P (stack_limit_rtx))
549 	{
550 #if defined (MOTOROLA)
551 	  asm_fprintf (stream, "\tcmp.l %s,%Rsp\n\ttrapcs\n",
552 		       reg_names[REGNO (stack_limit_rtx)]);
553 #else
554 	  asm_fprintf (stream, "\tcmpl %s,%Rsp\n\ttrapcs\n",
555 		       reg_names[REGNO (stack_limit_rtx)]);
556 #endif
557 	}
558       else if (GET_CODE (stack_limit_rtx) != SYMBOL_REF)
559 	warning ("stack limit expression is not supported");
560     }
561 
562   if (num_saved_regs <= 2)
563     {
564       /* Store each separately in the same order moveml uses.
565          Using two movel instructions instead of a single moveml
566          is about 15% faster for the 68020 and 68030 at no expense
567          in code size */
568 
569       int i;
570 
571       /* Undo the work from above.  */
572       for (i = 0; i< 16; i++)
573         if (mask & (1 << i))
574 	  {
575 	    asm_fprintf (stream,
576 #ifdef MOTOROLA
577 			 "\t%Omove.l %s,-(%Rsp)\n",
578 #else
579 			 "\tmovel %s,%Rsp@-\n",
580 #endif
581 			 reg_names[15 - i]);
582 	    if (dwarf2out_do_frame ())
583 	      {
584 		char *l = (char *) dwarf2out_cfi_label ();
585 
586 		cfa_store_offset += 4;
587  		if (! frame_pointer_needed)
588  		  {
589  		    cfa_offset = cfa_store_offset;
590  		    dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
591  		  }
592  		dwarf2out_reg_save (l, 15 - i, -cfa_store_offset);
593 	      }
594 	  }
595     }
596   else if (mask)
597     {
598       if (TARGET_5200)
599 	{
600 	  /* The coldfire does not support the predecrement form of the
601 	     movml instruction, so we must adjust the stack pointer and
602 	     then use the plain address register indirect mode.  We also
603 	     have to invert the register save mask to use the new mode.
604 
605 	     FIXME: if num_saved_regs was calculated earlier, we could
606 	     combine the stack pointer adjustment with any adjustment
607 	     done when the initial stack frame is created.  This would
608 	     save an instruction */
609 
610 	  int newmask = 0;
611 	  int i;
612 
613 	  for (i = 0; i < 16; i++)
614 	    if (mask & (1 << i))
615 		newmask |= (1 << (15-i));
616 
617 #ifdef MOTOROLA
618 	  asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", -num_saved_regs*4);
619 	  asm_fprintf (stream, "\tmovm.l %0I0x%x,(%Rsp)\n", newmask);
620 #else
621 	  asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", -num_saved_regs*4);
622 	  asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@\n", newmask);
623 #endif
624 	}
625       else
626 	{
627 #ifdef MOTOROLA
628 	  asm_fprintf (stream, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask);
629 #else
630 	  asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@-\n", mask);
631 #endif
632 	}
633       if (dwarf2out_do_frame ())
634 	{
635 	  char *l = (char *) dwarf2out_cfi_label ();
636 	  int n_regs;
637 
638 	  cfa_store_offset += num_saved_regs * 4;
639 	  if (! frame_pointer_needed)
640 	    {
641 	      cfa_offset = cfa_store_offset;
642 	      dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
643 	    }
644 	  for (regno = 0, n_regs = 0; regno < 16; regno++)
645 	    if (mask & (1 << (15 - regno)))
646 	      dwarf2out_reg_save (l, regno,
647 				  -cfa_store_offset + n_regs++ * 4);
648 	}
649     }
650   if (flag_pic && current_function_uses_pic_offset_table)
651     {
652 #ifdef MOTOROLA
653       asm_fprintf (stream, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
654 		   reg_names[PIC_OFFSET_TABLE_REGNUM]);
655 #else
656       asm_fprintf (stream, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
657 		   reg_names[PIC_OFFSET_TABLE_REGNUM]);
658       asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n",
659 		   reg_names[PIC_OFFSET_TABLE_REGNUM],
660 		   reg_names[PIC_OFFSET_TABLE_REGNUM]);
661 #endif
662     }
663 }
664 #endif   /* !CRDS  */
665 
666 /* Return true if this function's epilogue can be output as RTL.  */
667 
668 int
use_return_insn()669 use_return_insn ()
670 {
671   int regno;
672 
673   if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)
674     return 0;
675 
676   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
677     if (m68k_save_reg (regno))
678       return 0;
679 
680   return 1;
681 }
682 
683 /* This function generates the assembly code for function exit,
684    on machines that need it.
685 
686    The function epilogue should not depend on the current stack pointer!
687    It should use the frame pointer only, if there is a frame pointer.
688    This is mandatory because of alloca; we also take advantage of it to
689    omit stack adjustments before returning.  */
690 
691 #ifdef CRDS
692 
693 static void
m68k_output_function_epilogue(stream,size)694 m68k_output_function_epilogue (stream, size)
695      FILE *stream;
696      HOST_WIDE_INT size;
697 {
698   register int regno;
699   register int mask, fmask;
700   register int nregs;
701   HOST_WIDE_INT offset, foffset, fpoffset;
702   HOST_WIDE_INT fsize = ((size) + 3) & -4;
703   int big = 0;
704 
705   nregs = 0;  fmask = 0; fpoffset = 0;
706   for (regno = 16; regno < 24; regno++)
707     if (m68k_save_reg (regno))
708       {
709 	nregs++;
710 	fmask |= 1 << (23 - regno);
711       }
712 
713   foffset = fpoffset + nregs * 12;
714   nregs = 0;  mask = 0;
715 
716   for (regno = 0; regno < 16; regno++)
717     if (m68k_save_reg (regno))
718       {
719 	nregs++;
720 	mask |= 1 << regno;
721       }
722 
723   offset = foffset + nregs * 4;
724   if (offset + fsize >= 0x8000
725       && frame_pointer_needed
726       && (mask || fmask || fpoffset))
727     {
728       fprintf (stream, "\tmovel $%d,a0\n", -fsize);
729       fsize = 0, big = 1;
730     }
731 
732   if (exact_log2 (mask) >= 0)
733     {
734       if (big)
735 	fprintf (stream, "\tmovel -%d(a6,a0.l),%s\n",
736 		 offset + fsize, reg_names[exact_log2 (mask)]);
737       else if (! frame_pointer_needed)
738 	fprintf (stream, "\tmovel (sp)+,%s\n",
739 		 reg_names[exact_log2 (mask)]);
740       else
741 	fprintf (stream, "\tmovel -%d(a6),%s\n",
742 		 offset + fsize, reg_names[exact_log2 (mask)]);
743     }
744   else if (mask)
745     {
746       if (big)
747 	fprintf (stream, "\tmovem -%d(a6,a0.l),$0x%x\n",
748 		 offset + fsize, mask);
749       else if (! frame_pointer_needed)
750 	fprintf (stream, "\tmovem (sp)+,$0x%x\n", mask);
751       else
752 	fprintf (stream, "\tmovem -%d(a6),$0x%x\n",
753 		 offset + fsize, mask);
754     }
755 
756   if (fmask)
757     {
758       if (big)
759 	fprintf (stream, "\tfmovem -%d(a6,a0.l),$0x%x\n",
760 		 foffset + fsize, fmask);
761       else if (! frame_pointer_needed)
762 	fprintf (stream, "\tfmovem (sp)+,$0x%x\n", fmask);
763       else
764 	fprintf (stream, "\tfmovem -%d(a6),$0x%x\n",
765 		 foffset + fsize, fmask);
766     }
767 
768   if (fpoffset != 0)
769     for (regno = 55; regno >= 24; regno--)
770       if (m68k_save_reg (regno))
771 	{
772 	  if (big)
773 	    fprintf(stream, "\tfpmoved -%d(a6,a0.l), %s\n",
774 		    fpoffset + fsize, reg_names[regno]);
775 	  else if (! frame_pointer_needed)
776 	    fprintf(stream, "\tfpmoved (sp)+, %s\n",
777 		    reg_names[regno]);
778 	  else
779 	    fprintf(stream, "\tfpmoved -%d(a6), %s\n",
780 		    fpoffset + fsize, reg_names[regno]);
781 	  fpoffset -= 8;
782 	}
783 
784   if (frame_pointer_needed)
785     fprintf (stream, "\tunlk a6\n");
786   else if (fsize)
787     {
788       if (fsize + 4 < 0x8000)
789 	fprintf (stream, "\tadd.w $%d,sp\n", fsize + 4);
790       else
791 	fprintf (stream, "\tadd.l $%d,sp\n", fsize + 4);
792     }
793 
794   if (current_function_calls_eh_return)
795     fprintf (stream, "\tadd.l a0,sp\n");
796 
797   if (current_function_pops_args)
798     fprintf (stream, "\trtd $%d\n", current_function_pops_args);
799   else
800     fprintf (stream, "\trts\n");
801 }
802 
803 #else  /* !CRDS */
804 
805 static void
m68k_output_function_epilogue(stream,size)806 m68k_output_function_epilogue (stream, size)
807      FILE *stream;
808      HOST_WIDE_INT size;
809 {
810   register int regno;
811   register int mask, fmask;
812   register int nregs;
813   HOST_WIDE_INT offset, foffset, fpoffset;
814   HOST_WIDE_INT fsize = (size + 3) & -4;
815   int big = 0;
816   rtx insn = get_last_insn ();
817   int restore_from_sp = 0;
818 
819   /* If the last insn was a BARRIER, we don't have to write any code.  */
820   if (GET_CODE (insn) == NOTE)
821     insn = prev_nonnote_insn (insn);
822   if (insn && GET_CODE (insn) == BARRIER)
823     {
824       /* Output just a no-op so that debuggers don't get confused
825 	 about which function the pc is in at this address.  */
826       fprintf (stream, "\tnop\n");
827       return;
828     }
829 
830 #ifdef FUNCTION_EXTRA_EPILOGUE
831   FUNCTION_EXTRA_EPILOGUE (stream, size);
832 #endif
833   nregs = 0;  fmask = 0; fpoffset = 0;
834 #ifdef SUPPORT_SUN_FPA
835   for (regno = 24 ; regno < 56 ; regno++)
836     if (m68k_save_reg (regno))
837       nregs++;
838   fpoffset = nregs * 8;
839 #endif
840   nregs = 0;
841   if (TARGET_68881)
842     {
843       for (regno = 16; regno < 24; regno++)
844 	if (m68k_save_reg (regno))
845 	  {
846 	    nregs++;
847 	    fmask |= 1 << (23 - regno);
848 	  }
849     }
850   foffset = fpoffset + nregs * 12;
851   nregs = 0;  mask = 0;
852   for (regno = 0; regno < 16; regno++)
853     if (m68k_save_reg (regno))
854       {
855         nregs++;
856 	mask |= 1 << regno;
857       }
858   offset = foffset + nregs * 4;
859   /* FIXME : leaf_function_p below is too strong.
860      What we really need to know there is if there could be pending
861      stack adjustment needed at that point.  */
862   restore_from_sp = ! frame_pointer_needed
863 	     || (! current_function_calls_alloca && leaf_function_p ());
864   if (offset + fsize >= 0x8000
865       && ! restore_from_sp
866       && (mask || fmask || fpoffset))
867     {
868 #ifdef MOTOROLA
869       asm_fprintf (stream, "\t%Omove.l %0I%d,%Ra1\n", -fsize);
870 #else
871       asm_fprintf (stream, "\tmovel %0I%d,%Ra1\n", -fsize);
872 #endif
873       fsize = 0, big = 1;
874     }
875   if (TARGET_5200 || nregs <= 2)
876     {
877       /* Restore each separately in the same order moveml does.
878          Using two movel instructions instead of a single moveml
879          is about 15% faster for the 68020 and 68030 at no expense
880          in code size.  */
881 
882       int i;
883 
884       /* Undo the work from above.  */
885       for (i = 0; i< 16; i++)
886         if (mask & (1 << i))
887           {
888             if (big)
889 	      {
890 #ifdef MOTOROLA
891 		asm_fprintf (stream, "\t%Omove.l -%d(%s,%Ra1.l),%s\n",
892 			     offset + fsize,
893 			     reg_names[FRAME_POINTER_REGNUM],
894 			     reg_names[i]);
895 #else
896 		asm_fprintf (stream, "\tmovel %s@(-%d,%Ra1:l),%s\n",
897 			     reg_names[FRAME_POINTER_REGNUM],
898 			     offset + fsize, reg_names[i]);
899 #endif
900 	      }
901             else if (restore_from_sp)
902 	      {
903 #ifdef MOTOROLA
904 		asm_fprintf (stream, "\t%Omove.l (%Rsp)+,%s\n",
905 			     reg_names[i]);
906 #else
907 		asm_fprintf (stream, "\tmovel %Rsp@+,%s\n",
908 			     reg_names[i]);
909 #endif
910 	      }
911             else
912 	      {
913 #ifdef MOTOROLA
914 		asm_fprintf (stream, "\t%Omove.l -%d(%s),%s\n",
915 			     offset + fsize,
916 			     reg_names[FRAME_POINTER_REGNUM],
917 			     reg_names[i]);
918 #else
919 		fprintf (stream, "\tmovel %s@(-%d),%s\n",
920 			 reg_names[FRAME_POINTER_REGNUM],
921 			 offset + fsize, reg_names[i]);
922 #endif
923 	      }
924             offset = offset - 4;
925           }
926     }
927   else if (mask)
928     {
929       if (big)
930 	{
931 #ifdef MOTOROLA
932 	  asm_fprintf (stream, "\tmovm.l -%d(%s,%Ra1.l),%0I0x%x\n",
933 		       offset + fsize,
934 		       reg_names[FRAME_POINTER_REGNUM],
935 		       mask);
936 #else
937 	  asm_fprintf (stream, "\tmoveml %s@(-%d,%Ra1:l),%0I0x%x\n",
938 		       reg_names[FRAME_POINTER_REGNUM],
939 		       offset + fsize, mask);
940 #endif
941 	}
942       else if (restore_from_sp)
943 	{
944 #ifdef MOTOROLA
945 	  asm_fprintf (stream, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask);
946 #else
947 	  asm_fprintf (stream, "\tmoveml %Rsp@+,%0I0x%x\n", mask);
948 #endif
949 	}
950       else
951 	{
952 #ifdef MOTOROLA
953 	  asm_fprintf (stream, "\tmovm.l -%d(%s),%0I0x%x\n",
954 		       offset + fsize,
955 		       reg_names[FRAME_POINTER_REGNUM],
956 		       mask);
957 #else
958 	  asm_fprintf (stream, "\tmoveml %s@(-%d),%0I0x%x\n",
959 		       reg_names[FRAME_POINTER_REGNUM],
960 		       offset + fsize, mask);
961 #endif
962 	}
963     }
964   if (fmask)
965     {
966       if (big)
967 	{
968 #ifdef MOTOROLA
969 	  asm_fprintf (stream, "\tfmovm -%d(%s,%Ra1.l),%0I0x%x\n",
970 		       foffset + fsize,
971 		       reg_names[FRAME_POINTER_REGNUM],
972 		       fmask);
973 #else
974 	  asm_fprintf (stream, "\tfmovem %s@(-%d,%Ra1:l),%0I0x%x\n",
975 		       reg_names[FRAME_POINTER_REGNUM],
976 		       foffset + fsize, fmask);
977 #endif
978 	}
979       else if (restore_from_sp)
980 	{
981 #ifdef MOTOROLA
982 	  asm_fprintf (stream, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask);
983 #else
984 	  asm_fprintf (stream, "\tfmovem %Rsp@+,%0I0x%x\n", fmask);
985 #endif
986 	}
987       else
988 	{
989 #ifdef MOTOROLA
990 	  asm_fprintf (stream, "\tfmovm -%d(%s),%0I0x%x\n",
991 		       foffset + fsize,
992 		       reg_names[FRAME_POINTER_REGNUM],
993 		       fmask);
994 #else
995 	  asm_fprintf (stream, "\tfmovem %s@(-%d),%0I0x%x\n",
996 		       reg_names[FRAME_POINTER_REGNUM],
997 		       foffset + fsize, fmask);
998 #endif
999 	}
1000     }
1001   if (fpoffset != 0)
1002     for (regno = 55; regno >= 24; regno--)
1003       if (m68k_save_reg (regno))
1004         {
1005 	  if (big)
1006 	    {
1007 #ifdef MOTOROLA
1008 	      asm_fprintf (stream, "\tfpmovd -%d(%s,%Ra1.l), %s\n",
1009 			   fpoffset + fsize,
1010 			   reg_names[FRAME_POINTER_REGNUM],
1011 			   reg_names[regno]);
1012 #else
1013 	      asm_fprintf (stream, "\tfpmoved %s@(-%d,%Ra1:l), %s\n",
1014 			   reg_names[FRAME_POINTER_REGNUM],
1015 			   fpoffset + fsize, reg_names[regno]);
1016 #endif
1017 	    }
1018 	  else if (restore_from_sp)
1019 	    {
1020 #ifdef MOTOROLA
1021 	      asm_fprintf (stream, "\tfpmovd (%Rsp)+,%s\n",
1022 			   reg_names[regno]);
1023 #else
1024 	      asm_fprintf (stream, "\tfpmoved %Rsp@+, %s\n",
1025 			   reg_names[regno]);
1026 #endif
1027 	    }
1028 	  else
1029 	    {
1030 #ifdef MOTOROLA
1031 	      fprintf (stream, "\tfpmovd -%d(%s), %s\n",
1032 		       fpoffset + fsize,
1033 		       reg_names[FRAME_POINTER_REGNUM],
1034 		       reg_names[regno]);
1035 #else
1036 	      fprintf (stream, "\tfpmoved %s@(-%d), %s\n",
1037 		       reg_names[FRAME_POINTER_REGNUM],
1038 		       fpoffset + fsize, reg_names[regno]);
1039 #endif
1040 	    }
1041 	  fpoffset -= 8;
1042 	}
1043   if (frame_pointer_needed)
1044     fprintf (stream, "\tunlk %s\n",
1045 	     reg_names[FRAME_POINTER_REGNUM]);
1046   else if (fsize)
1047     {
1048 #ifndef NO_ADDSUB_Q
1049       if (fsize + 4 <= 8)
1050 	{
1051 	  if (!TARGET_5200)
1052 	    {
1053 #ifdef MOTOROLA
1054 	      asm_fprintf (stream, "\taddq.w %0I%d,%Rsp\n", fsize + 4);
1055 #else
1056 	      asm_fprintf (stream, "\taddqw %0I%d,%Rsp\n", fsize + 4);
1057 #endif
1058 	    }
1059 	  else
1060 	    {
1061 #ifdef MOTOROLA
1062 	      asm_fprintf (stream, "\taddq.l %0I%d,%Rsp\n", fsize + 4);
1063 #else
1064 	      asm_fprintf (stream, "\taddql %0I%d,%Rsp\n", fsize + 4);
1065 #endif
1066 	    }
1067 	}
1068       else if (fsize + 4 <= 16 && TARGET_CPU32)
1069 	{
1070 	  /* On the CPU32 it is faster to use two addqw instructions to
1071 	     add a small integer (8 < N <= 16) to a register.  */
1072 	  /* asm_fprintf() cannot handle %.  */
1073 #ifdef MOTOROLA
1074 	  asm_fprintf (stream, "\taddq.w %0I8,%Rsp\n\taddq.w %0I%d,%Rsp\n",
1075 		       fsize + 4 - 8);
1076 #else
1077 	  asm_fprintf (stream, "\taddqw %0I8,%Rsp\n\taddqw %0I%d,%Rsp\n",
1078 		       fsize + 4 - 8);
1079 #endif
1080 	}
1081       else
1082 #endif /* not NO_ADDSUB_Q */
1083       if (fsize + 4 < 0x8000)
1084 	{
1085 	  if (TARGET_68040)
1086 	    {
1087 	      /* asm_fprintf() cannot handle %.  */
1088 #ifdef MOTOROLA
1089 	      asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", fsize + 4);
1090 #else
1091 	      asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", fsize + 4);
1092 #endif
1093 	    }
1094 	  else
1095 	    {
1096 #ifdef MOTOROLA
1097 	      asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", fsize + 4);
1098 #else
1099 	      asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", fsize + 4);
1100 #endif
1101 	    }
1102 	}
1103       else
1104 	{
1105 	/* asm_fprintf() cannot handle %.  */
1106 #ifdef MOTOROLA
1107 	  asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", fsize + 4);
1108 #else
1109 	  asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", fsize + 4);
1110 #endif
1111 	}
1112     }
1113   if (current_function_calls_eh_return)
1114     {
1115 #ifdef MOTOROLA
1116       asm_fprintf (stream, "\tadd.l %Ra0,%Rsp\n");
1117 #else
1118       asm_fprintf (stream, "\taddl %Ra0,%Rsp\n");
1119 #endif
1120     }
1121   if (current_function_pops_args)
1122     asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args);
1123   else
1124     fprintf (stream, "\trts\n");
1125 }
1126 #endif   /* !CRDS  */
1127 
1128 /* Similar to general_operand, but exclude stack_pointer_rtx.  */
1129 
1130 int
not_sp_operand(op,mode)1131 not_sp_operand (op, mode)
1132      register rtx op;
1133      enum machine_mode mode;
1134 {
1135   return op != stack_pointer_rtx && nonimmediate_operand (op, mode);
1136 }
1137 
1138 /* Return TRUE if X is a valid comparison operator for the dbcc
1139    instruction.
1140 
1141    Note it rejects floating point comparison operators.
1142    (In the future we could use Fdbcc).
1143 
1144    It also rejects some comparisons when CC_NO_OVERFLOW is set.  */
1145 
1146 int
valid_dbcc_comparison_p(x,mode)1147 valid_dbcc_comparison_p (x, mode)
1148      rtx x;
1149      enum machine_mode mode ATTRIBUTE_UNUSED;
1150 {
1151   switch (GET_CODE (x))
1152     {
1153       case EQ: case NE: case GTU: case LTU:
1154       case GEU: case LEU:
1155         return 1;
1156 
1157       /* Reject some when CC_NO_OVERFLOW is set.  This may be over
1158          conservative */
1159       case GT: case LT: case GE: case LE:
1160         return ! (cc_prev_status.flags & CC_NO_OVERFLOW);
1161       default:
1162         return 0;
1163     }
1164 }
1165 
1166 /* Return nonzero if flags are currently in the 68881 flag register.  */
1167 int
flags_in_68881()1168 flags_in_68881 ()
1169 {
1170   /* We could add support for these in the future */
1171   return cc_status.flags & CC_IN_68881;
1172 }
1173 
1174 /* Output a dbCC; jCC sequence.  Note we do not handle the
1175    floating point version of this sequence (Fdbcc).  We also
1176    do not handle alternative conditions when CC_NO_OVERFLOW is
1177    set.  It is assumed that valid_dbcc_comparison_p and flags_in_68881 will
1178    kick those out before we get here.  */
1179 
1180 void
output_dbcc_and_branch(operands)1181 output_dbcc_and_branch (operands)
1182      rtx *operands;
1183 {
1184   switch (GET_CODE (operands[3]))
1185     {
1186       case EQ:
1187 #ifdef MOTOROLA
1188         output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands);
1189 #else
1190         output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands);
1191 #endif
1192         break;
1193 
1194       case NE:
1195 #ifdef MOTOROLA
1196         output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands);
1197 #else
1198         output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands);
1199 #endif
1200         break;
1201 
1202       case GT:
1203 #ifdef MOTOROLA
1204         output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands);
1205 #else
1206         output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands);
1207 #endif
1208         break;
1209 
1210       case GTU:
1211 #ifdef MOTOROLA
1212         output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands);
1213 #else
1214         output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands);
1215 #endif
1216         break;
1217 
1218       case LT:
1219 #ifdef MOTOROLA
1220         output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands);
1221 #else
1222         output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands);
1223 #endif
1224         break;
1225 
1226       case LTU:
1227 #ifdef MOTOROLA
1228         output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands);
1229 #else
1230         output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands);
1231 #endif
1232         break;
1233 
1234       case GE:
1235 #ifdef MOTOROLA
1236         output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands);
1237 #else
1238         output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands);
1239 #endif
1240         break;
1241 
1242       case GEU:
1243 #ifdef MOTOROLA
1244         output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands);
1245 #else
1246         output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands);
1247 #endif
1248         break;
1249 
1250       case LE:
1251 #ifdef MOTOROLA
1252         output_asm_insn ("dble %0,%l1\n\tjble %l2", operands);
1253 #else
1254         output_asm_insn ("dble %0,%l1\n\tjle %l2", operands);
1255 #endif
1256         break;
1257 
1258       case LEU:
1259 #ifdef MOTOROLA
1260         output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands);
1261 #else
1262         output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands);
1263 #endif
1264         break;
1265 
1266       default:
1267 	abort ();
1268     }
1269 
1270   /* If the decrement is to be done in SImode, then we have
1271      to compensate for the fact that dbcc decrements in HImode.  */
1272   switch (GET_MODE (operands[0]))
1273     {
1274       case SImode:
1275 #ifdef MOTOROLA
1276         output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands);
1277 #else
1278         output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands);
1279 #endif
1280         break;
1281 
1282       case HImode:
1283         break;
1284 
1285       default:
1286         abort ();
1287     }
1288 }
1289 
1290 const char *
output_scc_di(op,operand1,operand2,dest)1291 output_scc_di(op, operand1, operand2, dest)
1292      rtx op;
1293      rtx operand1;
1294      rtx operand2;
1295      rtx dest;
1296 {
1297   rtx loperands[7];
1298   enum rtx_code op_code = GET_CODE (op);
1299 
1300   /* This does not produce a useful cc.  */
1301   CC_STATUS_INIT;
1302 
1303   /* The m68k cmp.l instruction requires operand1 to be a reg as used
1304      below.  Swap the operands and change the op if these requirements
1305      are not fulfilled.  */
1306   if (GET_CODE (operand2) == REG && GET_CODE (operand1) != REG)
1307     {
1308       rtx tmp = operand1;
1309 
1310       operand1 = operand2;
1311       operand2 = tmp;
1312       op_code = swap_condition (op_code);
1313     }
1314   loperands[0] = operand1;
1315   if (GET_CODE (operand1) == REG)
1316     loperands[1] = gen_rtx_REG (SImode, REGNO (operand1) + 1);
1317   else
1318     loperands[1] = adjust_address (operand1, SImode, 4);
1319   if (operand2 != const0_rtx)
1320     {
1321       loperands[2] = operand2;
1322       if (GET_CODE (operand2) == REG)
1323 	loperands[3] = gen_rtx_REG (SImode, REGNO (operand2) + 1);
1324       else
1325 	loperands[3] = adjust_address (operand2, SImode, 4);
1326     }
1327   loperands[4] = gen_label_rtx();
1328   if (operand2 != const0_rtx)
1329     {
1330 #ifdef MOTOROLA
1331 #ifdef SGS_CMP_ORDER
1332       output_asm_insn ("cmp%.l %0,%2\n\tjbne %l4\n\tcmp%.l %1,%3", loperands);
1333 #else
1334       output_asm_insn ("cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1", loperands);
1335 #endif
1336 #else
1337 #ifdef SGS_CMP_ORDER
1338       output_asm_insn ("cmp%.l %0,%2\n\tjne %l4\n\tcmp%.l %1,%3", loperands);
1339 #else
1340       output_asm_insn ("cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1", loperands);
1341 #endif
1342 #endif
1343     }
1344   else
1345     {
1346       if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (loperands[0]))
1347 	output_asm_insn ("tst%.l %0", loperands);
1348       else
1349 	{
1350 #ifdef SGS_CMP_ORDER
1351 	  output_asm_insn ("cmp%.w %0,%#0", loperands);
1352 #else
1353 	  output_asm_insn ("cmp%.w %#0,%0", loperands);
1354 #endif
1355 	}
1356 
1357 #ifdef MOTOROLA
1358       output_asm_insn ("jbne %l4", loperands);
1359 #else
1360       output_asm_insn ("jne %l4", loperands);
1361 #endif
1362 
1363       if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (loperands[1]))
1364 	output_asm_insn ("tst%.l %1", loperands);
1365       else
1366 	{
1367 #ifdef SGS_CMP_ORDER
1368 	  output_asm_insn ("cmp%.w %1,%#0", loperands);
1369 #else
1370 	  output_asm_insn ("cmp%.w %#0,%1", loperands);
1371 #endif
1372 	}
1373     }
1374 
1375   loperands[5] = dest;
1376 
1377   switch (op_code)
1378     {
1379       case EQ:
1380         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1381 				    CODE_LABEL_NUMBER (loperands[4]));
1382         output_asm_insn ("seq %5", loperands);
1383         break;
1384 
1385       case NE:
1386         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1387 				    CODE_LABEL_NUMBER (loperands[4]));
1388         output_asm_insn ("sne %5", loperands);
1389         break;
1390 
1391       case GT:
1392         loperands[6] = gen_label_rtx();
1393 #ifdef MOTOROLA
1394         output_asm_insn ("shi %5\n\tjbra %l6", loperands);
1395 #else
1396         output_asm_insn ("shi %5\n\tjra %l6", loperands);
1397 #endif
1398         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1399 				    CODE_LABEL_NUMBER (loperands[4]));
1400         output_asm_insn ("sgt %5", loperands);
1401         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1402 				    CODE_LABEL_NUMBER (loperands[6]));
1403         break;
1404 
1405       case GTU:
1406         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1407 				    CODE_LABEL_NUMBER (loperands[4]));
1408         output_asm_insn ("shi %5", loperands);
1409         break;
1410 
1411       case LT:
1412         loperands[6] = gen_label_rtx();
1413 #ifdef MOTOROLA
1414         output_asm_insn ("scs %5\n\tjbra %l6", loperands);
1415 #else
1416         output_asm_insn ("scs %5\n\tjra %l6", loperands);
1417 #endif
1418         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1419 				    CODE_LABEL_NUMBER (loperands[4]));
1420         output_asm_insn ("slt %5", loperands);
1421         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1422 				    CODE_LABEL_NUMBER (loperands[6]));
1423         break;
1424 
1425       case LTU:
1426         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1427 				    CODE_LABEL_NUMBER (loperands[4]));
1428         output_asm_insn ("scs %5", loperands);
1429         break;
1430 
1431       case GE:
1432         loperands[6] = gen_label_rtx();
1433 #ifdef MOTOROLA
1434         output_asm_insn ("scc %5\n\tjbra %l6", loperands);
1435 #else
1436         output_asm_insn ("scc %5\n\tjra %l6", loperands);
1437 #endif
1438         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1439 				    CODE_LABEL_NUMBER (loperands[4]));
1440         output_asm_insn ("sge %5", loperands);
1441         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1442 				    CODE_LABEL_NUMBER (loperands[6]));
1443         break;
1444 
1445       case GEU:
1446         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1447 				    CODE_LABEL_NUMBER (loperands[4]));
1448         output_asm_insn ("scc %5", loperands);
1449         break;
1450 
1451       case LE:
1452         loperands[6] = gen_label_rtx();
1453 #ifdef MOTOROLA
1454         output_asm_insn ("sls %5\n\tjbra %l6", loperands);
1455 #else
1456         output_asm_insn ("sls %5\n\tjra %l6", loperands);
1457 #endif
1458         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1459 				    CODE_LABEL_NUMBER (loperands[4]));
1460         output_asm_insn ("sle %5", loperands);
1461         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1462 				    CODE_LABEL_NUMBER (loperands[6]));
1463         break;
1464 
1465       case LEU:
1466         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
1467 				    CODE_LABEL_NUMBER (loperands[4]));
1468         output_asm_insn ("sls %5", loperands);
1469         break;
1470 
1471       default:
1472 	abort ();
1473     }
1474   return "";
1475 }
1476 
1477 const char *
output_btst(operands,countop,dataop,insn,signpos)1478 output_btst (operands, countop, dataop, insn, signpos)
1479      rtx *operands;
1480      rtx countop, dataop;
1481      rtx insn;
1482      int signpos;
1483 {
1484   operands[0] = countop;
1485   operands[1] = dataop;
1486 
1487   if (GET_CODE (countop) == CONST_INT)
1488     {
1489       register int count = INTVAL (countop);
1490       /* If COUNT is bigger than size of storage unit in use,
1491 	 advance to the containing unit of same size.  */
1492       if (count > signpos)
1493 	{
1494 	  int offset = (count & ~signpos) / 8;
1495 	  count = count & signpos;
1496 	  operands[1] = dataop = adjust_address (dataop, QImode, offset);
1497 	}
1498       if (count == signpos)
1499 	cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
1500       else
1501 	cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
1502 
1503       /* These three statements used to use next_insns_test_no...
1504 	 but it appears that this should do the same job.  */
1505       if (count == 31
1506 	  && next_insn_tests_no_inequality (insn))
1507 	return "tst%.l %1";
1508       if (count == 15
1509 	  && next_insn_tests_no_inequality (insn))
1510 	return "tst%.w %1";
1511       if (count == 7
1512 	  && next_insn_tests_no_inequality (insn))
1513 	return "tst%.b %1";
1514 
1515       cc_status.flags = CC_NOT_NEGATIVE;
1516     }
1517   return "btst %0,%1";
1518 }
1519 
1520 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
1521    reference and a constant.  */
1522 
1523 int
symbolic_operand(op,mode)1524 symbolic_operand (op, mode)
1525      register rtx op;
1526      enum machine_mode mode ATTRIBUTE_UNUSED;
1527 {
1528   switch (GET_CODE (op))
1529     {
1530     case SYMBOL_REF:
1531     case LABEL_REF:
1532       return 1;
1533 
1534     case CONST:
1535       op = XEXP (op, 0);
1536       return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1537 	       || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1538 	      && GET_CODE (XEXP (op, 1)) == CONST_INT);
1539 
1540 #if 0 /* Deleted, with corresponding change in m68k.h,
1541 	 so as to fit the specs.  No CONST_DOUBLE is ever symbolic.  */
1542     case CONST_DOUBLE:
1543       return GET_MODE (op) == mode;
1544 #endif
1545 
1546     default:
1547       return 0;
1548     }
1549 }
1550 
1551 /* Check for sign_extend or zero_extend.  Used for bit-count operands.  */
1552 
1553 int
extend_operator(x,mode)1554 extend_operator(x, mode)
1555      rtx x;
1556      enum machine_mode mode;
1557 {
1558     if (mode != VOIDmode && GET_MODE(x) != mode)
1559 	return 0;
1560     switch (GET_CODE(x))
1561 	{
1562 	case SIGN_EXTEND :
1563 	case ZERO_EXTEND :
1564 	    return 1;
1565 	default :
1566 	    return 0;
1567 	}
1568 }
1569 
1570 
1571 /* Legitimize PIC addresses.  If the address is already
1572    position-independent, we return ORIG.  Newly generated
1573    position-independent addresses go to REG.  If we need more
1574    than one register, we lose.
1575 
1576    An address is legitimized by making an indirect reference
1577    through the Global Offset Table with the name of the symbol
1578    used as an offset.
1579 
1580    The assembler and linker are responsible for placing the
1581    address of the symbol in the GOT.  The function prologue
1582    is responsible for initializing a5 to the starting address
1583    of the GOT.
1584 
1585    The assembler is also responsible for translating a symbol name
1586    into a constant displacement from the start of the GOT.
1587 
1588    A quick example may make things a little clearer:
1589 
1590    When not generating PIC code to store the value 12345 into _foo
1591    we would generate the following code:
1592 
1593 	movel #12345, _foo
1594 
1595    When generating PIC two transformations are made.  First, the compiler
1596    loads the address of foo into a register.  So the first transformation makes:
1597 
1598 	lea	_foo, a0
1599 	movel   #12345, a0@
1600 
1601    The code in movsi will intercept the lea instruction and call this
1602    routine which will transform the instructions into:
1603 
1604 	movel   a5@(_foo:w), a0
1605 	movel   #12345, a0@
1606 
1607 
1608    That (in a nutshell) is how *all* symbol and label references are
1609    handled.  */
1610 
1611 rtx
legitimize_pic_address(orig,mode,reg)1612 legitimize_pic_address (orig, mode, reg)
1613      rtx orig, reg;
1614      enum machine_mode mode ATTRIBUTE_UNUSED;
1615 {
1616   rtx pic_ref = orig;
1617 
1618   /* First handle a simple SYMBOL_REF or LABEL_REF */
1619   if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
1620     {
1621       if (reg == 0)
1622 	abort ();
1623 
1624       pic_ref = gen_rtx_MEM (Pmode,
1625 			     gen_rtx_PLUS (Pmode,
1626 					   pic_offset_table_rtx, orig));
1627       current_function_uses_pic_offset_table = 1;
1628       RTX_UNCHANGING_P (pic_ref) = 1;
1629       emit_move_insn (reg, pic_ref);
1630       return reg;
1631     }
1632   else if (GET_CODE (orig) == CONST)
1633     {
1634       rtx base;
1635 
1636       /* Make sure this is CONST has not already been legitimized */
1637       if (GET_CODE (XEXP (orig, 0)) == PLUS
1638 	  && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
1639 	return orig;
1640 
1641       if (reg == 0)
1642 	abort ();
1643 
1644       /* legitimize both operands of the PLUS */
1645       if (GET_CODE (XEXP (orig, 0)) == PLUS)
1646 	{
1647 	  base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
1648 	  orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
1649 					 base == reg ? 0 : reg);
1650 	}
1651       else abort ();
1652 
1653       if (GET_CODE (orig) == CONST_INT)
1654 	return plus_constant (base, INTVAL (orig));
1655       pic_ref = gen_rtx_PLUS (Pmode, base, orig);
1656       /* Likewise, should we set special REG_NOTEs here?  */
1657     }
1658   return pic_ref;
1659 }
1660 
1661 
1662 typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ } CONST_METHOD;
1663 
1664 static CONST_METHOD const_method PARAMS ((rtx));
1665 
1666 #define USE_MOVQ(i)	((unsigned)((i) + 128) <= 255)
1667 
1668 static CONST_METHOD
const_method(constant)1669 const_method (constant)
1670      rtx constant;
1671 {
1672   int i;
1673   unsigned u;
1674 
1675   i = INTVAL (constant);
1676   if (USE_MOVQ (i))
1677     return MOVQ;
1678 
1679   /* The Coldfire doesn't have byte or word operations.  */
1680   /* FIXME: This may not be useful for the m68060 either */
1681   if (!TARGET_5200)
1682     {
1683       /* if -256 < N < 256 but N is not in range for a moveq
1684 	 N^ff will be, so use moveq #N^ff, dreg; not.b dreg.  */
1685       if (USE_MOVQ (i ^ 0xff))
1686 	return NOTB;
1687       /* Likewise, try with not.w */
1688       if (USE_MOVQ (i ^ 0xffff))
1689 	return NOTW;
1690       /* This is the only value where neg.w is useful */
1691       if (i == -65408)
1692 	return NEGW;
1693       /* Try also with swap */
1694       u = i;
1695       if (USE_MOVQ ((u >> 16) | (u << 16)))
1696 	return SWAP;
1697     }
1698   /* Otherwise, use move.l */
1699   return MOVL;
1700 }
1701 
1702 int
const_int_cost(constant)1703 const_int_cost (constant)
1704      rtx constant;
1705 {
1706   switch (const_method (constant))
1707     {
1708       case MOVQ :
1709       /* Constants between -128 and 127 are cheap due to moveq */
1710 	return 0;
1711       case NOTB :
1712       case NOTW :
1713       case NEGW :
1714       case SWAP :
1715       /* Constants easily generated by moveq + not.b/not.w/neg.w/swap  */
1716         return 1;
1717       case MOVL :
1718 	return 2;
1719       default :
1720         abort ();
1721     }
1722 }
1723 
1724 const char *
output_move_const_into_data_reg(operands)1725 output_move_const_into_data_reg (operands)
1726      rtx *operands;
1727 {
1728   int i;
1729 
1730   i = INTVAL (operands[1]);
1731   switch (const_method (operands[1]))
1732     {
1733     case MOVQ :
1734 #if defined (MOTOROLA) && !defined (CRDS)
1735       return "moveq%.l %1,%0";
1736 #else
1737       return "moveq %1,%0";
1738 #endif
1739     case NOTB :
1740       CC_STATUS_INIT;
1741       operands[1] = GEN_INT (i ^ 0xff);
1742 #if defined (MOTOROLA) && !defined (CRDS)
1743       return "moveq%.l %1,%0\n\tnot%.b %0";
1744 #else
1745       return "moveq %1,%0\n\tnot%.b %0";
1746 #endif
1747     case NOTW :
1748       CC_STATUS_INIT;
1749       operands[1] = GEN_INT (i ^ 0xffff);
1750 #if defined (MOTOROLA) && !defined (CRDS)
1751       return "moveq%.l %1,%0\n\tnot%.w %0";
1752 #else
1753       return "moveq %1,%0\n\tnot%.w %0";
1754 #endif
1755     case NEGW :
1756       CC_STATUS_INIT;
1757 #if defined (MOTOROLA) && !defined (CRDS)
1758       return "moveq%.l %#-128,%0\n\tneg%.w %0";
1759 #else
1760       return "moveq %#-128,%0\n\tneg%.w %0";
1761 #endif
1762     case SWAP :
1763       {
1764 	unsigned u = i;
1765 
1766 	operands[1] = GEN_INT ((u << 16) | (u >> 16));
1767 #if defined (MOTOROLA) && !defined (CRDS)
1768 	return "moveq%.l %1,%0\n\tswap %0";
1769 #else
1770 	return "moveq %1,%0\n\tswap %0";
1771 #endif
1772       }
1773     case MOVL :
1774 	return "move%.l %1,%0";
1775     default :
1776 	abort ();
1777     }
1778 }
1779 
1780 const char *
output_move_simode_const(operands)1781 output_move_simode_const (operands)
1782      rtx *operands;
1783 {
1784   if (operands[1] == const0_rtx
1785       && (DATA_REG_P (operands[0])
1786 	  || GET_CODE (operands[0]) == MEM)
1787       /* clr insns on 68000 read before writing.
1788 	 This isn't so on the 68010, but we have no TARGET_68010.  */
1789       && ((TARGET_68020 || TARGET_5200)
1790 	  || !(GET_CODE (operands[0]) == MEM
1791 	       && MEM_VOLATILE_P (operands[0]))))
1792     return "clr%.l %0";
1793   else if (operands[1] == const0_rtx
1794 	   && ADDRESS_REG_P (operands[0]))
1795     return "sub%.l %0,%0";
1796   else if (DATA_REG_P (operands[0]))
1797     return output_move_const_into_data_reg (operands);
1798   else if (ADDRESS_REG_P (operands[0])
1799 	   && INTVAL (operands[1]) < 0x8000
1800 	   && INTVAL (operands[1]) >= -0x8000)
1801     return "move%.w %1,%0";
1802   else if (GET_CODE (operands[0]) == MEM
1803       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
1804       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
1805 	   && INTVAL (operands[1]) < 0x8000
1806 	   && INTVAL (operands[1]) >= -0x8000)
1807     return "pea %a1";
1808   return "move%.l %1,%0";
1809 }
1810 
1811 const char *
output_move_simode(operands)1812 output_move_simode (operands)
1813      rtx *operands;
1814 {
1815   if (GET_CODE (operands[1]) == CONST_INT)
1816     return output_move_simode_const (operands);
1817   else if ((GET_CODE (operands[1]) == SYMBOL_REF
1818 	    || GET_CODE (operands[1]) == CONST)
1819 	   && push_operand (operands[0], SImode))
1820     return "pea %a1";
1821   else if ((GET_CODE (operands[1]) == SYMBOL_REF
1822 	    || GET_CODE (operands[1]) == CONST)
1823 	   && ADDRESS_REG_P (operands[0]))
1824     return "lea %a1,%0";
1825   return "move%.l %1,%0";
1826 }
1827 
1828 const char *
output_move_himode(operands)1829 output_move_himode (operands)
1830      rtx *operands;
1831 {
1832  if (GET_CODE (operands[1]) == CONST_INT)
1833     {
1834       if (operands[1] == const0_rtx
1835 	  && (DATA_REG_P (operands[0])
1836 	      || GET_CODE (operands[0]) == MEM)
1837 	  /* clr insns on 68000 read before writing.
1838 	     This isn't so on the 68010, but we have no TARGET_68010.  */
1839 	  && ((TARGET_68020 || TARGET_5200)
1840 	      || !(GET_CODE (operands[0]) == MEM
1841 		   && MEM_VOLATILE_P (operands[0]))))
1842 	return "clr%.w %0";
1843       else if (operands[1] == const0_rtx
1844 	       && ADDRESS_REG_P (operands[0]))
1845 	return "sub%.l %0,%0";
1846       else if (DATA_REG_P (operands[0])
1847 	       && INTVAL (operands[1]) < 128
1848 	       && INTVAL (operands[1]) >= -128)
1849 	{
1850 #if defined(MOTOROLA) && !defined(CRDS)
1851 	  return "moveq%.l %1,%0";
1852 #else
1853 	  return "moveq %1,%0";
1854 #endif
1855 	}
1856       else if (INTVAL (operands[1]) < 0x8000
1857 	       && INTVAL (operands[1]) >= -0x8000)
1858 	return "move%.w %1,%0";
1859     }
1860   else if (CONSTANT_P (operands[1]))
1861     return "move%.l %1,%0";
1862 #ifndef SGS_NO_LI
1863   /* Recognize the insn before a tablejump, one that refers
1864      to a table of offsets.  Such an insn will need to refer
1865      to a label on the insn.  So output one.  Use the label-number
1866      of the table of offsets to generate this label.  This code,
1867      and similar code below, assumes that there will be at most one
1868      reference to each table.  */
1869   if (GET_CODE (operands[1]) == MEM
1870       && GET_CODE (XEXP (operands[1], 0)) == PLUS
1871       && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF
1872       && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS)
1873     {
1874       rtx labelref = XEXP (XEXP (operands[1], 0), 1);
1875 #if defined (MOTOROLA) && !defined (SGS_SWITCH_TABLES)
1876 #ifdef SGS
1877       asm_fprintf (asm_out_file, "\tset %LLI%d,.+2\n",
1878 		   CODE_LABEL_NUMBER (XEXP (labelref, 0)));
1879 #else /* not SGS */
1880       asm_fprintf (asm_out_file, "\t.set %LLI%d,.+2\n",
1881 		   CODE_LABEL_NUMBER (XEXP (labelref, 0)));
1882 #endif /* not SGS */
1883 #else /* SGS_SWITCH_TABLES or not MOTOROLA */
1884       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LI",
1885 				 CODE_LABEL_NUMBER (XEXP (labelref, 0)));
1886 #ifdef SGS_SWITCH_TABLES
1887       /* Set flag saying we need to define the symbol
1888 	 LD%n (with value L%n-LI%n) at the end of the switch table.  */
1889       switch_table_difference_label_flag = 1;
1890 #endif /* SGS_SWITCH_TABLES */
1891 #endif /* SGS_SWITCH_TABLES or not MOTOROLA */
1892     }
1893 #endif /* SGS_NO_LI */
1894   return "move%.w %1,%0";
1895 }
1896 
1897 const char *
output_move_qimode(operands)1898 output_move_qimode (operands)
1899      rtx *operands;
1900 {
1901   rtx xoperands[4];
1902 
1903   /* This is probably useless, since it loses for pushing a struct
1904      of several bytes a byte at a time.	 */
1905   /* 68k family always modifies the stack pointer by at least 2, even for
1906      byte pushes.  The 5200 (coldfire) does not do this.  */
1907   if (GET_CODE (operands[0]) == MEM
1908       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
1909       && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx
1910       && ! ADDRESS_REG_P (operands[1])
1911       && ! TARGET_5200)
1912     {
1913       xoperands[1] = operands[1];
1914       xoperands[2]
1915 	= gen_rtx_MEM (QImode,
1916 		       gen_rtx_PLUS (VOIDmode, stack_pointer_rtx, const1_rtx));
1917       /* Just pushing a byte puts it in the high byte of the halfword.	*/
1918       /* We must put it in the low-order, high-numbered byte.  */
1919       if (!reg_mentioned_p (stack_pointer_rtx, operands[1]))
1920 	{
1921 	  xoperands[3] = stack_pointer_rtx;
1922 #ifndef NO_ADDSUB_Q
1923 	  output_asm_insn ("subq%.l %#2,%3\n\tmove%.b %1,%2", xoperands);
1924 #else
1925 	  output_asm_insn ("sub%.l %#2,%3\n\tmove%.b %1,%2", xoperands);
1926 #endif
1927 	}
1928       else
1929 	output_asm_insn ("move%.b %1,%-\n\tmove%.b %@,%2", xoperands);
1930       return "";
1931     }
1932 
1933   /* clr and st insns on 68000 read before writing.
1934      This isn't so on the 68010, but we have no TARGET_68010.  */
1935   if (!ADDRESS_REG_P (operands[0])
1936       && ((TARGET_68020 || TARGET_5200)
1937 	  || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
1938     {
1939       if (operands[1] == const0_rtx)
1940 	return "clr%.b %0";
1941       if ((!TARGET_5200 || DATA_REG_P (operands[0]))
1942 	  && GET_CODE (operands[1]) == CONST_INT
1943 	  && (INTVAL (operands[1]) & 255) == 255)
1944 	{
1945 	  CC_STATUS_INIT;
1946 	  return "st %0";
1947 	}
1948     }
1949   if (GET_CODE (operands[1]) == CONST_INT
1950       && DATA_REG_P (operands[0])
1951       && INTVAL (operands[1]) < 128
1952       && INTVAL (operands[1]) >= -128)
1953     {
1954 #if defined(MOTOROLA) && !defined(CRDS)
1955       return "moveq%.l %1,%0";
1956 #else
1957       return "moveq %1,%0";
1958 #endif
1959     }
1960   if (operands[1] == const0_rtx && ADDRESS_REG_P (operands[0]))
1961     return "sub%.l %0,%0";
1962   if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
1963     return "move%.l %1,%0";
1964   /* 68k family (including the 5200 coldfire) does not support byte moves to
1965      from address registers.  */
1966   if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1]))
1967     return "move%.w %1,%0";
1968   return "move%.b %1,%0";
1969 }
1970 
1971 const char *
output_move_stricthi(operands)1972 output_move_stricthi (operands)
1973      rtx *operands;
1974 {
1975   if (operands[1] == const0_rtx
1976       /* clr insns on 68000 read before writing.
1977 	 This isn't so on the 68010, but we have no TARGET_68010.  */
1978       && ((TARGET_68020 || TARGET_5200)
1979 	  || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
1980     return "clr%.w %0";
1981   return "move%.w %1,%0";
1982 }
1983 
1984 const char *
output_move_strictqi(operands)1985 output_move_strictqi (operands)
1986      rtx *operands;
1987 {
1988   if (operands[1] == const0_rtx
1989       /* clr insns on 68000 read before writing.
1990          This isn't so on the 68010, but we have no TARGET_68010.  */
1991       && ((TARGET_68020 || TARGET_5200)
1992           || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
1993     return "clr%.b %0";
1994   return "move%.b %1,%0";
1995 }
1996 
1997 /* Return the best assembler insn template
1998    for moving operands[1] into operands[0] as a fullword.  */
1999 
2000 static const char *
singlemove_string(operands)2001 singlemove_string (operands)
2002      rtx *operands;
2003 {
2004 #ifdef SUPPORT_SUN_FPA
2005   if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
2006     return "fpmoves %1,%0";
2007 #endif
2008   if (GET_CODE (operands[1]) == CONST_INT)
2009     return output_move_simode_const (operands);
2010   return "move%.l %1,%0";
2011 }
2012 
2013 
2014 /* Output assembler code to perform a doubleword move insn
2015    with operands OPERANDS.  */
2016 
2017 const char *
output_move_double(operands)2018 output_move_double (operands)
2019      rtx *operands;
2020 {
2021   enum
2022     {
2023       REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP
2024     } optype0, optype1;
2025   rtx latehalf[2];
2026   rtx middlehalf[2];
2027   rtx xops[2];
2028   rtx addreg0 = 0, addreg1 = 0;
2029   int dest_overlapped_low = 0;
2030   int size = GET_MODE_SIZE (GET_MODE (operands[0]));
2031 
2032   middlehalf[0] = 0;
2033   middlehalf[1] = 0;
2034 
2035   /* First classify both operands.  */
2036 
2037   if (REG_P (operands[0]))
2038     optype0 = REGOP;
2039   else if (offsettable_memref_p (operands[0]))
2040     optype0 = OFFSOP;
2041   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
2042     optype0 = POPOP;
2043   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
2044     optype0 = PUSHOP;
2045   else if (GET_CODE (operands[0]) == MEM)
2046     optype0 = MEMOP;
2047   else
2048     optype0 = RNDOP;
2049 
2050   if (REG_P (operands[1]))
2051     optype1 = REGOP;
2052   else if (CONSTANT_P (operands[1]))
2053     optype1 = CNSTOP;
2054   else if (offsettable_memref_p (operands[1]))
2055     optype1 = OFFSOP;
2056   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
2057     optype1 = POPOP;
2058   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
2059     optype1 = PUSHOP;
2060   else if (GET_CODE (operands[1]) == MEM)
2061     optype1 = MEMOP;
2062   else
2063     optype1 = RNDOP;
2064 
2065   /* Check for the cases that the operand constraints are not
2066      supposed to allow to happen.  Abort if we get one,
2067      because generating code for these cases is painful.  */
2068 
2069   if (optype0 == RNDOP || optype1 == RNDOP)
2070     abort ();
2071 
2072   /* If one operand is decrementing and one is incrementing
2073      decrement the former register explicitly
2074      and change that operand into ordinary indexing.  */
2075 
2076   if (optype0 == PUSHOP && optype1 == POPOP)
2077     {
2078       operands[0] = XEXP (XEXP (operands[0], 0), 0);
2079       if (size == 12)
2080         output_asm_insn ("sub%.l %#12,%0", operands);
2081       else
2082         output_asm_insn ("subq%.l %#8,%0", operands);
2083       if (GET_MODE (operands[1]) == XFmode)
2084 	operands[0] = gen_rtx_MEM (XFmode, operands[0]);
2085       else if (GET_MODE (operands[0]) == DFmode)
2086 	operands[0] = gen_rtx_MEM (DFmode, operands[0]);
2087       else
2088 	operands[0] = gen_rtx_MEM (DImode, operands[0]);
2089       optype0 = OFFSOP;
2090     }
2091   if (optype0 == POPOP && optype1 == PUSHOP)
2092     {
2093       operands[1] = XEXP (XEXP (operands[1], 0), 0);
2094       if (size == 12)
2095         output_asm_insn ("sub%.l %#12,%1", operands);
2096       else
2097         output_asm_insn ("subq%.l %#8,%1", operands);
2098       if (GET_MODE (operands[1]) == XFmode)
2099 	operands[1] = gen_rtx_MEM (XFmode, operands[1]);
2100       else if (GET_MODE (operands[1]) == DFmode)
2101 	operands[1] = gen_rtx_MEM (DFmode, operands[1]);
2102       else
2103 	operands[1] = gen_rtx_MEM (DImode, operands[1]);
2104       optype1 = OFFSOP;
2105     }
2106 
2107   /* If an operand is an unoffsettable memory ref, find a register
2108      we can increment temporarily to make it refer to the second word.  */
2109 
2110   if (optype0 == MEMOP)
2111     addreg0 = find_addr_reg (XEXP (operands[0], 0));
2112 
2113   if (optype1 == MEMOP)
2114     addreg1 = find_addr_reg (XEXP (operands[1], 0));
2115 
2116   /* Ok, we can do one word at a time.
2117      Normally we do the low-numbered word first,
2118      but if either operand is autodecrementing then we
2119      do the high-numbered word first.
2120 
2121      In either case, set up in LATEHALF the operands to use
2122      for the high-numbered word and in some cases alter the
2123      operands in OPERANDS to be suitable for the low-numbered word.  */
2124 
2125   if (size == 12)
2126     {
2127       if (optype0 == REGOP)
2128 	{
2129 	  latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
2130 	  middlehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
2131 	}
2132       else if (optype0 == OFFSOP)
2133 	{
2134 	  middlehalf[0] = adjust_address (operands[0], SImode, 4);
2135 	  latehalf[0] = adjust_address (operands[0], SImode, size - 4);
2136 	}
2137       else
2138 	{
2139 	  middlehalf[0] = operands[0];
2140 	  latehalf[0] = operands[0];
2141 	}
2142 
2143       if (optype1 == REGOP)
2144 	{
2145 	  latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
2146 	  middlehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
2147 	}
2148       else if (optype1 == OFFSOP)
2149 	{
2150 	  middlehalf[1] = adjust_address (operands[1], SImode, 4);
2151 	  latehalf[1] = adjust_address (operands[1], SImode, size - 4);
2152 	}
2153       else if (optype1 == CNSTOP)
2154 	{
2155 	  if (GET_CODE (operands[1]) == CONST_DOUBLE)
2156 	    {
2157 	      REAL_VALUE_TYPE r;
2158 	      long l[3];
2159 
2160 	      REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2161 	      REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
2162 	      operands[1] = GEN_INT (l[0]);
2163 	      middlehalf[1] = GEN_INT (l[1]);
2164 	      latehalf[1] = GEN_INT (l[2]);
2165 	    }
2166 	  else if (CONSTANT_P (operands[1]))
2167 	    {
2168 	      /* actually, no non-CONST_DOUBLE constant should ever
2169 		 appear here.  */
2170 	      abort ();
2171 	      if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
2172 		latehalf[1] = constm1_rtx;
2173 	      else
2174 		latehalf[1] = const0_rtx;
2175 	    }
2176 	}
2177       else
2178 	{
2179 	  middlehalf[1] = operands[1];
2180 	  latehalf[1] = operands[1];
2181 	}
2182     }
2183   else
2184     /* size is not 12: */
2185     {
2186       if (optype0 == REGOP)
2187 	latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
2188       else if (optype0 == OFFSOP)
2189 	latehalf[0] = adjust_address (operands[0], SImode, size - 4);
2190       else
2191 	latehalf[0] = operands[0];
2192 
2193       if (optype1 == REGOP)
2194 	latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
2195       else if (optype1 == OFFSOP)
2196 	latehalf[1] = adjust_address (operands[1], SImode, size - 4);
2197       else if (optype1 == CNSTOP)
2198 	split_double (operands[1], &operands[1], &latehalf[1]);
2199       else
2200 	latehalf[1] = operands[1];
2201     }
2202 
2203   /* If insn is effectively movd N(sp),-(sp) then we will do the
2204      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
2205      for the low word as well, to compensate for the first decrement of sp.  */
2206   if (optype0 == PUSHOP
2207       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
2208       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
2209     operands[1] = middlehalf[1] = latehalf[1];
2210 
2211   /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
2212      if the upper part of reg N does not appear in the MEM, arrange to
2213      emit the move late-half first.  Otherwise, compute the MEM address
2214      into the upper part of N and use that as a pointer to the memory
2215      operand.  */
2216   if (optype0 == REGOP
2217       && (optype1 == OFFSOP || optype1 == MEMOP))
2218     {
2219       rtx testlow = gen_rtx_REG (SImode, REGNO (operands[0]));
2220 
2221       if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
2222 	  && reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
2223 	{
2224 	  /* If both halves of dest are used in the src memory address,
2225 	     compute the address into latehalf of dest.
2226 	     Note that this can't happen if the dest is two data regs.  */
2227 compadr:
2228 	  xops[0] = latehalf[0];
2229 	  xops[1] = XEXP (operands[1], 0);
2230 	  output_asm_insn ("lea %a1,%0", xops);
2231 	  if (GET_MODE (operands[1]) == XFmode )
2232 	    {
2233 	      operands[1] = gen_rtx_MEM (XFmode, latehalf[0]);
2234 	      middlehalf[1] = adjust_address (operands[1], DImode, size - 8);
2235 	      latehalf[1] = adjust_address (operands[1], DImode, size - 4);
2236 	    }
2237 	  else
2238 	    {
2239 	      operands[1] = gen_rtx_MEM (DImode, latehalf[0]);
2240 	      latehalf[1] = adjust_address (operands[1], DImode, size - 4);
2241 	    }
2242 	}
2243       else if (size == 12
2244 	       && reg_overlap_mentioned_p (middlehalf[0],
2245 					   XEXP (operands[1], 0)))
2246 	{
2247 	  /* Check for two regs used by both source and dest.
2248 	     Note that this can't happen if the dest is all data regs.
2249 	     It can happen if the dest is d6, d7, a0.
2250 	     But in that case, latehalf is an addr reg, so
2251 	     the code at compadr does ok.  */
2252 
2253 	  if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
2254 	      || reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
2255 	    goto compadr;
2256 
2257 	  /* JRV says this can't happen: */
2258 	  if (addreg0 || addreg1)
2259 	    abort ();
2260 
2261 	  /* Only the middle reg conflicts; simply put it last.  */
2262 	  output_asm_insn (singlemove_string (operands), operands);
2263 	  output_asm_insn (singlemove_string (latehalf), latehalf);
2264 	  output_asm_insn (singlemove_string (middlehalf), middlehalf);
2265 	  return "";
2266 	}
2267       else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)))
2268 	/* If the low half of dest is mentioned in the source memory
2269 	   address, the arrange to emit the move late half first.  */
2270 	dest_overlapped_low = 1;
2271     }
2272 
2273   /* If one or both operands autodecrementing,
2274      do the two words, high-numbered first.  */
2275 
2276   /* Likewise,  the first move would clobber the source of the second one,
2277      do them in the other order.  This happens only for registers;
2278      such overlap can't happen in memory unless the user explicitly
2279      sets it up, and that is an undefined circumstance.  */
2280 
2281   if (optype0 == PUSHOP || optype1 == PUSHOP
2282       || (optype0 == REGOP && optype1 == REGOP
2283 	  && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1]))
2284 	      || REGNO (operands[0]) == REGNO (latehalf[1])))
2285       || dest_overlapped_low)
2286     {
2287       /* Make any unoffsettable addresses point at high-numbered word.  */
2288       if (addreg0)
2289 	{
2290 	  if (size == 12)
2291 	    output_asm_insn ("addq%.l %#8,%0", &addreg0);
2292 	  else
2293 	    output_asm_insn ("addq%.l %#4,%0", &addreg0);
2294 	}
2295       if (addreg1)
2296 	{
2297 	  if (size == 12)
2298 	    output_asm_insn ("addq%.l %#8,%0", &addreg1);
2299 	  else
2300 	    output_asm_insn ("addq%.l %#4,%0", &addreg1);
2301 	}
2302 
2303       /* Do that word.  */
2304       output_asm_insn (singlemove_string (latehalf), latehalf);
2305 
2306       /* Undo the adds we just did.  */
2307       if (addreg0)
2308 	output_asm_insn ("subq%.l %#4,%0", &addreg0);
2309       if (addreg1)
2310 	output_asm_insn ("subq%.l %#4,%0", &addreg1);
2311 
2312       if (size == 12)
2313 	{
2314 	  output_asm_insn (singlemove_string (middlehalf), middlehalf);
2315 	  if (addreg0)
2316 	    output_asm_insn ("subq%.l %#4,%0", &addreg0);
2317 	  if (addreg1)
2318 	    output_asm_insn ("subq%.l %#4,%0", &addreg1);
2319 	}
2320 
2321       /* Do low-numbered word.  */
2322       return singlemove_string (operands);
2323     }
2324 
2325   /* Normal case: do the two words, low-numbered first.  */
2326 
2327   output_asm_insn (singlemove_string (operands), operands);
2328 
2329   /* Do the middle one of the three words for long double */
2330   if (size == 12)
2331     {
2332       if (addreg0)
2333 	output_asm_insn ("addq%.l %#4,%0", &addreg0);
2334       if (addreg1)
2335 	output_asm_insn ("addq%.l %#4,%0", &addreg1);
2336 
2337       output_asm_insn (singlemove_string (middlehalf), middlehalf);
2338     }
2339 
2340   /* Make any unoffsettable addresses point at high-numbered word.  */
2341   if (addreg0)
2342     output_asm_insn ("addq%.l %#4,%0", &addreg0);
2343   if (addreg1)
2344     output_asm_insn ("addq%.l %#4,%0", &addreg1);
2345 
2346   /* Do that word.  */
2347   output_asm_insn (singlemove_string (latehalf), latehalf);
2348 
2349   /* Undo the adds we just did.  */
2350   if (addreg0)
2351     {
2352       if (size == 12)
2353         output_asm_insn ("subq%.l %#8,%0", &addreg0);
2354       else
2355         output_asm_insn ("subq%.l %#4,%0", &addreg0);
2356     }
2357   if (addreg1)
2358     {
2359       if (size == 12)
2360         output_asm_insn ("subq%.l %#8,%0", &addreg1);
2361       else
2362         output_asm_insn ("subq%.l %#4,%0", &addreg1);
2363     }
2364 
2365   return "";
2366 }
2367 
2368 /* Return a REG that occurs in ADDR with coefficient 1.
2369    ADDR can be effectively incremented by incrementing REG.  */
2370 
2371 static rtx
find_addr_reg(addr)2372 find_addr_reg (addr)
2373      rtx addr;
2374 {
2375   while (GET_CODE (addr) == PLUS)
2376     {
2377       if (GET_CODE (XEXP (addr, 0)) == REG)
2378 	addr = XEXP (addr, 0);
2379       else if (GET_CODE (XEXP (addr, 1)) == REG)
2380 	addr = XEXP (addr, 1);
2381       else if (CONSTANT_P (XEXP (addr, 0)))
2382 	addr = XEXP (addr, 1);
2383       else if (CONSTANT_P (XEXP (addr, 1)))
2384 	addr = XEXP (addr, 0);
2385       else
2386 	abort ();
2387     }
2388   if (GET_CODE (addr) == REG)
2389     return addr;
2390   abort ();
2391 }
2392 
2393 /* Output assembler code to perform a 32 bit 3 operand add.  */
2394 
2395 const char *
output_addsi3(operands)2396 output_addsi3 (operands)
2397      rtx *operands;
2398 {
2399   if (! operands_match_p (operands[0], operands[1]))
2400     {
2401       if (!ADDRESS_REG_P (operands[1]))
2402 	{
2403 	  rtx tmp = operands[1];
2404 
2405 	  operands[1] = operands[2];
2406 	  operands[2] = tmp;
2407 	}
2408 
2409       /* These insns can result from reloads to access
2410 	 stack slots over 64k from the frame pointer.  */
2411       if (GET_CODE (operands[2]) == CONST_INT
2412 	  && INTVAL (operands[2]) + 0x8000 >= (unsigned) 0x10000)
2413         return "move%.l %2,%0\n\tadd%.l %1,%0";
2414 #ifdef SGS
2415       if (GET_CODE (operands[2]) == REG)
2416 	return "lea 0(%1,%2.l),%0";
2417       else
2418 	return "lea %c2(%1),%0";
2419 #else /* not SGS */
2420 #ifdef MOTOROLA
2421       if (GET_CODE (operands[2]) == REG)
2422 	return "lea (%1,%2.l),%0";
2423       else
2424 	return "lea (%c2,%1),%0";
2425 #else /* not MOTOROLA (MIT syntax) */
2426       if (GET_CODE (operands[2]) == REG)
2427 	return "lea %1@(0,%2:l),%0";
2428       else
2429 	return "lea %1@(%c2),%0";
2430 #endif /* not MOTOROLA */
2431 #endif /* not SGS */
2432     }
2433   if (GET_CODE (operands[2]) == CONST_INT)
2434     {
2435 #ifndef NO_ADDSUB_Q
2436       if (INTVAL (operands[2]) > 0
2437 	  && INTVAL (operands[2]) <= 8)
2438 	return "addq%.l %2,%0";
2439       if (INTVAL (operands[2]) < 0
2440 	  && INTVAL (operands[2]) >= -8)
2441         {
2442 	  operands[2] = GEN_INT (- INTVAL (operands[2]));
2443 	  return "subq%.l %2,%0";
2444 	}
2445       /* On the CPU32 it is faster to use two addql instructions to
2446 	 add a small integer (8 < N <= 16) to a register.
2447 	 Likewise for subql.  */
2448       if (TARGET_CPU32 && REG_P (operands[0]))
2449 	{
2450 	  if (INTVAL (operands[2]) > 8
2451 	      && INTVAL (operands[2]) <= 16)
2452 	    {
2453 	      operands[2] = GEN_INT (INTVAL (operands[2]) - 8);
2454 	      return "addq%.l %#8,%0\n\taddq%.l %2,%0";
2455 	    }
2456 	  if (INTVAL (operands[2]) < -8
2457 	      && INTVAL (operands[2]) >= -16)
2458 	    {
2459 	      operands[2] = GEN_INT (- INTVAL (operands[2]) - 8);
2460 	      return "subq%.l %#8,%0\n\tsubq%.l %2,%0";
2461 	    }
2462 	}
2463 #endif
2464       if (ADDRESS_REG_P (operands[0])
2465 	  && INTVAL (operands[2]) >= -0x8000
2466 	  && INTVAL (operands[2]) < 0x8000)
2467 	{
2468 	  if (TARGET_68040)
2469 	    return "add%.w %2,%0";
2470 	  else
2471 #ifdef MOTOROLA
2472 	    return "lea (%c2,%0),%0";
2473 #else
2474 	    return "lea %0@(%c2),%0";
2475 #endif
2476 	}
2477     }
2478   return "add%.l %2,%0";
2479 }
2480 
2481 /* Store in cc_status the expressions that the condition codes will
2482    describe after execution of an instruction whose pattern is EXP.
2483    Do not alter them if the instruction would not alter the cc's.  */
2484 
2485 /* On the 68000, all the insns to store in an address register fail to
2486    set the cc's.  However, in some cases these instructions can make it
2487    possibly invalid to use the saved cc's.  In those cases we clear out
2488    some or all of the saved cc's so they won't be used.  */
2489 
2490 void
notice_update_cc(exp,insn)2491 notice_update_cc (exp, insn)
2492      rtx exp;
2493      rtx insn;
2494 {
2495   /* If the cc is being set from the fpa and the expression is not an
2496      explicit floating point test instruction (which has code to deal with
2497      this), reinit the CC.  */
2498   if (((cc_status.value1 && FPA_REG_P (cc_status.value1))
2499        || (cc_status.value2 && FPA_REG_P (cc_status.value2)))
2500       && !(GET_CODE (exp) == PARALLEL
2501 	   && GET_CODE (XVECEXP (exp, 0, 0)) == SET
2502 	   && XEXP (XVECEXP (exp, 0, 0), 0) == cc0_rtx))
2503     {
2504       CC_STATUS_INIT;
2505     }
2506   else if (GET_CODE (exp) == SET)
2507     {
2508       if (GET_CODE (SET_SRC (exp)) == CALL)
2509 	{
2510 	  CC_STATUS_INIT;
2511 	}
2512       else if (ADDRESS_REG_P (SET_DEST (exp)))
2513 	{
2514 	  if (cc_status.value1 && modified_in_p (cc_status.value1, insn))
2515 	    cc_status.value1 = 0;
2516 	  if (cc_status.value2 && modified_in_p (cc_status.value2, insn))
2517 	    cc_status.value2 = 0;
2518 	}
2519       else if (!FP_REG_P (SET_DEST (exp))
2520 	       && SET_DEST (exp) != cc0_rtx
2521 	       && (FP_REG_P (SET_SRC (exp))
2522 		   || GET_CODE (SET_SRC (exp)) == FIX
2523 		   || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE
2524 		   || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND))
2525 	{
2526 	  CC_STATUS_INIT;
2527 	}
2528       /* A pair of move insns doesn't produce a useful overall cc.  */
2529       else if (!FP_REG_P (SET_DEST (exp))
2530 	       && !FP_REG_P (SET_SRC (exp))
2531 	       && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
2532 	       && (GET_CODE (SET_SRC (exp)) == REG
2533 		   || GET_CODE (SET_SRC (exp)) == MEM
2534 		   || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
2535 	{
2536 	  CC_STATUS_INIT;
2537 	}
2538       else if (GET_CODE (SET_SRC (exp)) == CALL)
2539 	{
2540 	  CC_STATUS_INIT;
2541 	}
2542       else if (XEXP (exp, 0) != pc_rtx)
2543 	{
2544 	  cc_status.flags = 0;
2545 	  cc_status.value1 = XEXP (exp, 0);
2546 	  cc_status.value2 = XEXP (exp, 1);
2547 	}
2548     }
2549   else if (GET_CODE (exp) == PARALLEL
2550 	   && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
2551     {
2552       if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0)))
2553 	CC_STATUS_INIT;
2554       else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx)
2555 	{
2556 	  cc_status.flags = 0;
2557 	  cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
2558 	  cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
2559 	}
2560     }
2561   else
2562     CC_STATUS_INIT;
2563   if (cc_status.value2 != 0
2564       && ADDRESS_REG_P (cc_status.value2)
2565       && GET_MODE (cc_status.value2) == QImode)
2566     CC_STATUS_INIT;
2567   if (cc_status.value2 != 0
2568       && !(cc_status.value1 && FPA_REG_P (cc_status.value1)))
2569     switch (GET_CODE (cc_status.value2))
2570       {
2571       case PLUS: case MINUS: case MULT:
2572       case DIV: case UDIV: case MOD: case UMOD: case NEG:
2573 #if 0 /* These instructions always clear the overflow bit */
2574       case ASHIFT: case ASHIFTRT: case LSHIFTRT:
2575       case ROTATE: case ROTATERT:
2576 #endif
2577 	if (GET_MODE (cc_status.value2) != VOIDmode)
2578 	  cc_status.flags |= CC_NO_OVERFLOW;
2579 	break;
2580       case ZERO_EXTEND:
2581 	/* (SET r1 (ZERO_EXTEND r2)) on this machine
2582 	   ends with a move insn moving r2 in r2's mode.
2583 	   Thus, the cc's are set for r2.
2584 	   This can set N bit spuriously.  */
2585 	cc_status.flags |= CC_NOT_NEGATIVE;
2586 
2587       default:
2588 	break;
2589       }
2590   if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
2591       && cc_status.value2
2592       && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
2593     cc_status.value2 = 0;
2594   if (((cc_status.value1 && FP_REG_P (cc_status.value1))
2595        || (cc_status.value2 && FP_REG_P (cc_status.value2)))
2596       && !((cc_status.value1 && FPA_REG_P (cc_status.value1))
2597 	   || (cc_status.value2 && FPA_REG_P (cc_status.value2))))
2598     cc_status.flags = CC_IN_68881;
2599 }
2600 
2601 const char *
output_move_const_double(operands)2602 output_move_const_double (operands)
2603      rtx *operands;
2604 {
2605 #ifdef SUPPORT_SUN_FPA
2606   if (TARGET_FPA && FPA_REG_P (operands[0]))
2607     {
2608       int code = standard_sun_fpa_constant_p (operands[1]);
2609 
2610       if (code != 0)
2611 	{
2612 	  static char buf[40];
2613 
2614 	  sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff);
2615 	  return buf;
2616 	}
2617       return "fpmove%.d %1,%0";
2618     }
2619   else
2620 #endif
2621     {
2622       int code = standard_68881_constant_p (operands[1]);
2623 
2624       if (code != 0)
2625 	{
2626 	  static char buf[40];
2627 
2628 	  sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
2629 	  return buf;
2630 	}
2631       return "fmove%.d %1,%0";
2632     }
2633 }
2634 
2635 const char *
output_move_const_single(operands)2636 output_move_const_single (operands)
2637      rtx *operands;
2638 {
2639 #ifdef SUPPORT_SUN_FPA
2640   if (TARGET_FPA)
2641     {
2642       int code = standard_sun_fpa_constant_p (operands[1]);
2643 
2644       if (code != 0)
2645 	{
2646 	  static char buf[40];
2647 
2648 	  sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff);
2649 	  return buf;
2650 	}
2651       return "fpmove%.s %1,%0";
2652     }
2653   else
2654 #endif /* defined SUPPORT_SUN_FPA */
2655     {
2656       int code = standard_68881_constant_p (operands[1]);
2657 
2658       if (code != 0)
2659 	{
2660 	  static char buf[40];
2661 
2662 	  sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
2663 	  return buf;
2664 	}
2665       return "fmove%.s %f1,%0";
2666     }
2667 }
2668 
2669 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
2670    from the "fmovecr" instruction.
2671    The value, anded with 0xff, gives the code to use in fmovecr
2672    to get the desired constant.  */
2673 
2674 /* This code has been fixed for cross-compilation.  */
2675 
2676 static int inited_68881_table = 0;
2677 
2678 static const char *const strings_68881[7] = {
2679   "0.0",
2680   "1.0",
2681   "10.0",
2682   "100.0",
2683   "10000.0",
2684   "1e8",
2685   "1e16"
2686   };
2687 
2688 static const int codes_68881[7] = {
2689   0x0f,
2690   0x32,
2691   0x33,
2692   0x34,
2693   0x35,
2694   0x36,
2695   0x37
2696   };
2697 
2698 REAL_VALUE_TYPE values_68881[7];
2699 
2700 /* Set up values_68881 array by converting the decimal values
2701    strings_68881 to binary.  */
2702 
2703 void
init_68881_table()2704 init_68881_table ()
2705 {
2706   int i;
2707   REAL_VALUE_TYPE r;
2708   enum machine_mode mode;
2709 
2710   mode = SFmode;
2711   for (i = 0; i < 7; i++)
2712     {
2713       if (i == 6)
2714         mode = DFmode;
2715       r = REAL_VALUE_ATOF (strings_68881[i], mode);
2716       values_68881[i] = r;
2717     }
2718   inited_68881_table = 1;
2719 }
2720 
2721 int
standard_68881_constant_p(x)2722 standard_68881_constant_p (x)
2723      rtx x;
2724 {
2725   REAL_VALUE_TYPE r;
2726   int i;
2727 
2728 #ifdef NO_ASM_FMOVECR
2729   return 0;
2730 #endif
2731 
2732   /* fmovecr must be emulated on the 68040 and 68060, so it shouldn't be
2733      used at all on those chips.  */
2734   if (TARGET_68040 || TARGET_68060)
2735     return 0;
2736 
2737   if (! inited_68881_table)
2738     init_68881_table ();
2739 
2740   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2741 
2742   /* Use REAL_VALUES_IDENTICAL instead of REAL_VALUES_EQUAL so that -0.0
2743      is rejected.  */
2744   for (i = 0; i < 6; i++)
2745     {
2746       if (REAL_VALUES_IDENTICAL (r, values_68881[i]))
2747         return (codes_68881[i]);
2748     }
2749 
2750   if (GET_MODE (x) == SFmode)
2751     return 0;
2752 
2753   if (REAL_VALUES_EQUAL (r, values_68881[6]))
2754     return (codes_68881[6]);
2755 
2756   /* larger powers of ten in the constants ram are not used
2757      because they are not equal to a `double' C constant.  */
2758   return 0;
2759 }
2760 
2761 /* If X is a floating-point constant, return the logarithm of X base 2,
2762    or 0 if X is not a power of 2.  */
2763 
2764 int
floating_exact_log2(x)2765 floating_exact_log2 (x)
2766      rtx x;
2767 {
2768   REAL_VALUE_TYPE r, r1;
2769   int exp;
2770 
2771   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2772 
2773   if (REAL_VALUES_LESS (r, dconst1))
2774     return 0;
2775 
2776   exp = real_exponent (&r);
2777   real_2expN (&r1, exp);
2778   if (REAL_VALUES_EQUAL (r1, r))
2779     return exp;
2780 
2781   return 0;
2782 }
2783 
2784 #ifdef SUPPORT_SUN_FPA
2785 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
2786    from the Sun FPA's constant RAM.
2787    The value returned, anded with 0x1ff, gives the code to use in fpmove
2788    to get the desired constant.  */
2789 
2790 static int inited_FPA_table = 0;
2791 
2792 static const char *const strings_FPA[38] = {
2793 /* small rationals */
2794   "0.0",
2795   "1.0",
2796   "0.5",
2797   "-1.0",
2798   "2.0",
2799   "3.0",
2800   "4.0",
2801   "8.0",
2802   "0.25",
2803   "0.125",
2804   "10.0",
2805   "-0.5",
2806 /* Decimal equivalents of double precision values */
2807   "2.718281828459045091", /* D_E */
2808   "6.283185307179586477", /* 2 pi */
2809   "3.141592653589793116", /* D_PI */
2810   "1.570796326794896619", /* pi/2 */
2811   "1.414213562373095145", /* D_SQRT2 */
2812   "0.7071067811865475244", /* 1/sqrt(2) */
2813   "-1.570796326794896619", /* -pi/2 */
2814   "1.442695040888963387", /* D_LOG2ofE */
2815   "3.321928024887362182", /* D_LOG2of10 */
2816   "0.6931471805599452862", /* D_LOGEof2 */
2817   "2.302585092994045901", /* D_LOGEof10 */
2818   "0.3010299956639811980", /* D_LOG10of2 */
2819   "0.4342944819032518167", /* D_LOG10ofE */
2820 /* Decimal equivalents of single precision values */
2821   "2.718281745910644531", /* S_E */
2822   "6.283185307179586477", /* 2 pi */
2823   "3.141592741012573242", /* S_PI */
2824   "1.570796326794896619", /* pi/2 */
2825   "1.414213538169860840", /* S_SQRT2 */
2826   "0.7071067811865475244", /* 1/sqrt(2) */
2827   "-1.570796326794896619", /* -pi/2 */
2828   "1.442695021629333496", /* S_LOG2ofE */
2829   "3.321928024291992188", /* S_LOG2of10 */
2830   "0.6931471824645996094", /* S_LOGEof2 */
2831   "2.302585124969482442", /* S_LOGEof10 */
2832   "0.3010300099849700928", /* S_LOG10of2 */
2833   "0.4342944920063018799", /* S_LOG10ofE */
2834 };
2835 
2836 
2837 static const int codes_FPA[38] = {
2838 /* small rationals */
2839   0x200,
2840   0xe,
2841   0xf,
2842   0x10,
2843   0x11,
2844   0xb1,
2845   0x12,
2846   0x13,
2847   0x15,
2848   0x16,
2849   0x17,
2850   0x2e,
2851 /* double precision */
2852   0x8,
2853   0x9,
2854   0xa,
2855   0xb,
2856   0xc,
2857   0xd,
2858   0x27,
2859   0x28,
2860   0x29,
2861   0x2a,
2862   0x2b,
2863   0x2c,
2864   0x2d,
2865 /* single precision */
2866   0x8,
2867   0x9,
2868   0xa,
2869   0xb,
2870   0xc,
2871   0xd,
2872   0x27,
2873   0x28,
2874   0x29,
2875   0x2a,
2876   0x2b,
2877   0x2c,
2878   0x2d
2879   };
2880 
2881 REAL_VALUE_TYPE values_FPA[38];
2882 
2883 /* This code has been fixed for cross-compilation.  */
2884 
2885 static void init_FPA_table PARAMS ((void));
2886 static void
init_FPA_table()2887 init_FPA_table ()
2888 {
2889   enum machine_mode mode;
2890   int i;
2891   REAL_VALUE_TYPE r;
2892 
2893   mode = DFmode;
2894   for (i = 0; i < 38; i++)
2895     {
2896       if (i == 25)
2897         mode = SFmode;
2898       r = REAL_VALUE_ATOF (strings_FPA[i], mode);
2899       values_FPA[i] = r;
2900     }
2901   inited_FPA_table = 1;
2902 }
2903 
2904 
2905 int
standard_sun_fpa_constant_p(x)2906 standard_sun_fpa_constant_p (x)
2907      rtx x;
2908 {
2909   REAL_VALUE_TYPE r;
2910   int i;
2911 
2912   if (! inited_FPA_table)
2913     init_FPA_table ();
2914 
2915   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2916 
2917   for (i=0; i<12; i++)
2918     {
2919       if (REAL_VALUES_EQUAL (r, values_FPA[i]))
2920         return (codes_FPA[i]);
2921     }
2922 
2923   if (GET_MODE (x) == SFmode)
2924     {
2925       for (i=25; i<38; i++)
2926         {
2927           if (REAL_VALUES_EQUAL (r, values_FPA[i]))
2928             return (codes_FPA[i]);
2929         }
2930     }
2931   else
2932     {
2933       for (i=12; i<25; i++)
2934         {
2935           if (REAL_VALUES_EQUAL (r, values_FPA[i]))
2936             return (codes_FPA[i]);
2937         }
2938     }
2939   return 0x0;
2940 }
2941 #endif /* define SUPPORT_SUN_FPA */
2942 
2943 /* A C compound statement to output to stdio stream STREAM the
2944    assembler syntax for an instruction operand X.  X is an RTL
2945    expression.
2946 
2947    CODE is a value that can be used to specify one of several ways
2948    of printing the operand.  It is used when identical operands
2949    must be printed differently depending on the context.  CODE
2950    comes from the `%' specification that was used to request
2951    printing of the operand.  If the specification was just `%DIGIT'
2952    then CODE is 0; if the specification was `%LTR DIGIT' then CODE
2953    is the ASCII code for LTR.
2954 
2955    If X is a register, this macro should print the register's name.
2956    The names can be found in an array `reg_names' whose type is
2957    `char *[]'.  `reg_names' is initialized from `REGISTER_NAMES'.
2958 
2959    When the machine description has a specification `%PUNCT' (a `%'
2960    followed by a punctuation character), this macro is called with
2961    a null pointer for X and the punctuation character for CODE.
2962 
2963    The m68k specific codes are:
2964 
2965    '.' for dot needed in Motorola-style opcode names.
2966    '-' for an operand pushing on the stack:
2967        sp@-, -(sp) or -(%sp) depending on the style of syntax.
2968    '+' for an operand pushing on the stack:
2969        sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
2970    '@' for a reference to the top word on the stack:
2971        sp@, (sp) or (%sp) depending on the style of syntax.
2972    '#' for an immediate operand prefix (# in MIT and Motorola syntax
2973        but & in SGS syntax, $ in CRDS/UNOS syntax).
2974    '!' for the cc register (used in an `and to cc' insn).
2975    '$' for the letter `s' in an op code, but only on the 68040.
2976    '&' for the letter `d' in an op code, but only on the 68040.
2977    '/' for register prefix needed by longlong.h.
2978 
2979    'b' for byte insn (no effect, on the Sun; this is for the ISI).
2980    'd' to force memory addressing to be absolute, not relative.
2981    'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
2982    'o' for operands to go directly to output_operand_address (bypassing
2983        print_operand_address--used only for SYMBOL_REFs under TARGET_PCREL)
2984    'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
2985        than directly).  Second part of 'y' below.
2986    'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
2987        or print pair of registers as rx:ry.
2988    'y' for a FPA insn (print pair of registers as rx:ry).  This also outputs
2989        CONST_DOUBLE's as SunFPA constant RAM registers if
2990        possible, so it should not be used except for the SunFPA.
2991 
2992    */
2993 
2994 void
print_operand(file,op,letter)2995 print_operand (file, op, letter)
2996      FILE *file;		/* file to write to */
2997      rtx op;			/* operand to print */
2998      int letter;		/* %<letter> or 0 */
2999 {
3000 #ifdef SUPPORT_SUN_FPA
3001   int i;
3002 #endif
3003 
3004   if (letter == '.')
3005     {
3006 #if defined (MOTOROLA) && !defined (CRDS)
3007       fprintf (file, ".");
3008 #endif
3009     }
3010   else if (letter == '#')
3011     {
3012       asm_fprintf (file, "%0I");
3013     }
3014   else if (letter == '-')
3015     {
3016 #ifdef MOTOROLA
3017       asm_fprintf (file, "-(%Rsp)");
3018 #else
3019       asm_fprintf (file, "%Rsp@-");
3020 #endif
3021     }
3022   else if (letter == '+')
3023     {
3024 #ifdef MOTOROLA
3025       asm_fprintf (file, "(%Rsp)+");
3026 #else
3027       asm_fprintf (file, "%Rsp@+");
3028 #endif
3029     }
3030   else if (letter == '@')
3031     {
3032 #ifdef MOTOROLA
3033       asm_fprintf (file, "(%Rsp)");
3034 #else
3035       asm_fprintf (file, "%Rsp@");
3036 #endif
3037     }
3038   else if (letter == '!')
3039     {
3040       asm_fprintf (file, "%Rfpcr");
3041     }
3042   else if (letter == '$')
3043     {
3044       if (TARGET_68040_ONLY)
3045 	{
3046 	  fprintf (file, "s");
3047 	}
3048     }
3049   else if (letter == '&')
3050     {
3051       if (TARGET_68040_ONLY)
3052 	{
3053 	  fprintf (file, "d");
3054 	}
3055     }
3056   else if (letter == '/')
3057     {
3058       asm_fprintf (file, "%R");
3059     }
3060   else if (letter == 'o')
3061     {
3062       /* This is only for direct addresses with TARGET_PCREL */
3063       if (GET_CODE (op) != MEM || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
3064           || !TARGET_PCREL)
3065 	abort ();
3066       output_addr_const (file, XEXP (op, 0));
3067     }
3068   else if (GET_CODE (op) == REG)
3069     {
3070 #ifdef SUPPORT_SUN_FPA
3071       if (REGNO (op) < 16
3072 	  && (letter == 'y' || letter == 'x')
3073 	  && GET_MODE (op) == DFmode)
3074 	{
3075 	  fprintf (file, "%s:%s", reg_names[REGNO (op)],
3076 		   reg_names[REGNO (op)+1]);
3077 	}
3078       else
3079 #endif
3080 	{
3081 	  if (letter == 'R')
3082 	    /* Print out the second register name of a register pair.
3083 	       I.e., R (6) => 7.  */
3084 	    fputs (reg_names[REGNO (op) + 1], file);
3085 	  else
3086 	    fputs (reg_names[REGNO (op)], file);
3087 	}
3088     }
3089   else if (GET_CODE (op) == MEM)
3090     {
3091       output_address (XEXP (op, 0));
3092       if (letter == 'd' && ! TARGET_68020
3093 	  && CONSTANT_ADDRESS_P (XEXP (op, 0))
3094 	  && !(GET_CODE (XEXP (op, 0)) == CONST_INT
3095 	       && INTVAL (XEXP (op, 0)) < 0x8000
3096 	       && INTVAL (XEXP (op, 0)) >= -0x8000))
3097 	{
3098 #ifdef MOTOROLA
3099 	  fprintf (file, ".l");
3100 #else
3101 	  fprintf (file, ":l");
3102 #endif
3103 	}
3104     }
3105 #ifdef SUPPORT_SUN_FPA
3106   else if ((letter == 'y' || letter == 'w')
3107 	   && GET_CODE (op) == CONST_DOUBLE
3108 	   && (i = standard_sun_fpa_constant_p (op)))
3109     {
3110       fprintf (file, "%%%d", i & 0x1ff);
3111     }
3112 #endif
3113   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
3114     {
3115       REAL_VALUE_TYPE r;
3116       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
3117       ASM_OUTPUT_FLOAT_OPERAND (letter, file, r);
3118     }
3119   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode)
3120     {
3121       REAL_VALUE_TYPE r;
3122       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
3123       ASM_OUTPUT_LONG_DOUBLE_OPERAND (file, r);
3124     }
3125   else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
3126     {
3127       REAL_VALUE_TYPE r;
3128       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
3129       ASM_OUTPUT_DOUBLE_OPERAND (file, r);
3130     }
3131   else
3132     {
3133       /* Use `print_operand_address' instead of `output_addr_const'
3134 	 to ensure that we print relevant PIC stuff.  */
3135       asm_fprintf (file, "%0I");
3136       if (TARGET_PCREL
3137 	  && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST))
3138 	print_operand_address (file, op);
3139       else
3140 	output_addr_const (file, op);
3141     }
3142 }
3143 
3144 
3145 /* A C compound statement to output to stdio stream STREAM the
3146    assembler syntax for an instruction operand that is a memory
3147    reference whose address is ADDR.  ADDR is an RTL expression.
3148 
3149    Note that this contains a kludge that knows that the only reason
3150    we have an address (plus (label_ref...) (reg...)) when not generating
3151    PIC code is in the insn before a tablejump, and we know that m68k.md
3152    generates a label LInnn: on such an insn.
3153 
3154    It is possible for PIC to generate a (plus (label_ref...) (reg...))
3155    and we handle that just like we would a (plus (symbol_ref...) (reg...)).
3156 
3157    Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
3158    fails to assemble.  Luckily "Lnnn(pc,d0.l*2)" produces the results
3159    we want.  This difference can be accommodated by using an assembler
3160    define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
3161    string, as necessary.  This is accomplished via the ASM_OUTPUT_CASE_END
3162    macro.  See m68k/sgs.h for an example; for versions without the bug.
3163    Some assemblers refuse all the above solutions.  The workaround is to
3164    emit "K(pc,d0.l*2)" with K being a small constant known to give the
3165    right behavior.
3166 
3167    They also do not like things like "pea 1.w", so we simple leave off
3168    the .w on small constants.
3169 
3170    This routine is responsible for distinguishing between -fpic and -fPIC
3171    style relocations in an address.  When generating -fpic code the
3172    offset is output in word mode (eg movel a5@(_foo:w), a0).  When generating
3173    -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
3174 
3175 #ifndef ASM_OUTPUT_CASE_FETCH
3176 #ifdef MOTOROLA
3177 #ifdef SGS
3178 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
3179 	asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
3180 #else
3181 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
3182 	asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
3183 #endif
3184 #else
3185 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
3186 	asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
3187 #endif
3188 #endif /* ASM_OUTPUT_CASE_FETCH */
3189 
3190 void
print_operand_address(file,addr)3191 print_operand_address (file, addr)
3192      FILE *file;
3193      rtx addr;
3194 {
3195   register rtx reg1, reg2, breg, ireg;
3196   rtx offset;
3197 
3198   switch (GET_CODE (addr))
3199     {
3200       case REG:
3201 #ifdef MOTOROLA
3202 	fprintf (file, "(%s)", reg_names[REGNO (addr)]);
3203 #else
3204 	fprintf (file, "%s@", reg_names[REGNO (addr)]);
3205 #endif
3206 	break;
3207       case PRE_DEC:
3208 #ifdef MOTOROLA
3209 	fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
3210 #else
3211 	fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);
3212 #endif
3213 	break;
3214       case POST_INC:
3215 #ifdef MOTOROLA
3216 	fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
3217 #else
3218 	fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);
3219 #endif
3220 	break;
3221       case PLUS:
3222 	reg1 = reg2 = ireg = breg = offset = 0;
3223 	if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
3224 	  {
3225 	    offset = XEXP (addr, 0);
3226 	    addr = XEXP (addr, 1);
3227 	  }
3228 	else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
3229 	  {
3230 	    offset = XEXP (addr, 1);
3231 	    addr = XEXP (addr, 0);
3232 	  }
3233 	if (GET_CODE (addr) != PLUS)
3234 	  {
3235 	    ;
3236 	  }
3237 	else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
3238 	  {
3239 	    reg1 = XEXP (addr, 0);
3240 	    addr = XEXP (addr, 1);
3241 	  }
3242 	else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
3243 	  {
3244 	    reg1 = XEXP (addr, 1);
3245 	    addr = XEXP (addr, 0);
3246 	  }
3247 	else if (GET_CODE (XEXP (addr, 0)) == MULT)
3248 	  {
3249 	    reg1 = XEXP (addr, 0);
3250 	    addr = XEXP (addr, 1);
3251 	  }
3252 	else if (GET_CODE (XEXP (addr, 1)) == MULT)
3253 	  {
3254 	    reg1 = XEXP (addr, 1);
3255 	    addr = XEXP (addr, 0);
3256 	  }
3257 	else if (GET_CODE (XEXP (addr, 0)) == REG)
3258 	  {
3259 	    reg1 = XEXP (addr, 0);
3260 	    addr = XEXP (addr, 1);
3261 	  }
3262 	else if (GET_CODE (XEXP (addr, 1)) == REG)
3263 	  {
3264 	    reg1 = XEXP (addr, 1);
3265 	    addr = XEXP (addr, 0);
3266 	  }
3267 	if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
3268 	    || GET_CODE (addr) == SIGN_EXTEND)
3269 	  {
3270 	    if (reg1 == 0)
3271 	      {
3272 		reg1 = addr;
3273 	      }
3274 	    else
3275 	      {
3276 		reg2 = addr;
3277 	      }
3278 	    addr = 0;
3279 	  }
3280 #if 0	/* for OLD_INDEXING */
3281 	else if (GET_CODE (addr) == PLUS)
3282 	  {
3283 	    if (GET_CODE (XEXP (addr, 0)) == REG)
3284 	      {
3285 		reg2 = XEXP (addr, 0);
3286 		addr = XEXP (addr, 1);
3287 	      }
3288 	    else if (GET_CODE (XEXP (addr, 1)) == REG)
3289 	      {
3290 		reg2 = XEXP (addr, 1);
3291 		addr = XEXP (addr, 0);
3292 	      }
3293 	  }
3294 #endif
3295 	if (offset != 0)
3296 	  {
3297 	    if (addr != 0)
3298 	      {
3299 		abort ();
3300 	      }
3301 	    addr = offset;
3302 	  }
3303 	if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
3304 		      || GET_CODE (reg1) == MULT))
3305 	    || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
3306 	  {
3307 	    breg = reg2;
3308 	    ireg = reg1;
3309 	  }
3310 	else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
3311 	  {
3312 	    breg = reg1;
3313 	    ireg = reg2;
3314 	  }
3315 	if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
3316 	    && ! (flag_pic && ireg == pic_offset_table_rtx))
3317 	  {
3318 	    int scale = 1;
3319 	    if (GET_CODE (ireg) == MULT)
3320 	      {
3321 		scale = INTVAL (XEXP (ireg, 1));
3322 		ireg = XEXP (ireg, 0);
3323 	      }
3324 	    if (GET_CODE (ireg) == SIGN_EXTEND)
3325 	      {
3326 		ASM_OUTPUT_CASE_FETCH (file,
3327 			     CODE_LABEL_NUMBER (XEXP (addr, 0)),
3328 			     reg_names[REGNO (XEXP (ireg, 0))]);
3329 		fprintf (file, "w");
3330 	      }
3331 	    else
3332 	      {
3333 		ASM_OUTPUT_CASE_FETCH (file,
3334 			     CODE_LABEL_NUMBER (XEXP (addr, 0)),
3335 			     reg_names[REGNO (ireg)]);
3336 		fprintf (file, "l");
3337 	      }
3338 	    if (scale != 1)
3339 	      {
3340 #ifdef MOTOROLA
3341 		fprintf (file, "*%d", scale);
3342 #else
3343 		fprintf (file, ":%d", scale);
3344 #endif
3345 	      }
3346 	    putc (')', file);
3347 	    break;
3348 	  }
3349 	if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
3350 	    && ! (flag_pic && breg == pic_offset_table_rtx))
3351 	  {
3352 	    ASM_OUTPUT_CASE_FETCH (file,
3353 			 CODE_LABEL_NUMBER (XEXP (addr, 0)),
3354 			 reg_names[REGNO (breg)]);
3355 	    fprintf (file, "l)");
3356 	    break;
3357 	  }
3358 	if (ireg != 0 || breg != 0)
3359 	  {
3360 	    int scale = 1;
3361 	    if (breg == 0)
3362 	      {
3363 		abort ();
3364 	      }
3365 	    if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
3366 	      {
3367 		abort ();
3368 	      }
3369 #ifdef MOTOROLA
3370 	    if (addr != 0)
3371 	      {
3372 		output_addr_const (file, addr);
3373 	        if (flag_pic && (breg == pic_offset_table_rtx))
3374 		  {
3375 		    fprintf (file, "@GOT");
3376 		    if (flag_pic == 1)
3377 		      fprintf (file, ".w");
3378 		  }
3379 	      }
3380 	    fprintf (file, "(%s", reg_names[REGNO (breg)]);
3381 	    if (ireg != 0)
3382 	      {
3383 		putc (',', file);
3384 	      }
3385 #else
3386 	    fprintf (file, "%s@(", reg_names[REGNO (breg)]);
3387 	    if (addr != 0)
3388 	      {
3389 		output_addr_const (file, addr);
3390 	        if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
3391 	          fprintf (file, ":w");
3392 	        if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
3393 	          fprintf (file, ":l");
3394 	      }
3395 	    if (addr != 0 && ireg != 0)
3396 	      {
3397 		putc (',', file);
3398 	      }
3399 #endif
3400 	    if (ireg != 0 && GET_CODE (ireg) == MULT)
3401 	      {
3402 		scale = INTVAL (XEXP (ireg, 1));
3403 		ireg = XEXP (ireg, 0);
3404 	      }
3405 	    if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
3406 	      {
3407 #ifdef MOTOROLA
3408 		fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);
3409 #else
3410 		fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);
3411 #endif
3412 	      }
3413 	    else if (ireg != 0)
3414 	      {
3415 #ifdef MOTOROLA
3416 		fprintf (file, "%s.l", reg_names[REGNO (ireg)]);
3417 #else
3418 		fprintf (file, "%s:l", reg_names[REGNO (ireg)]);
3419 #endif
3420 	      }
3421 	    if (scale != 1)
3422 	      {
3423 #ifdef MOTOROLA
3424 		fprintf (file, "*%d", scale);
3425 #else
3426 		fprintf (file, ":%d", scale);
3427 #endif
3428 	      }
3429 	    putc (')', file);
3430 	    break;
3431 	  }
3432 	else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
3433 		 && ! (flag_pic && reg1 == pic_offset_table_rtx))
3434 	  {
3435 	    ASM_OUTPUT_CASE_FETCH (file,
3436 			 CODE_LABEL_NUMBER (XEXP (addr, 0)),
3437 			 reg_names[REGNO (reg1)]);
3438 	    fprintf (file, "l)");
3439 	    break;
3440 	  }
3441 	/* FALL-THROUGH (is this really what we want?)  */
3442       default:
3443         if (GET_CODE (addr) == CONST_INT
3444 	    && INTVAL (addr) < 0x8000
3445 	    && INTVAL (addr) >= -0x8000)
3446 	  {
3447 #ifdef MOTOROLA
3448 #ifdef SGS
3449 	    /* Many SGS assemblers croak on size specifiers for constants.  */
3450 	    fprintf (file, "%d", (int) INTVAL (addr));
3451 #else
3452 	    fprintf (file, "%d.w", (int) INTVAL (addr));
3453 #endif
3454 #else
3455 	    fprintf (file, "%d:w", (int) INTVAL (addr));
3456 #endif
3457 	  }
3458 	else if (GET_CODE (addr) == CONST_INT)
3459 	  {
3460 	    fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr));
3461 	  }
3462 	else if (TARGET_PCREL)
3463 	  {
3464 	    fputc ('(', file);
3465 	    output_addr_const (file, addr);
3466 	    if (flag_pic == 1)
3467 	      asm_fprintf (file, ":w,%Rpc)");
3468 	    else
3469 	      asm_fprintf (file, ":l,%Rpc)");
3470 	  }
3471 	else
3472 	  {
3473 	    /* Special case for SYMBOL_REF if the symbol name ends in
3474 	       `.<letter>', this can be mistaken as a size suffix.  Put
3475 	       the name in parentheses.  */
3476 	    if (GET_CODE (addr) == SYMBOL_REF
3477 		&& strlen (XSTR (addr, 0)) > 2
3478 		&& XSTR (addr, 0)[strlen (XSTR (addr, 0)) - 2] == '.')
3479 	      {
3480 		putc ('(', file);
3481 		output_addr_const (file, addr);
3482 		putc (')', file);
3483 	      }
3484 	    else
3485 	      output_addr_const (file, addr);
3486 	  }
3487 	break;
3488     }
3489 }
3490 
3491 /* Check for cases where a clr insns can be omitted from code using
3492    strict_low_part sets.  For example, the second clrl here is not needed:
3493    clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
3494 
3495    MODE is the mode of this STRICT_LOW_PART set.  FIRST_INSN is the clear
3496    insn we are checking for redundancy.  TARGET is the register set by the
3497    clear insn.  */
3498 
3499 int
strict_low_part_peephole_ok(mode,first_insn,target)3500 strict_low_part_peephole_ok (mode, first_insn, target)
3501      enum machine_mode mode;
3502      rtx first_insn;
3503      rtx target;
3504 {
3505   rtx p;
3506 
3507   p = prev_nonnote_insn (first_insn);
3508 
3509   while (p)
3510     {
3511       /* If it isn't an insn, then give up.  */
3512       if (GET_CODE (p) != INSN)
3513 	return 0;
3514 
3515       if (reg_set_p (target, p))
3516 	{
3517 	  rtx set = single_set (p);
3518 	  rtx dest;
3519 
3520 	  /* If it isn't an easy to recognize insn, then give up.  */
3521 	  if (! set)
3522 	    return 0;
3523 
3524 	  dest = SET_DEST (set);
3525 
3526 	  /* If this sets the entire target register to zero, then our
3527 	     first_insn is redundant.  */
3528 	  if (rtx_equal_p (dest, target)
3529 	      && SET_SRC (set) == const0_rtx)
3530 	    return 1;
3531 	  else if (GET_CODE (dest) == STRICT_LOW_PART
3532 		   && GET_CODE (XEXP (dest, 0)) == REG
3533 		   && REGNO (XEXP (dest, 0)) == REGNO (target)
3534 		   && (GET_MODE_SIZE (GET_MODE (XEXP (dest, 0)))
3535 		       <= GET_MODE_SIZE (mode)))
3536 	    /* This is a strict low part set which modifies less than
3537 	       we are using, so it is safe.  */
3538 	    ;
3539 	  else
3540 	    return 0;
3541 	}
3542 
3543       p = prev_nonnote_insn (p);
3544 
3545     }
3546 
3547   return 0;
3548 }
3549 
3550 /* Accept integer operands in the range 0..0xffffffff.  We have to check the
3551    range carefully since this predicate is used in DImode contexts.  Also, we
3552    need some extra crud to make it work when hosted on 64-bit machines.  */
3553 
3554 int
const_uint32_operand(op,mode)3555 const_uint32_operand (op, mode)
3556      rtx op;
3557      enum machine_mode mode;
3558 {
3559   /* It doesn't make sense to ask this question with a mode that is
3560      not larger than 32 bits.  */
3561   if (GET_MODE_BITSIZE (mode) <= 32)
3562     abort ();
3563 
3564 #if HOST_BITS_PER_WIDE_INT > 32
3565   /* All allowed constants will fit a CONST_INT.  */
3566   return (GET_CODE (op) == CONST_INT
3567 	  && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
3568 #else
3569   return (GET_CODE (op) == CONST_INT
3570 	  || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
3571 #endif
3572 }
3573 
3574 /* Accept integer operands in the range -0x80000000..0x7fffffff.  We have
3575    to check the range carefully since this predicate is used in DImode
3576    contexts.  */
3577 
3578 int
const_sint32_operand(op,mode)3579 const_sint32_operand (op, mode)
3580      rtx op;
3581      enum machine_mode mode;
3582 {
3583   /* It doesn't make sense to ask this question with a mode that is
3584      not larger than 32 bits.  */
3585   if (GET_MODE_BITSIZE (mode) <= 32)
3586     abort ();
3587 
3588   /* All allowed constants will fit a CONST_INT.  */
3589   return (GET_CODE (op) == CONST_INT
3590 	  && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
3591 }
3592 
3593 /* Operand predicates for implementing asymmetric pc-relative addressing
3594    on m68k.  The m68k supports pc-relative addressing (mode 7, register 2)
3595    when used as a source operand, but not as a destintation operand.
3596 
3597    We model this by restricting the meaning of the basic predicates
3598    (general_operand, memory_operand, etc) to forbid the use of this
3599    addressing mode, and then define the following predicates that permit
3600    this addressing mode.  These predicates can then be used for the
3601    source operands of the appropriate instructions.
3602 
3603    n.b.  While it is theoretically possible to change all machine patterns
3604    to use this addressing more where permitted by the architecture,
3605    it has only been implemented for "common" cases: SImode, HImode, and
3606    QImode operands, and only for the principle operations that would
3607    require this addressing mode: data movement and simple integer operations.
3608 
3609    In parallel with these new predicates, two new constraint letters
3610    were defined: 'S' and 'T'.  'S' is the -mpcrel analog of 'm'.
3611    'T' replaces 's' in the non-pcrel case.  It is a no-op in the pcrel case.
3612    In the pcrel case 's' is only valid in combination with 'a' registers.
3613    See addsi3, subsi3, cmpsi, and movsi patterns for a better understanding
3614    of how these constraints are used.
3615 
3616    The use of these predicates is strictly optional, though patterns that
3617    don't will cause an extra reload register to be allocated where one
3618    was not necessary:
3619 
3620 	lea (abc:w,%pc),%a0	; need to reload address
3621 	moveq &1,%d1		; since write to pc-relative space
3622 	movel %d1,%a0@		; is not allowed
3623 	...
3624 	lea (abc:w,%pc),%a1	; no need to reload address here
3625 	movel %a1@,%d0		; since "movel (abc:w,%pc),%d0" is ok
3626 
3627    For more info, consult tiemann@cygnus.com.
3628 
3629 
3630    All of the ugliness with predicates and constraints is due to the
3631    simple fact that the m68k does not allow a pc-relative addressing
3632    mode as a destination.  gcc does not distinguish between source and
3633    destination addresses.  Hence, if we claim that pc-relative address
3634    modes are valid, e.g. GO_IF_LEGITIMATE_ADDRESS accepts them, then we
3635    end up with invalid code.  To get around this problem, we left
3636    pc-relative modes as invalid addresses, and then added special
3637    predicates and constraints to accept them.
3638 
3639    A cleaner way to handle this is to modify gcc to distinguish
3640    between source and destination addresses.  We can then say that
3641    pc-relative is a valid source address but not a valid destination
3642    address, and hopefully avoid a lot of the predicate and constraint
3643    hackery.  Unfortunately, this would be a pretty big change.  It would
3644    be a useful change for a number of ports, but there aren't any current
3645    plans to undertake this.
3646 
3647    ***************************************************************************/
3648 
3649 
3650 /* Special case of a general operand that's used as a source operand.
3651    Use this to permit reads from PC-relative memory when -mpcrel
3652    is specified.  */
3653 
3654 int
general_src_operand(op,mode)3655 general_src_operand (op, mode)
3656      rtx op;
3657      enum machine_mode mode;
3658 {
3659   if (TARGET_PCREL
3660       && GET_CODE (op) == MEM
3661       && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
3662 	  || GET_CODE (XEXP (op, 0)) == LABEL_REF
3663 	  || GET_CODE (XEXP (op, 0)) == CONST))
3664     return 1;
3665   return general_operand (op, mode);
3666 }
3667 
3668 /* Special case of a nonimmediate operand that's used as a source.
3669    Use this to permit reads from PC-relative memory when -mpcrel
3670    is specified.  */
3671 
3672 int
nonimmediate_src_operand(op,mode)3673 nonimmediate_src_operand (op, mode)
3674      rtx op;
3675      enum machine_mode mode;
3676 {
3677   if (TARGET_PCREL && GET_CODE (op) == MEM
3678       && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
3679 	  || GET_CODE (XEXP (op, 0)) == LABEL_REF
3680 	  || GET_CODE (XEXP (op, 0)) == CONST))
3681     return 1;
3682   return nonimmediate_operand (op, mode);
3683 }
3684 
3685 /* Special case of a memory operand that's used as a source.
3686    Use this to permit reads from PC-relative memory when -mpcrel
3687    is specified.  */
3688 
3689 int
memory_src_operand(op,mode)3690 memory_src_operand (op, mode)
3691      rtx op;
3692      enum machine_mode mode;
3693 {
3694   if (TARGET_PCREL && GET_CODE (op) == MEM
3695       && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
3696 	  || GET_CODE (XEXP (op, 0)) == LABEL_REF
3697 	  || GET_CODE (XEXP (op, 0)) == CONST))
3698     return 1;
3699   return memory_operand (op, mode);
3700 }
3701 
3702 /* Predicate that accepts only a pc-relative address.  This is needed
3703    because pc-relative addresses don't satisfy the predicate
3704    "general_src_operand".  */
3705 
3706 int
pcrel_address(op,mode)3707 pcrel_address (op, mode)
3708      rtx op;
3709      enum machine_mode mode ATTRIBUTE_UNUSED;
3710 {
3711   return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF
3712 	  || GET_CODE (op) == CONST);
3713 }
3714 
3715 const char *
output_andsi3(operands)3716 output_andsi3 (operands)
3717      rtx *operands;
3718 {
3719   int logval;
3720   if (GET_CODE (operands[2]) == CONST_INT
3721       && (INTVAL (operands[2]) | 0xffff) == 0xffffffff
3722       && (DATA_REG_P (operands[0])
3723 	  || offsettable_memref_p (operands[0]))
3724       && !TARGET_5200)
3725     {
3726       if (GET_CODE (operands[0]) != REG)
3727         operands[0] = adjust_address (operands[0], HImode, 2);
3728       operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
3729       /* Do not delete a following tstl %0 insn; that would be incorrect.  */
3730       CC_STATUS_INIT;
3731       if (operands[2] == const0_rtx)
3732         return "clr%.w %0";
3733       return "and%.w %2,%0";
3734     }
3735   if (GET_CODE (operands[2]) == CONST_INT
3736       && (logval = exact_log2 (~ INTVAL (operands[2]))) >= 0
3737       && (DATA_REG_P (operands[0])
3738           || offsettable_memref_p (operands[0])))
3739     {
3740       if (DATA_REG_P (operands[0]))
3741         {
3742           operands[1] = GEN_INT (logval);
3743         }
3744       else
3745         {
3746 	  operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
3747 	  operands[1] = GEN_INT (logval % 8);
3748         }
3749       /* This does not set condition codes in a standard way.  */
3750       CC_STATUS_INIT;
3751       return "bclr %1,%0";
3752     }
3753   return "and%.l %2,%0";
3754 }
3755 
3756 const char *
output_iorsi3(operands)3757 output_iorsi3 (operands)
3758      rtx *operands;
3759 {
3760   register int logval;
3761   if (GET_CODE (operands[2]) == CONST_INT
3762       && INTVAL (operands[2]) >> 16 == 0
3763       && (DATA_REG_P (operands[0])
3764 	  || offsettable_memref_p (operands[0]))
3765       && !TARGET_5200)
3766     {
3767       if (GET_CODE (operands[0]) != REG)
3768         operands[0] = adjust_address (operands[0], HImode, 2);
3769       /* Do not delete a following tstl %0 insn; that would be incorrect.  */
3770       CC_STATUS_INIT;
3771       if (INTVAL (operands[2]) == 0xffff)
3772 	return "mov%.w %2,%0";
3773       return "or%.w %2,%0";
3774     }
3775   if (GET_CODE (operands[2]) == CONST_INT
3776       && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
3777       && (DATA_REG_P (operands[0])
3778 	  || offsettable_memref_p (operands[0])))
3779     {
3780       if (DATA_REG_P (operands[0]))
3781 	operands[1] = GEN_INT (logval);
3782       else
3783         {
3784 	  operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
3785 	  operands[1] = GEN_INT (logval % 8);
3786 	}
3787       CC_STATUS_INIT;
3788       return "bset %1,%0";
3789     }
3790   return "or%.l %2,%0";
3791 }
3792 
3793 const char *
output_xorsi3(operands)3794 output_xorsi3 (operands)
3795      rtx *operands;
3796 {
3797   register int logval;
3798   if (GET_CODE (operands[2]) == CONST_INT
3799       && INTVAL (operands[2]) >> 16 == 0
3800       && (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0]))
3801       && !TARGET_5200)
3802     {
3803       if (! DATA_REG_P (operands[0]))
3804 	operands[0] = adjust_address (operands[0], HImode, 2);
3805       /* Do not delete a following tstl %0 insn; that would be incorrect.  */
3806       CC_STATUS_INIT;
3807       if (INTVAL (operands[2]) == 0xffff)
3808 	return "not%.w %0";
3809       return "eor%.w %2,%0";
3810     }
3811   if (GET_CODE (operands[2]) == CONST_INT
3812       && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
3813       && (DATA_REG_P (operands[0])
3814 	  || offsettable_memref_p (operands[0])))
3815     {
3816       if (DATA_REG_P (operands[0]))
3817 	operands[1] = GEN_INT (logval);
3818       else
3819         {
3820 	  operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
3821 	  operands[1] = GEN_INT (logval % 8);
3822 	}
3823       CC_STATUS_INIT;
3824       return "bchg %1,%0";
3825     }
3826   return "eor%.l %2,%0";
3827 }
3828 
3829 /* Output assembly to switch to section NAME with attribute FLAGS.  */
3830 
3831 static void
m68k_coff_asm_named_section(name,flags)3832 m68k_coff_asm_named_section (name, flags)
3833      const char *name;
3834      unsigned int flags;
3835 {
3836   char flagchar;
3837 
3838   if (flags & SECTION_WRITE)
3839     flagchar = 'd';
3840   else
3841     flagchar = 'x';
3842 
3843   fprintf (asm_out_file, "\t.section\t%s,\"%c\"\n", name, flagchar);
3844 }
3845 
3846 #ifdef CTOR_LIST_BEGIN
3847 static void
m68k_svr3_asm_out_constructor(symbol,priority)3848 m68k_svr3_asm_out_constructor (symbol, priority)
3849      rtx symbol;
3850      int priority ATTRIBUTE_UNUSED;
3851 {
3852   rtx xop[2];
3853 
3854   xop[1] = symbol;
3855   xop[0] = gen_rtx_MEM (SImode, gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
3856 
3857   init_section ();
3858   output_asm_insn (output_move_simode (xop), xop);
3859 }
3860 #endif
3861 
3862 static void
m68k_output_mi_thunk(file,thunk,delta,vcall_offset,function)3863 m68k_output_mi_thunk (file, thunk, delta, vcall_offset, function)
3864      FILE *file;
3865      tree thunk ATTRIBUTE_UNUSED;
3866      HOST_WIDE_INT delta;
3867      HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
3868      tree function;
3869 {
3870   rtx xops[1];
3871   const char *fmt;
3872 
3873   if (delta > 0 && delta <= 8)
3874 #ifdef MOTOROLA
3875     asm_fprintf (file, "\taddq.l %I%d,4(%Rsp)\n", (int) delta);
3876 #else
3877     asm_fprintf (file, "\taddql %I%d,%Rsp@(4)\n", (int) delta);
3878 #endif
3879   else if (delta < 0 && delta >= -8)
3880 #ifdef MOTOROLA
3881     asm_fprintf (file, "\tsubq.l %I%d,4(%Rsp)\n", (int) -delta);
3882 #else
3883     asm_fprintf (file, "\tsubql %I%d,%Rsp@(4)\n", (int) -delta);
3884 #endif
3885   else
3886     {
3887 #ifdef MOTOROLA
3888       asm_fprintf (file, "\tadd.l %I");
3889 #else
3890       asm_fprintf (file, "\taddl %I");
3891 #endif
3892       fprintf (file, HOST_WIDE_INT_PRINT_DEC, delta);
3893 #ifdef MOTOROLA
3894       asm_fprintf (file, ",4(%Rsp)\n");
3895 #else
3896       asm_fprintf (file, ",%Rsp@(4)\n");
3897 #endif
3898     }
3899 
3900   xops[0] = DECL_RTL (function);
3901 
3902   /* Logic taken from call patterns in m68k.md.  */
3903   if (flag_pic)
3904     {
3905       if (TARGET_PCREL)
3906 	fmt = "bra.l %o0";
3907       else
3908 	{
3909 #ifdef MOTOROLA
3910 #ifdef HPUX_ASM
3911 	  fmt = "bra.l %0";
3912 #else
3913 #ifdef USE_GAS
3914 	  fmt = "bra.l %0@PLTPC";
3915 #else
3916 	  fmt = "bra %0@PLTPC";
3917 #endif
3918 #endif
3919 #else
3920 #ifdef USE_GAS
3921 	  fmt = "bra.l %0";
3922 #else
3923 	  fmt = "jra %0,a1";
3924 #endif
3925 #endif
3926 	}
3927     }
3928   else
3929     {
3930 #if defined (MOTOROLA) && !defined (USE_GAS)
3931 #ifdef MOTOROLA_BSR
3932       fmt = "bra %0";
3933 #else
3934       fmt = "jmp %0";
3935 #endif
3936 #else
3937       fmt = "jra %0";
3938 #endif
3939     }
3940 
3941   output_asm_insn (fmt, xops);
3942 }
3943