1 /* Subroutines for insn-output.c for Motorola 68000 family.
2 Copyright (C) 1987, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
5 This file is part of GNU CC.
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)
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.
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. */
28 #include "hard-reg-set.h"
30 #include "insn-config.h"
31 #include "conditions.h"
33 #include "insn-attr.h"
40 #include "target-def.h"
43 /* Needed for use_return_insn. */
46 #ifdef SUPPORT_SUN_FPA
48 /* Index into this array by (register number >> 3) to find the
49 smallest class which contains that register. */
50 enum reg_class regno_reg_class
[]
51 = { DATA_REGS
, ADDR_REGS
, FP_REGS
,
52 LO_FPA_REGS
, LO_FPA_REGS
, FPA_REGS
, FPA_REGS
};
54 #endif /* defined SUPPORT_SUN_FPA */
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
;
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));
70 /* Alignment to use for loops and jumps */
71 /* Specify power of two alignment used for loops. */
72 const char *m68k_align_loops_string
;
73 /* Specify power of two alignment used for non-loop jumps. */
74 const char *m68k_align_jumps_string
;
75 /* Specify power of two alignment used for functions. */
76 const char *m68k_align_funcs_string
;
78 /* Specify power of two alignment used for loops. */
80 /* Specify power of two alignment used for non-loop jumps. */
82 /* Specify power of two alignment used for functions. */
85 /* Nonzero if the last compare/test insn had FP operands. The
86 sCC expanders peek at this to determine what to do for the
87 68060, which has no fsCC instructions. */
88 int m68k_last_compare_had_fp_operands
;
90 /* Initialize the GCC target structure. */
91 #undef TARGET_ASM_FUNCTION_PROLOGUE
92 #define TARGET_ASM_FUNCTION_PROLOGUE m68k_output_function_prologue
93 #undef TARGET_ASM_FUNCTION_EPILOGUE
94 #define TARGET_ASM_FUNCTION_EPILOGUE m68k_output_function_epilogue
96 struct gcc_target targetm
= TARGET_INITIALIZER
;
98 /* Sometimes certain combinations of command options do not make
99 sense on a particular target machine. You can define a macro
100 `OVERRIDE_OPTIONS' to take account of this. This macro, if
101 defined, is executed once just after all the command options have
104 Don't use this macro to turn on various extra optimizations for
105 `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
115 /* Validate -malign-loops= value, or provide default */
116 m68k_align_loops
= def_align
;
117 if (m68k_align_loops_string
)
119 i
= atoi (m68k_align_loops_string
);
120 if (i
< 1 || i
> MAX_CODE_ALIGN
)
121 error ("-malign-loops=%d is not between 1 and %d", i
, MAX_CODE_ALIGN
);
123 m68k_align_loops
= i
;
126 /* Validate -malign-jumps= value, or provide default */
127 m68k_align_jumps
= def_align
;
128 if (m68k_align_jumps_string
)
130 i
= atoi (m68k_align_jumps_string
);
131 if (i
< 1 || i
> MAX_CODE_ALIGN
)
132 error ("-malign-jumps=%d is not between 1 and %d", i
, MAX_CODE_ALIGN
);
134 m68k_align_jumps
= i
;
137 /* Validate -malign-functions= value, or provide default */
138 m68k_align_funcs
= def_align
;
139 if (m68k_align_funcs_string
)
141 i
= atoi (m68k_align_funcs_string
);
142 if (i
< 1 || i
> MAX_CODE_ALIGN
)
143 error ("-malign-functions=%d is not between 1 and %d",
146 m68k_align_funcs
= i
;
150 /* This function generates the assembly code for function entry.
151 STREAM is a stdio stream to output the code to.
152 SIZE is an int: how many units of temporary storage to allocate.
153 Refer to the array `regs_ever_live' to determine which registers
154 to save; `regs_ever_live[I]' is nonzero if register number I
155 is ever used in the function. This function is responsible for
156 knowing which registers should not be saved even if used. */
159 /* Note that the order of the bit mask for fmovem is the opposite
160 of the order for movem! */
165 m68k_output_function_prologue (stream
, size
)
170 register int mask
= 0;
171 extern char call_used_regs
[];
172 HOST_WIDE_INT fsize
= ((size
) + 3) & -4;
174 /* unos stack probe */
177 fprintf (stream
, "\tmovel sp,a0\n");
178 fprintf (stream
, "\taddl $-%d,a0\n", 2048 + fsize
);
179 fprintf (stream
, "\ttstb (a0)\n");
182 fprintf (stream
, "\ttstb -%d(sp)\n", 2048 + fsize
);
184 if (frame_pointer_needed
)
186 if (TARGET_68020
|| fsize
< 0x8000)
187 fprintf (stream
, "\tlink a6,$%d\n", -fsize
);
189 fprintf (stream
, "\tlink a6,$0\n\tsubl $%d,sp\n", fsize
);
193 /* Adding negative number is faster on the 68040. */
194 if (fsize
+ 4 < 0x8000)
195 fprintf (stream
, "\tadd.w #%d,sp\n", - (fsize
+ 4));
197 fprintf (stream
, "\tadd.l #%d,sp\n", - (fsize
+ 4));
200 for (regno
= 16; regno
< 24; regno
++)
201 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
202 mask
|= 1 << (regno
- 16);
204 if ((mask
& 0xff) != 0)
205 fprintf (stream
, "\tfmovem $0x%x,-(sp)\n", mask
& 0xff);
208 for (regno
= 0; regno
< 16; regno
++)
209 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
210 mask
|= 1 << (15 - regno
);
211 if (frame_pointer_needed
)
212 mask
&= ~ (1 << (15-FRAME_POINTER_REGNUM
));
214 if (exact_log2 (mask
) >= 0)
215 fprintf (stream
, "\tmovel %s,-(sp)\n", reg_names
[15 - exact_log2 (mask
)]);
217 fprintf (stream
, "\tmovem $0x%x,-(sp)\n", mask
);
221 #if defined (DPX2) && defined (MOTOROLA)
224 m68k_output_function_prologue (stream
, size
)
229 register int mask
= 0;
230 int num_saved_regs
= 0, first
= 1;
231 extern char call_used_regs
[];
232 HOST_WIDE_INT fsize
= ((size
) + 3) & -4;
234 if (frame_pointer_needed
)
236 /* Adding negative number is faster on the 68040. */
237 if (fsize
< 0x8000 && !TARGET_68040
)
238 fprintf (stream
, "\tlink %s,#%d\n",
239 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
240 else if (TARGET_68020
)
241 fprintf (stream
, "\tlink %s,#%d\n",
242 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
244 fprintf (stream
, "\tlink %s,#0\n\tadd.l #%d,sp\n",
245 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
249 /* Adding negative number is faster on the 68040. */
250 if (fsize
+ 4 < 0x8000)
251 fprintf (stream
, "\tadd.w #%d,sp\n", - (fsize
+ 4));
253 fprintf (stream
, "\tadd.l #%d,sp\n", - (fsize
+ 4));
256 for (regno
= 23; regno
>= 16; regno
--)
257 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
261 fprintf (stream
, "\tfmovem.x %s", reg_names
[regno
]);
265 fprintf (stream
, "/%s", reg_names
[regno
]);
268 fprintf (stream
, ",-(sp)\n");
271 for (regno
= 0; regno
< 16; regno
++)
272 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
274 mask
|= 1 << (15 - regno
);
278 if (frame_pointer_needed
)
280 mask
&= ~ (1 << (15 - FRAME_POINTER_REGNUM
));
284 if (num_saved_regs
<= 2)
286 /* Store each separately in the same order moveml uses.
287 Using two movel instructions instead of a single moveml
288 is about 15% faster for the 68020 and 68030 at no expense
293 /* Undo the work from above. */
294 for (i
= 0; i
< 16; i
++)
296 fprintf (stream
, "\tmove.l %s,-(sp)\n", reg_names
[15 - i
]);
301 for (regno
= 0; regno
< 16; regno
++)
302 if (mask
& (1 << regno
))
306 fprintf (stream
, "\tmovem.l %s", reg_names
[15 - regno
]);
310 fprintf (stream
, "/%s", reg_names
[15 - regno
]);
312 fprintf (stream
, ",-(sp)\n");
315 if (flag_pic
&& current_function_uses_pic_offset_table
)
317 fprintf (stream
, "\tmove.l #__GLOBAL_OFFSET_TABLE_, %s\n",
318 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
319 fprintf (stream
, "\tlea.l (pc,%s.l),%s\n",
320 reg_names
[PIC_OFFSET_TABLE_REGNUM
],
321 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
326 #if defined (NEWS) && defined (MOTOROLA)
329 m68k_output_function_prologue (stream
, size
)
334 register int mask
= 0;
335 extern char call_used_regs
[];
336 HOST_WIDE_INT fsize
= ((size
) + 3) & -4;
338 if (frame_pointer_needed
)
341 fprintf (stream
, "\tlink fp,#%d\n", -fsize
);
342 else if (TARGET_68020
)
343 fprintf (stream
, "\tlink.l fp,#%d\n", -fsize
);
345 fprintf (stream
, "\tlink fp,#0\n\tsub.l #%d,sp\n", fsize
);
350 /* Adding negative number is faster on the 68040. */
351 if (fsize
+ 4 < 0x8000)
352 asm_fprintf (stream
, "\tadd.w %0I%d,%Rsp\n", - amt
);
354 asm_fprintf (stream
, "\tadd.l %0I%d,%Rsp\n", - amt
);
357 for (regno
= 16; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
358 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
359 mask
|= 1 << (regno
- 16);
362 fprintf (stream
, "\tfmovem.x #0x%x,-(sp)\n", mask
& 0xff);
365 for (regno
= 0; regno
< 16; regno
++)
366 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
367 mask
|= 1 << (15 - regno
);
369 if (frame_pointer_needed
)
370 mask
&= ~ (1 << (15-FRAME_POINTER_REGNUM
));
372 if (exact_log2 (mask
) >= 0)
373 fprintf (stream
, "\tmove.l %s,-(sp)\n", reg_names
[15 - exact_log2 (mask
)]);
375 if (mask
) fprintf (stream
, "\tmovem.l #0x%x,-(sp)\n", mask
);
378 #else /* !CRDS && ! (NEWS && MOTOROLA) && ! (DPX2 && MOTOROLA) */
381 m68k_output_function_prologue (stream
, size
)
386 register int mask
= 0;
387 int num_saved_regs
= 0;
388 extern char call_used_regs
[];
389 HOST_WIDE_INT fsize
= (size
+ 3) & -4;
390 HOST_WIDE_INT cfa_offset
= INCOMING_FRAME_SP_OFFSET
;
391 HOST_WIDE_INT cfa_store_offset
= cfa_offset
;
393 /* If the stack limit is a symbol, we can check it here,
394 before actually allocating the space. */
395 if (current_function_limit_stack
396 && GET_CODE (stack_limit_rtx
) == SYMBOL_REF
)
398 #if defined (MOTOROLA)
399 asm_fprintf (stream
, "\tcmp.l %0I%s+%d,%Rsp\n\ttrapcs\n",
400 XSTR (stack_limit_rtx
, 0), fsize
+ 4);
402 asm_fprintf (stream
, "\tcmpl %0I%s+%d,%Rsp\n\ttrapcs\n",
403 XSTR (stack_limit_rtx
, 0), fsize
+ 4);
407 if (frame_pointer_needed
)
409 if (fsize
== 0 && TARGET_68040
)
411 /* on the 68040, pea + move is faster than link.w 0 */
413 asm_fprintf (stream
, "\tpea (%s)\n\tmove.l %s,%s\n",
414 reg_names
[FRAME_POINTER_REGNUM
], reg_names
[STACK_POINTER_REGNUM
],
415 reg_names
[FRAME_POINTER_REGNUM
]);
417 asm_fprintf (stream
, "\tpea %s@\n\tmovel %s,%s\n",
418 reg_names
[FRAME_POINTER_REGNUM
], reg_names
[STACK_POINTER_REGNUM
],
419 reg_names
[FRAME_POINTER_REGNUM
]);
422 else if (fsize
< 0x8000)
425 asm_fprintf (stream
, "\tlink.w %s,%0I%d\n",
426 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
428 asm_fprintf (stream
, "\tlink %s,%0I%d\n",
429 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
432 else if (TARGET_68020
)
435 asm_fprintf (stream
, "\tlink.l %s,%0I%d\n",
436 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
438 asm_fprintf (stream
, "\tlink %s,%0I%d\n",
439 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
444 /* Adding negative number is faster on the 68040. */
446 asm_fprintf (stream
, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
447 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
449 asm_fprintf (stream
, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
450 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
453 if (dwarf2out_do_frame ())
456 l
= (char *) dwarf2out_cfi_label ();
457 cfa_store_offset
+= 4;
458 cfa_offset
= cfa_store_offset
;
459 dwarf2out_reg_save (l
, FRAME_POINTER_REGNUM
, -cfa_store_offset
);
460 dwarf2out_def_cfa (l
, FRAME_POINTER_REGNUM
, cfa_offset
);
461 cfa_store_offset
+= fsize
;
466 if (fsize
+ 4 < 0x8000)
473 /* asm_fprintf() cannot handle %. */
475 asm_fprintf (stream
, "\tsubq.w %0I%d,%Rsp\n", fsize
+ 4);
477 asm_fprintf (stream
, "\tsubqw %0I%d,%Rsp\n", fsize
+ 4);
482 /* asm_fprintf() cannot handle %. */
484 asm_fprintf (stream
, "\tsubq.l %0I%d,%Rsp\n", fsize
+ 4);
486 asm_fprintf (stream
, "\tsubql %0I%d,%Rsp\n", fsize
+ 4);
490 else if (fsize
+ 4 <= 16 && TARGET_CPU32
)
492 /* On the CPU32 it is faster to use two subqw instructions to
493 subtract a small integer (8 < N <= 16) to a register. */
494 /* asm_fprintf() cannot handle %. */
496 asm_fprintf (stream
, "\tsubq.w %0I8,%Rsp\n\tsubq.w %0I%d,%Rsp\n",
499 asm_fprintf (stream
, "\tsubqw %0I8,%Rsp\n\tsubqw %0I%d,%Rsp\n",
504 #endif /* not NO_ADDSUB_Q */
507 /* Adding negative number is faster on the 68040. */
508 /* asm_fprintf() cannot handle %. */
510 asm_fprintf (stream
, "\tadd.w %0I%d,%Rsp\n", - (fsize
+ 4));
512 asm_fprintf (stream
, "\taddw %0I%d,%Rsp\n", - (fsize
+ 4));
518 asm_fprintf (stream
, "\tlea (%d,%Rsp),%Rsp\n", - (fsize
+ 4));
520 asm_fprintf (stream
, "\tlea %Rsp@(%d),%Rsp\n", - (fsize
+ 4));
526 /* asm_fprintf() cannot handle %. */
528 asm_fprintf (stream
, "\tadd.l %0I%d,%Rsp\n", - (fsize
+ 4));
530 asm_fprintf (stream
, "\taddl %0I%d,%Rsp\n", - (fsize
+ 4));
533 if (dwarf2out_do_frame ())
535 cfa_store_offset
+= fsize
;
536 cfa_offset
= cfa_store_offset
;
537 dwarf2out_def_cfa ("", STACK_POINTER_REGNUM
, cfa_offset
);
540 #ifdef SUPPORT_SUN_FPA
541 for (regno
= 24; regno
< 56; regno
++)
542 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
545 asm_fprintf (stream
, "\tfpmovd %s,-(%Rsp)\n",
548 asm_fprintf (stream
, "\tfpmoved %s,%Rsp@-\n",
551 if (dwarf2out_do_frame ())
553 char *l
= dwarf2out_cfi_label ();
555 cfa_store_offset
+= 8;
556 if (! frame_pointer_needed
)
558 cfa_offset
= cfa_store_offset
;
559 dwarf2out_def_cfa (l
, STACK_POINTER_REGNUM
, cfa_offset
);
561 dwarf2out_reg_save (l
, regno
, -cfa_store_offset
);
567 for (regno
= 16; regno
< 24; regno
++)
568 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
570 mask
|= 1 << (regno
- 16);
573 if ((mask
& 0xff) != 0)
576 asm_fprintf (stream
, "\tfmovm %0I0x%x,-(%Rsp)\n", mask
& 0xff);
578 asm_fprintf (stream
, "\tfmovem %0I0x%x,%Rsp@-\n", mask
& 0xff);
580 if (dwarf2out_do_frame ())
582 char *l
= (char *) dwarf2out_cfi_label ();
585 cfa_store_offset
+= num_saved_regs
* 12;
586 if (! frame_pointer_needed
)
588 cfa_offset
= cfa_store_offset
;
589 dwarf2out_def_cfa (l
, STACK_POINTER_REGNUM
, cfa_offset
);
591 for (regno
= 16, n_regs
= 0; regno
< 24; regno
++)
592 if (mask
& (1 << (regno
- 16)))
593 dwarf2out_reg_save (l
, regno
,
594 -cfa_store_offset
+ n_regs
++ * 12);
600 for (regno
= 0; regno
< 16; regno
++)
601 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
603 mask
|= 1 << (15 - regno
);
606 if (frame_pointer_needed
)
608 mask
&= ~ (1 << (15 - FRAME_POINTER_REGNUM
));
611 if (flag_pic
&& current_function_uses_pic_offset_table
)
613 mask
|= 1 << (15 - PIC_OFFSET_TABLE_REGNUM
);
619 asm_fprintf (stream
, "\ttst.l %d(%Rsp)\n", NEED_PROBE
- num_saved_regs
* 4);
621 asm_fprintf (stream
, "\ttstl %Rsp@(%d)\n", NEED_PROBE
- num_saved_regs
* 4);
625 /* If the stack limit is not a symbol, check it here.
626 This has the disadvantage that it may be too late... */
627 if (current_function_limit_stack
)
629 if (REG_P (stack_limit_rtx
))
631 #if defined (MOTOROLA)
632 asm_fprintf (stream
, "\tcmp.l %s,%Rsp\n\ttrapcs\n",
633 reg_names
[REGNO (stack_limit_rtx
)]);
635 asm_fprintf (stream
, "\tcmpl %s,%Rsp\n\ttrapcs\n",
636 reg_names
[REGNO (stack_limit_rtx
)]);
639 else if (GET_CODE (stack_limit_rtx
) != SYMBOL_REF
)
640 warning ("stack limit expression is not supported");
643 if (num_saved_regs
<= 2)
645 /* Store each separately in the same order moveml uses.
646 Using two movel instructions instead of a single moveml
647 is about 15% faster for the 68020 and 68030 at no expense
652 /* Undo the work from above. */
653 for (i
= 0; i
< 16; i
++)
658 "\t%Omove.l %s,-(%Rsp)\n",
660 "\tmovel %s,%Rsp@-\n",
663 if (dwarf2out_do_frame ())
665 char *l
= (char *) dwarf2out_cfi_label ();
667 cfa_store_offset
+= 4;
668 if (! frame_pointer_needed
)
670 cfa_offset
= cfa_store_offset
;
671 dwarf2out_def_cfa (l
, STACK_POINTER_REGNUM
, cfa_offset
);
673 dwarf2out_reg_save (l
, 15 - i
, -cfa_store_offset
);
681 /* The coldfire does not support the predecrement form of the
682 movml instruction, so we must adjust the stack pointer and
683 then use the plain address register indirect mode. We also
684 have to invert the register save mask to use the new mode.
686 FIXME: if num_saved_regs was calculated earlier, we could
687 combine the stack pointer adjustment with any adjustment
688 done when the initial stack frame is created. This would
689 save an instruction */
694 for (i
= 0; i
< 16; i
++)
696 newmask
|= (1 << (15-i
));
699 asm_fprintf (stream
, "\tlea (%d,%Rsp),%Rsp\n", -num_saved_regs
*4);
700 asm_fprintf (stream
, "\tmovm.l %0I0x%x,(%Rsp)\n", newmask
);
702 asm_fprintf (stream
, "\tlea %Rsp@(%d),%Rsp\n", -num_saved_regs
*4);
703 asm_fprintf (stream
, "\tmoveml %0I0x%x,%Rsp@\n", newmask
);
709 asm_fprintf (stream
, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask
);
711 asm_fprintf (stream
, "\tmoveml %0I0x%x,%Rsp@-\n", mask
);
714 if (dwarf2out_do_frame ())
716 char *l
= (char *) dwarf2out_cfi_label ();
719 cfa_store_offset
+= num_saved_regs
* 4;
720 if (! frame_pointer_needed
)
722 cfa_offset
= cfa_store_offset
;
723 dwarf2out_def_cfa (l
, STACK_POINTER_REGNUM
, cfa_offset
);
725 for (regno
= 0, n_regs
= 0; regno
< 16; regno
++)
726 if (mask
& (1 << (15 - regno
)))
727 dwarf2out_reg_save (l
, regno
,
728 -cfa_store_offset
+ n_regs
++ * 4);
731 if (flag_pic
&& current_function_uses_pic_offset_table
)
734 asm_fprintf (stream
, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
735 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
737 asm_fprintf (stream
, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
738 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
739 asm_fprintf (stream
, "\tlea %Rpc@(0,%s:l),%s\n",
740 reg_names
[PIC_OFFSET_TABLE_REGNUM
],
741 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
745 #endif /* ! (DPX2 && MOTOROLA) */
746 #endif /* ! (NEWS && MOTOROLA) */
749 /* Return true if this function's epilogue can be output as RTL. */
756 if (!reload_completed
|| frame_pointer_needed
|| get_frame_size () != 0)
759 /* Copied from output_function_epilogue (). We should probably create a
760 separate layout routine to perform the common work. */
762 for (regno
= 0 ; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
763 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
766 if (flag_pic
&& current_function_uses_pic_offset_table
)
772 /* This function generates the assembly code for function exit,
773 on machines that need it.
775 The function epilogue should not depend on the current stack pointer!
776 It should use the frame pointer only, if there is a frame pointer.
777 This is mandatory because of alloca; we also take advantage of it to
778 omit stack adjustments before returning. */
783 m68k_output_function_epilogue (stream
, size
)
788 register int mask
, fmask
;
790 HOST_WIDE_INT offset
, foffset
, fpoffset
;
791 extern char call_used_regs
[];
792 HOST_WIDE_INT fsize
= ((size
) + 3) & -4;
795 nregs
= 0; fmask
= 0; fpoffset
= 0;
796 for (regno
= 16; regno
< 24; regno
++)
797 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
800 fmask
|= 1 << (23 - regno
);
803 foffset
= fpoffset
+ nregs
* 12;
805 if (frame_pointer_needed
)
806 regs_ever_live
[FRAME_POINTER_REGNUM
] = 0;
808 for (regno
= 0; regno
< 16; regno
++)
809 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
815 offset
= foffset
+ nregs
* 4;
816 if (offset
+ fsize
>= 0x8000
817 && frame_pointer_needed
818 && (mask
|| fmask
|| fpoffset
))
820 fprintf (stream
, "\tmovel $%d,a0\n", -fsize
);
824 if (exact_log2 (mask
) >= 0)
827 fprintf (stream
, "\tmovel -%d(a6,a0.l),%s\n",
828 offset
+ fsize
, reg_names
[exact_log2 (mask
)]);
829 else if (! frame_pointer_needed
)
830 fprintf (stream
, "\tmovel (sp)+,%s\n",
831 reg_names
[exact_log2 (mask
)]);
833 fprintf (stream
, "\tmovel -%d(a6),%s\n",
834 offset
+ fsize
, reg_names
[exact_log2 (mask
)]);
839 fprintf (stream
, "\tmovem -%d(a6,a0.l),$0x%x\n",
840 offset
+ fsize
, mask
);
841 else if (! frame_pointer_needed
)
842 fprintf (stream
, "\tmovem (sp)+,$0x%x\n", mask
);
844 fprintf (stream
, "\tmovem -%d(a6),$0x%x\n",
845 offset
+ fsize
, mask
);
851 fprintf (stream
, "\tfmovem -%d(a6,a0.l),$0x%x\n",
852 foffset
+ fsize
, fmask
);
853 else if (! frame_pointer_needed
)
854 fprintf (stream
, "\tfmovem (sp)+,$0x%x\n", fmask
);
856 fprintf (stream
, "\tfmovem -%d(a6),$0x%x\n",
857 foffset
+ fsize
, fmask
);
861 for (regno
= 55; regno
>= 24; regno
--)
862 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
865 fprintf(stream
, "\tfpmoved -%d(a6,a0.l), %s\n",
866 fpoffset
+ fsize
, reg_names
[regno
]);
867 else if (! frame_pointer_needed
)
868 fprintf(stream
, "\tfpmoved (sp)+, %s\n",
871 fprintf(stream
, "\tfpmoved -%d(a6), %s\n",
872 fpoffset
+ fsize
, reg_names
[regno
]);
876 if (frame_pointer_needed
)
877 fprintf (stream
, "\tunlk a6\n");
880 if (fsize
+ 4 < 0x8000)
881 fprintf (stream
, "\tadd.w #%d,sp\n", fsize
+ 4);
883 fprintf (stream
, "\tadd.l #%d,sp\n", fsize
+ 4);
886 if (current_function_pops_args
)
887 fprintf (stream
, "\trtd $%d\n", current_function_pops_args
);
889 fprintf (stream
, "\trts\n");
893 #if defined (DPX2) && defined (MOTOROLA)
896 m68k_output_function_epilogue (stream
, size
)
901 register int mask
, fmask
;
903 HOST_WIDE_INT offset
, foffset
, fpoffset
, first
= 1;
904 extern char call_used_regs
[];
905 HOST_WIDE_INT fsize
= ((size
) + 3) & -4;
907 rtx insn
= get_last_insn ();
909 /* If the last insn was a BARRIER, we don't have to write any code. */
910 if (GET_CODE (insn
) == NOTE
)
911 insn
= prev_nonnote_insn (insn
);
912 if (insn
&& GET_CODE (insn
) == BARRIER
)
914 /* Output just a no-op so that debuggers don't get confused
915 about which function the pc is in at this address. */
916 fprintf (stream
, "\tnop\n");
920 nregs
= 0; fmask
= 0; fpoffset
= 0;
921 for (regno
= 16; regno
< 24; regno
++)
922 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
925 fmask
|= 1 << (23 - regno
);
928 foffset
= fpoffset
+ nregs
* 12;
930 if (frame_pointer_needed
)
931 regs_ever_live
[FRAME_POINTER_REGNUM
] = 0;
933 for (regno
= 0; regno
< 16; regno
++)
934 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
940 offset
= foffset
+ nregs
* 4;
941 if (offset
+ fsize
>= 0x8000
942 && frame_pointer_needed
943 && (mask
|| fmask
|| fpoffset
))
945 fprintf (stream
, "\tmove.l #%d,a0\n", -fsize
);
951 /* Restore each separately in the same order moveml does.
952 Using two movel instructions instead of a single moveml
953 is about 15% faster for the 68020 and 68030 at no expense
958 /* Undo the work from above. */
959 for (i
= 0; i
< 16; i
++)
963 fprintf (stream
, "\tmove.l -%d(%s,a0.l),%s\n",
965 reg_names
[FRAME_POINTER_REGNUM
],
967 else if (! frame_pointer_needed
)
968 fprintf (stream
, "\tmove.l (sp)+,%s\n",
971 fprintf (stream
, "\tmove.l -%d(%s),%s\n",
973 reg_names
[FRAME_POINTER_REGNUM
],
981 for (regno
= 0; regno
< 16; regno
++)
982 if (mask
& (1 << regno
))
986 fprintf (stream
, "\tmovem.l -%d(%s,a0.l),%s",
988 reg_names
[FRAME_POINTER_REGNUM
],
992 else if (first
&& ! frame_pointer_needed
)
994 fprintf (stream
, "\tmovem.l (sp)+,%s",
1000 fprintf (stream
, "\tmovem.l -%d(%s),%s",
1002 reg_names
[FRAME_POINTER_REGNUM
],
1007 fprintf (stream
, "/%s", reg_names
[regno
]);
1009 fprintf (stream
, "\n");
1015 for (regno
= 16; regno
< 24; regno
++)
1016 if (fmask
& (1 << (23 - regno
)))
1020 fprintf (stream
, "\tfmovem.x -%d(%s,a0.l),%s",
1022 reg_names
[FRAME_POINTER_REGNUM
],
1026 else if (first
&& ! frame_pointer_needed
)
1028 fprintf (stream
, "\tfmovem.x (sp)+,%s",
1034 fprintf (stream
, "\tfmovem.x -%d(%s),%s",
1036 reg_names
[FRAME_POINTER_REGNUM
],
1041 fprintf (stream
, "/%s", reg_names
[regno
]);
1043 fprintf (stream
, "\n");
1046 if (frame_pointer_needed
)
1047 fprintf (stream
, "\tunlk %s\n",
1048 reg_names
[FRAME_POINTER_REGNUM
]);
1051 if (fsize
+ 4 < 0x8000)
1052 fprintf (stream
, "\tadd.w #%d,sp\n", fsize
+ 4);
1054 fprintf (stream
, "\tadd.l #%d,sp\n", fsize
+ 4);
1057 if (current_function_pops_args
)
1058 fprintf (stream
, "\trtd #%d\n", current_function_pops_args
);
1060 fprintf (stream
, "\trts\n");
1064 #if defined (NEWS) && defined (MOTOROLA)
1067 m68k_output_function_epilogue (stream
, size
)
1072 register int mask
, fmask
;
1074 HOST_WIDE_INT offset
, foffset
;
1075 extern char call_used_regs
[];
1076 HOST_WIDE_INT fsize
= ((size
) + 3) & -4;
1079 nregs
= 0; fmask
= 0;
1080 for (regno
= 16; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
1081 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
1084 fmask
|= 1 << (23 - regno
);
1087 foffset
= nregs
* 12;
1088 nregs
= 0; mask
= 0;
1089 if (frame_pointer_needed
)
1090 regs_ever_live
[FRAME_POINTER_REGNUM
] = 0;
1092 for (regno
= 0; regno
< 16; regno
++)
1093 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
1099 offset
= foffset
+ nregs
* 4;
1100 if (offset
+ fsize
>= 0x8000
1101 && frame_pointer_needed
1104 fprintf (stream
, "\tmove.l #%d,a0\n", -fsize
);
1108 if (exact_log2 (mask
) >= 0)
1111 fprintf (stream
, "\tmove.l (-%d,fp,a0.l),%s\n",
1112 offset
+ fsize
, reg_names
[exact_log2 (mask
)]);
1113 else if (! frame_pointer_needed
)
1114 fprintf (stream
, "\tmove.l (sp)+,%s\n",
1115 reg_names
[exact_log2 (mask
)]);
1117 fprintf (stream
, "\tmove.l (-%d,fp),%s\n",
1118 offset
+ fsize
, reg_names
[exact_log2 (mask
)]);
1123 fprintf (stream
, "\tmovem.l (-%d,fp,a0.l),#0x%x\n",
1124 offset
+ fsize
, mask
);
1125 else if (! frame_pointer_needed
)
1126 fprintf (stream
, "\tmovem.l (sp)+,#0x%x\n", mask
);
1128 fprintf (stream
, "\tmovem.l (-%d,fp),#0x%x\n",
1129 offset
+ fsize
, mask
);
1135 fprintf (stream
, "\tfmovem.x (-%d,fp,a0.l),#0x%x\n",
1136 foffset
+ fsize
, fmask
);
1137 else if (! frame_pointer_needed
)
1138 fprintf (stream
, "\tfmovem.x (sp)+,#0x%x\n", fmask
);
1140 fprintf (stream
, "\tfmovem.x (-%d,fp),#0x%x\n",
1141 foffset
+ fsize
, fmask
);
1144 if (frame_pointer_needed
)
1145 fprintf (stream
, "\tunlk fp\n");
1148 if (fsize
+ 4 < 0x8000)
1149 fprintf (stream
, "\tadd.w #%d,sp\n", fsize
+ 4);
1151 fprintf (stream
, "\tadd.l #%d,sp\n", fsize
+ 4);
1154 if (current_function_pops_args
)
1155 fprintf (stream
, "\trtd #%d\n", current_function_pops_args
);
1157 fprintf (stream
, "\trts\n");
1160 #else /* !CRDS && ! (NEWS && MOTOROLA) && ! (DPX2 && MOTOROLA) */
1163 m68k_output_function_epilogue (stream
, size
)
1168 register int mask
, fmask
;
1170 HOST_WIDE_INT offset
, foffset
, fpoffset
;
1171 extern char call_used_regs
[];
1172 HOST_WIDE_INT fsize
= (size
+ 3) & -4;
1174 rtx insn
= get_last_insn ();
1175 int restore_from_sp
= 0;
1177 /* If the last insn was a BARRIER, we don't have to write any code. */
1178 if (GET_CODE (insn
) == NOTE
)
1179 insn
= prev_nonnote_insn (insn
);
1180 if (insn
&& GET_CODE (insn
) == BARRIER
)
1182 /* Output just a no-op so that debuggers don't get confused
1183 about which function the pc is in at this address. */
1184 asm_fprintf (stream
, "\tnop\n");
1188 #ifdef FUNCTION_EXTRA_EPILOGUE
1189 FUNCTION_EXTRA_EPILOGUE (stream
, size
);
1191 nregs
= 0; fmask
= 0; fpoffset
= 0;
1192 #ifdef SUPPORT_SUN_FPA
1193 for (regno
= 24 ; regno
< 56 ; regno
++)
1194 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
1196 fpoffset
= nregs
* 8;
1201 for (regno
= 16; regno
< 24; regno
++)
1202 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
1205 fmask
|= 1 << (23 - regno
);
1208 foffset
= fpoffset
+ nregs
* 12;
1209 nregs
= 0; mask
= 0;
1210 if (frame_pointer_needed
)
1211 regs_ever_live
[FRAME_POINTER_REGNUM
] = 0;
1212 for (regno
= 0; regno
< 16; regno
++)
1213 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
1218 if (flag_pic
&& current_function_uses_pic_offset_table
)
1221 mask
|= 1 << PIC_OFFSET_TABLE_REGNUM
;
1223 offset
= foffset
+ nregs
* 4;
1224 /* FIXME : leaf_function_p below is too strong.
1225 What we really need to know there is if there could be pending
1226 stack adjustment needed at that point. */
1227 restore_from_sp
= ! frame_pointer_needed
1228 || (! current_function_calls_alloca
&& leaf_function_p ());
1229 if (offset
+ fsize
>= 0x8000
1230 && ! restore_from_sp
1231 && (mask
|| fmask
|| fpoffset
))
1234 asm_fprintf (stream
, "\t%Omove.l %0I%d,%Ra1\n", -fsize
);
1236 asm_fprintf (stream
, "\tmovel %0I%d,%Ra1\n", -fsize
);
1240 if (TARGET_5200
|| nregs
<= 2)
1242 /* Restore each separately in the same order moveml does.
1243 Using two movel instructions instead of a single moveml
1244 is about 15% faster for the 68020 and 68030 at no expense
1249 /* Undo the work from above. */
1250 for (i
= 0; i
< 16; i
++)
1251 if (mask
& (1 << i
))
1256 asm_fprintf (stream
, "\t%Omove.l -%d(%s,%Ra1.l),%s\n",
1258 reg_names
[FRAME_POINTER_REGNUM
],
1261 asm_fprintf (stream
, "\tmovel %s@(-%d,%Ra1:l),%s\n",
1262 reg_names
[FRAME_POINTER_REGNUM
],
1263 offset
+ fsize
, reg_names
[i
]);
1266 else if (restore_from_sp
)
1269 asm_fprintf (stream
, "\t%Omove.l (%Rsp)+,%s\n",
1272 asm_fprintf (stream
, "\tmovel %Rsp@+,%s\n",
1279 asm_fprintf (stream
, "\t%Omove.l -%d(%s),%s\n",
1281 reg_names
[FRAME_POINTER_REGNUM
],
1284 asm_fprintf (stream
, "\tmovel %s@(-%d),%s\n",
1285 reg_names
[FRAME_POINTER_REGNUM
],
1286 offset
+ fsize
, reg_names
[i
]);
1289 offset
= offset
- 4;
1297 asm_fprintf (stream
, "\tmovm.l -%d(%s,%Ra1.l),%0I0x%x\n",
1299 reg_names
[FRAME_POINTER_REGNUM
],
1302 asm_fprintf (stream
, "\tmoveml %s@(-%d,%Ra1:l),%0I0x%x\n",
1303 reg_names
[FRAME_POINTER_REGNUM
],
1304 offset
+ fsize
, mask
);
1307 else if (restore_from_sp
)
1310 asm_fprintf (stream
, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask
);
1312 asm_fprintf (stream
, "\tmoveml %Rsp@+,%0I0x%x\n", mask
);
1318 asm_fprintf (stream
, "\tmovm.l -%d(%s),%0I0x%x\n",
1320 reg_names
[FRAME_POINTER_REGNUM
],
1323 asm_fprintf (stream
, "\tmoveml %s@(-%d),%0I0x%x\n",
1324 reg_names
[FRAME_POINTER_REGNUM
],
1325 offset
+ fsize
, mask
);
1334 asm_fprintf (stream
, "\tfmovm -%d(%s,%Ra1.l),%0I0x%x\n",
1336 reg_names
[FRAME_POINTER_REGNUM
],
1339 asm_fprintf (stream
, "\tfmovem %s@(-%d,%Ra1:l),%0I0x%x\n",
1340 reg_names
[FRAME_POINTER_REGNUM
],
1341 foffset
+ fsize
, fmask
);
1344 else if (restore_from_sp
)
1347 asm_fprintf (stream
, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask
);
1349 asm_fprintf (stream
, "\tfmovem %Rsp@+,%0I0x%x\n", fmask
);
1355 asm_fprintf (stream
, "\tfmovm -%d(%s),%0I0x%x\n",
1357 reg_names
[FRAME_POINTER_REGNUM
],
1360 asm_fprintf (stream
, "\tfmovem %s@(-%d),%0I0x%x\n",
1361 reg_names
[FRAME_POINTER_REGNUM
],
1362 foffset
+ fsize
, fmask
);
1367 for (regno
= 55; regno
>= 24; regno
--)
1368 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
1373 asm_fprintf (stream
, "\tfpmovd -%d(%s,%Ra1.l), %s\n",
1375 reg_names
[FRAME_POINTER_REGNUM
],
1378 asm_fprintf (stream
, "\tfpmoved %s@(-%d,%Ra1:l), %s\n",
1379 reg_names
[FRAME_POINTER_REGNUM
],
1380 fpoffset
+ fsize
, reg_names
[regno
]);
1383 else if (restore_from_sp
)
1386 asm_fprintf (stream
, "\tfpmovd (%Rsp)+,%s\n",
1389 asm_fprintf (stream
, "\tfpmoved %Rsp@+, %s\n",
1396 asm_fprintf (stream
, "\tfpmovd -%d(%s), %s\n",
1398 reg_names
[FRAME_POINTER_REGNUM
],
1401 asm_fprintf (stream
, "\tfpmoved %s@(-%d), %s\n",
1402 reg_names
[FRAME_POINTER_REGNUM
],
1403 fpoffset
+ fsize
, reg_names
[regno
]);
1408 if (frame_pointer_needed
)
1409 fprintf (stream
, "\tunlk %s\n",
1410 reg_names
[FRAME_POINTER_REGNUM
]);
1419 asm_fprintf (stream
, "\taddq.w %0I%d,%Rsp\n", fsize
+ 4);
1421 asm_fprintf (stream
, "\taddqw %0I%d,%Rsp\n", fsize
+ 4);
1427 asm_fprintf (stream
, "\taddq.l %0I%d,%Rsp\n", fsize
+ 4);
1429 asm_fprintf (stream
, "\taddql %0I%d,%Rsp\n", fsize
+ 4);
1433 else if (fsize
+ 4 <= 16 && TARGET_CPU32
)
1435 /* On the CPU32 it is faster to use two addqw instructions to
1436 add a small integer (8 < N <= 16) to a register. */
1437 /* asm_fprintf() cannot handle %. */
1439 asm_fprintf (stream
, "\taddq.w %0I8,%Rsp\n\taddq.w %0I%d,%Rsp\n",
1442 asm_fprintf (stream
, "\taddqw %0I8,%Rsp\n\taddqw %0I%d,%Rsp\n",
1447 #endif /* not NO_ADDSUB_Q */
1448 if (fsize
+ 4 < 0x8000)
1452 /* asm_fprintf() cannot handle %. */
1454 asm_fprintf (stream
, "\tadd.w %0I%d,%Rsp\n", fsize
+ 4);
1456 asm_fprintf (stream
, "\taddw %0I%d,%Rsp\n", fsize
+ 4);
1462 asm_fprintf (stream
, "\tlea (%d,%Rsp),%Rsp\n", fsize
+ 4);
1464 asm_fprintf (stream
, "\tlea %Rsp@(%d),%Rsp\n", fsize
+ 4);
1470 /* asm_fprintf() cannot handle %. */
1472 asm_fprintf (stream
, "\tadd.l %0I%d,%Rsp\n", fsize
+ 4);
1474 asm_fprintf (stream
, "\taddl %0I%d,%Rsp\n", fsize
+ 4);
1478 if (current_function_pops_args
)
1479 asm_fprintf (stream
, "\trtd %0I%d\n", current_function_pops_args
);
1481 fprintf (stream
, "\trts\n");
1484 #endif /* ! (DPX2 && MOTOROLA) */
1485 #endif /* ! (NEWS && MOTOROLA) */
1488 /* Similar to general_operand, but exclude stack_pointer_rtx. */
1491 not_sp_operand (op
, mode
)
1493 enum machine_mode mode
;
1495 return op
!= stack_pointer_rtx
&& nonimmediate_operand (op
, mode
);
1498 /* Return TRUE if X is a valid comparison operator for the dbcc
1501 Note it rejects floating point comparison operators.
1502 (In the future we could use Fdbcc).
1504 It also rejects some comparisons when CC_NO_OVERFLOW is set. */
1507 valid_dbcc_comparison_p (x
, mode
)
1509 enum machine_mode mode ATTRIBUTE_UNUSED
;
1511 switch (GET_CODE (x
))
1513 case EQ
: case NE
: case GTU
: case LTU
:
1517 /* Reject some when CC_NO_OVERFLOW is set. This may be over
1519 case GT
: case LT
: case GE
: case LE
:
1520 return ! (cc_prev_status
.flags
& CC_NO_OVERFLOW
);
1526 /* Return non-zero if flags are currently in the 68881 flag register. */
1530 /* We could add support for these in the future */
1531 return cc_status
.flags
& CC_IN_68881
;
1534 /* Output a dbCC; jCC sequence. Note we do not handle the
1535 floating point version of this sequence (Fdbcc). We also
1536 do not handle alternative conditions when CC_NO_OVERFLOW is
1537 set. It is assumed that valid_dbcc_comparison_p and flags_in_68881 will
1538 kick those out before we get here. */
1541 output_dbcc_and_branch (operands
)
1544 switch (GET_CODE (operands
[3]))
1548 output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands
);
1550 output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands
);
1556 output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands
);
1558 output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands
);
1564 output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands
);
1566 output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands
);
1572 output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands
);
1574 output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands
);
1580 output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands
);
1582 output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands
);
1588 output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands
);
1590 output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands
);
1596 output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands
);
1598 output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands
);
1604 output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands
);
1606 output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands
);
1612 output_asm_insn ("dble %0,%l1\n\tjble %l2", operands
);
1614 output_asm_insn ("dble %0,%l1\n\tjle %l2", operands
);
1620 output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands
);
1622 output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands
);
1630 /* If the decrement is to be done in SImode, then we have
1631 to compensate for the fact that dbcc decrements in HImode. */
1632 switch (GET_MODE (operands
[0]))
1636 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands
);
1638 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands
);
1651 output_scc_di(op
, operand1
, operand2
, dest
)
1658 enum rtx_code op_code
= GET_CODE (op
);
1660 /* This does not produce a useful cc. */
1663 /* The m68k cmp.l instruction requires operand1 to be a reg as used
1664 below. Swap the operands and change the op if these requirements
1665 are not fulfilled. */
1666 if (GET_CODE (operand2
) == REG
&& GET_CODE (operand1
) != REG
)
1670 operand1
= operand2
;
1672 op_code
= swap_condition (op_code
);
1674 loperands
[0] = operand1
;
1675 if (GET_CODE (operand1
) == REG
)
1676 loperands
[1] = gen_rtx_REG (SImode
, REGNO (operand1
) + 1);
1678 loperands
[1] = adjust_address (operand1
, SImode
, 4);
1679 if (operand2
!= const0_rtx
)
1681 loperands
[2] = operand2
;
1682 if (GET_CODE (operand2
) == REG
)
1683 loperands
[3] = gen_rtx_REG (SImode
, REGNO (operand2
) + 1);
1685 loperands
[3] = adjust_address (operand2
, SImode
, 4);
1687 loperands
[4] = gen_label_rtx();
1688 if (operand2
!= const0_rtx
)
1691 #ifdef SGS_CMP_ORDER
1692 output_asm_insn ("cmp%.l %0,%2\n\tjbne %l4\n\tcmp%.l %1,%3", loperands
);
1694 output_asm_insn ("cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1", loperands
);
1697 #ifdef SGS_CMP_ORDER
1698 output_asm_insn ("cmp%.l %0,%2\n\tjne %l4\n\tcmp%.l %1,%3", loperands
);
1700 output_asm_insn ("cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1", loperands
);
1706 if (TARGET_68020
|| TARGET_5200
|| ! ADDRESS_REG_P (loperands
[0]))
1707 output_asm_insn ("tst%.l %0", loperands
);
1710 #ifdef SGS_CMP_ORDER
1711 output_asm_insn ("cmp%.w %0,%#0", loperands
);
1713 output_asm_insn ("cmp%.w %#0,%0", loperands
);
1718 output_asm_insn ("jbne %l4", loperands
);
1720 output_asm_insn ("jne %l4", loperands
);
1723 if (TARGET_68020
|| TARGET_5200
|| ! ADDRESS_REG_P (loperands
[1]))
1724 output_asm_insn ("tst%.l %1", loperands
);
1727 #ifdef SGS_CMP_ORDER
1728 output_asm_insn ("cmp%.w %1,%#0", loperands
);
1730 output_asm_insn ("cmp%.w %#0,%1", loperands
);
1735 loperands
[5] = dest
;
1740 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1741 CODE_LABEL_NUMBER (loperands
[4]));
1742 output_asm_insn ("seq %5", loperands
);
1746 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1747 CODE_LABEL_NUMBER (loperands
[4]));
1748 output_asm_insn ("sne %5", loperands
);
1752 loperands
[6] = gen_label_rtx();
1754 output_asm_insn ("shi %5\n\tjbra %l6", loperands
);
1756 output_asm_insn ("shi %5\n\tjra %l6", loperands
);
1758 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1759 CODE_LABEL_NUMBER (loperands
[4]));
1760 output_asm_insn ("sgt %5", loperands
);
1761 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1762 CODE_LABEL_NUMBER (loperands
[6]));
1766 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1767 CODE_LABEL_NUMBER (loperands
[4]));
1768 output_asm_insn ("shi %5", loperands
);
1772 loperands
[6] = gen_label_rtx();
1774 output_asm_insn ("scs %5\n\tjbra %l6", loperands
);
1776 output_asm_insn ("scs %5\n\tjra %l6", loperands
);
1778 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1779 CODE_LABEL_NUMBER (loperands
[4]));
1780 output_asm_insn ("slt %5", loperands
);
1781 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1782 CODE_LABEL_NUMBER (loperands
[6]));
1786 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1787 CODE_LABEL_NUMBER (loperands
[4]));
1788 output_asm_insn ("scs %5", loperands
);
1792 loperands
[6] = gen_label_rtx();
1794 output_asm_insn ("scc %5\n\tjbra %l6", loperands
);
1796 output_asm_insn ("scc %5\n\tjra %l6", loperands
);
1798 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1799 CODE_LABEL_NUMBER (loperands
[4]));
1800 output_asm_insn ("sge %5", loperands
);
1801 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1802 CODE_LABEL_NUMBER (loperands
[6]));
1806 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1807 CODE_LABEL_NUMBER (loperands
[4]));
1808 output_asm_insn ("scc %5", loperands
);
1812 loperands
[6] = gen_label_rtx();
1814 output_asm_insn ("sls %5\n\tjbra %l6", loperands
);
1816 output_asm_insn ("sls %5\n\tjra %l6", loperands
);
1818 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1819 CODE_LABEL_NUMBER (loperands
[4]));
1820 output_asm_insn ("sle %5", loperands
);
1821 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1822 CODE_LABEL_NUMBER (loperands
[6]));
1826 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1827 CODE_LABEL_NUMBER (loperands
[4]));
1828 output_asm_insn ("sls %5", loperands
);
1838 output_btst (operands
, countop
, dataop
, insn
, signpos
)
1840 rtx countop
, dataop
;
1844 operands
[0] = countop
;
1845 operands
[1] = dataop
;
1847 if (GET_CODE (countop
) == CONST_INT
)
1849 register int count
= INTVAL (countop
);
1850 /* If COUNT is bigger than size of storage unit in use,
1851 advance to the containing unit of same size. */
1852 if (count
> signpos
)
1854 int offset
= (count
& ~signpos
) / 8;
1855 count
= count
& signpos
;
1856 operands
[1] = dataop
= adjust_address (dataop
, QImode
, offset
);
1858 if (count
== signpos
)
1859 cc_status
.flags
= CC_NOT_POSITIVE
| CC_Z_IN_NOT_N
;
1861 cc_status
.flags
= CC_NOT_NEGATIVE
| CC_Z_IN_NOT_N
;
1863 /* These three statements used to use next_insns_test_no...
1864 but it appears that this should do the same job. */
1866 && next_insn_tests_no_inequality (insn
))
1869 && next_insn_tests_no_inequality (insn
))
1872 && next_insn_tests_no_inequality (insn
))
1875 cc_status
.flags
= CC_NOT_NEGATIVE
;
1877 return "btst %0,%1";
1880 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
1881 reference and a constant. */
1884 symbolic_operand (op
, mode
)
1886 enum machine_mode mode ATTRIBUTE_UNUSED
;
1888 switch (GET_CODE (op
))
1896 return ((GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
1897 || GET_CODE (XEXP (op
, 0)) == LABEL_REF
)
1898 && GET_CODE (XEXP (op
, 1)) == CONST_INT
);
1900 #if 0 /* Deleted, with corresponding change in m68k.h,
1901 so as to fit the specs. No CONST_DOUBLE is ever symbolic. */
1903 return GET_MODE (op
) == mode
;
1911 /* Check for sign_extend or zero_extend. Used for bit-count operands. */
1914 extend_operator(x
, mode
)
1916 enum machine_mode mode
;
1918 if (mode
!= VOIDmode
&& GET_MODE(x
) != mode
)
1920 switch (GET_CODE(x
))
1931 /* Legitimize PIC addresses. If the address is already
1932 position-independent, we return ORIG. Newly generated
1933 position-independent addresses go to REG. If we need more
1934 than one register, we lose.
1936 An address is legitimized by making an indirect reference
1937 through the Global Offset Table with the name of the symbol
1940 The assembler and linker are responsible for placing the
1941 address of the symbol in the GOT. The function prologue
1942 is responsible for initializing a5 to the starting address
1945 The assembler is also responsible for translating a symbol name
1946 into a constant displacement from the start of the GOT.
1948 A quick example may make things a little clearer:
1950 When not generating PIC code to store the value 12345 into _foo
1951 we would generate the following code:
1955 When generating PIC two transformations are made. First, the compiler
1956 loads the address of foo into a register. So the first transformation makes:
1961 The code in movsi will intercept the lea instruction and call this
1962 routine which will transform the instructions into:
1964 movel a5@(_foo:w), a0
1968 That (in a nutshell) is how *all* symbol and label references are
1972 legitimize_pic_address (orig
, mode
, reg
)
1974 enum machine_mode mode ATTRIBUTE_UNUSED
;
1978 /* First handle a simple SYMBOL_REF or LABEL_REF */
1979 if (GET_CODE (orig
) == SYMBOL_REF
|| GET_CODE (orig
) == LABEL_REF
)
1984 pic_ref
= gen_rtx_MEM (Pmode
,
1985 gen_rtx_PLUS (Pmode
,
1986 pic_offset_table_rtx
, orig
));
1987 current_function_uses_pic_offset_table
= 1;
1988 RTX_UNCHANGING_P (pic_ref
) = 1;
1989 emit_move_insn (reg
, pic_ref
);
1992 else if (GET_CODE (orig
) == CONST
)
1996 /* Make sure this is CONST has not already been legitimized */
1997 if (GET_CODE (XEXP (orig
, 0)) == PLUS
1998 && XEXP (XEXP (orig
, 0), 0) == pic_offset_table_rtx
)
2004 /* legitimize both operands of the PLUS */
2005 if (GET_CODE (XEXP (orig
, 0)) == PLUS
)
2007 base
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 0), Pmode
, reg
);
2008 orig
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 1), Pmode
,
2009 base
== reg
? 0 : reg
);
2013 if (GET_CODE (orig
) == CONST_INT
)
2014 return plus_constant (base
, INTVAL (orig
));
2015 pic_ref
= gen_rtx_PLUS (Pmode
, base
, orig
);
2016 /* Likewise, should we set special REG_NOTEs here? */
2022 typedef enum { MOVL
, SWAP
, NEGW
, NOTW
, NOTB
, MOVQ
} CONST_METHOD
;
2024 static CONST_METHOD const_method
PARAMS ((rtx
));
2026 #define USE_MOVQ(i) ((unsigned)((i) + 128) <= 255)
2029 const_method (constant
)
2035 i
= INTVAL (constant
);
2039 /* The Coldfire doesn't have byte or word operations. */
2040 /* FIXME: This may not be useful for the m68060 either */
2043 /* if -256 < N < 256 but N is not in range for a moveq
2044 N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */
2045 if (USE_MOVQ (i
^ 0xff))
2047 /* Likewise, try with not.w */
2048 if (USE_MOVQ (i
^ 0xffff))
2050 /* This is the only value where neg.w is useful */
2053 /* Try also with swap */
2055 if (USE_MOVQ ((u
>> 16) | (u
<< 16)))
2058 /* Otherwise, use move.l */
2063 const_int_cost (constant
)
2066 switch (const_method (constant
))
2069 /* Constants between -128 and 127 are cheap due to moveq */
2075 /* Constants easily generated by moveq + not.b/not.w/neg.w/swap */
2085 output_move_const_into_data_reg (operands
)
2090 i
= INTVAL (operands
[1]);
2091 switch (const_method (operands
[1]))
2094 #if defined (MOTOROLA) && !defined (CRDS)
2095 return "moveq%.l %1,%0";
2097 return "moveq %1,%0";
2100 operands
[1] = GEN_INT (i
^ 0xff);
2101 #if defined (MOTOROLA) && !defined (CRDS)
2102 return "moveq%.l %1,%0\n\tnot%.b %0";
2104 return "moveq %1,%0\n\tnot%.b %0";
2107 operands
[1] = GEN_INT (i
^ 0xffff);
2108 #if defined (MOTOROLA) && !defined (CRDS)
2109 return "moveq%.l %1,%0\n\tnot%.w %0";
2111 return "moveq %1,%0\n\tnot%.w %0";
2114 #if defined (MOTOROLA) && !defined (CRDS)
2115 return "moveq%.l %#-128,%0\n\tneg%.w %0";
2117 return "moveq %#-128,%0\n\tneg%.w %0";
2123 operands
[1] = GEN_INT ((u
<< 16) | (u
>> 16));
2124 #if defined (MOTOROLA) && !defined (CRDS)
2125 return "moveq%.l %1,%0\n\tswap %0";
2127 return "moveq %1,%0\n\tswap %0";
2131 return "move%.l %1,%0";
2138 output_move_simode_const (operands
)
2141 if (operands
[1] == const0_rtx
2142 && (DATA_REG_P (operands
[0])
2143 || GET_CODE (operands
[0]) == MEM
)
2144 /* clr insns on 68000 read before writing.
2145 This isn't so on the 68010, but we have no TARGET_68010. */
2146 && ((TARGET_68020
|| TARGET_5200
)
2147 || !(GET_CODE (operands
[0]) == MEM
2148 && MEM_VOLATILE_P (operands
[0]))))
2150 else if (operands
[1] == const0_rtx
2151 && ADDRESS_REG_P (operands
[0]))
2152 return "sub%.l %0,%0";
2153 else if (DATA_REG_P (operands
[0]))
2154 return output_move_const_into_data_reg (operands
);
2155 else if (ADDRESS_REG_P (operands
[0])
2156 && INTVAL (operands
[1]) < 0x8000
2157 && INTVAL (operands
[1]) >= -0x8000)
2158 return "move%.w %1,%0";
2159 else if (GET_CODE (operands
[0]) == MEM
2160 && GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
2161 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
2162 && INTVAL (operands
[1]) < 0x8000
2163 && INTVAL (operands
[1]) >= -0x8000)
2165 return "move%.l %1,%0";
2169 output_move_simode (operands
)
2172 if (GET_CODE (operands
[1]) == CONST_INT
)
2173 return output_move_simode_const (operands
);
2174 else if ((GET_CODE (operands
[1]) == SYMBOL_REF
2175 || GET_CODE (operands
[1]) == CONST
)
2176 && push_operand (operands
[0], SImode
))
2178 else if ((GET_CODE (operands
[1]) == SYMBOL_REF
2179 || GET_CODE (operands
[1]) == CONST
)
2180 && ADDRESS_REG_P (operands
[0]))
2181 return "lea %a1,%0";
2182 return "move%.l %1,%0";
2186 output_move_himode (operands
)
2189 if (GET_CODE (operands
[1]) == CONST_INT
)
2191 if (operands
[1] == const0_rtx
2192 && (DATA_REG_P (operands
[0])
2193 || GET_CODE (operands
[0]) == MEM
)
2194 /* clr insns on 68000 read before writing.
2195 This isn't so on the 68010, but we have no TARGET_68010. */
2196 && ((TARGET_68020
|| TARGET_5200
)
2197 || !(GET_CODE (operands
[0]) == MEM
2198 && MEM_VOLATILE_P (operands
[0]))))
2200 else if (operands
[1] == const0_rtx
2201 && ADDRESS_REG_P (operands
[0]))
2202 return "sub%.l %0,%0";
2203 else if (DATA_REG_P (operands
[0])
2204 && INTVAL (operands
[1]) < 128
2205 && INTVAL (operands
[1]) >= -128)
2207 #if defined(MOTOROLA) && !defined(CRDS)
2208 return "moveq%.l %1,%0";
2210 return "moveq %1,%0";
2213 else if (INTVAL (operands
[1]) < 0x8000
2214 && INTVAL (operands
[1]) >= -0x8000)
2215 return "move%.w %1,%0";
2217 else if (CONSTANT_P (operands
[1]))
2218 return "move%.l %1,%0";
2220 /* Recognize the insn before a tablejump, one that refers
2221 to a table of offsets. Such an insn will need to refer
2222 to a label on the insn. So output one. Use the label-number
2223 of the table of offsets to generate this label. This code,
2224 and similar code below, assumes that there will be at most one
2225 reference to each table. */
2226 if (GET_CODE (operands
[1]) == MEM
2227 && GET_CODE (XEXP (operands
[1], 0)) == PLUS
2228 && GET_CODE (XEXP (XEXP (operands
[1], 0), 1)) == LABEL_REF
2229 && GET_CODE (XEXP (XEXP (operands
[1], 0), 0)) != PLUS
)
2231 rtx labelref
= XEXP (XEXP (operands
[1], 0), 1);
2232 #if defined (MOTOROLA) && !defined (SGS_SWITCH_TABLES)
2234 asm_fprintf (asm_out_file
, "\tset %LLI%d,.+2\n",
2235 CODE_LABEL_NUMBER (XEXP (labelref
, 0)));
2237 asm_fprintf (asm_out_file
, "\t.set %LLI%d,.+2\n",
2238 CODE_LABEL_NUMBER (XEXP (labelref
, 0)));
2239 #endif /* not SGS */
2240 #else /* SGS_SWITCH_TABLES or not MOTOROLA */
2241 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "LI",
2242 CODE_LABEL_NUMBER (XEXP (labelref
, 0)));
2243 #ifdef SGS_SWITCH_TABLES
2244 /* Set flag saying we need to define the symbol
2245 LD%n (with value L%n-LI%n) at the end of the switch table. */
2246 switch_table_difference_label_flag
= 1;
2247 #endif /* SGS_SWITCH_TABLES */
2248 #endif /* SGS_SWITCH_TABLES or not MOTOROLA */
2250 #endif /* SGS_NO_LI */
2251 return "move%.w %1,%0";
2255 output_move_qimode (operands
)
2260 /* This is probably useless, since it loses for pushing a struct
2261 of several bytes a byte at a time. */
2262 /* 68k family always modifies the stack pointer by at least 2, even for
2263 byte pushes. The 5200 (coldfire) does not do this. */
2264 if (GET_CODE (operands
[0]) == MEM
2265 && GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
2266 && XEXP (XEXP (operands
[0], 0), 0) == stack_pointer_rtx
2267 && ! ADDRESS_REG_P (operands
[1])
2270 xoperands
[1] = operands
[1];
2272 = gen_rtx_MEM (QImode
,
2273 gen_rtx_PLUS (VOIDmode
, stack_pointer_rtx
, const1_rtx
));
2274 /* Just pushing a byte puts it in the high byte of the halfword. */
2275 /* We must put it in the low-order, high-numbered byte. */
2276 if (!reg_mentioned_p (stack_pointer_rtx
, operands
[1]))
2278 xoperands
[3] = stack_pointer_rtx
;
2280 output_asm_insn ("subq%.l %#2,%3\n\tmove%.b %1,%2", xoperands
);
2282 output_asm_insn ("sub%.l %#2,%3\n\tmove%.b %1,%2", xoperands
);
2286 output_asm_insn ("move%.b %1,%-\n\tmove%.b %@,%2", xoperands
);
2290 /* clr and st insns on 68000 read before writing.
2291 This isn't so on the 68010, but we have no TARGET_68010. */
2292 if (!ADDRESS_REG_P (operands
[0])
2293 && ((TARGET_68020
|| TARGET_5200
)
2294 || !(GET_CODE (operands
[0]) == MEM
&& MEM_VOLATILE_P (operands
[0]))))
2296 if (operands
[1] == const0_rtx
)
2298 if ((!TARGET_5200
|| DATA_REG_P (operands
[0]))
2299 && GET_CODE (operands
[1]) == CONST_INT
2300 && (INTVAL (operands
[1]) & 255) == 255)
2306 if (GET_CODE (operands
[1]) == CONST_INT
2307 && DATA_REG_P (operands
[0])
2308 && INTVAL (operands
[1]) < 128
2309 && INTVAL (operands
[1]) >= -128)
2311 #if defined(MOTOROLA) && !defined(CRDS)
2312 return "moveq%.l %1,%0";
2314 return "moveq %1,%0";
2317 if (operands
[1] == const0_rtx
&& ADDRESS_REG_P (operands
[0]))
2318 return "sub%.l %0,%0";
2319 if (GET_CODE (operands
[1]) != CONST_INT
&& CONSTANT_P (operands
[1]))
2320 return "move%.l %1,%0";
2321 /* 68k family (including the 5200 coldfire) does not support byte moves to
2322 from address registers. */
2323 if (ADDRESS_REG_P (operands
[0]) || ADDRESS_REG_P (operands
[1]))
2324 return "move%.w %1,%0";
2325 return "move%.b %1,%0";
2329 output_move_stricthi (operands
)
2332 if (operands
[1] == const0_rtx
2333 /* clr insns on 68000 read before writing.
2334 This isn't so on the 68010, but we have no TARGET_68010. */
2335 && ((TARGET_68020
|| TARGET_5200
)
2336 || !(GET_CODE (operands
[0]) == MEM
&& MEM_VOLATILE_P (operands
[0]))))
2338 return "move%.w %1,%0";
2342 output_move_strictqi (operands
)
2345 if (operands
[1] == const0_rtx
2346 /* clr insns on 68000 read before writing.
2347 This isn't so on the 68010, but we have no TARGET_68010. */
2348 && ((TARGET_68020
|| TARGET_5200
)
2349 || !(GET_CODE (operands
[0]) == MEM
&& MEM_VOLATILE_P (operands
[0]))))
2351 return "move%.b %1,%0";
2354 /* Return the best assembler insn template
2355 for moving operands[1] into operands[0] as a fullword. */
2358 singlemove_string (operands
)
2361 #ifdef SUPPORT_SUN_FPA
2362 if (FPA_REG_P (operands
[0]) || FPA_REG_P (operands
[1]))
2363 return "fpmoves %1,%0";
2365 if (GET_CODE (operands
[1]) == CONST_INT
)
2366 return output_move_simode_const (operands
);
2367 return "move%.l %1,%0";
2371 /* Output assembler code to perform a doubleword move insn
2372 with operands OPERANDS. */
2375 output_move_double (operands
)
2380 REGOP
, OFFSOP
, MEMOP
, PUSHOP
, POPOP
, CNSTOP
, RNDOP
2385 rtx addreg0
= 0, addreg1
= 0;
2386 int dest_overlapped_low
= 0;
2387 int size
= GET_MODE_SIZE (GET_MODE (operands
[0]));
2392 /* First classify both operands. */
2394 if (REG_P (operands
[0]))
2396 else if (offsettable_memref_p (operands
[0]))
2398 else if (GET_CODE (XEXP (operands
[0], 0)) == POST_INC
)
2400 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
)
2402 else if (GET_CODE (operands
[0]) == MEM
)
2407 if (REG_P (operands
[1]))
2409 else if (CONSTANT_P (operands
[1]))
2411 else if (offsettable_memref_p (operands
[1]))
2413 else if (GET_CODE (XEXP (operands
[1], 0)) == POST_INC
)
2415 else if (GET_CODE (XEXP (operands
[1], 0)) == PRE_DEC
)
2417 else if (GET_CODE (operands
[1]) == MEM
)
2422 /* Check for the cases that the operand constraints are not
2423 supposed to allow to happen. Abort if we get one,
2424 because generating code for these cases is painful. */
2426 if (optype0
== RNDOP
|| optype1
== RNDOP
)
2429 /* If one operand is decrementing and one is incrementing
2430 decrement the former register explicitly
2431 and change that operand into ordinary indexing. */
2433 if (optype0
== PUSHOP
&& optype1
== POPOP
)
2435 operands
[0] = XEXP (XEXP (operands
[0], 0), 0);
2437 output_asm_insn ("sub%.l %#12,%0", operands
);
2439 output_asm_insn ("subq%.l %#8,%0", operands
);
2440 if (GET_MODE (operands
[1]) == XFmode
)
2441 operands
[0] = gen_rtx_MEM (XFmode
, operands
[0]);
2442 else if (GET_MODE (operands
[0]) == DFmode
)
2443 operands
[0] = gen_rtx_MEM (DFmode
, operands
[0]);
2445 operands
[0] = gen_rtx_MEM (DImode
, operands
[0]);
2448 if (optype0
== POPOP
&& optype1
== PUSHOP
)
2450 operands
[1] = XEXP (XEXP (operands
[1], 0), 0);
2452 output_asm_insn ("sub%.l %#12,%1", operands
);
2454 output_asm_insn ("subq%.l %#8,%1", operands
);
2455 if (GET_MODE (operands
[1]) == XFmode
)
2456 operands
[1] = gen_rtx_MEM (XFmode
, operands
[1]);
2457 else if (GET_MODE (operands
[1]) == DFmode
)
2458 operands
[1] = gen_rtx_MEM (DFmode
, operands
[1]);
2460 operands
[1] = gen_rtx_MEM (DImode
, operands
[1]);
2464 /* If an operand is an unoffsettable memory ref, find a register
2465 we can increment temporarily to make it refer to the second word. */
2467 if (optype0
== MEMOP
)
2468 addreg0
= find_addr_reg (XEXP (operands
[0], 0));
2470 if (optype1
== MEMOP
)
2471 addreg1
= find_addr_reg (XEXP (operands
[1], 0));
2473 /* Ok, we can do one word at a time.
2474 Normally we do the low-numbered word first,
2475 but if either operand is autodecrementing then we
2476 do the high-numbered word first.
2478 In either case, set up in LATEHALF the operands to use
2479 for the high-numbered word and in some cases alter the
2480 operands in OPERANDS to be suitable for the low-numbered word. */
2484 if (optype0
== REGOP
)
2486 latehalf
[0] = gen_rtx_REG (SImode
, REGNO (operands
[0]) + 2);
2487 middlehalf
[0] = gen_rtx_REG (SImode
, REGNO (operands
[0]) + 1);
2489 else if (optype0
== OFFSOP
)
2491 middlehalf
[0] = adjust_address (operands
[0], SImode
, 4);
2492 latehalf
[0] = adjust_address (operands
[0], SImode
, size
- 4);
2496 middlehalf
[0] = operands
[0];
2497 latehalf
[0] = operands
[0];
2500 if (optype1
== REGOP
)
2502 latehalf
[1] = gen_rtx_REG (SImode
, REGNO (operands
[1]) + 2);
2503 middlehalf
[1] = gen_rtx_REG (SImode
, REGNO (operands
[1]) + 1);
2505 else if (optype1
== OFFSOP
)
2507 middlehalf
[1] = adjust_address (operands
[1], SImode
, 4);
2508 latehalf
[1] = adjust_address (operands
[1], SImode
, size
- 4);
2510 else if (optype1
== CNSTOP
)
2512 if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
2517 REAL_VALUE_FROM_CONST_DOUBLE (r
, operands
[1]);
2518 REAL_VALUE_TO_TARGET_LONG_DOUBLE (r
, l
);
2519 operands
[1] = GEN_INT (l
[0]);
2520 middlehalf
[1] = GEN_INT (l
[1]);
2521 latehalf
[1] = GEN_INT (l
[2]);
2523 else if (CONSTANT_P (operands
[1]))
2525 /* actually, no non-CONST_DOUBLE constant should ever
2528 if (GET_CODE (operands
[1]) == CONST_INT
&& INTVAL (operands
[1]) < 0)
2529 latehalf
[1] = constm1_rtx
;
2531 latehalf
[1] = const0_rtx
;
2536 middlehalf
[1] = operands
[1];
2537 latehalf
[1] = operands
[1];
2541 /* size is not 12: */
2543 if (optype0
== REGOP
)
2544 latehalf
[0] = gen_rtx_REG (SImode
, REGNO (operands
[0]) + 1);
2545 else if (optype0
== OFFSOP
)
2546 latehalf
[0] = adjust_address (operands
[0], SImode
, size
- 4);
2548 latehalf
[0] = operands
[0];
2550 if (optype1
== REGOP
)
2551 latehalf
[1] = gen_rtx_REG (SImode
, REGNO (operands
[1]) + 1);
2552 else if (optype1
== OFFSOP
)
2553 latehalf
[1] = adjust_address (operands
[1], SImode
, size
- 4);
2554 else if (optype1
== CNSTOP
)
2555 split_double (operands
[1], &operands
[1], &latehalf
[1]);
2557 latehalf
[1] = operands
[1];
2560 /* If insn is effectively movd N(sp),-(sp) then we will do the
2561 high word first. We should use the adjusted operand 1 (which is N+4(sp))
2562 for the low word as well, to compensate for the first decrement of sp. */
2563 if (optype0
== PUSHOP
2564 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
2565 && reg_overlap_mentioned_p (stack_pointer_rtx
, operands
[1]))
2566 operands
[1] = middlehalf
[1] = latehalf
[1];
2568 /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
2569 if the upper part of reg N does not appear in the MEM, arrange to
2570 emit the move late-half first. Otherwise, compute the MEM address
2571 into the upper part of N and use that as a pointer to the memory
2573 if (optype0
== REGOP
2574 && (optype1
== OFFSOP
|| optype1
== MEMOP
))
2576 rtx testlow
= gen_rtx_REG (SImode
, REGNO (operands
[0]));
2578 if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0))
2579 && reg_overlap_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
2581 /* If both halves of dest are used in the src memory address,
2582 compute the address into latehalf of dest.
2583 Note that this can't happen if the dest is two data regs. */
2585 xops
[0] = latehalf
[0];
2586 xops
[1] = XEXP (operands
[1], 0);
2587 output_asm_insn ("lea %a1,%0", xops
);
2588 if (GET_MODE (operands
[1]) == XFmode
)
2590 operands
[1] = gen_rtx_MEM (XFmode
, latehalf
[0]);
2591 middlehalf
[1] = adjust_address (operands
[1], DImode
, size
- 8);
2592 latehalf
[1] = adjust_address (operands
[1], DImode
, size
- 4);
2596 operands
[1] = gen_rtx_MEM (DImode
, latehalf
[0]);
2597 latehalf
[1] = adjust_address (operands
[1], DImode
, size
- 4);
2601 && reg_overlap_mentioned_p (middlehalf
[0],
2602 XEXP (operands
[1], 0)))
2604 /* Check for two regs used by both source and dest.
2605 Note that this can't happen if the dest is all data regs.
2606 It can happen if the dest is d6, d7, a0.
2607 But in that case, latehalf is an addr reg, so
2608 the code at compadr does ok. */
2610 if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0))
2611 || reg_overlap_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
2614 /* JRV says this can't happen: */
2615 if (addreg0
|| addreg1
)
2618 /* Only the middle reg conflicts; simply put it last. */
2619 output_asm_insn (singlemove_string (operands
), operands
);
2620 output_asm_insn (singlemove_string (latehalf
), latehalf
);
2621 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
2624 else if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0)))
2625 /* If the low half of dest is mentioned in the source memory
2626 address, the arrange to emit the move late half first. */
2627 dest_overlapped_low
= 1;
2630 /* If one or both operands autodecrementing,
2631 do the two words, high-numbered first. */
2633 /* Likewise, the first move would clobber the source of the second one,
2634 do them in the other order. This happens only for registers;
2635 such overlap can't happen in memory unless the user explicitly
2636 sets it up, and that is an undefined circumstance. */
2638 if (optype0
== PUSHOP
|| optype1
== PUSHOP
2639 || (optype0
== REGOP
&& optype1
== REGOP
2640 && ((middlehalf
[1] && REGNO (operands
[0]) == REGNO (middlehalf
[1]))
2641 || REGNO (operands
[0]) == REGNO (latehalf
[1])))
2642 || dest_overlapped_low
)
2644 /* Make any unoffsettable addresses point at high-numbered word. */
2648 output_asm_insn ("addq%.l %#8,%0", &addreg0
);
2650 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
2655 output_asm_insn ("addq%.l %#8,%0", &addreg1
);
2657 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
2661 output_asm_insn (singlemove_string (latehalf
), latehalf
);
2663 /* Undo the adds we just did. */
2665 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
2667 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
2671 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
2673 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
2675 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
2678 /* Do low-numbered word. */
2679 return singlemove_string (operands
);
2682 /* Normal case: do the two words, low-numbered first. */
2684 output_asm_insn (singlemove_string (operands
), operands
);
2686 /* Do the middle one of the three words for long double */
2690 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
2692 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
2694 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
2697 /* Make any unoffsettable addresses point at high-numbered word. */
2699 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
2701 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
2704 output_asm_insn (singlemove_string (latehalf
), latehalf
);
2706 /* Undo the adds we just did. */
2710 output_asm_insn ("subq%.l %#8,%0", &addreg0
);
2712 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
2717 output_asm_insn ("subq%.l %#8,%0", &addreg1
);
2719 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
2725 /* Return a REG that occurs in ADDR with coefficient 1.
2726 ADDR can be effectively incremented by incrementing REG. */
2729 find_addr_reg (addr
)
2732 while (GET_CODE (addr
) == PLUS
)
2734 if (GET_CODE (XEXP (addr
, 0)) == REG
)
2735 addr
= XEXP (addr
, 0);
2736 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
2737 addr
= XEXP (addr
, 1);
2738 else if (CONSTANT_P (XEXP (addr
, 0)))
2739 addr
= XEXP (addr
, 1);
2740 else if (CONSTANT_P (XEXP (addr
, 1)))
2741 addr
= XEXP (addr
, 0);
2745 if (GET_CODE (addr
) == REG
)
2750 /* Output assembler code to perform a 32 bit 3 operand add. */
2753 output_addsi3 (operands
)
2756 if (! operands_match_p (operands
[0], operands
[1]))
2758 if (!ADDRESS_REG_P (operands
[1]))
2760 rtx tmp
= operands
[1];
2762 operands
[1] = operands
[2];
2766 /* These insns can result from reloads to access
2767 stack slots over 64k from the frame pointer. */
2768 if (GET_CODE (operands
[2]) == CONST_INT
2769 && INTVAL (operands
[2]) + 0x8000 >= (unsigned) 0x10000)
2770 return "move%.l %2,%0\n\tadd%.l %1,%0";
2772 if (GET_CODE (operands
[2]) == REG
)
2773 return "lea 0(%1,%2.l),%0";
2775 return "lea %c2(%1),%0";
2778 if (GET_CODE (operands
[2]) == REG
)
2779 return "lea (%1,%2.l),%0";
2781 return "lea (%c2,%1),%0";
2782 #else /* not MOTOROLA (MIT syntax) */
2783 if (GET_CODE (operands
[2]) == REG
)
2784 return "lea %1@(0,%2:l),%0";
2786 return "lea %1@(%c2),%0";
2787 #endif /* not MOTOROLA */
2788 #endif /* not SGS */
2790 if (GET_CODE (operands
[2]) == CONST_INT
)
2793 if (INTVAL (operands
[2]) > 0
2794 && INTVAL (operands
[2]) <= 8)
2795 return "addq%.l %2,%0";
2796 if (INTVAL (operands
[2]) < 0
2797 && INTVAL (operands
[2]) >= -8)
2799 operands
[2] = GEN_INT (- INTVAL (operands
[2]));
2800 return "subq%.l %2,%0";
2802 /* On the CPU32 it is faster to use two addql instructions to
2803 add a small integer (8 < N <= 16) to a register.
2804 Likewise for subql. */
2805 if (TARGET_CPU32
&& REG_P (operands
[0]))
2807 if (INTVAL (operands
[2]) > 8
2808 && INTVAL (operands
[2]) <= 16)
2810 operands
[2] = GEN_INT (INTVAL (operands
[2]) - 8);
2811 return "addq%.l %#8,%0\n\taddq%.l %2,%0";
2813 if (INTVAL (operands
[2]) < -8
2814 && INTVAL (operands
[2]) >= -16)
2816 operands
[2] = GEN_INT (- INTVAL (operands
[2]) - 8);
2817 return "subq%.l %#8,%0\n\tsubq%.l %2,%0";
2821 if (ADDRESS_REG_P (operands
[0])
2822 && INTVAL (operands
[2]) >= -0x8000
2823 && INTVAL (operands
[2]) < 0x8000)
2826 return "add%.w %2,%0";
2829 return "lea (%c2,%0),%0";
2831 return "lea %0@(%c2),%0";
2835 return "add%.l %2,%0";
2838 /* Store in cc_status the expressions that the condition codes will
2839 describe after execution of an instruction whose pattern is EXP.
2840 Do not alter them if the instruction would not alter the cc's. */
2842 /* On the 68000, all the insns to store in an address register fail to
2843 set the cc's. However, in some cases these instructions can make it
2844 possibly invalid to use the saved cc's. In those cases we clear out
2845 some or all of the saved cc's so they won't be used. */
2848 notice_update_cc (exp
, insn
)
2852 /* If the cc is being set from the fpa and the expression is not an
2853 explicit floating point test instruction (which has code to deal with
2854 this), reinit the CC. */
2855 if (((cc_status
.value1
&& FPA_REG_P (cc_status
.value1
))
2856 || (cc_status
.value2
&& FPA_REG_P (cc_status
.value2
)))
2857 && !(GET_CODE (exp
) == PARALLEL
2858 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
2859 && XEXP (XVECEXP (exp
, 0, 0), 0) == cc0_rtx
))
2863 else if (GET_CODE (exp
) == SET
)
2865 if (GET_CODE (SET_SRC (exp
)) == CALL
)
2869 else if (ADDRESS_REG_P (SET_DEST (exp
)))
2871 if (cc_status
.value1
&& modified_in_p (cc_status
.value1
, insn
))
2872 cc_status
.value1
= 0;
2873 if (cc_status
.value2
&& modified_in_p (cc_status
.value2
, insn
))
2874 cc_status
.value2
= 0;
2876 else if (!FP_REG_P (SET_DEST (exp
))
2877 && SET_DEST (exp
) != cc0_rtx
2878 && (FP_REG_P (SET_SRC (exp
))
2879 || GET_CODE (SET_SRC (exp
)) == FIX
2880 || GET_CODE (SET_SRC (exp
)) == FLOAT_TRUNCATE
2881 || GET_CODE (SET_SRC (exp
)) == FLOAT_EXTEND
))
2885 /* A pair of move insns doesn't produce a useful overall cc. */
2886 else if (!FP_REG_P (SET_DEST (exp
))
2887 && !FP_REG_P (SET_SRC (exp
))
2888 && GET_MODE_SIZE (GET_MODE (SET_SRC (exp
))) > 4
2889 && (GET_CODE (SET_SRC (exp
)) == REG
2890 || GET_CODE (SET_SRC (exp
)) == MEM
2891 || GET_CODE (SET_SRC (exp
)) == CONST_DOUBLE
))
2895 else if (GET_CODE (SET_SRC (exp
)) == CALL
)
2899 else if (XEXP (exp
, 0) != pc_rtx
)
2901 cc_status
.flags
= 0;
2902 cc_status
.value1
= XEXP (exp
, 0);
2903 cc_status
.value2
= XEXP (exp
, 1);
2906 else if (GET_CODE (exp
) == PARALLEL
2907 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
)
2909 if (ADDRESS_REG_P (XEXP (XVECEXP (exp
, 0, 0), 0)))
2911 else if (XEXP (XVECEXP (exp
, 0, 0), 0) != pc_rtx
)
2913 cc_status
.flags
= 0;
2914 cc_status
.value1
= XEXP (XVECEXP (exp
, 0, 0), 0);
2915 cc_status
.value2
= XEXP (XVECEXP (exp
, 0, 0), 1);
2920 if (cc_status
.value2
!= 0
2921 && ADDRESS_REG_P (cc_status
.value2
)
2922 && GET_MODE (cc_status
.value2
) == QImode
)
2924 if (cc_status
.value2
!= 0
2925 && !(cc_status
.value1
&& FPA_REG_P (cc_status
.value1
)))
2926 switch (GET_CODE (cc_status
.value2
))
2928 case PLUS
: case MINUS
: case MULT
:
2929 case DIV
: case UDIV
: case MOD
: case UMOD
: case NEG
:
2930 #if 0 /* These instructions always clear the overflow bit */
2931 case ASHIFT
: case ASHIFTRT
: case LSHIFTRT
:
2932 case ROTATE
: case ROTATERT
:
2934 if (GET_MODE (cc_status
.value2
) != VOIDmode
)
2935 cc_status
.flags
|= CC_NO_OVERFLOW
;
2938 /* (SET r1 (ZERO_EXTEND r2)) on this machine
2939 ends with a move insn moving r2 in r2's mode.
2940 Thus, the cc's are set for r2.
2941 This can set N bit spuriously. */
2942 cc_status
.flags
|= CC_NOT_NEGATIVE
;
2947 if (cc_status
.value1
&& GET_CODE (cc_status
.value1
) == REG
2949 && reg_overlap_mentioned_p (cc_status
.value1
, cc_status
.value2
))
2950 cc_status
.value2
= 0;
2951 if (((cc_status
.value1
&& FP_REG_P (cc_status
.value1
))
2952 || (cc_status
.value2
&& FP_REG_P (cc_status
.value2
)))
2953 && !((cc_status
.value1
&& FPA_REG_P (cc_status
.value1
))
2954 || (cc_status
.value2
&& FPA_REG_P (cc_status
.value2
))))
2955 cc_status
.flags
= CC_IN_68881
;
2959 output_move_const_double (operands
)
2962 #ifdef SUPPORT_SUN_FPA
2963 if (TARGET_FPA
&& FPA_REG_P (operands
[0]))
2965 int code
= standard_sun_fpa_constant_p (operands
[1]);
2969 static char buf
[40];
2971 sprintf (buf
, "fpmove%%.d %%%%%d,%%0", code
& 0x1ff);
2974 return "fpmove%.d %1,%0";
2979 int code
= standard_68881_constant_p (operands
[1]);
2983 static char buf
[40];
2985 sprintf (buf
, "fmovecr %%#0x%x,%%0", code
& 0xff);
2988 return "fmove%.d %1,%0";
2993 output_move_const_single (operands
)
2996 #ifdef SUPPORT_SUN_FPA
2999 int code
= standard_sun_fpa_constant_p (operands
[1]);
3003 static char buf
[40];
3005 sprintf (buf
, "fpmove%%.s %%%%%d,%%0", code
& 0x1ff);
3008 return "fpmove%.s %1,%0";
3011 #endif /* defined SUPPORT_SUN_FPA */
3013 int code
= standard_68881_constant_p (operands
[1]);
3017 static char buf
[40];
3019 sprintf (buf
, "fmovecr %%#0x%x,%%0", code
& 0xff);
3022 return "fmove%.s %f1,%0";
3026 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
3027 from the "fmovecr" instruction.
3028 The value, anded with 0xff, gives the code to use in fmovecr
3029 to get the desired constant. */
3031 /* This code has been fixed for cross-compilation. */
3033 static int inited_68881_table
= 0;
3035 static const char *const strings_68881
[7] = {
3045 static const int codes_68881
[7] = {
3055 REAL_VALUE_TYPE values_68881
[7];
3057 /* Set up values_68881 array by converting the decimal values
3058 strings_68881 to binary. */
3065 enum machine_mode mode
;
3068 for (i
= 0; i
< 7; i
++)
3072 r
= REAL_VALUE_ATOF (strings_68881
[i
], mode
);
3073 values_68881
[i
] = r
;
3075 inited_68881_table
= 1;
3079 standard_68881_constant_p (x
)
3085 #ifdef NO_ASM_FMOVECR
3089 /* fmovecr must be emulated on the 68040 and 68060, so it shouldn't be
3090 used at all on those chips. */
3091 if (TARGET_68040
|| TARGET_68060
)
3094 #ifndef REAL_ARITHMETIC
3095 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
3096 if (! flag_pretend_float
)
3101 if (! inited_68881_table
)
3102 init_68881_table ();
3104 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
3106 /* Use REAL_VALUES_IDENTICAL instead of REAL_VALUES_EQUAL so that -0.0
3108 for (i
= 0; i
< 6; i
++)
3110 if (REAL_VALUES_IDENTICAL (r
, values_68881
[i
]))
3111 return (codes_68881
[i
]);
3114 if (GET_MODE (x
) == SFmode
)
3117 if (REAL_VALUES_EQUAL (r
, values_68881
[6]))
3118 return (codes_68881
[6]);
3120 /* larger powers of ten in the constants ram are not used
3121 because they are not equal to a `double' C constant. */
3125 /* If X is a floating-point constant, return the logarithm of X base 2,
3126 or 0 if X is not a power of 2. */
3129 floating_exact_log2 (x
)
3132 REAL_VALUE_TYPE r
, r1
;
3135 #ifndef REAL_ARITHMETIC
3136 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
3137 if (! flag_pretend_float
)
3142 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
3144 if (REAL_VALUES_LESS (r
, dconst0
))
3149 while (REAL_VALUES_LESS (r1
, r
))
3151 r1
= REAL_VALUE_LDEXP (dconst1
, i
);
3152 if (REAL_VALUES_EQUAL (r1
, r
))
3159 #ifdef SUPPORT_SUN_FPA
3160 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
3161 from the Sun FPA's constant RAM.
3162 The value returned, anded with 0x1ff, gives the code to use in fpmove
3163 to get the desired constant. */
3165 static int inited_FPA_table
= 0;
3167 static const char *const strings_FPA
[38] = {
3168 /* small rationals */
3181 /* Decimal equivalents of double precision values */
3182 "2.718281828459045091", /* D_E */
3183 "6.283185307179586477", /* 2 pi */
3184 "3.141592653589793116", /* D_PI */
3185 "1.570796326794896619", /* pi/2 */
3186 "1.414213562373095145", /* D_SQRT2 */
3187 "0.7071067811865475244", /* 1/sqrt(2) */
3188 "-1.570796326794896619", /* -pi/2 */
3189 "1.442695040888963387", /* D_LOG2ofE */
3190 "3.321928024887362182", /* D_LOG2of10 */
3191 "0.6931471805599452862", /* D_LOGEof2 */
3192 "2.302585092994045901", /* D_LOGEof10 */
3193 "0.3010299956639811980", /* D_LOG10of2 */
3194 "0.4342944819032518167", /* D_LOG10ofE */
3195 /* Decimal equivalents of single precision values */
3196 "2.718281745910644531", /* S_E */
3197 "6.283185307179586477", /* 2 pi */
3198 "3.141592741012573242", /* S_PI */
3199 "1.570796326794896619", /* pi/2 */
3200 "1.414213538169860840", /* S_SQRT2 */
3201 "0.7071067811865475244", /* 1/sqrt(2) */
3202 "-1.570796326794896619", /* -pi/2 */
3203 "1.442695021629333496", /* S_LOG2ofE */
3204 "3.321928024291992188", /* S_LOG2of10 */
3205 "0.6931471824645996094", /* S_LOGEof2 */
3206 "2.302585124969482442", /* S_LOGEof10 */
3207 "0.3010300099849700928", /* S_LOG10of2 */
3208 "0.4342944920063018799", /* S_LOG10ofE */
3212 static const int codes_FPA
[38] = {
3213 /* small rationals */
3226 /* double precision */
3240 /* single precision */
3256 REAL_VALUE_TYPE values_FPA
[38];
3258 /* This code has been fixed for cross-compilation. */
3260 static void init_FPA_table
PARAMS ((void));
3264 enum machine_mode mode
;
3269 for (i
= 0; i
< 38; i
++)
3273 r
= REAL_VALUE_ATOF (strings_FPA
[i
], mode
);
3276 inited_FPA_table
= 1;
3281 standard_sun_fpa_constant_p (x
)
3287 #ifndef REAL_ARITHMETIC
3288 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
3289 if (! flag_pretend_float
)
3294 if (! inited_FPA_table
)
3297 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
3299 for (i
=0; i
<12; i
++)
3301 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
3302 return (codes_FPA
[i
]);
3305 if (GET_MODE (x
) == SFmode
)
3307 for (i
=25; i
<38; i
++)
3309 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
3310 return (codes_FPA
[i
]);
3315 for (i
=12; i
<25; i
++)
3317 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
3318 return (codes_FPA
[i
]);
3323 #endif /* define SUPPORT_SUN_FPA */
3325 /* A C compound statement to output to stdio stream STREAM the
3326 assembler syntax for an instruction operand X. X is an RTL
3329 CODE is a value that can be used to specify one of several ways
3330 of printing the operand. It is used when identical operands
3331 must be printed differently depending on the context. CODE
3332 comes from the `%' specification that was used to request
3333 printing of the operand. If the specification was just `%DIGIT'
3334 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
3335 is the ASCII code for LTR.
3337 If X is a register, this macro should print the register's name.
3338 The names can be found in an array `reg_names' whose type is
3339 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
3341 When the machine description has a specification `%PUNCT' (a `%'
3342 followed by a punctuation character), this macro is called with
3343 a null pointer for X and the punctuation character for CODE.
3345 The m68k specific codes are:
3347 '.' for dot needed in Motorola-style opcode names.
3348 '-' for an operand pushing on the stack:
3349 sp@-, -(sp) or -(%sp) depending on the style of syntax.
3350 '+' for an operand pushing on the stack:
3351 sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
3352 '@' for a reference to the top word on the stack:
3353 sp@, (sp) or (%sp) depending on the style of syntax.
3354 '#' for an immediate operand prefix (# in MIT and Motorola syntax
3355 but & in SGS syntax, $ in CRDS/UNOS syntax).
3356 '!' for the cc register (used in an `and to cc' insn).
3357 '$' for the letter `s' in an op code, but only on the 68040.
3358 '&' for the letter `d' in an op code, but only on the 68040.
3359 '/' for register prefix needed by longlong.h.
3361 'b' for byte insn (no effect, on the Sun; this is for the ISI).
3362 'd' to force memory addressing to be absolute, not relative.
3363 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
3364 'o' for operands to go directly to output_operand_address (bypassing
3365 print_operand_address--used only for SYMBOL_REFs under TARGET_PCREL)
3366 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
3367 than directly). Second part of 'y' below.
3368 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
3369 or print pair of registers as rx:ry.
3370 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
3371 CONST_DOUBLE's as SunFPA constant RAM registers if
3372 possible, so it should not be used except for the SunFPA.
3377 print_operand (file
, op
, letter
)
3378 FILE *file
; /* file to write to */
3379 rtx op
; /* operand to print */
3380 int letter
; /* %<letter> or 0 */
3382 #ifdef SUPPORT_SUN_FPA
3388 #if defined (MOTOROLA) && !defined (CRDS)
3389 asm_fprintf (file
, ".");
3392 else if (letter
== '#')
3394 asm_fprintf (file
, "%0I");
3396 else if (letter
== '-')
3399 asm_fprintf (file
, "-(%Rsp)");
3401 asm_fprintf (file
, "%Rsp@-");
3404 else if (letter
== '+')
3407 asm_fprintf (file
, "(%Rsp)+");
3409 asm_fprintf (file
, "%Rsp@+");
3412 else if (letter
== '@')
3415 asm_fprintf (file
, "(%Rsp)");
3417 asm_fprintf (file
, "%Rsp@");
3420 else if (letter
== '!')
3422 asm_fprintf (file
, "%Rfpcr");
3424 else if (letter
== '$')
3426 if (TARGET_68040_ONLY
)
3428 fprintf (file
, "s");
3431 else if (letter
== '&')
3433 if (TARGET_68040_ONLY
)
3435 fprintf (file
, "d");
3438 else if (letter
== '/')
3440 asm_fprintf (file
, "%R");
3442 else if (letter
== 'o')
3444 /* This is only for direct addresses with TARGET_PCREL */
3445 if (GET_CODE (op
) != MEM
|| GET_CODE (XEXP (op
, 0)) != SYMBOL_REF
3448 output_addr_const (file
, XEXP (op
, 0));
3450 else if (GET_CODE (op
) == REG
)
3452 #ifdef SUPPORT_SUN_FPA
3454 && (letter
== 'y' || letter
== 'x')
3455 && GET_MODE (op
) == DFmode
)
3457 fprintf (file
, "%s:%s", reg_names
[REGNO (op
)],
3458 reg_names
[REGNO (op
)+1]);
3464 /* Print out the second register name of a register pair.
3465 I.e., R (6) => 7. */
3466 fputs (reg_names
[REGNO (op
) + 1], file
);
3468 fputs (reg_names
[REGNO (op
)], file
);
3471 else if (GET_CODE (op
) == MEM
)
3473 output_address (XEXP (op
, 0));
3474 if (letter
== 'd' && ! TARGET_68020
3475 && CONSTANT_ADDRESS_P (XEXP (op
, 0))
3476 && !(GET_CODE (XEXP (op
, 0)) == CONST_INT
3477 && INTVAL (XEXP (op
, 0)) < 0x8000
3478 && INTVAL (XEXP (op
, 0)) >= -0x8000))
3481 fprintf (file
, ".l");
3483 fprintf (file
, ":l");
3487 #ifdef SUPPORT_SUN_FPA
3488 else if ((letter
== 'y' || letter
== 'w')
3489 && GET_CODE (op
) == CONST_DOUBLE
3490 && (i
= standard_sun_fpa_constant_p (op
)))
3492 fprintf (file
, "%%%d", i
& 0x1ff);
3495 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == SFmode
)
3498 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
3499 ASM_OUTPUT_FLOAT_OPERAND (letter
, file
, r
);
3501 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == XFmode
)
3504 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
3505 ASM_OUTPUT_LONG_DOUBLE_OPERAND (file
, r
);
3507 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == DFmode
)
3510 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
3511 ASM_OUTPUT_DOUBLE_OPERAND (file
, r
);
3515 /* Use `print_operand_address' instead of `output_addr_const'
3516 to ensure that we print relevant PIC stuff. */
3517 asm_fprintf (file
, "%0I");
3519 && (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == CONST
))
3520 print_operand_address (file
, op
);
3522 output_addr_const (file
, op
);
3527 /* A C compound statement to output to stdio stream STREAM the
3528 assembler syntax for an instruction operand that is a memory
3529 reference whose address is ADDR. ADDR is an RTL expression.
3531 Note that this contains a kludge that knows that the only reason
3532 we have an address (plus (label_ref...) (reg...)) when not generating
3533 PIC code is in the insn before a tablejump, and we know that m68k.md
3534 generates a label LInnn: on such an insn.
3536 It is possible for PIC to generate a (plus (label_ref...) (reg...))
3537 and we handle that just like we would a (plus (symbol_ref...) (reg...)).
3539 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
3540 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
3541 we want. This difference can be accommodated by using an assembler
3542 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
3543 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
3544 macro. See m68k/sgs.h for an example; for versions without the bug.
3545 Some assemblers refuse all the above solutions. The workaround is to
3546 emit "K(pc,d0.l*2)" with K being a small constant known to give the
3549 They also do not like things like "pea 1.w", so we simple leave off
3550 the .w on small constants.
3552 This routine is responsible for distinguishing between -fpic and -fPIC
3553 style relocations in an address. When generating -fpic code the
3554 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating
3555 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
3557 #ifndef ASM_OUTPUT_CASE_FETCH
3560 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
3561 asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
3563 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
3564 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
3567 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
3568 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
3570 #endif /* ASM_OUTPUT_CASE_FETCH */
3573 print_operand_address (file
, addr
)
3577 register rtx reg1
, reg2
, breg
, ireg
;
3580 switch (GET_CODE (addr
))
3584 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
3586 fprintf (file
, "%s@", reg_names
[REGNO (addr
)]);
3591 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
3593 fprintf (file
, "%s@-", reg_names
[REGNO (XEXP (addr
, 0))]);
3598 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
3600 fprintf (file
, "%s@+", reg_names
[REGNO (XEXP (addr
, 0))]);
3604 reg1
= reg2
= ireg
= breg
= offset
= 0;
3605 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0)))
3607 offset
= XEXP (addr
, 0);
3608 addr
= XEXP (addr
, 1);
3610 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1)))
3612 offset
= XEXP (addr
, 1);
3613 addr
= XEXP (addr
, 0);
3615 if (GET_CODE (addr
) != PLUS
)
3619 else if (GET_CODE (XEXP (addr
, 0)) == SIGN_EXTEND
)
3621 reg1
= XEXP (addr
, 0);
3622 addr
= XEXP (addr
, 1);
3624 else if (GET_CODE (XEXP (addr
, 1)) == SIGN_EXTEND
)
3626 reg1
= XEXP (addr
, 1);
3627 addr
= XEXP (addr
, 0);
3629 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3631 reg1
= XEXP (addr
, 0);
3632 addr
= XEXP (addr
, 1);
3634 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
3636 reg1
= XEXP (addr
, 1);
3637 addr
= XEXP (addr
, 0);
3639 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
3641 reg1
= XEXP (addr
, 0);
3642 addr
= XEXP (addr
, 1);
3644 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
3646 reg1
= XEXP (addr
, 1);
3647 addr
= XEXP (addr
, 0);
3649 if (GET_CODE (addr
) == REG
|| GET_CODE (addr
) == MULT
3650 || GET_CODE (addr
) == SIGN_EXTEND
)
3662 #if 0 /* for OLD_INDEXING */
3663 else if (GET_CODE (addr
) == PLUS
)
3665 if (GET_CODE (XEXP (addr
, 0)) == REG
)
3667 reg2
= XEXP (addr
, 0);
3668 addr
= XEXP (addr
, 1);
3670 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
3672 reg2
= XEXP (addr
, 1);
3673 addr
= XEXP (addr
, 0);
3685 if ((reg1
&& (GET_CODE (reg1
) == SIGN_EXTEND
3686 || GET_CODE (reg1
) == MULT
))
3687 || (reg2
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2
))))
3692 else if (reg1
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1
)))
3697 if (ireg
!= 0 && breg
== 0 && GET_CODE (addr
) == LABEL_REF
3698 && ! (flag_pic
&& ireg
== pic_offset_table_rtx
))
3701 if (GET_CODE (ireg
) == MULT
)
3703 scale
= INTVAL (XEXP (ireg
, 1));
3704 ireg
= XEXP (ireg
, 0);
3706 if (GET_CODE (ireg
) == SIGN_EXTEND
)
3708 ASM_OUTPUT_CASE_FETCH (file
,
3709 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
3710 reg_names
[REGNO (XEXP (ireg
, 0))]);
3711 fprintf (file
, "w");
3715 ASM_OUTPUT_CASE_FETCH (file
,
3716 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
3717 reg_names
[REGNO (ireg
)]);
3718 fprintf (file
, "l");
3723 fprintf (file
, "*%d", scale
);
3725 fprintf (file
, ":%d", scale
);
3731 if (breg
!= 0 && ireg
== 0 && GET_CODE (addr
) == LABEL_REF
3732 && ! (flag_pic
&& breg
== pic_offset_table_rtx
))
3734 ASM_OUTPUT_CASE_FETCH (file
,
3735 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
3736 reg_names
[REGNO (breg
)]);
3737 fprintf (file
, "l)");
3740 if (ireg
!= 0 || breg
!= 0)
3747 if (! flag_pic
&& addr
&& GET_CODE (addr
) == LABEL_REF
)
3754 output_addr_const (file
, addr
);
3755 if (flag_pic
&& (breg
== pic_offset_table_rtx
))
3757 fprintf (file
, "@GOT");
3759 fprintf (file
, ".w");
3762 fprintf (file
, "(%s", reg_names
[REGNO (breg
)]);
3768 fprintf (file
, "%s@(", reg_names
[REGNO (breg
)]);
3771 output_addr_const (file
, addr
);
3772 if ((flag_pic
== 1) && (breg
== pic_offset_table_rtx
))
3773 fprintf (file
, ":w");
3774 if ((flag_pic
== 2) && (breg
== pic_offset_table_rtx
))
3775 fprintf (file
, ":l");
3777 if (addr
!= 0 && ireg
!= 0)
3782 if (ireg
!= 0 && GET_CODE (ireg
) == MULT
)
3784 scale
= INTVAL (XEXP (ireg
, 1));
3785 ireg
= XEXP (ireg
, 0);
3787 if (ireg
!= 0 && GET_CODE (ireg
) == SIGN_EXTEND
)
3790 fprintf (file
, "%s.w", reg_names
[REGNO (XEXP (ireg
, 0))]);
3792 fprintf (file
, "%s:w", reg_names
[REGNO (XEXP (ireg
, 0))]);
3798 fprintf (file
, "%s.l", reg_names
[REGNO (ireg
)]);
3800 fprintf (file
, "%s:l", reg_names
[REGNO (ireg
)]);
3806 fprintf (file
, "*%d", scale
);
3808 fprintf (file
, ":%d", scale
);
3814 else if (reg1
!= 0 && GET_CODE (addr
) == LABEL_REF
3815 && ! (flag_pic
&& reg1
== pic_offset_table_rtx
))
3817 ASM_OUTPUT_CASE_FETCH (file
,
3818 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
3819 reg_names
[REGNO (reg1
)]);
3820 fprintf (file
, "l)");
3823 /* FALL-THROUGH (is this really what we want?) */
3825 if (GET_CODE (addr
) == CONST_INT
3826 && INTVAL (addr
) < 0x8000
3827 && INTVAL (addr
) >= -0x8000)
3831 /* Many SGS assemblers croak on size specifiers for constants. */
3832 fprintf (file
, "%d", (int) INTVAL (addr
));
3834 fprintf (file
, "%d.w", (int) INTVAL (addr
));
3837 fprintf (file
, "%d:w", (int) INTVAL (addr
));
3840 else if (GET_CODE (addr
) == CONST_INT
)
3842 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (addr
));
3844 else if (TARGET_PCREL
)
3847 output_addr_const (file
, addr
);
3849 asm_fprintf (file
, ":w,%Rpc)");
3851 asm_fprintf (file
, ":l,%Rpc)");
3855 /* Special case for SYMBOL_REF if the symbol name ends in
3856 `.<letter>', this can be mistaken as a size suffix. Put
3857 the name in parentheses. */
3858 if (GET_CODE (addr
) == SYMBOL_REF
3859 && strlen (XSTR (addr
, 0)) > 2
3860 && XSTR (addr
, 0)[strlen (XSTR (addr
, 0)) - 2] == '.')
3863 output_addr_const (file
, addr
);
3867 output_addr_const (file
, addr
);
3873 /* Check for cases where a clr insns can be omitted from code using
3874 strict_low_part sets. For example, the second clrl here is not needed:
3875 clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
3877 MODE is the mode of this STRICT_LOW_PART set. FIRST_INSN is the clear
3878 insn we are checking for redundancy. TARGET is the register set by the
3882 strict_low_part_peephole_ok (mode
, first_insn
, target
)
3883 enum machine_mode mode
;
3889 p
= prev_nonnote_insn (first_insn
);
3893 /* If it isn't an insn, then give up. */
3894 if (GET_CODE (p
) != INSN
)
3897 if (reg_set_p (target
, p
))
3899 rtx set
= single_set (p
);
3902 /* If it isn't an easy to recognize insn, then give up. */
3906 dest
= SET_DEST (set
);
3908 /* If this sets the entire target register to zero, then our
3909 first_insn is redundant. */
3910 if (rtx_equal_p (dest
, target
)
3911 && SET_SRC (set
) == const0_rtx
)
3913 else if (GET_CODE (dest
) == STRICT_LOW_PART
3914 && GET_CODE (XEXP (dest
, 0)) == REG
3915 && REGNO (XEXP (dest
, 0)) == REGNO (target
)
3916 && (GET_MODE_SIZE (GET_MODE (XEXP (dest
, 0)))
3917 <= GET_MODE_SIZE (mode
)))
3918 /* This is a strict low part set which modifies less than
3919 we are using, so it is safe. */
3925 p
= prev_nonnote_insn (p
);
3932 /* Accept integer operands in the range 0..0xffffffff. We have to check the
3933 range carefully since this predicate is used in DImode contexts. Also, we
3934 need some extra crud to make it work when hosted on 64-bit machines. */
3937 const_uint32_operand (op
, mode
)
3939 enum machine_mode mode
;
3941 /* It doesn't make sense to ask this question with a mode that is
3942 not larger than 32 bits. */
3943 if (GET_MODE_BITSIZE (mode
) <= 32)
3946 #if HOST_BITS_PER_WIDE_INT > 32
3947 /* All allowed constants will fit a CONST_INT. */
3948 return (GET_CODE (op
) == CONST_INT
3949 && (INTVAL (op
) >= 0 && INTVAL (op
) <= 0xffffffffL
));
3951 return (GET_CODE (op
) == CONST_INT
3952 || (GET_CODE (op
) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (op
) == 0));
3956 /* Accept integer operands in the range -0x80000000..0x7fffffff. We have
3957 to check the range carefully since this predicate is used in DImode
3961 const_sint32_operand (op
, mode
)
3963 enum machine_mode mode
;
3965 /* It doesn't make sense to ask this question with a mode that is
3966 not larger than 32 bits. */
3967 if (GET_MODE_BITSIZE (mode
) <= 32)
3970 /* All allowed constants will fit a CONST_INT. */
3971 return (GET_CODE (op
) == CONST_INT
3972 && (INTVAL (op
) >= (-0x7fffffff - 1) && INTVAL (op
) <= 0x7fffffff));
3975 /* Operand predicates for implementing asymmetric pc-relative addressing
3976 on m68k. The m68k supports pc-relative addressing (mode 7, register 2)
3977 when used as a source operand, but not as a destintation operand.
3979 We model this by restricting the meaning of the basic predicates
3980 (general_operand, memory_operand, etc) to forbid the use of this
3981 addressing mode, and then define the following predicates that permit
3982 this addressing mode. These predicates can then be used for the
3983 source operands of the appropriate instructions.
3985 n.b. While it is theoretically possible to change all machine patterns
3986 to use this addressing more where permitted by the architecture,
3987 it has only been implemented for "common" cases: SImode, HImode, and
3988 QImode operands, and only for the principle operations that would
3989 require this addressing mode: data movement and simple integer operations.
3991 In parallel with these new predicates, two new constraint letters
3992 were defined: 'S' and 'T'. 'S' is the -mpcrel analog of 'm'.
3993 'T' replaces 's' in the non-pcrel case. It is a no-op in the pcrel case.
3994 In the pcrel case 's' is only valid in combination with 'a' registers.
3995 See addsi3, subsi3, cmpsi, and movsi patterns for a better understanding
3996 of how these constraints are used.
3998 The use of these predicates is strictly optional, though patterns that
3999 don't will cause an extra reload register to be allocated where one
4002 lea (abc:w,%pc),%a0 ; need to reload address
4003 moveq &1,%d1 ; since write to pc-relative space
4004 movel %d1,%a0@ ; is not allowed
4006 lea (abc:w,%pc),%a1 ; no need to reload address here
4007 movel %a1@,%d0 ; since "movel (abc:w,%pc),%d0" is ok
4009 For more info, consult tiemann@cygnus.com.
4012 All of the ugliness with predicates and constraints is due to the
4013 simple fact that the m68k does not allow a pc-relative addressing
4014 mode as a destination. gcc does not distinguish between source and
4015 destination addresses. Hence, if we claim that pc-relative address
4016 modes are valid, e.g. GO_IF_LEGITIMATE_ADDRESS accepts them, then we
4017 end up with invalid code. To get around this problem, we left
4018 pc-relative modes as invalid addresses, and then added special
4019 predicates and constraints to accept them.
4021 A cleaner way to handle this is to modify gcc to distinguish
4022 between source and destination addresses. We can then say that
4023 pc-relative is a valid source address but not a valid destination
4024 address, and hopefully avoid a lot of the predicate and constraint
4025 hackery. Unfortunately, this would be a pretty big change. It would
4026 be a useful change for a number of ports, but there aren't any current
4027 plans to undertake this.
4029 ***************************************************************************/
4032 /* Special case of a general operand that's used as a source operand.
4033 Use this to permit reads from PC-relative memory when -mpcrel
4037 general_src_operand (op
, mode
)
4039 enum machine_mode mode
;
4042 && GET_CODE (op
) == MEM
4043 && (GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
4044 || GET_CODE (XEXP (op
, 0)) == LABEL_REF
4045 || GET_CODE (XEXP (op
, 0)) == CONST
))
4047 return general_operand (op
, mode
);
4050 /* Special case of a nonimmediate operand that's used as a source.
4051 Use this to permit reads from PC-relative memory when -mpcrel
4055 nonimmediate_src_operand (op
, mode
)
4057 enum machine_mode mode
;
4059 if (TARGET_PCREL
&& GET_CODE (op
) == MEM
4060 && (GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
4061 || GET_CODE (XEXP (op
, 0)) == LABEL_REF
4062 || GET_CODE (XEXP (op
, 0)) == CONST
))
4064 return nonimmediate_operand (op
, mode
);
4067 /* Special case of a memory operand that's used as a source.
4068 Use this to permit reads from PC-relative memory when -mpcrel
4072 memory_src_operand (op
, mode
)
4074 enum machine_mode mode
;
4076 if (TARGET_PCREL
&& GET_CODE (op
) == MEM
4077 && (GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
4078 || GET_CODE (XEXP (op
, 0)) == LABEL_REF
4079 || GET_CODE (XEXP (op
, 0)) == CONST
))
4081 return memory_operand (op
, mode
);
4084 /* Predicate that accepts only a pc-relative address. This is needed
4085 because pc-relative addresses don't satisfy the predicate
4086 "general_src_operand". */
4089 pcrel_address (op
, mode
)
4091 enum machine_mode mode ATTRIBUTE_UNUSED
;
4093 return (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == LABEL_REF
4094 || GET_CODE (op
) == CONST
);
4098 output_andsi3 (operands
)
4102 if (GET_CODE (operands
[2]) == CONST_INT
4103 && (INTVAL (operands
[2]) | 0xffff) == 0xffffffff
4104 && (DATA_REG_P (operands
[0])
4105 || offsettable_memref_p (operands
[0]))
4108 if (GET_CODE (operands
[0]) != REG
)
4109 operands
[0] = adjust_address (operands
[0], HImode
, 2);
4110 operands
[2] = GEN_INT (INTVAL (operands
[2]) & 0xffff);
4111 /* Do not delete a following tstl %0 insn; that would be incorrect. */
4113 if (operands
[2] == const0_rtx
)
4115 return "and%.w %2,%0";
4117 if (GET_CODE (operands
[2]) == CONST_INT
4118 && (logval
= exact_log2 (~ INTVAL (operands
[2]))) >= 0
4119 && (DATA_REG_P (operands
[0])
4120 || offsettable_memref_p (operands
[0])))
4122 if (DATA_REG_P (operands
[0]))
4124 operands
[1] = GEN_INT (logval
);
4128 operands
[0] = adjust_address (operands
[0], SImode
, 3 - (logval
/ 8));
4129 operands
[1] = GEN_INT (logval
% 8);
4131 /* This does not set condition codes in a standard way. */
4133 return "bclr %1,%0";
4135 return "and%.l %2,%0";
4139 output_iorsi3 (operands
)
4142 register int logval
;
4143 if (GET_CODE (operands
[2]) == CONST_INT
4144 && INTVAL (operands
[2]) >> 16 == 0
4145 && (DATA_REG_P (operands
[0])
4146 || offsettable_memref_p (operands
[0]))
4149 if (GET_CODE (operands
[0]) != REG
)
4150 operands
[0] = adjust_address (operands
[0], HImode
, 2);
4151 /* Do not delete a following tstl %0 insn; that would be incorrect. */
4153 if (INTVAL (operands
[2]) == 0xffff)
4154 return "mov%.w %2,%0";
4155 return "or%.w %2,%0";
4157 if (GET_CODE (operands
[2]) == CONST_INT
4158 && (logval
= exact_log2 (INTVAL (operands
[2]))) >= 0
4159 && (DATA_REG_P (operands
[0])
4160 || offsettable_memref_p (operands
[0])))
4162 if (DATA_REG_P (operands
[0]))
4163 operands
[1] = GEN_INT (logval
);
4166 operands
[0] = adjust_address (operands
[0], SImode
, 3 - (logval
/ 8));
4167 operands
[1] = GEN_INT (logval
% 8);
4170 return "bset %1,%0";
4172 return "or%.l %2,%0";
4176 output_xorsi3 (operands
)
4179 register int logval
;
4180 if (GET_CODE (operands
[2]) == CONST_INT
4181 && INTVAL (operands
[2]) >> 16 == 0
4182 && (offsettable_memref_p (operands
[0]) || DATA_REG_P (operands
[0]))
4185 if (! DATA_REG_P (operands
[0]))
4186 operands
[0] = adjust_address (operands
[0], HImode
, 2);
4187 /* Do not delete a following tstl %0 insn; that would be incorrect. */
4189 if (INTVAL (operands
[2]) == 0xffff)
4191 return "eor%.w %2,%0";
4193 if (GET_CODE (operands
[2]) == CONST_INT
4194 && (logval
= exact_log2 (INTVAL (operands
[2]))) >= 0
4195 && (DATA_REG_P (operands
[0])
4196 || offsettable_memref_p (operands
[0])))
4198 if (DATA_REG_P (operands
[0]))
4199 operands
[1] = GEN_INT (logval
);
4202 operands
[0] = adjust_address (operands
[0], SImode
, 3 - (logval
/ 8));
4203 operands
[1] = GEN_INT (logval
% 8);
4206 return "bchg %1,%0";
4208 return "eor%.l %2,%0";
4211 /* Output assembly to switch to section NAME with attribute FLAGS. */
4214 m68k_coff_asm_named_section (name
, flags
)
4220 if (flags
& SECTION_WRITE
)
4225 fprintf (asm_out_file
, "\t.section\t%s,\"%c\"\n", name
, flagchar
);
4228 #ifdef CTOR_LIST_BEGIN
4230 m68k_svr3_asm_out_constructor (symbol
, priority
)
4232 int priority ATTRIBUTE_UNUSED
;
4237 xop
[0] = gen_rtx_MEM (SImode
, gen_rtx_PRE_DEC (SImode
, stack_pointer_rtx
));
4240 output_asm_insn (output_move_simode (xop
), xop
);