1 /* Subroutines for insn-output.c for Motorola 68000 family.
2 Copyright (C) 1987, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
22 /* Some output-actions in m68k.md need these. */
28 #include "hard-reg-set.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "insn-flags.h"
34 #include "insn-attr.h"
38 /* Needed for use_return_insn. */
41 #ifdef SUPPORT_SUN_FPA
43 /* Index into this array by (register number >> 3) to find the
44 smallest class which contains that register. */
45 enum reg_class regno_reg_class
[]
46 = { DATA_REGS
, ADDR_REGS
, FP_REGS
,
47 LO_FPA_REGS
, LO_FPA_REGS
, FPA_REGS
, FPA_REGS
};
49 #endif /* defined SUPPORT_SUN_FPA */
51 /* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
52 if SGS_SWITCH_TABLE. */
53 int switch_table_difference_label_flag
;
55 static rtx
find_addr_reg ();
56 rtx
legitimize_pic_address ();
59 /* Alignment to use for loops and jumps */
60 /* Specify power of two alignment used for loops. */
61 char *m68k_align_loops_string
;
62 /* Specify power of two alignment used for non-loop jumps. */
63 char *m68k_align_jumps_string
;
64 /* Specify power of two alignment used for functions. */
65 char *m68k_align_funcs_string
;
67 /* Specify power of two alignment used for loops. */
69 /* Specify power of two alignment used for non-loop jumps. */
71 /* Specify power of two alignment used for functions. */
74 /* Nonzero if the last compare/test insn had FP operands. The
75 sCC expanders peek at this to determine what to do for the
76 68060, which has no fsCC instructions. */
77 int m68k_last_compare_had_fp_operands
;
79 /* Sometimes certain combinations of command options do not make
80 sense on a particular target machine. You can define a macro
81 `OVERRIDE_OPTIONS' to take account of this. This macro, if
82 defined, is executed once just after all the command options have
85 Don't use this macro to turn on various extra optimizations for
86 `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
95 /* Validate -malign-loops= value, or provide default */
96 if (m68k_align_loops_string
)
98 m68k_align_loops
= atoi (m68k_align_loops_string
);
99 if (m68k_align_loops
< 1 || m68k_align_loops
> MAX_CODE_ALIGN
)
100 fatal ("-malign-loops=%d is not between 1 and %d",
101 m68k_align_loops
, MAX_CODE_ALIGN
);
104 m68k_align_loops
= def_align
;
106 /* Validate -malign-jumps= value, or provide default */
107 if (m68k_align_jumps_string
)
109 m68k_align_jumps
= atoi (m68k_align_jumps_string
);
110 if (m68k_align_jumps
< 1 || m68k_align_jumps
> MAX_CODE_ALIGN
)
111 fatal ("-malign-jumps=%d is not between 1 and %d",
112 m68k_align_jumps
, MAX_CODE_ALIGN
);
115 m68k_align_jumps
= def_align
;
117 /* Validate -malign-functions= value, or provide default */
118 if (m68k_align_funcs_string
)
120 m68k_align_funcs
= atoi (m68k_align_funcs_string
);
121 if (m68k_align_funcs
< 1 || m68k_align_funcs
> MAX_CODE_ALIGN
)
122 fatal ("-malign-functions=%d is not between 1 and %d",
123 m68k_align_funcs
, MAX_CODE_ALIGN
);
126 m68k_align_funcs
= def_align
;
129 /* Emit a (use pic_offset_table_rtx) if we used PIC relocation in the
130 function at any time during the compilation process. In the future
131 we should try and eliminate the USE if we can easily determine that
132 all PIC references were deleted from the current function. That would
133 save an address register */
138 if (flag_pic
&& current_function_uses_pic_offset_table
)
140 rtx insn
= gen_rtx_USE (VOIDmode
, pic_offset_table_rtx
);
141 emit_insn_after (insn
, get_insns ());
147 /* This function generates the assembly code for function entry.
148 STREAM is a stdio stream to output the code to.
149 SIZE is an int: how many units of temporary storage to allocate.
150 Refer to the array `regs_ever_live' to determine which registers
151 to save; `regs_ever_live[I]' is nonzero if register number I
152 is ever used in the function. This function is responsible for
153 knowing which registers should not be saved even if used. */
156 /* Note that the order of the bit mask for fmovem is the opposite
157 of the order for movem! */
161 output_function_prologue (stream
, size
)
166 register int mask
= 0;
167 int num_saved_regs
= 0;
168 extern char call_used_regs
[];
169 int fsize
= (size
+ 3) & -4;
170 int cfa_offset
= INCOMING_FRAME_SP_OFFSET
, cfa_store_offset
= cfa_offset
;
173 if (frame_pointer_needed
)
175 if (fsize
== 0 && TARGET_68040
)
177 /* on the 68040, pea + move is faster than link.w 0 */
179 asm_fprintf (stream
, "\tpea (%s)\n\tmove.l %s,%s\n",
180 reg_names
[FRAME_POINTER_REGNUM
], reg_names
[STACK_POINTER_REGNUM
],
181 reg_names
[FRAME_POINTER_REGNUM
]);
183 asm_fprintf (stream
, "\tpea %s@\n\tmovel %s,%s\n",
184 reg_names
[FRAME_POINTER_REGNUM
], reg_names
[STACK_POINTER_REGNUM
],
185 reg_names
[FRAME_POINTER_REGNUM
]);
188 else if (fsize
< 0x8000)
191 asm_fprintf (stream
, "\tlink.w %s,%0I%d\n",
192 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
194 asm_fprintf (stream
, "\tlink %s,%0I%d\n",
195 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
198 else if (TARGET_68020
)
201 asm_fprintf (stream
, "\tlink.l %s,%0I%d\n",
202 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
204 asm_fprintf (stream
, "\tlink %s,%0I%d\n",
205 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
210 /* Adding negative number is faster on the 68040. */
212 asm_fprintf (stream
, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
213 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
215 asm_fprintf (stream
, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
216 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
219 if (dwarf2out_do_frame ())
222 l
= (char *) dwarf2out_cfi_label ();
223 cfa_store_offset
+= 4;
224 cfa_offset
= cfa_store_offset
;
225 dwarf2out_def_cfa (l
, FRAME_POINTER_REGNUM
, cfa_offset
);
226 dwarf2out_reg_save (l
, FRAME_POINTER_REGNUM
, -cfa_store_offset
);
227 cfa_store_offset
+= fsize
;
232 if (fsize
+ 4 < 0x8000)
239 /* asm_fprintf() cannot handle %. */
241 asm_fprintf (stream
, "\tsubq.w %0I%d,%Rsp\n", fsize
+ 4);
243 asm_fprintf (stream
, "\tsubqw %0I%d,%Rsp\n", fsize
+ 4);
248 /* asm_fprintf() cannot handle %. */
250 asm_fprintf (stream
, "\tsubq.l %0I%d,%Rsp\n", fsize
+ 4);
252 asm_fprintf (stream
, "\tsubql %0I%d,%Rsp\n", fsize
+ 4);
256 else if (fsize
+ 4 <= 16 && TARGET_CPU32
)
258 /* On the CPU32 it is faster to use two subqw instructions to
259 subtract a small integer (8 < N <= 16) to a register. */
260 /* asm_fprintf() cannot handle %. */
262 asm_fprintf (stream
, "\tsubq.w %0I8,%Rsp\n\tsubq.w %0I%d,%Rsp\n",
265 asm_fprintf (stream
, "\tsubqw %0I8,%Rsp\n\tsubqw %0I%d,%Rsp\n",
270 #endif /* not NO_ADDSUB_Q */
273 /* Adding negative number is faster on the 68040. */
274 /* asm_fprintf() cannot handle %. */
276 asm_fprintf (stream
, "\tadd.w %0I%d,%Rsp\n", - (fsize
+ 4));
278 asm_fprintf (stream
, "\taddw %0I%d,%Rsp\n", - (fsize
+ 4));
284 asm_fprintf (stream
, "\tlea (%d,%Rsp),%Rsp\n", - (fsize
+ 4));
286 asm_fprintf (stream
, "\tlea %Rsp@(%d),%Rsp\n", - (fsize
+ 4));
292 /* asm_fprintf() cannot handle %. */
294 asm_fprintf (stream
, "\tadd.l %0I%d,%Rsp\n", - (fsize
+ 4));
296 asm_fprintf (stream
, "\taddl %0I%d,%Rsp\n", - (fsize
+ 4));
299 if (dwarf2out_do_frame ())
301 cfa_store_offset
+= fsize
;
302 cfa_offset
= cfa_store_offset
;
303 dwarf2out_def_cfa ("", STACK_POINTER_REGNUM
, cfa_offset
);
306 #ifdef SUPPORT_SUN_FPA
307 for (regno
= 24; regno
< 56; regno
++)
308 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
311 asm_fprintf (stream
, "\tfpmovd %s,-(%Rsp)\n",
314 asm_fprintf (stream
, "\tfpmoved %s,%Rsp@-\n",
317 if (dwarf2out_do_frame ())
319 char *l
= dwarf2out_cfi_label ();
321 cfa_store_offset
+= 8;
322 if (! frame_pointer_needed
)
324 cfa_offset
= cfa_store_offset
;
325 dwarf2out_def_cfa (l
, STACK_POINTER_REGNUM
, cfa_offset
);
327 dwarf2out_reg_save (l
, regno
, -cfa_store_offset
);
333 for (regno
= 16; regno
< 24; regno
++)
334 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
336 mask
|= 1 << (regno
- 16);
339 if ((mask
& 0xff) != 0)
342 asm_fprintf (stream
, "\tfmovm %0I0x%x,-(%Rsp)\n", mask
& 0xff);
344 asm_fprintf (stream
, "\tfmovem %0I0x%x,%Rsp@-\n", mask
& 0xff);
346 if (dwarf2out_do_frame ())
348 char *l
= (char *) dwarf2out_cfi_label ();
351 cfa_store_offset
+= num_saved_regs
* 12;
352 if (! frame_pointer_needed
)
354 cfa_offset
= cfa_store_offset
;
355 dwarf2out_def_cfa (l
, STACK_POINTER_REGNUM
, cfa_offset
);
357 for (regno
= 16, n_regs
= 0; regno
< 24; regno
++)
358 if (mask
& (1 << (regno
- 16)))
359 dwarf2out_reg_save (l
, regno
,
360 -cfa_store_offset
+ n_regs
++ * 12);
366 for (regno
= 0; regno
< 16; regno
++)
367 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
369 mask
|= 1 << (15 - regno
);
372 if (frame_pointer_needed
)
374 mask
&= ~ (1 << (15 - FRAME_POINTER_REGNUM
));
381 asm_fprintf (stream
, "\ttstl %d(%Rsp)\n", NEED_PROBE
- num_saved_regs
* 4);
383 asm_fprintf (stream
, "\ttst.l %d(%Rsp)\n", NEED_PROBE
- num_saved_regs
* 4);
386 asm_fprintf (stream
, "\ttstl %Rsp@(%d)\n", NEED_PROBE
- num_saved_regs
* 4);
390 if (num_saved_regs
<= 2)
392 /* Store each separately in the same order moveml uses.
393 Using two movel instructions instead of a single moveml
394 is about 15% faster for the 68020 and 68030 at no expense
399 /* Undo the work from above. */
400 for (i
= 0; i
< 16; i
++)
405 "\t%Omove.l %s,-(%Rsp)\n",
407 "\tmovel %s,%Rsp@-\n",
410 if (dwarf2out_do_frame ())
412 char *l
= (char *) dwarf2out_cfi_label ();
414 cfa_store_offset
+= 4;
415 if (! frame_pointer_needed
)
417 cfa_offset
= cfa_store_offset
;
418 dwarf2out_def_cfa (l
, STACK_POINTER_REGNUM
, cfa_offset
);
420 dwarf2out_reg_save (l
, 15 - i
, -cfa_store_offset
);
428 /* The coldfire does not support the predecrement form of the
429 movml instruction, so we must adjust the stack pointer and
430 then use the plain address register indirect mode. We also
431 have to invert the register save mask to use the new mode.
433 FIXME: if num_saved_regs was calculated earlier, we could
434 combine the stack pointer adjustment with any adjustment
435 done when the initial stack frame is created. This would
436 save an instruction */
441 for (i
= 0; i
< 16; i
++)
443 newmask
|= (1 << (15-i
));
446 asm_fprintf (stream
, "\tlea (%d,%Rsp),%Rsp\n", -num_saved_regs
*4);
447 asm_fprintf (stream
, "\tmovm.l %0I0x%x,(%Rsp)\n", newmask
);
449 asm_fprintf (stream
, "\tlea %Rsp@(%d),%Rsp\n", -num_saved_regs
*4);
450 asm_fprintf (stream
, "\tmoveml %0I0x%x,%Rsp@\n", newmask
);
456 asm_fprintf (stream
, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask
);
458 asm_fprintf (stream
, "\tmoveml %0I0x%x,%Rsp@-\n", mask
);
461 if (dwarf2out_do_frame ())
463 char *l
= (char *) dwarf2out_cfi_label ();
466 cfa_store_offset
+= num_saved_regs
* 4;
467 if (! frame_pointer_needed
)
469 cfa_offset
= cfa_store_offset
;
470 dwarf2out_def_cfa (l
, STACK_POINTER_REGNUM
, cfa_offset
);
472 for (regno
= 0, n_regs
= 0; regno
< 16; regno
++)
473 if (mask
& (1 << (15 - regno
)))
474 dwarf2out_reg_save (l
, regno
,
475 -cfa_store_offset
+ n_regs
++ * 4);
478 if (flag_pic
&& current_function_uses_pic_offset_table
)
481 asm_fprintf (stream
, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
482 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
484 asm_fprintf (stream
, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
485 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
486 asm_fprintf (stream
, "\tlea %Rpc@(0,%s:l),%s\n",
487 reg_names
[PIC_OFFSET_TABLE_REGNUM
],
488 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
493 /* Return true if this function's epilogue can be output as RTL. */
500 if (!reload_completed
|| frame_pointer_needed
|| get_frame_size () != 0)
503 /* Copied from output_function_epilogue (). We should probably create a
504 separate layout routine to perform the common work. */
506 for (regno
= 0 ; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
507 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
513 /* This function generates the assembly code for function exit,
514 on machines that need it. Args are same as for FUNCTION_PROLOGUE.
516 The function epilogue should not depend on the current stack pointer!
517 It should use the frame pointer only, if there is a frame pointer.
518 This is mandatory because of alloca; we also take advantage of it to
519 omit stack adjustments before returning. */
522 output_function_epilogue (stream
, size
)
527 register int mask
, fmask
;
529 int offset
, foffset
, fpoffset
;
530 extern char call_used_regs
[];
531 int fsize
= (size
+ 3) & -4;
533 rtx insn
= get_last_insn ();
534 int restore_from_sp
= 0;
536 /* If the last insn was a BARRIER, we don't have to write any code. */
537 if (GET_CODE (insn
) == NOTE
)
538 insn
= prev_nonnote_insn (insn
);
539 if (insn
&& GET_CODE (insn
) == BARRIER
)
541 /* Output just a no-op so that debuggers don't get confused
542 about which function the pc is in at this address. */
543 asm_fprintf (stream
, "\tnop\n");
547 #ifdef FUNCTION_BLOCK_PROFILER_EXIT
548 if (profile_block_flag
== 2)
550 FUNCTION_BLOCK_PROFILER_EXIT (stream
);
554 #ifdef FUNCTION_EXTRA_EPILOGUE
555 FUNCTION_EXTRA_EPILOGUE (stream
, size
);
557 nregs
= 0; fmask
= 0; fpoffset
= 0;
558 #ifdef SUPPORT_SUN_FPA
559 for (regno
= 24 ; regno
< 56 ; regno
++)
560 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
562 fpoffset
= nregs
* 8;
567 for (regno
= 16; regno
< 24; regno
++)
568 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
571 fmask
|= 1 << (23 - regno
);
574 foffset
= fpoffset
+ nregs
* 12;
576 if (frame_pointer_needed
)
577 regs_ever_live
[FRAME_POINTER_REGNUM
] = 0;
578 for (regno
= 0; regno
< 16; regno
++)
579 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
584 offset
= foffset
+ nregs
* 4;
585 /* FIXME : leaf_function_p below is too strong.
586 What we really need to know there is if there could be pending
587 stack adjustment needed at that point. */
588 restore_from_sp
= ! frame_pointer_needed
589 || (! current_function_calls_alloca
&& leaf_function_p ());
590 if (offset
+ fsize
>= 0x8000
592 && (mask
|| fmask
|| fpoffset
))
595 asm_fprintf (stream
, "\t%Omove.l %0I%d,%Ra1\n", -fsize
);
597 asm_fprintf (stream
, "\tmovel %0I%d,%Ra1\n", -fsize
);
601 if (TARGET_5200
|| nregs
<= 2)
603 /* Restore each separately in the same order moveml does.
604 Using two movel instructions instead of a single moveml
605 is about 15% faster for the 68020 and 68030 at no expense
610 /* Undo the work from above. */
611 for (i
= 0; i
< 16; i
++)
617 asm_fprintf (stream
, "\t%Omove.l -%d(%s,%Ra1.l),%s\n",
619 reg_names
[FRAME_POINTER_REGNUM
],
622 asm_fprintf (stream
, "\tmovel %s@(-%d,%Ra1:l),%s\n",
623 reg_names
[FRAME_POINTER_REGNUM
],
624 offset
+ fsize
, reg_names
[i
]);
627 else if (restore_from_sp
)
630 asm_fprintf (stream
, "\t%Omove.l (%Rsp)+,%s\n",
633 asm_fprintf (stream
, "\tmovel %Rsp@+,%s\n",
640 asm_fprintf (stream
, "\t%Omove.l -%d(%s),%s\n",
642 reg_names
[FRAME_POINTER_REGNUM
],
645 asm_fprintf (stream
, "\tmovel %s@(-%d),%s\n",
646 reg_names
[FRAME_POINTER_REGNUM
],
647 offset
+ fsize
, reg_names
[i
]);
658 asm_fprintf (stream
, "\tmovm.l -%d(%s,%Ra1.l),%0I0x%x\n",
660 reg_names
[FRAME_POINTER_REGNUM
],
663 asm_fprintf (stream
, "\tmoveml %s@(-%d,%Ra1:l),%0I0x%x\n",
664 reg_names
[FRAME_POINTER_REGNUM
],
665 offset
+ fsize
, mask
);
668 else if (restore_from_sp
)
671 asm_fprintf (stream
, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask
);
673 asm_fprintf (stream
, "\tmoveml %Rsp@+,%0I0x%x\n", mask
);
679 asm_fprintf (stream
, "\tmovm.l -%d(%s),%0I0x%x\n",
681 reg_names
[FRAME_POINTER_REGNUM
],
684 asm_fprintf (stream
, "\tmoveml %s@(-%d),%0I0x%x\n",
685 reg_names
[FRAME_POINTER_REGNUM
],
686 offset
+ fsize
, mask
);
695 asm_fprintf (stream
, "\tfmovm -%d(%s,%Ra1.l),%0I0x%x\n",
697 reg_names
[FRAME_POINTER_REGNUM
],
700 asm_fprintf (stream
, "\tfmovem %s@(-%d,%Ra1:l),%0I0x%x\n",
701 reg_names
[FRAME_POINTER_REGNUM
],
702 foffset
+ fsize
, fmask
);
705 else if (restore_from_sp
)
708 asm_fprintf (stream
, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask
);
710 asm_fprintf (stream
, "\tfmovem %Rsp@+,%0I0x%x\n", fmask
);
716 asm_fprintf (stream
, "\tfmovm -%d(%s),%0I0x%x\n",
718 reg_names
[FRAME_POINTER_REGNUM
],
721 asm_fprintf (stream
, "\tfmovem %s@(-%d),%0I0x%x\n",
722 reg_names
[FRAME_POINTER_REGNUM
],
723 foffset
+ fsize
, fmask
);
728 for (regno
= 55; regno
>= 24; regno
--)
729 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
734 asm_fprintf (stream
, "\tfpmovd -%d(%s,%Ra1.l), %s\n",
736 reg_names
[FRAME_POINTER_REGNUM
],
739 asm_fprintf (stream
, "\tfpmoved %s@(-%d,%Ra1:l), %s\n",
740 reg_names
[FRAME_POINTER_REGNUM
],
741 fpoffset
+ fsize
, reg_names
[regno
]);
744 else if (restore_from_sp
)
747 asm_fprintf (stream
, "\tfpmovd (%Rsp)+,%s\n",
750 asm_fprintf (stream
, "\tfpmoved %Rsp@+, %s\n",
757 asm_fprintf (stream
, "\tfpmovd -%d(%s), %s\n",
759 reg_names
[FRAME_POINTER_REGNUM
],
762 asm_fprintf (stream
, "\tfpmoved %s@(-%d), %s\n",
763 reg_names
[FRAME_POINTER_REGNUM
],
764 fpoffset
+ fsize
, reg_names
[regno
]);
769 if (frame_pointer_needed
)
770 fprintf (stream
, "\tunlk %s\n",
771 reg_names
[FRAME_POINTER_REGNUM
]);
780 asm_fprintf (stream
, "\taddq.w %0I%d,%Rsp\n", fsize
+ 4);
782 asm_fprintf (stream
, "\taddqw %0I%d,%Rsp\n", fsize
+ 4);
788 asm_fprintf (stream
, "\taddq.l %0I%d,%Rsp\n", fsize
+ 4);
790 asm_fprintf (stream
, "\taddql %0I%d,%Rsp\n", fsize
+ 4);
794 else if (fsize
+ 4 <= 16 && TARGET_CPU32
)
796 /* On the CPU32 it is faster to use two addqw instructions to
797 add a small integer (8 < N <= 16) to a register. */
798 /* asm_fprintf() cannot handle %. */
800 asm_fprintf (stream
, "\taddq.w %0I8,%Rsp\n\taddq.w %0I%d,%Rsp\n",
803 asm_fprintf (stream
, "\taddqw %0I8,%Rsp\n\taddqw %0I%d,%Rsp\n",
808 #endif /* not NO_ADDSUB_Q */
809 if (fsize
+ 4 < 0x8000)
813 /* asm_fprintf() cannot handle %. */
815 asm_fprintf (stream
, "\tadd.w %0I%d,%Rsp\n", fsize
+ 4);
817 asm_fprintf (stream
, "\taddw %0I%d,%Rsp\n", fsize
+ 4);
823 asm_fprintf (stream
, "\tlea (%d,%Rsp),%Rsp\n", fsize
+ 4);
825 asm_fprintf (stream
, "\tlea %Rsp@(%d),%Rsp\n", fsize
+ 4);
831 /* asm_fprintf() cannot handle %. */
833 asm_fprintf (stream
, "\tadd.l %0I%d,%Rsp\n", fsize
+ 4);
835 asm_fprintf (stream
, "\taddl %0I%d,%Rsp\n", fsize
+ 4);
839 if (current_function_pops_args
)
840 asm_fprintf (stream
, "\trtd %0I%d\n", current_function_pops_args
);
842 fprintf (stream
, "\trts\n");
845 /* Similar to general_operand, but exclude stack_pointer_rtx. */
848 not_sp_operand (op
, mode
)
850 enum machine_mode mode
;
852 return op
!= stack_pointer_rtx
&& general_operand (op
, mode
);
855 /* Return TRUE if X is a valid comparison operator for the dbcc
858 Note it rejects floating point comparison operators.
859 (In the future we could use Fdbcc).
861 It also rejects some comparisons when CC_NO_OVERFLOW is set. */
864 valid_dbcc_comparison_p (x
, mode
)
866 enum machine_mode mode ATTRIBUTE_UNUSED
;
868 switch (GET_CODE (x
))
870 case EQ
: case NE
: case GTU
: case LTU
:
874 /* Reject some when CC_NO_OVERFLOW is set. This may be over
876 case GT
: case LT
: case GE
: case LE
:
877 return ! (cc_prev_status
.flags
& CC_NO_OVERFLOW
);
883 /* Return non-zero if flags are currently in the 68881 flag register. */
887 /* We could add support for these in the future */
888 return cc_status
.flags
& CC_IN_68881
;
891 /* Output a dbCC; jCC sequence. Note we do not handle the
892 floating point version of this sequence (Fdbcc). We also
893 do not handle alternative conditions when CC_NO_OVERFLOW is
894 set. It is assumed that valid_dbcc_comparison_p and flags_in_68881 will
895 kick those out before we get here. */
898 output_dbcc_and_branch (operands
)
901 switch (GET_CODE (operands
[3]))
905 output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands
);
907 output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands
);
913 output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands
);
915 output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands
);
921 output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands
);
923 output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands
);
929 output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands
);
931 output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands
);
937 output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands
);
939 output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands
);
945 output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands
);
947 output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands
);
953 output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands
);
955 output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands
);
961 output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands
);
963 output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands
);
969 output_asm_insn ("dble %0,%l1\n\tjble %l2", operands
);
971 output_asm_insn ("dble %0,%l1\n\tjle %l2", operands
);
977 output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands
);
979 output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands
);
987 /* If the decrement is to be done in SImode, then we have
988 to compensate for the fact that dbcc decrements in HImode. */
989 switch (GET_MODE (operands
[0]))
993 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands
);
995 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands
);
1008 output_scc_di(op
, operand1
, operand2
, dest
)
1015 enum rtx_code op_code
= GET_CODE (op
);
1017 /* This does not produce a usefull cc. */
1020 /* The m68k cmp.l instruction requires operand1 to be a reg as used
1021 below. Swap the operands and change the op if these requirements
1022 are not fulfilled. */
1023 if (GET_CODE (operand2
) == REG
&& GET_CODE (operand1
) != REG
)
1027 operand1
= operand2
;
1029 op_code
= swap_condition (op_code
);
1031 loperands
[0] = operand1
;
1032 if (GET_CODE (operand1
) == REG
)
1033 loperands
[1] = gen_rtx_REG (SImode
, REGNO (operand1
) + 1);
1035 loperands
[1] = adj_offsettable_operand (operand1
, 4);
1036 if (operand2
!= const0_rtx
)
1038 loperands
[2] = operand2
;
1039 if (GET_CODE (operand2
) == REG
)
1040 loperands
[3] = gen_rtx_REG (SImode
, REGNO (operand2
) + 1);
1042 loperands
[3] = adj_offsettable_operand (operand2
, 4);
1044 loperands
[4] = gen_label_rtx();
1045 if (operand2
!= const0_rtx
)
1048 #ifdef SGS_CMP_ORDER
1049 output_asm_insn ("cmp%.l %0,%2\n\tjbne %l4\n\tcmp%.l %1,%3", loperands
);
1051 output_asm_insn ("cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1", loperands
);
1054 #ifdef SGS_CMP_ORDER
1055 output_asm_insn ("cmp%.l %0,%2\n\tjne %l4\n\tcmp%.l %1,%3", loperands
);
1057 output_asm_insn ("cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1", loperands
);
1063 if (TARGET_68020
|| TARGET_5200
|| ! ADDRESS_REG_P (loperands
[0]))
1064 output_asm_insn ("tst%.l %0", loperands
);
1067 #ifdef SGS_CMP_ORDER
1068 output_asm_insn ("cmp%.w %0,%#0", loperands
);
1070 output_asm_insn ("cmp%.w %#0,%0", loperands
);
1075 output_asm_insn ("jbne %l4", loperands
);
1077 output_asm_insn ("jne %l4", loperands
);
1080 if (TARGET_68020
|| TARGET_5200
|| ! ADDRESS_REG_P (loperands
[1]))
1081 output_asm_insn ("tst%.l %1", loperands
);
1084 #ifdef SGS_CMP_ORDER
1085 output_asm_insn ("cmp%.w %1,%#0", loperands
);
1087 output_asm_insn ("cmp%.w %#0,%1", loperands
);
1092 loperands
[5] = dest
;
1097 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1098 CODE_LABEL_NUMBER (loperands
[4]));
1099 output_asm_insn ("seq %5", loperands
);
1103 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1104 CODE_LABEL_NUMBER (loperands
[4]));
1105 output_asm_insn ("sne %5", loperands
);
1109 loperands
[6] = gen_label_rtx();
1111 output_asm_insn ("shi %5\n\tjbra %l6", loperands
);
1113 output_asm_insn ("shi %5\n\tjra %l6", loperands
);
1115 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1116 CODE_LABEL_NUMBER (loperands
[4]));
1117 output_asm_insn ("sgt %5", loperands
);
1118 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1119 CODE_LABEL_NUMBER (loperands
[6]));
1123 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1124 CODE_LABEL_NUMBER (loperands
[4]));
1125 output_asm_insn ("shi %5", loperands
);
1129 loperands
[6] = gen_label_rtx();
1131 output_asm_insn ("scs %5\n\tjbra %l6", loperands
);
1133 output_asm_insn ("scs %5\n\tjra %l6", loperands
);
1135 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1136 CODE_LABEL_NUMBER (loperands
[4]));
1137 output_asm_insn ("slt %5", loperands
);
1138 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1139 CODE_LABEL_NUMBER (loperands
[6]));
1143 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1144 CODE_LABEL_NUMBER (loperands
[4]));
1145 output_asm_insn ("scs %5", loperands
);
1149 loperands
[6] = gen_label_rtx();
1151 output_asm_insn ("scc %5\n\tjbra %l6", loperands
);
1153 output_asm_insn ("scc %5\n\tjra %l6", loperands
);
1155 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1156 CODE_LABEL_NUMBER (loperands
[4]));
1157 output_asm_insn ("sge %5", loperands
);
1158 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1159 CODE_LABEL_NUMBER (loperands
[6]));
1163 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1164 CODE_LABEL_NUMBER (loperands
[4]));
1165 output_asm_insn ("scc %5", loperands
);
1169 loperands
[6] = gen_label_rtx();
1171 output_asm_insn ("sls %5\n\tjbra %l6", loperands
);
1173 output_asm_insn ("sls %5\n\tjra %l6", loperands
);
1175 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1176 CODE_LABEL_NUMBER (loperands
[4]));
1177 output_asm_insn ("sle %5", loperands
);
1178 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1179 CODE_LABEL_NUMBER (loperands
[6]));
1183 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1184 CODE_LABEL_NUMBER (loperands
[4]));
1185 output_asm_insn ("sls %5", loperands
);
1195 output_btst (operands
, countop
, dataop
, insn
, signpos
)
1197 rtx countop
, dataop
;
1201 operands
[0] = countop
;
1202 operands
[1] = dataop
;
1204 if (GET_CODE (countop
) == CONST_INT
)
1206 register int count
= INTVAL (countop
);
1207 /* If COUNT is bigger than size of storage unit in use,
1208 advance to the containing unit of same size. */
1209 if (count
> signpos
)
1211 int offset
= (count
& ~signpos
) / 8;
1212 count
= count
& signpos
;
1213 operands
[1] = dataop
= adj_offsettable_operand (dataop
, offset
);
1215 if (count
== signpos
)
1216 cc_status
.flags
= CC_NOT_POSITIVE
| CC_Z_IN_NOT_N
;
1218 cc_status
.flags
= CC_NOT_NEGATIVE
| CC_Z_IN_NOT_N
;
1220 /* These three statements used to use next_insns_test_no...
1221 but it appears that this should do the same job. */
1223 && next_insn_tests_no_inequality (insn
))
1226 && next_insn_tests_no_inequality (insn
))
1229 && next_insn_tests_no_inequality (insn
))
1232 cc_status
.flags
= CC_NOT_NEGATIVE
;
1234 return "btst %0,%1";
1237 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
1238 reference and a constant. */
1241 symbolic_operand (op
, mode
)
1243 enum machine_mode mode ATTRIBUTE_UNUSED
;
1245 switch (GET_CODE (op
))
1253 return ((GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
1254 || GET_CODE (XEXP (op
, 0)) == LABEL_REF
)
1255 && GET_CODE (XEXP (op
, 1)) == CONST_INT
);
1257 #if 0 /* Deleted, with corresponding change in m68k.h,
1258 so as to fit the specs. No CONST_DOUBLE is ever symbolic. */
1260 return GET_MODE (op
) == mode
;
1268 /* Check for sign_extend or zero_extend. Used for bit-count operands. */
1271 extend_operator(x
, mode
)
1273 enum machine_mode mode
;
1275 if (mode
!= VOIDmode
&& GET_MODE(x
) != mode
)
1277 switch (GET_CODE(x
))
1288 /* Legitimize PIC addresses. If the address is already
1289 position-independent, we return ORIG. Newly generated
1290 position-independent addresses go to REG. If we need more
1291 than one register, we lose.
1293 An address is legitimized by making an indirect reference
1294 through the Global Offset Table with the name of the symbol
1297 The assembler and linker are responsible for placing the
1298 address of the symbol in the GOT. The function prologue
1299 is responsible for initializing a5 to the starting address
1302 The assembler is also responsible for translating a symbol name
1303 into a constant displacement from the start of the GOT.
1305 A quick example may make things a little clearer:
1307 When not generating PIC code to store the value 12345 into _foo
1308 we would generate the following code:
1312 When generating PIC two transformations are made. First, the compiler
1313 loads the address of foo into a register. So the first transformation makes:
1318 The code in movsi will intercept the lea instruction and call this
1319 routine which will transform the instructions into:
1321 movel a5@(_foo:w), a0
1325 That (in a nutshell) is how *all* symbol and label references are
1329 legitimize_pic_address (orig
, mode
, reg
)
1331 enum machine_mode mode ATTRIBUTE_UNUSED
;
1335 /* First handle a simple SYMBOL_REF or LABEL_REF */
1336 if (GET_CODE (orig
) == SYMBOL_REF
|| GET_CODE (orig
) == LABEL_REF
)
1341 pic_ref
= gen_rtx_MEM (Pmode
,
1342 gen_rtx_PLUS (Pmode
,
1343 pic_offset_table_rtx
, orig
));
1344 current_function_uses_pic_offset_table
= 1;
1345 if (reload_in_progress
)
1346 regs_ever_live
[PIC_OFFSET_TABLE_REGNUM
] = 1;
1347 RTX_UNCHANGING_P (pic_ref
) = 1;
1348 emit_move_insn (reg
, pic_ref
);
1351 else if (GET_CODE (orig
) == CONST
)
1355 /* Make sure this is CONST has not already been legitimized */
1356 if (GET_CODE (XEXP (orig
, 0)) == PLUS
1357 && XEXP (XEXP (orig
, 0), 0) == pic_offset_table_rtx
)
1363 /* legitimize both operands of the PLUS */
1364 if (GET_CODE (XEXP (orig
, 0)) == PLUS
)
1366 base
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 0), Pmode
, reg
);
1367 orig
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 1), Pmode
,
1368 base
== reg
? 0 : reg
);
1372 if (GET_CODE (orig
) == CONST_INT
)
1373 return plus_constant_for_output (base
, INTVAL (orig
));
1374 pic_ref
= gen_rtx_PLUS (Pmode
, base
, orig
);
1375 /* Likewise, should we set special REG_NOTEs here? */
1381 typedef enum { MOVL
, SWAP
, NEGW
, NOTW
, NOTB
, MOVQ
} CONST_METHOD
;
1383 #define USE_MOVQ(i) ((unsigned)((i) + 128) <= 255)
1386 const_method (constant
)
1392 i
= INTVAL (constant
);
1396 /* The Coldfire doesn't have byte or word operations. */
1397 /* FIXME: This may not be useful for the m68060 either */
1400 /* if -256 < N < 256 but N is not in range for a moveq
1401 N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */
1402 if (USE_MOVQ (i
^ 0xff))
1404 /* Likewise, try with not.w */
1405 if (USE_MOVQ (i
^ 0xffff))
1407 /* This is the only value where neg.w is useful */
1410 /* Try also with swap */
1412 if (USE_MOVQ ((u
>> 16) | (u
<< 16)))
1415 /* Otherwise, use move.l */
1420 const_int_cost (constant
)
1423 switch (const_method (constant
))
1426 /* Constants between -128 and 127 are cheap due to moveq */
1432 /* Constants easily generated by moveq + not.b/not.w/neg.w/swap */
1442 output_move_const_into_data_reg (operands
)
1447 i
= INTVAL (operands
[1]);
1448 switch (const_method (operands
[1]))
1451 #if defined (MOTOROLA) && !defined (CRDS)
1452 return "moveq%.l %1,%0";
1454 return "moveq %1,%0";
1457 operands
[1] = GEN_INT (i
^ 0xff);
1458 #if defined (MOTOROLA) && !defined (CRDS)
1459 return "moveq%.l %1,%0\n\tnot%.b %0";
1461 return "moveq %1,%0\n\tnot%.b %0";
1464 operands
[1] = GEN_INT (i
^ 0xffff);
1465 #if defined (MOTOROLA) && !defined (CRDS)
1466 return "moveq%.l %1,%0\n\tnot%.w %0";
1468 return "moveq %1,%0\n\tnot%.w %0";
1471 #if defined (MOTOROLA) && !defined (CRDS)
1472 return "moveq%.l %#-128,%0\n\tneg%.w %0";
1474 return "moveq %#-128,%0\n\tneg%.w %0";
1480 operands
[1] = GEN_INT ((u
<< 16) | (u
>> 16));
1481 #if defined (MOTOROLA) && !defined (CRDS)
1482 return "moveq%.l %1,%0\n\tswap %0";
1484 return "moveq %1,%0\n\tswap %0";
1488 return "move%.l %1,%0";
1495 output_move_simode_const (operands
)
1498 if (operands
[1] == const0_rtx
1499 && (DATA_REG_P (operands
[0])
1500 || GET_CODE (operands
[0]) == MEM
)
1501 /* clr insns on 68000 read before writing.
1502 This isn't so on the 68010, but we have no TARGET_68010. */
1503 && ((TARGET_68020
|| TARGET_5200
)
1504 || !(GET_CODE (operands
[0]) == MEM
1505 && MEM_VOLATILE_P (operands
[0]))))
1507 else if (operands
[1] == const0_rtx
1508 && ADDRESS_REG_P (operands
[0]))
1509 return "sub%.l %0,%0";
1510 else if (DATA_REG_P (operands
[0]))
1511 return output_move_const_into_data_reg (operands
);
1512 else if (ADDRESS_REG_P (operands
[0])
1513 && INTVAL (operands
[1]) < 0x8000
1514 && INTVAL (operands
[1]) >= -0x8000)
1515 return "move%.w %1,%0";
1516 else if (GET_CODE (operands
[0]) == MEM
1517 && GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
1518 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
1519 && INTVAL (operands
[1]) < 0x8000
1520 && INTVAL (operands
[1]) >= -0x8000)
1522 return "move%.l %1,%0";
1526 output_move_simode (operands
)
1529 if (GET_CODE (operands
[1]) == CONST_INT
)
1530 return output_move_simode_const (operands
);
1531 else if ((GET_CODE (operands
[1]) == SYMBOL_REF
1532 || GET_CODE (operands
[1]) == CONST
)
1533 && push_operand (operands
[0], SImode
))
1535 else if ((GET_CODE (operands
[1]) == SYMBOL_REF
1536 || GET_CODE (operands
[1]) == CONST
)
1537 && ADDRESS_REG_P (operands
[0]))
1538 return "lea %a1,%0";
1539 return "move%.l %1,%0";
1543 output_move_himode (operands
)
1546 if (GET_CODE (operands
[1]) == CONST_INT
)
1548 if (operands
[1] == const0_rtx
1549 && (DATA_REG_P (operands
[0])
1550 || GET_CODE (operands
[0]) == MEM
)
1551 /* clr insns on 68000 read before writing.
1552 This isn't so on the 68010, but we have no TARGET_68010. */
1553 && ((TARGET_68020
|| TARGET_5200
)
1554 || !(GET_CODE (operands
[0]) == MEM
1555 && MEM_VOLATILE_P (operands
[0]))))
1557 else if (operands
[1] == const0_rtx
1558 && ADDRESS_REG_P (operands
[0]))
1559 return "sub%.l %0,%0";
1560 else if (DATA_REG_P (operands
[0])
1561 && INTVAL (operands
[1]) < 128
1562 && INTVAL (operands
[1]) >= -128)
1564 #if defined(MOTOROLA) && !defined(CRDS)
1565 return "moveq%.l %1,%0";
1567 return "moveq %1,%0";
1570 else if (INTVAL (operands
[1]) < 0x8000
1571 && INTVAL (operands
[1]) >= -0x8000)
1572 return "move%.w %1,%0";
1574 else if (CONSTANT_P (operands
[1]))
1575 return "move%.l %1,%0";
1577 /* Recognize the insn before a tablejump, one that refers
1578 to a table of offsets. Such an insn will need to refer
1579 to a label on the insn. So output one. Use the label-number
1580 of the table of offsets to generate this label. This code,
1581 and similar code below, assumes that there will be at most one
1582 reference to each table. */
1583 if (GET_CODE (operands
[1]) == MEM
1584 && GET_CODE (XEXP (operands
[1], 0)) == PLUS
1585 && GET_CODE (XEXP (XEXP (operands
[1], 0), 1)) == LABEL_REF
1586 && GET_CODE (XEXP (XEXP (operands
[1], 0), 0)) != PLUS
)
1588 rtx labelref
= XEXP (XEXP (operands
[1], 0), 1);
1589 #if defined (MOTOROLA) && !defined (SGS_SWITCH_TABLES)
1591 asm_fprintf (asm_out_file
, "\tset %LLI%d,.+2\n",
1592 CODE_LABEL_NUMBER (XEXP (labelref
, 0)));
1594 asm_fprintf (asm_out_file
, "\t.set %LLI%d,.+2\n",
1595 CODE_LABEL_NUMBER (XEXP (labelref
, 0)));
1596 #endif /* not SGS */
1597 #else /* SGS_SWITCH_TABLES or not MOTOROLA */
1598 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "LI",
1599 CODE_LABEL_NUMBER (XEXP (labelref
, 0)));
1600 #ifdef SGS_SWITCH_TABLES
1601 /* Set flag saying we need to define the symbol
1602 LD%n (with value L%n-LI%n) at the end of the switch table. */
1603 switch_table_difference_label_flag
= 1;
1604 #endif /* SGS_SWITCH_TABLES */
1605 #endif /* SGS_SWITCH_TABLES or not MOTOROLA */
1607 #endif /* SGS_NO_LI */
1608 return "move%.w %1,%0";
1612 output_move_qimode (operands
)
1617 /* This is probably useless, since it loses for pushing a struct
1618 of several bytes a byte at a time. */
1619 /* 68k family always modifies the stack pointer by at least 2, even for
1620 byte pushes. The 5200 (coldfire) does not do this. */
1621 if (GET_CODE (operands
[0]) == MEM
1622 && GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
1623 && XEXP (XEXP (operands
[0], 0), 0) == stack_pointer_rtx
1624 && ! ADDRESS_REG_P (operands
[1])
1627 xoperands
[1] = operands
[1];
1629 = gen_rtx_MEM (QImode
,
1630 gen_rtx_PLUS (VOIDmode
, stack_pointer_rtx
, const1_rtx
));
1631 /* Just pushing a byte puts it in the high byte of the halfword. */
1632 /* We must put it in the low-order, high-numbered byte. */
1633 if (!reg_mentioned_p (stack_pointer_rtx
, operands
[1]))
1635 xoperands
[3] = stack_pointer_rtx
;
1637 output_asm_insn ("subq%.l %#2,%3\n\tmove%.b %1,%2", xoperands
);
1639 output_asm_insn ("sub%.l %#2,%3\n\tmove%.b %1,%2", xoperands
);
1643 output_asm_insn ("move%.b %1,%-\n\tmove%.b %@,%2", xoperands
);
1647 /* clr and st insns on 68000 read before writing.
1648 This isn't so on the 68010, but we have no TARGET_68010. */
1649 if (!ADDRESS_REG_P (operands
[0])
1650 && ((TARGET_68020
|| TARGET_5200
)
1651 || !(GET_CODE (operands
[0]) == MEM
&& MEM_VOLATILE_P (operands
[0]))))
1653 if (operands
[1] == const0_rtx
)
1655 if ((!TARGET_5200
|| DATA_REG_P (operands
[0]))
1656 && GET_CODE (operands
[1]) == CONST_INT
1657 && (INTVAL (operands
[1]) & 255) == 255)
1663 if (GET_CODE (operands
[1]) == CONST_INT
1664 && DATA_REG_P (operands
[0])
1665 && INTVAL (operands
[1]) < 128
1666 && INTVAL (operands
[1]) >= -128)
1668 #if defined(MOTOROLA) && !defined(CRDS)
1669 return "moveq%.l %1,%0";
1671 return "moveq %1,%0";
1674 if (operands
[1] == const0_rtx
&& ADDRESS_REG_P (operands
[0]))
1675 return "sub%.l %0,%0";
1676 if (GET_CODE (operands
[1]) != CONST_INT
&& CONSTANT_P (operands
[1]))
1677 return "move%.l %1,%0";
1678 /* 68k family (including the 5200 coldfire) does not support byte moves to
1679 from address registers. */
1680 if (ADDRESS_REG_P (operands
[0]) || ADDRESS_REG_P (operands
[1]))
1681 return "move%.w %1,%0";
1682 return "move%.b %1,%0";
1686 output_move_stricthi (operands
)
1689 if (operands
[1] == const0_rtx
1690 /* clr insns on 68000 read before writing.
1691 This isn't so on the 68010, but we have no TARGET_68010. */
1692 && ((TARGET_68020
|| TARGET_5200
)
1693 || !(GET_CODE (operands
[0]) == MEM
&& MEM_VOLATILE_P (operands
[0]))))
1695 return "move%.w %1,%0";
1699 output_move_strictqi (operands
)
1702 if (operands
[1] == const0_rtx
1703 /* clr insns on 68000 read before writing.
1704 This isn't so on the 68010, but we have no TARGET_68010. */
1705 && ((TARGET_68020
|| TARGET_5200
)
1706 || !(GET_CODE (operands
[0]) == MEM
&& MEM_VOLATILE_P (operands
[0]))))
1708 return "move%.b %1,%0";
1711 /* Return the best assembler insn template
1712 for moving operands[1] into operands[0] as a fullword. */
1715 singlemove_string (operands
)
1718 #ifdef SUPPORT_SUN_FPA
1719 if (FPA_REG_P (operands
[0]) || FPA_REG_P (operands
[1]))
1720 return "fpmoves %1,%0";
1722 if (GET_CODE (operands
[1]) == CONST_INT
)
1723 return output_move_simode_const (operands
);
1724 return "move%.l %1,%0";
1728 /* Output assembler code to perform a doubleword move insn
1729 with operands OPERANDS. */
1732 output_move_double (operands
)
1737 REGOP
, OFFSOP
, MEMOP
, PUSHOP
, POPOP
, CNSTOP
, RNDOP
1742 rtx addreg0
= 0, addreg1
= 0;
1743 int dest_overlapped_low
= 0;
1744 int size
= GET_MODE_SIZE (GET_MODE (operands
[0]));
1749 /* First classify both operands. */
1751 if (REG_P (operands
[0]))
1753 else if (offsettable_memref_p (operands
[0]))
1755 else if (GET_CODE (XEXP (operands
[0], 0)) == POST_INC
)
1757 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
)
1759 else if (GET_CODE (operands
[0]) == MEM
)
1764 if (REG_P (operands
[1]))
1766 else if (CONSTANT_P (operands
[1]))
1768 else if (offsettable_memref_p (operands
[1]))
1770 else if (GET_CODE (XEXP (operands
[1], 0)) == POST_INC
)
1772 else if (GET_CODE (XEXP (operands
[1], 0)) == PRE_DEC
)
1774 else if (GET_CODE (operands
[1]) == MEM
)
1779 /* Check for the cases that the operand constraints are not
1780 supposed to allow to happen. Abort if we get one,
1781 because generating code for these cases is painful. */
1783 if (optype0
== RNDOP
|| optype1
== RNDOP
)
1786 /* If one operand is decrementing and one is incrementing
1787 decrement the former register explicitly
1788 and change that operand into ordinary indexing. */
1790 if (optype0
== PUSHOP
&& optype1
== POPOP
)
1792 operands
[0] = XEXP (XEXP (operands
[0], 0), 0);
1794 output_asm_insn ("sub%.l %#12,%0", operands
);
1796 output_asm_insn ("subq%.l %#8,%0", operands
);
1797 if (GET_MODE (operands
[1]) == XFmode
)
1798 operands
[0] = gen_rtx_MEM (XFmode
, operands
[0]);
1799 else if (GET_MODE (operands
[0]) == DFmode
)
1800 operands
[0] = gen_rtx_MEM (DFmode
, operands
[0]);
1802 operands
[0] = gen_rtx_MEM (DImode
, operands
[0]);
1805 if (optype0
== POPOP
&& optype1
== PUSHOP
)
1807 operands
[1] = XEXP (XEXP (operands
[1], 0), 0);
1809 output_asm_insn ("sub%.l %#12,%1", operands
);
1811 output_asm_insn ("subq%.l %#8,%1", operands
);
1812 if (GET_MODE (operands
[1]) == XFmode
)
1813 operands
[1] = gen_rtx_MEM (XFmode
, operands
[1]);
1814 else if (GET_MODE (operands
[1]) == DFmode
)
1815 operands
[1] = gen_rtx_MEM (DFmode
, operands
[1]);
1817 operands
[1] = gen_rtx_MEM (DImode
, operands
[1]);
1821 /* If an operand is an unoffsettable memory ref, find a register
1822 we can increment temporarily to make it refer to the second word. */
1824 if (optype0
== MEMOP
)
1825 addreg0
= find_addr_reg (XEXP (operands
[0], 0));
1827 if (optype1
== MEMOP
)
1828 addreg1
= find_addr_reg (XEXP (operands
[1], 0));
1830 /* Ok, we can do one word at a time.
1831 Normally we do the low-numbered word first,
1832 but if either operand is autodecrementing then we
1833 do the high-numbered word first.
1835 In either case, set up in LATEHALF the operands to use
1836 for the high-numbered word and in some cases alter the
1837 operands in OPERANDS to be suitable for the low-numbered word. */
1841 if (optype0
== REGOP
)
1843 latehalf
[0] = gen_rtx_REG (SImode
, REGNO (operands
[0]) + 2);
1844 middlehalf
[0] = gen_rtx_REG (SImode
, REGNO (operands
[0]) + 1);
1846 else if (optype0
== OFFSOP
)
1848 middlehalf
[0] = adj_offsettable_operand (operands
[0], 4);
1849 latehalf
[0] = adj_offsettable_operand (operands
[0], size
- 4);
1853 middlehalf
[0] = operands
[0];
1854 latehalf
[0] = operands
[0];
1857 if (optype1
== REGOP
)
1859 latehalf
[1] = gen_rtx_REG (SImode
, REGNO (operands
[1]) + 2);
1860 middlehalf
[1] = gen_rtx_REG (SImode
, REGNO (operands
[1]) + 1);
1862 else if (optype1
== OFFSOP
)
1864 middlehalf
[1] = adj_offsettable_operand (operands
[1], 4);
1865 latehalf
[1] = adj_offsettable_operand (operands
[1], size
- 4);
1867 else if (optype1
== CNSTOP
)
1869 if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
1874 REAL_VALUE_FROM_CONST_DOUBLE (r
, operands
[1]);
1875 REAL_VALUE_TO_TARGET_LONG_DOUBLE (r
, l
);
1876 operands
[1] = GEN_INT (l
[0]);
1877 middlehalf
[1] = GEN_INT (l
[1]);
1878 latehalf
[1] = GEN_INT (l
[2]);
1880 else if (CONSTANT_P (operands
[1]))
1882 /* actually, no non-CONST_DOUBLE constant should ever
1885 if (GET_CODE (operands
[1]) == CONST_INT
&& INTVAL (operands
[1]) < 0)
1886 latehalf
[1] = constm1_rtx
;
1888 latehalf
[1] = const0_rtx
;
1893 middlehalf
[1] = operands
[1];
1894 latehalf
[1] = operands
[1];
1898 /* size is not 12: */
1900 if (optype0
== REGOP
)
1901 latehalf
[0] = gen_rtx_REG (SImode
, REGNO (operands
[0]) + 1);
1902 else if (optype0
== OFFSOP
)
1903 latehalf
[0] = adj_offsettable_operand (operands
[0], size
- 4);
1905 latehalf
[0] = operands
[0];
1907 if (optype1
== REGOP
)
1908 latehalf
[1] = gen_rtx_REG (SImode
, REGNO (operands
[1]) + 1);
1909 else if (optype1
== OFFSOP
)
1910 latehalf
[1] = adj_offsettable_operand (operands
[1], size
- 4);
1911 else if (optype1
== CNSTOP
)
1912 split_double (operands
[1], &operands
[1], &latehalf
[1]);
1914 latehalf
[1] = operands
[1];
1917 /* If insn is effectively movd N(sp),-(sp) then we will do the
1918 high word first. We should use the adjusted operand 1 (which is N+4(sp))
1919 for the low word as well, to compensate for the first decrement of sp. */
1920 if (optype0
== PUSHOP
1921 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
1922 && reg_overlap_mentioned_p (stack_pointer_rtx
, operands
[1]))
1923 operands
[1] = middlehalf
[1] = latehalf
[1];
1925 /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
1926 if the upper part of reg N does not appear in the MEM, arrange to
1927 emit the move late-half first. Otherwise, compute the MEM address
1928 into the upper part of N and use that as a pointer to the memory
1930 if (optype0
== REGOP
1931 && (optype1
== OFFSOP
|| optype1
== MEMOP
))
1933 rtx testlow
= gen_rtx_REG (SImode
, REGNO (operands
[0]));
1935 if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0))
1936 && reg_overlap_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
1938 /* If both halves of dest are used in the src memory address,
1939 compute the address into latehalf of dest.
1940 Note that this can't happen if the dest is two data regs. */
1942 xops
[0] = latehalf
[0];
1943 xops
[1] = XEXP (operands
[1], 0);
1944 output_asm_insn ("lea %a1,%0", xops
);
1945 if( GET_MODE (operands
[1]) == XFmode
)
1947 operands
[1] = gen_rtx_MEM (XFmode
, latehalf
[0]);
1948 middlehalf
[1] = adj_offsettable_operand (operands
[1], size
-8);
1949 latehalf
[1] = adj_offsettable_operand (operands
[1], size
-4);
1953 operands
[1] = gen_rtx_MEM (DImode
, latehalf
[0]);
1954 latehalf
[1] = adj_offsettable_operand (operands
[1], size
-4);
1958 && reg_overlap_mentioned_p (middlehalf
[0],
1959 XEXP (operands
[1], 0)))
1961 /* Check for two regs used by both source and dest.
1962 Note that this can't happen if the dest is all data regs.
1963 It can happen if the dest is d6, d7, a0.
1964 But in that case, latehalf is an addr reg, so
1965 the code at compadr does ok. */
1967 if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0))
1968 || reg_overlap_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
1971 /* JRV says this can't happen: */
1972 if (addreg0
|| addreg1
)
1975 /* Only the middle reg conflicts; simply put it last. */
1976 output_asm_insn (singlemove_string (operands
), operands
);
1977 output_asm_insn (singlemove_string (latehalf
), latehalf
);
1978 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
1981 else if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0)))
1982 /* If the low half of dest is mentioned in the source memory
1983 address, the arrange to emit the move late half first. */
1984 dest_overlapped_low
= 1;
1987 /* If one or both operands autodecrementing,
1988 do the two words, high-numbered first. */
1990 /* Likewise, the first move would clobber the source of the second one,
1991 do them in the other order. This happens only for registers;
1992 such overlap can't happen in memory unless the user explicitly
1993 sets it up, and that is an undefined circumstance. */
1995 if (optype0
== PUSHOP
|| optype1
== PUSHOP
1996 || (optype0
== REGOP
&& optype1
== REGOP
1997 && ((middlehalf
[1] && REGNO (operands
[0]) == REGNO (middlehalf
[1]))
1998 || REGNO (operands
[0]) == REGNO (latehalf
[1])))
1999 || dest_overlapped_low
)
2001 /* Make any unoffsettable addresses point at high-numbered word. */
2005 output_asm_insn ("addq%.l %#8,%0", &addreg0
);
2007 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
2012 output_asm_insn ("addq%.l %#8,%0", &addreg1
);
2014 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
2018 output_asm_insn (singlemove_string (latehalf
), latehalf
);
2020 /* Undo the adds we just did. */
2022 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
2024 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
2028 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
2030 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
2032 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
2035 /* Do low-numbered word. */
2036 return singlemove_string (operands
);
2039 /* Normal case: do the two words, low-numbered first. */
2041 output_asm_insn (singlemove_string (operands
), operands
);
2043 /* Do the middle one of the three words for long double */
2047 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
2049 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
2051 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
2054 /* Make any unoffsettable addresses point at high-numbered word. */
2056 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
2058 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
2061 output_asm_insn (singlemove_string (latehalf
), latehalf
);
2063 /* Undo the adds we just did. */
2067 output_asm_insn ("subq%.l %#8,%0", &addreg0
);
2069 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
2074 output_asm_insn ("subq%.l %#8,%0", &addreg1
);
2076 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
2082 /* Return a REG that occurs in ADDR with coefficient 1.
2083 ADDR can be effectively incremented by incrementing REG. */
2086 find_addr_reg (addr
)
2089 while (GET_CODE (addr
) == PLUS
)
2091 if (GET_CODE (XEXP (addr
, 0)) == REG
)
2092 addr
= XEXP (addr
, 0);
2093 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
2094 addr
= XEXP (addr
, 1);
2095 else if (CONSTANT_P (XEXP (addr
, 0)))
2096 addr
= XEXP (addr
, 1);
2097 else if (CONSTANT_P (XEXP (addr
, 1)))
2098 addr
= XEXP (addr
, 0);
2102 if (GET_CODE (addr
) == REG
)
2107 /* Output assembler code to perform a 32 bit 3 operand add. */
2110 output_addsi3 (operands
)
2113 if (! operands_match_p (operands
[0], operands
[1]))
2115 if (!ADDRESS_REG_P (operands
[1]))
2117 rtx tmp
= operands
[1];
2119 operands
[1] = operands
[2];
2123 /* These insns can result from reloads to access
2124 stack slots over 64k from the frame pointer. */
2125 if (GET_CODE (operands
[2]) == CONST_INT
2126 && INTVAL (operands
[2]) + 0x8000 >= (unsigned) 0x10000)
2127 return "move%.l %2,%0\n\tadd%.l %1,%0";
2129 if (GET_CODE (operands
[2]) == REG
)
2130 return "lea 0(%1,%2.l),%0";
2132 return "lea %c2(%1),%0";
2135 if (GET_CODE (operands
[2]) == REG
)
2136 return "lea (%1,%2.l),%0";
2138 return "lea (%c2,%1),%0";
2139 #else /* not MOTOROLA (MIT syntax) */
2140 if (GET_CODE (operands
[2]) == REG
)
2141 return "lea %1@(0,%2:l),%0";
2143 return "lea %1@(%c2),%0";
2144 #endif /* not MOTOROLA */
2145 #endif /* not SGS */
2147 if (GET_CODE (operands
[2]) == CONST_INT
)
2150 if (INTVAL (operands
[2]) > 0
2151 && INTVAL (operands
[2]) <= 8)
2152 return "addq%.l %2,%0";
2153 if (INTVAL (operands
[2]) < 0
2154 && INTVAL (operands
[2]) >= -8)
2156 operands
[2] = GEN_INT (-INTVAL (operands
[2]));
2157 return "subq%.l %2,%0";
2159 /* On the CPU32 it is faster to use two addql instructions to
2160 add a small integer (8 < N <= 16) to a register.
2161 Likewise for subql. */
2162 if (TARGET_CPU32
&& REG_P (operands
[0]))
2164 if (INTVAL (operands
[2]) > 8
2165 && INTVAL (operands
[2]) <= 16)
2167 operands
[2] = GEN_INT (INTVAL (operands
[2]) - 8);
2168 return "addq%.l %#8,%0\n\taddq%.l %2,%0";
2170 if (INTVAL (operands
[2]) < -8
2171 && INTVAL (operands
[2]) >= -16)
2173 operands
[2] = GEN_INT (-INTVAL (operands
[2]) - 8);
2174 return "subq%.l %#8,%0\n\tsubq%.l %2,%0";
2178 if (ADDRESS_REG_P (operands
[0])
2179 && INTVAL (operands
[2]) >= -0x8000
2180 && INTVAL (operands
[2]) < 0x8000)
2183 return "add%.w %2,%0";
2186 return "lea (%c2,%0),%0";
2188 return "lea %0@(%c2),%0";
2192 return "add%.l %2,%0";
2195 /* Store in cc_status the expressions that the condition codes will
2196 describe after execution of an instruction whose pattern is EXP.
2197 Do not alter them if the instruction would not alter the cc's. */
2199 /* On the 68000, all the insns to store in an address register fail to
2200 set the cc's. However, in some cases these instructions can make it
2201 possibly invalid to use the saved cc's. In those cases we clear out
2202 some or all of the saved cc's so they won't be used. */
2205 notice_update_cc (exp
, insn
)
2209 /* If the cc is being set from the fpa and the expression is not an
2210 explicit floating point test instruction (which has code to deal with
2211 this), reinit the CC. */
2212 if (((cc_status
.value1
&& FPA_REG_P (cc_status
.value1
))
2213 || (cc_status
.value2
&& FPA_REG_P (cc_status
.value2
)))
2214 && !(GET_CODE (exp
) == PARALLEL
2215 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
2216 && XEXP (XVECEXP (exp
, 0, 0), 0) == cc0_rtx
))
2220 else if (GET_CODE (exp
) == SET
)
2222 if (GET_CODE (SET_SRC (exp
)) == CALL
)
2226 else if (ADDRESS_REG_P (SET_DEST (exp
)))
2228 if (cc_status
.value1
&& modified_in_p (cc_status
.value1
, insn
))
2229 cc_status
.value1
= 0;
2230 if (cc_status
.value2
&& modified_in_p (cc_status
.value2
, insn
))
2231 cc_status
.value2
= 0;
2233 else if (!FP_REG_P (SET_DEST (exp
))
2234 && SET_DEST (exp
) != cc0_rtx
2235 && (FP_REG_P (SET_SRC (exp
))
2236 || GET_CODE (SET_SRC (exp
)) == FIX
2237 || GET_CODE (SET_SRC (exp
)) == FLOAT_TRUNCATE
2238 || GET_CODE (SET_SRC (exp
)) == FLOAT_EXTEND
))
2242 /* A pair of move insns doesn't produce a useful overall cc. */
2243 else if (!FP_REG_P (SET_DEST (exp
))
2244 && !FP_REG_P (SET_SRC (exp
))
2245 && GET_MODE_SIZE (GET_MODE (SET_SRC (exp
))) > 4
2246 && (GET_CODE (SET_SRC (exp
)) == REG
2247 || GET_CODE (SET_SRC (exp
)) == MEM
2248 || GET_CODE (SET_SRC (exp
)) == CONST_DOUBLE
))
2252 else if (GET_CODE (SET_SRC (exp
)) == CALL
)
2256 else if (XEXP (exp
, 0) != pc_rtx
)
2258 cc_status
.flags
= 0;
2259 cc_status
.value1
= XEXP (exp
, 0);
2260 cc_status
.value2
= XEXP (exp
, 1);
2263 else if (GET_CODE (exp
) == PARALLEL
2264 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
)
2266 if (ADDRESS_REG_P (XEXP (XVECEXP (exp
, 0, 0), 0)))
2268 else if (XEXP (XVECEXP (exp
, 0, 0), 0) != pc_rtx
)
2270 cc_status
.flags
= 0;
2271 cc_status
.value1
= XEXP (XVECEXP (exp
, 0, 0), 0);
2272 cc_status
.value2
= XEXP (XVECEXP (exp
, 0, 0), 1);
2277 if (cc_status
.value2
!= 0
2278 && ADDRESS_REG_P (cc_status
.value2
)
2279 && GET_MODE (cc_status
.value2
) == QImode
)
2281 if (cc_status
.value2
!= 0
2282 && !(cc_status
.value1
&& FPA_REG_P (cc_status
.value1
)))
2283 switch (GET_CODE (cc_status
.value2
))
2285 case PLUS
: case MINUS
: case MULT
:
2286 case DIV
: case UDIV
: case MOD
: case UMOD
: case NEG
:
2287 #if 0 /* These instructions always clear the overflow bit */
2288 case ASHIFT
: case ASHIFTRT
: case LSHIFTRT
:
2289 case ROTATE
: case ROTATERT
:
2291 if (GET_MODE (cc_status
.value2
) != VOIDmode
)
2292 cc_status
.flags
|= CC_NO_OVERFLOW
;
2295 /* (SET r1 (ZERO_EXTEND r2)) on this machine
2296 ends with a move insn moving r2 in r2's mode.
2297 Thus, the cc's are set for r2.
2298 This can set N bit spuriously. */
2299 cc_status
.flags
|= CC_NOT_NEGATIVE
;
2304 if (cc_status
.value1
&& GET_CODE (cc_status
.value1
) == REG
2306 && reg_overlap_mentioned_p (cc_status
.value1
, cc_status
.value2
))
2307 cc_status
.value2
= 0;
2308 if (((cc_status
.value1
&& FP_REG_P (cc_status
.value1
))
2309 || (cc_status
.value2
&& FP_REG_P (cc_status
.value2
)))
2310 && !((cc_status
.value1
&& FPA_REG_P (cc_status
.value1
))
2311 || (cc_status
.value2
&& FPA_REG_P (cc_status
.value2
))))
2312 cc_status
.flags
= CC_IN_68881
;
2316 output_move_const_double (operands
)
2319 #ifdef SUPPORT_SUN_FPA
2320 if (TARGET_FPA
&& FPA_REG_P (operands
[0]))
2322 int code
= standard_sun_fpa_constant_p (operands
[1]);
2326 static char buf
[40];
2328 sprintf (buf
, "fpmove%%.d %%%%%d,%%0", code
& 0x1ff);
2331 return "fpmove%.d %1,%0";
2336 int code
= standard_68881_constant_p (operands
[1]);
2340 static char buf
[40];
2342 sprintf (buf
, "fmovecr %%#0x%x,%%0", code
& 0xff);
2345 return "fmove%.d %1,%0";
2350 output_move_const_single (operands
)
2353 #ifdef SUPPORT_SUN_FPA
2356 int code
= standard_sun_fpa_constant_p (operands
[1]);
2360 static char buf
[40];
2362 sprintf (buf
, "fpmove%%.s %%%%%d,%%0", code
& 0x1ff);
2365 return "fpmove%.s %1,%0";
2368 #endif /* defined SUPPORT_SUN_FPA */
2370 int code
= standard_68881_constant_p (operands
[1]);
2374 static char buf
[40];
2376 sprintf (buf
, "fmovecr %%#0x%x,%%0", code
& 0xff);
2379 return "fmove%.s %f1,%0";
2383 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
2384 from the "fmovecr" instruction.
2385 The value, anded with 0xff, gives the code to use in fmovecr
2386 to get the desired constant. */
2388 /* This code has been fixed for cross-compilation. */
2390 static int inited_68881_table
= 0;
2392 char *strings_68881
[7] = {
2402 int codes_68881
[7] = {
2412 REAL_VALUE_TYPE values_68881
[7];
2414 /* Set up values_68881 array by converting the decimal values
2415 strings_68881 to binary. */
2422 enum machine_mode mode
;
2425 for (i
= 0; i
< 7; i
++)
2429 r
= REAL_VALUE_ATOF (strings_68881
[i
], mode
);
2430 values_68881
[i
] = r
;
2432 inited_68881_table
= 1;
2436 standard_68881_constant_p (x
)
2442 #ifdef NO_ASM_FMOVECR
2446 /* fmovecr must be emulated on the 68040 and 68060, so it shouldn't be
2447 used at all on those chips. */
2448 if (TARGET_68040
|| TARGET_68060
)
2451 #ifndef REAL_ARITHMETIC
2452 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2453 if (! flag_pretend_float
)
2458 if (! inited_68881_table
)
2459 init_68881_table ();
2461 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
2463 for (i
= 0; i
< 6; i
++)
2465 if (REAL_VALUES_EQUAL (r
, values_68881
[i
]))
2466 return (codes_68881
[i
]);
2469 if (GET_MODE (x
) == SFmode
)
2472 if (REAL_VALUES_EQUAL (r
, values_68881
[6]))
2473 return (codes_68881
[6]);
2475 /* larger powers of ten in the constants ram are not used
2476 because they are not equal to a `double' C constant. */
2480 /* If X is a floating-point constant, return the logarithm of X base 2,
2481 or 0 if X is not a power of 2. */
2484 floating_exact_log2 (x
)
2487 REAL_VALUE_TYPE r
, r1
;
2490 #ifndef REAL_ARITHMETIC
2491 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2492 if (! flag_pretend_float
)
2497 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
2499 if (REAL_VALUES_LESS (r
, dconst0
))
2504 while (REAL_VALUES_LESS (r1
, r
))
2506 r1
= REAL_VALUE_LDEXP (dconst1
, i
);
2507 if (REAL_VALUES_EQUAL (r1
, r
))
2514 #ifdef SUPPORT_SUN_FPA
2515 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
2516 from the Sun FPA's constant RAM.
2517 The value returned, anded with 0x1ff, gives the code to use in fpmove
2518 to get the desired constant. */
2520 static int inited_FPA_table
= 0;
2522 char *strings_FPA
[38] = {
2523 /* small rationals */
2536 /* Decimal equivalents of double precision values */
2537 "2.718281828459045091", /* D_E */
2538 "6.283185307179586477", /* 2 pi */
2539 "3.141592653589793116", /* D_PI */
2540 "1.570796326794896619", /* pi/2 */
2541 "1.414213562373095145", /* D_SQRT2 */
2542 "0.7071067811865475244", /* 1/sqrt(2) */
2543 "-1.570796326794896619", /* -pi/2 */
2544 "1.442695040888963387", /* D_LOG2ofE */
2545 "3.321928024887362182", /* D_LOG2of10 */
2546 "0.6931471805599452862", /* D_LOGEof2 */
2547 "2.302585092994045901", /* D_LOGEof10 */
2548 "0.3010299956639811980", /* D_LOG10of2 */
2549 "0.4342944819032518167", /* D_LOG10ofE */
2550 /* Decimal equivalents of single precision values */
2551 "2.718281745910644531", /* S_E */
2552 "6.283185307179586477", /* 2 pi */
2553 "3.141592741012573242", /* S_PI */
2554 "1.570796326794896619", /* pi/2 */
2555 "1.414213538169860840", /* S_SQRT2 */
2556 "0.7071067811865475244", /* 1/sqrt(2) */
2557 "-1.570796326794896619", /* -pi/2 */
2558 "1.442695021629333496", /* S_LOG2ofE */
2559 "3.321928024291992188", /* S_LOG2of10 */
2560 "0.6931471824645996094", /* S_LOGEof2 */
2561 "2.302585124969482442", /* S_LOGEof10 */
2562 "0.3010300099849700928", /* S_LOG10of2 */
2563 "0.4342944920063018799", /* S_LOG10ofE */
2567 int codes_FPA
[38] = {
2568 /* small rationals */
2581 /* double precision */
2595 /* single precision */
2611 REAL_VALUE_TYPE values_FPA
[38];
2613 /* This code has been fixed for cross-compilation. */
2618 enum machine_mode mode
;
2623 for (i
= 0; i
< 38; i
++)
2627 r
= REAL_VALUE_ATOF (strings_FPA
[i
], mode
);
2630 inited_FPA_table
= 1;
2635 standard_sun_fpa_constant_p (x
)
2641 #ifndef REAL_ARITHMETIC
2642 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2643 if (! flag_pretend_float
)
2648 if (! inited_FPA_table
)
2651 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
2653 for (i
=0; i
<12; i
++)
2655 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
2656 return (codes_FPA
[i
]);
2659 if (GET_MODE (x
) == SFmode
)
2661 for (i
=25; i
<38; i
++)
2663 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
2664 return (codes_FPA
[i
]);
2669 for (i
=12; i
<25; i
++)
2671 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
2672 return (codes_FPA
[i
]);
2677 #endif /* define SUPPORT_SUN_FPA */
2679 /* A C compound statement to output to stdio stream STREAM the
2680 assembler syntax for an instruction operand X. X is an RTL
2683 CODE is a value that can be used to specify one of several ways
2684 of printing the operand. It is used when identical operands
2685 must be printed differently depending on the context. CODE
2686 comes from the `%' specification that was used to request
2687 printing of the operand. If the specification was just `%DIGIT'
2688 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
2689 is the ASCII code for LTR.
2691 If X is a register, this macro should print the register's name.
2692 The names can be found in an array `reg_names' whose type is
2693 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
2695 When the machine description has a specification `%PUNCT' (a `%'
2696 followed by a punctuation character), this macro is called with
2697 a null pointer for X and the punctuation character for CODE.
2699 The m68k specific codes are:
2701 '.' for dot needed in Motorola-style opcode names.
2702 '-' for an operand pushing on the stack:
2703 sp@-, -(sp) or -(%sp) depending on the style of syntax.
2704 '+' for an operand pushing on the stack:
2705 sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
2706 '@' for a reference to the top word on the stack:
2707 sp@, (sp) or (%sp) depending on the style of syntax.
2708 '#' for an immediate operand prefix (# in MIT and Motorola syntax
2709 but & in SGS syntax, $ in CRDS/UNOS syntax).
2710 '!' for the cc register (used in an `and to cc' insn).
2711 '$' for the letter `s' in an op code, but only on the 68040.
2712 '&' for the letter `d' in an op code, but only on the 68040.
2713 '/' for register prefix needed by longlong.h.
2715 'b' for byte insn (no effect, on the Sun; this is for the ISI).
2716 'd' to force memory addressing to be absolute, not relative.
2717 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
2718 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
2719 than directly). Second part of 'y' below.
2720 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
2721 or print pair of registers as rx:ry.
2722 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
2723 CONST_DOUBLE's as SunFPA constant RAM registers if
2724 possible, so it should not be used except for the SunFPA.
2729 print_operand (file
, op
, letter
)
2730 FILE *file
; /* file to write to */
2731 rtx op
; /* operand to print */
2732 int letter
; /* %<letter> or 0 */
2734 #ifdef SUPPORT_SUN_FPA
2740 #if defined (MOTOROLA) && !defined (CRDS)
2741 asm_fprintf (file
, ".");
2744 else if (letter
== '#')
2746 asm_fprintf (file
, "%0I");
2748 else if (letter
== '-')
2751 asm_fprintf (file
, "-(%Rsp)");
2753 asm_fprintf (file
, "%Rsp@-");
2756 else if (letter
== '+')
2759 asm_fprintf (file
, "(%Rsp)+");
2761 asm_fprintf (file
, "%Rsp@+");
2764 else if (letter
== '@')
2767 asm_fprintf (file
, "(%Rsp)");
2769 asm_fprintf (file
, "%Rsp@");
2772 else if (letter
== '!')
2774 asm_fprintf (file
, "%Rfpcr");
2776 else if (letter
== '$')
2778 if (TARGET_68040_ONLY
)
2780 fprintf (file
, "s");
2783 else if (letter
== '&')
2785 if (TARGET_68040_ONLY
)
2787 fprintf (file
, "d");
2790 else if (letter
== '/')
2792 asm_fprintf (file
, "%R");
2794 else if (GET_CODE (op
) == REG
)
2796 #ifdef SUPPORT_SUN_FPA
2798 && (letter
== 'y' || letter
== 'x')
2799 && GET_MODE (op
) == DFmode
)
2801 fprintf (file
, "%s:%s", reg_names
[REGNO (op
)],
2802 reg_names
[REGNO (op
)+1]);
2808 /* Print out the second register name of a register pair.
2809 I.e., R (6) => 7. */
2810 fputs (reg_names
[REGNO (op
) + 1], file
);
2812 fputs (reg_names
[REGNO (op
)], file
);
2815 else if (GET_CODE (op
) == MEM
)
2817 output_address (XEXP (op
, 0));
2818 if (letter
== 'd' && ! TARGET_68020
2819 && CONSTANT_ADDRESS_P (XEXP (op
, 0))
2820 && !(GET_CODE (XEXP (op
, 0)) == CONST_INT
2821 && INTVAL (XEXP (op
, 0)) < 0x8000
2822 && INTVAL (XEXP (op
, 0)) >= -0x8000))
2825 fprintf (file
, ".l");
2827 fprintf (file
, ":l");
2831 #ifdef SUPPORT_SUN_FPA
2832 else if ((letter
== 'y' || letter
== 'w')
2833 && GET_CODE (op
) == CONST_DOUBLE
2834 && (i
= standard_sun_fpa_constant_p (op
)))
2836 fprintf (file
, "%%%d", i
& 0x1ff);
2839 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == SFmode
)
2842 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2843 ASM_OUTPUT_FLOAT_OPERAND (letter
, file
, r
);
2845 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == XFmode
)
2848 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2849 ASM_OUTPUT_LONG_DOUBLE_OPERAND (file
, r
);
2851 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == DFmode
)
2854 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2855 ASM_OUTPUT_DOUBLE_OPERAND (file
, r
);
2859 asm_fprintf (file
, "%0I"); output_addr_const (file
, op
);
2864 /* A C compound statement to output to stdio stream STREAM the
2865 assembler syntax for an instruction operand that is a memory
2866 reference whose address is ADDR. ADDR is an RTL expression.
2868 Note that this contains a kludge that knows that the only reason
2869 we have an address (plus (label_ref...) (reg...)) when not generating
2870 PIC code is in the insn before a tablejump, and we know that m68k.md
2871 generates a label LInnn: on such an insn.
2873 It is possible for PIC to generate a (plus (label_ref...) (reg...))
2874 and we handle that just like we would a (plus (symbol_ref...) (reg...)).
2876 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
2877 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
2878 we want. This difference can be accommodated by using an assembler
2879 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
2880 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
2881 macro. See m68k/sgs.h for an example; for versions without the bug.
2882 Some assemblers refuse all the above solutions. The workaround is to
2883 emit "K(pc,d0.l*2)" with K being a small constant known to give the
2886 They also do not like things like "pea 1.w", so we simple leave off
2887 the .w on small constants.
2889 This routine is responsible for distinguishing between -fpic and -fPIC
2890 style relocations in an address. When generating -fpic code the
2891 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating
2892 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
2894 #ifndef ASM_OUTPUT_CASE_FETCH
2897 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2898 asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
2900 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2901 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
2904 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2905 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
2907 #endif /* ASM_OUTPUT_CASE_FETCH */
2910 print_operand_address (file
, addr
)
2914 register rtx reg1
, reg2
, breg
, ireg
;
2917 switch (GET_CODE (addr
))
2921 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
2923 fprintf (file
, "%s@", reg_names
[REGNO (addr
)]);
2928 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
2930 fprintf (file
, "%s@-", reg_names
[REGNO (XEXP (addr
, 0))]);
2935 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
2937 fprintf (file
, "%s@+", reg_names
[REGNO (XEXP (addr
, 0))]);
2941 reg1
= reg2
= ireg
= breg
= offset
= 0;
2942 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0)))
2944 offset
= XEXP (addr
, 0);
2945 addr
= XEXP (addr
, 1);
2947 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1)))
2949 offset
= XEXP (addr
, 1);
2950 addr
= XEXP (addr
, 0);
2952 if (GET_CODE (addr
) != PLUS
)
2956 else if (GET_CODE (XEXP (addr
, 0)) == SIGN_EXTEND
)
2958 reg1
= XEXP (addr
, 0);
2959 addr
= XEXP (addr
, 1);
2961 else if (GET_CODE (XEXP (addr
, 1)) == SIGN_EXTEND
)
2963 reg1
= XEXP (addr
, 1);
2964 addr
= XEXP (addr
, 0);
2966 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
2968 reg1
= XEXP (addr
, 0);
2969 addr
= XEXP (addr
, 1);
2971 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
2973 reg1
= XEXP (addr
, 1);
2974 addr
= XEXP (addr
, 0);
2976 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
2978 reg1
= XEXP (addr
, 0);
2979 addr
= XEXP (addr
, 1);
2981 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
2983 reg1
= XEXP (addr
, 1);
2984 addr
= XEXP (addr
, 0);
2986 if (GET_CODE (addr
) == REG
|| GET_CODE (addr
) == MULT
2987 || GET_CODE (addr
) == SIGN_EXTEND
)
2999 #if 0 /* for OLD_INDEXING */
3000 else if (GET_CODE (addr
) == PLUS
)
3002 if (GET_CODE (XEXP (addr
, 0)) == REG
)
3004 reg2
= XEXP (addr
, 0);
3005 addr
= XEXP (addr
, 1);
3007 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
3009 reg2
= XEXP (addr
, 1);
3010 addr
= XEXP (addr
, 0);
3022 if ((reg1
&& (GET_CODE (reg1
) == SIGN_EXTEND
3023 || GET_CODE (reg1
) == MULT
))
3024 || (reg2
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2
))))
3029 else if (reg1
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1
)))
3034 if (ireg
!= 0 && breg
== 0 && GET_CODE (addr
) == LABEL_REF
3035 && ! (flag_pic
&& ireg
== pic_offset_table_rtx
))
3038 if (GET_CODE (ireg
) == MULT
)
3040 scale
= INTVAL (XEXP (ireg
, 1));
3041 ireg
= XEXP (ireg
, 0);
3043 if (GET_CODE (ireg
) == SIGN_EXTEND
)
3045 ASM_OUTPUT_CASE_FETCH (file
,
3046 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
3047 reg_names
[REGNO (XEXP (ireg
, 0))]);
3048 fprintf (file
, "w");
3052 ASM_OUTPUT_CASE_FETCH (file
,
3053 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
3054 reg_names
[REGNO (ireg
)]);
3055 fprintf (file
, "l");
3060 fprintf (file
, "*%d", scale
);
3062 fprintf (file
, ":%d", scale
);
3068 if (breg
!= 0 && ireg
== 0 && GET_CODE (addr
) == LABEL_REF
3069 && ! (flag_pic
&& breg
== pic_offset_table_rtx
))
3071 ASM_OUTPUT_CASE_FETCH (file
,
3072 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
3073 reg_names
[REGNO (breg
)]);
3074 fprintf (file
, "l)");
3077 if (ireg
!= 0 || breg
!= 0)
3084 if (! flag_pic
&& addr
&& GET_CODE (addr
) == LABEL_REF
)
3091 output_addr_const (file
, addr
);
3092 if (flag_pic
&& (breg
== pic_offset_table_rtx
))
3094 fprintf (file
, "@GOT");
3096 fprintf (file
, ".w");
3099 fprintf (file
, "(%s", reg_names
[REGNO (breg
)]);
3105 fprintf (file
, "%s@(", reg_names
[REGNO (breg
)]);
3108 output_addr_const (file
, addr
);
3109 if ((flag_pic
== 1) && (breg
== pic_offset_table_rtx
))
3110 fprintf (file
, ":w");
3111 if ((flag_pic
== 2) && (breg
== pic_offset_table_rtx
))
3112 fprintf (file
, ":l");
3114 if (addr
!= 0 && ireg
!= 0)
3119 if (ireg
!= 0 && GET_CODE (ireg
) == MULT
)
3121 scale
= INTVAL (XEXP (ireg
, 1));
3122 ireg
= XEXP (ireg
, 0);
3124 if (ireg
!= 0 && GET_CODE (ireg
) == SIGN_EXTEND
)
3127 fprintf (file
, "%s.w", reg_names
[REGNO (XEXP (ireg
, 0))]);
3129 fprintf (file
, "%s:w", reg_names
[REGNO (XEXP (ireg
, 0))]);
3135 fprintf (file
, "%s.l", reg_names
[REGNO (ireg
)]);
3137 fprintf (file
, "%s:l", reg_names
[REGNO (ireg
)]);
3143 fprintf (file
, "*%d", scale
);
3145 fprintf (file
, ":%d", scale
);
3151 else if (reg1
!= 0 && GET_CODE (addr
) == LABEL_REF
3152 && ! (flag_pic
&& reg1
== pic_offset_table_rtx
))
3154 ASM_OUTPUT_CASE_FETCH (file
,
3155 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
3156 reg_names
[REGNO (reg1
)]);
3157 fprintf (file
, "l)");
3160 /* FALL-THROUGH (is this really what we want? */
3162 if (GET_CODE (addr
) == CONST_INT
3163 && INTVAL (addr
) < 0x8000
3164 && INTVAL (addr
) >= -0x8000)
3168 /* Many SGS assemblers croak on size specifiers for constants. */
3169 fprintf (file
, "%d", INTVAL (addr
));
3171 fprintf (file
, "%d.w", INTVAL (addr
));
3174 fprintf (file
, "%d:w", INTVAL (addr
));
3179 output_addr_const (file
, addr
);
3185 /* Check for cases where a clr insns can be omitted from code using
3186 strict_low_part sets. For example, the second clrl here is not needed:
3187 clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
3189 MODE is the mode of this STRICT_LOW_PART set. FIRST_INSN is the clear
3190 insn we are checking for redundancy. TARGET is the register set by the
3194 strict_low_part_peephole_ok (mode
, first_insn
, target
)
3195 enum machine_mode mode
;
3201 p
= prev_nonnote_insn (first_insn
);
3205 /* If it isn't an insn, then give up. */
3206 if (GET_CODE (p
) != INSN
)
3209 if (reg_set_p (target
, p
))
3211 rtx set
= single_set (p
);
3214 /* If it isn't an easy to recognize insn, then give up. */
3218 dest
= SET_DEST (set
);
3220 /* If this sets the entire target register to zero, then our
3221 first_insn is redundant. */
3222 if (rtx_equal_p (dest
, target
)
3223 && SET_SRC (set
) == const0_rtx
)
3225 else if (GET_CODE (dest
) == STRICT_LOW_PART
3226 && GET_CODE (XEXP (dest
, 0)) == REG
3227 && REGNO (XEXP (dest
, 0)) == REGNO (target
)
3228 && (GET_MODE_SIZE (GET_MODE (XEXP (dest
, 0)))
3229 <= GET_MODE_SIZE (mode
)))
3230 /* This is a strict low part set which modifies less than
3231 we are using, so it is safe. */
3237 p
= prev_nonnote_insn (p
);
3244 /* Accept integer operands in the range 0..0xffffffff. We have to check the
3245 range carefully since this predicate is used in DImode contexts. Also, we
3246 need some extra crud to make it work when hosted on 64-bit machines. */
3249 const_uint32_operand (op
, mode
)
3251 enum machine_mode mode ATTRIBUTE_UNUSED
;
3253 #if HOST_BITS_PER_WIDE_INT > 32
3254 /* All allowed constants will fit a CONST_INT. */
3255 return (GET_CODE (op
) == CONST_INT
3256 && (INTVAL (op
) >= 0 && INTVAL (op
) <= 0xffffffffL
));
3258 return ((GET_CODE (op
) == CONST_INT
&& INTVAL (op
) >= 0)
3259 || (GET_CODE (op
) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (op
) == 0));
3263 /* Accept integer operands in the range -0x80000000..0x7fffffff. We have
3264 to check the range carefully since this predicate is used in DImode
3268 const_sint32_operand (op
, mode
)
3270 enum machine_mode mode ATTRIBUTE_UNUSED
;
3272 /* All allowed constants will fit a CONST_INT. */
3273 return (GET_CODE (op
) == CONST_INT
3274 && (INTVAL (op
) >= (-0x7fffffff - 1) && INTVAL (op
) <= 0x7fffffff));
3278 output_andsi3 (operands
)
3282 if (GET_CODE (operands
[2]) == CONST_INT
3283 && (INTVAL (operands
[2]) | 0xffff) == 0xffffffff
3284 && (DATA_REG_P (operands
[0])
3285 || offsettable_memref_p (operands
[0]))
3288 if (GET_CODE (operands
[0]) != REG
)
3289 operands
[0] = adj_offsettable_operand (operands
[0], 2);
3290 operands
[2] = GEN_INT (INTVAL (operands
[2]) & 0xffff);
3291 /* Do not delete a following tstl %0 insn; that would be incorrect. */
3293 if (operands
[2] == const0_rtx
)
3295 return "and%.w %2,%0";
3297 if (GET_CODE (operands
[2]) == CONST_INT
3298 && (logval
= exact_log2 (~ INTVAL (operands
[2]))) >= 0
3299 && (DATA_REG_P (operands
[0])
3300 || offsettable_memref_p (operands
[0])))
3302 if (DATA_REG_P (operands
[0]))
3304 operands
[1] = GEN_INT (logval
);
3308 operands
[0] = adj_offsettable_operand (operands
[0], 3 - (logval
/ 8));
3309 operands
[1] = GEN_INT (logval
% 8);
3311 /* This does not set condition codes in a standard way. */
3313 return "bclr %1,%0";
3315 return "and%.l %2,%0";
3319 output_iorsi3 (operands
)
3322 register int logval
;
3323 if (GET_CODE (operands
[2]) == CONST_INT
3324 && INTVAL (operands
[2]) >> 16 == 0
3325 && (DATA_REG_P (operands
[0])
3326 || offsettable_memref_p (operands
[0]))
3329 if (GET_CODE (operands
[0]) != REG
)
3330 operands
[0] = adj_offsettable_operand (operands
[0], 2);
3331 /* Do not delete a following tstl %0 insn; that would be incorrect. */
3333 if (INTVAL (operands
[2]) == 0xffff)
3334 return "mov%.w %2,%0";
3335 return "or%.w %2,%0";
3337 if (GET_CODE (operands
[2]) == CONST_INT
3338 && (logval
= exact_log2 (INTVAL (operands
[2]))) >= 0
3339 && (DATA_REG_P (operands
[0])
3340 || offsettable_memref_p (operands
[0])))
3342 if (DATA_REG_P (operands
[0]))
3344 operands
[1] = GEN_INT (logval
);
3348 operands
[0] = adj_offsettable_operand (operands
[0], 3 - (logval
/ 8));
3349 operands
[1] = GEN_INT (logval
% 8);
3352 return "bset %1,%0";
3354 return "or%.l %2,%0";
3358 output_xorsi3 (operands
)
3361 register int logval
;
3362 if (GET_CODE (operands
[2]) == CONST_INT
3363 && INTVAL (operands
[2]) >> 16 == 0
3364 && (offsettable_memref_p (operands
[0]) || DATA_REG_P (operands
[0]))
3367 if (! DATA_REG_P (operands
[0]))
3368 operands
[0] = adj_offsettable_operand (operands
[0], 2);
3369 /* Do not delete a following tstl %0 insn; that would be incorrect. */
3371 if (INTVAL (operands
[2]) == 0xffff)
3373 return "eor%.w %2,%0";
3375 if (GET_CODE (operands
[2]) == CONST_INT
3376 && (logval
= exact_log2 (INTVAL (operands
[2]))) >= 0
3377 && (DATA_REG_P (operands
[0])
3378 || offsettable_memref_p (operands
[0])))
3380 if (DATA_REG_P (operands
[0]))
3382 operands
[1] = GEN_INT (logval
);
3386 operands
[0] = adj_offsettable_operand (operands
[0], 3 - (logval
/ 8));
3387 operands
[1] = GEN_INT (logval
% 8);
3390 return "bchg %1,%0";
3392 return "eor%.l %2,%0";