1 /* Subroutines for insn-output.c for Motorola 68000 family.
2 Copyright (C) 1987, 93, 94, 95, 96, 1997 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. */
27 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "insn-flags.h"
33 #include "insn-attr.h"
35 /* Needed for use_return_insn. */
38 #ifdef SUPPORT_SUN_FPA
40 /* Index into this array by (register number >> 3) to find the
41 smallest class which contains that register. */
42 enum reg_class regno_reg_class
[]
43 = { DATA_REGS
, ADDR_REGS
, FP_REGS
,
44 LO_FPA_REGS
, LO_FPA_REGS
, FPA_REGS
, FPA_REGS
};
46 #endif /* defined SUPPORT_SUN_FPA */
48 /* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
49 if SGS_SWITCH_TABLE. */
50 int switch_table_difference_label_flag
;
52 static rtx
find_addr_reg ();
53 rtx
legitimize_pic_address ();
56 /* Alignment to use for loops and jumps */
57 /* Specify power of two alignment used for loops. */
58 char *m68k_align_loops_string
;
59 /* Specify power of two alignment used for non-loop jumps. */
60 char *m68k_align_jumps_string
;
61 /* Specify power of two alignment used for functions. */
62 char *m68k_align_funcs_string
;
64 /* Specify power of two alignment used for loops. */
66 /* Specify power of two alignment used for non-loop jumps. */
68 /* Specify power of two alignment used for functions. */
72 /* Sometimes certain combinations of command options do not make
73 sense on a particular target machine. You can define a macro
74 `OVERRIDE_OPTIONS' to take account of this. This macro, if
75 defined, is executed once just after all the command options have
78 Don't use this macro to turn on various extra optimizations for
79 `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
88 /* Validate -malign-loops= value, or provide default */
89 if (m68k_align_loops_string
)
91 m68k_align_loops
= atoi (m68k_align_loops_string
);
92 if (m68k_align_loops
< 1 || m68k_align_loops
> MAX_CODE_ALIGN
)
93 fatal ("-malign-loops=%d is not between 1 and %d",
94 m68k_align_loops
, MAX_CODE_ALIGN
);
97 m68k_align_loops
= def_align
;
99 /* Validate -malign-jumps= value, or provide default */
100 if (m68k_align_jumps_string
)
102 m68k_align_jumps
= atoi (m68k_align_jumps_string
);
103 if (m68k_align_jumps
< 1 || m68k_align_jumps
> MAX_CODE_ALIGN
)
104 fatal ("-malign-jumps=%d is not between 1 and %d",
105 m68k_align_jumps
, MAX_CODE_ALIGN
);
108 m68k_align_jumps
= def_align
;
110 /* Validate -malign-functions= value, or provide default */
111 if (m68k_align_funcs_string
)
113 m68k_align_funcs
= atoi (m68k_align_funcs_string
);
114 if (m68k_align_funcs
< 1 || m68k_align_funcs
> MAX_CODE_ALIGN
)
115 fatal ("-malign-functions=%d is not between 1 and %d",
116 m68k_align_funcs
, MAX_CODE_ALIGN
);
119 m68k_align_funcs
= def_align
;
122 /* Emit a (use pic_offset_table_rtx) if we used PIC relocation in the
123 function at any time during the compilation process. In the future
124 we should try and eliminate the USE if we can easily determine that
125 all PIC references were deleted from the current function. That would
126 save an address register */
131 if (flag_pic
&& current_function_uses_pic_offset_table
)
133 rtx insn
= gen_rtx (USE
, VOIDmode
, pic_offset_table_rtx
);
134 emit_insn_after (insn
, get_insns ());
140 /* This function generates the assembly code for function entry.
141 STREAM is a stdio stream to output the code to.
142 SIZE is an int: how many units of temporary storage to allocate.
143 Refer to the array `regs_ever_live' to determine which registers
144 to save; `regs_ever_live[I]' is nonzero if register number I
145 is ever used in the function. This function is responsible for
146 knowing which registers should not be saved even if used. */
149 /* Note that the order of the bit mask for fmovem is the opposite
150 of the order for movem! */
154 output_function_prologue (stream
, size
)
159 register int mask
= 0;
160 int num_saved_regs
= 0;
161 extern char call_used_regs
[];
162 int fsize
= (size
+ 3) & -4;
165 if (frame_pointer_needed
)
167 if (fsize
== 0 && TARGET_68040
)
169 /* on the 68040, pea + move is faster than link.w 0 */
171 asm_fprintf (stream
, "\tpea (%s)\n\tmove.l %s,%s\n",
172 reg_names
[FRAME_POINTER_REGNUM
], reg_names
[STACK_POINTER_REGNUM
],
173 reg_names
[FRAME_POINTER_REGNUM
]);
175 asm_fprintf (stream
, "\tpea %s@\n\tmovel %s,%s\n",
176 reg_names
[FRAME_POINTER_REGNUM
], reg_names
[STACK_POINTER_REGNUM
],
177 reg_names
[FRAME_POINTER_REGNUM
]);
180 else if (fsize
< 0x8000)
183 asm_fprintf (stream
, "\tlink.w %s,%0I%d\n",
184 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
186 asm_fprintf (stream
, "\tlink %s,%0I%d\n",
187 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
190 else if (TARGET_68020
)
193 asm_fprintf (stream
, "\tlink.l %s,%0I%d\n",
194 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
196 asm_fprintf (stream
, "\tlink %s,%0I%d\n",
197 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
202 /* Adding negative number is faster on the 68040. */
204 asm_fprintf (stream
, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
205 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
207 asm_fprintf (stream
, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
208 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
214 if (fsize
+ 4 < 0x8000)
221 /* asm_fprintf() cannot handle %. */
223 asm_fprintf (stream
, "\tsubq.w %OI%d,%Rsp\n", fsize
+ 4);
225 asm_fprintf (stream
, "\tsubqw %OI%d,%Rsp\n", fsize
+ 4);
231 asm_fprintf (stream
, "\tsubq.l %OI%d,%Rsp\n", fsize
+ 4);
233 asm_fprintf (stream
, "\tsubql %OI%d,%Rsp\n", fsize
+ 4);
237 else if (fsize
+ 4 <= 16 && TARGET_CPU32
)
239 /* On the CPU32 it is faster to use two subqw instructions to
240 subtract a small integer (8 < N <= 16) to a register. */
241 /* asm_fprintf() cannot handle %. */
243 asm_fprintf (stream
, "\tsubq.w %OI8,%Rsp\n\tsubq.w %OI%d,%Rsp\n",
246 asm_fprintf (stream
, "\tsubqw %OI8,%Rsp\n\tsubqw %OI%d,%Rsp\n",
251 #endif /* NO_ADDSUB_Q */
254 /* Adding negative number is faster on the 68040. */
255 /* asm_fprintf() cannot handle %. */
257 asm_fprintf (stream
, "\tadd.w %0I%d,%Rsp\n", - (fsize
+ 4));
259 asm_fprintf (stream
, "\taddw %0I%d,%Rsp\n", - (fsize
+ 4));
264 /* asm_fprintf() cannot handle %. */
266 asm_fprintf (stream
, "\tlea (%d,%Rsp),%Rsp\n", - (fsize
+ 4));
268 asm_fprintf (stream
, "\tlea %Rsp@(%d),%Rsp\n", - (fsize
+ 4));
274 /* asm_fprintf() cannot handle %. */
276 asm_fprintf (stream
, "\tadd.l %0I%d,%Rsp\n", - (fsize
+ 4));
278 asm_fprintf (stream
, "\taddl %0I%d,%Rsp\n", - (fsize
+ 4));
282 #ifdef SUPPORT_SUN_FPA
283 for (regno
= 24; regno
< 56; regno
++)
284 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
287 asm_fprintf (stream
, "\tfpmovd %s,-(%Rsp)\n",
290 asm_fprintf (stream
, "\tfpmoved %s,%Rsp@-\n",
297 for (regno
= 16; regno
< 24; regno
++)
298 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
299 mask
|= 1 << (regno
- 16);
300 if ((mask
& 0xff) != 0)
303 asm_fprintf (stream
, "\tfmovm %0I0x%x,-(%Rsp)\n", mask
& 0xff);
305 asm_fprintf (stream
, "\tfmovem %0I0x%x,%Rsp@-\n", mask
& 0xff);
310 for (regno
= 0; regno
< 16; regno
++)
311 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
313 mask
|= 1 << (15 - regno
);
316 if (frame_pointer_needed
)
318 mask
&= ~ (1 << (15 - FRAME_POINTER_REGNUM
));
323 asm_fprintf (stream
, "\ttstl %Rsp@(%d)\n", NEED_PROBE
- num_saved_regs
* 4);
326 if (num_saved_regs
<= 2)
328 /* Store each separately in the same order moveml uses.
329 Using two movel instructions instead of a single moveml
330 is about 15% faster for the 68020 and 68030 at no expense
335 /* Undo the work from above. */
336 for (i
= 0; i
< 16; i
++)
340 "\t%Omove.l %s,-(%Rsp)\n",
342 "\tmovel %s,%Rsp@-\n",
350 /* The coldfire does not support the predecrement form of the
351 movml instruction, so we must adjust the stack pointer and
352 then use the plain address register indirect mode. We also
353 have to invert the register save mask to use the new mode.
355 FIXME: if num_saved_regs was calculated earlier, we could
356 combine the stack pointer adjustment with any adjustment
357 done when the initial stack frame is created. This would
358 save an instruction */
363 for (i
= 0; i
< 16; i
++)
365 newmask
|= (1 << (15-i
));
368 asm_fprintf (stream
, "\tlea (%d,%Rsp),%Rsp\n", -num_saved_regs
*4);
369 asm_fprintf (stream
, "\tmovm.l %0I0x%x,(%Rsp)\n", newmask
);
371 asm_fprintf (stream
, "\tlea %Rsp@(%d),%Rsp\n", -num_saved_regs
*4);
372 asm_fprintf (stream
, "\tmoveml %0I0x%x,%Rsp@\n", newmask
);
378 asm_fprintf (stream
, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask
);
380 asm_fprintf (stream
, "\tmoveml %0I0x%x,%Rsp@-\n", mask
);
384 if (flag_pic
&& current_function_uses_pic_offset_table
)
387 asm_fprintf (stream
, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
388 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
390 asm_fprintf (stream
, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
391 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
392 asm_fprintf (stream
, "\tlea %Rpc@(0,%s:l),%s\n",
393 reg_names
[PIC_OFFSET_TABLE_REGNUM
],
394 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
399 /* Return true if this function's epilogue can be output as RTL. */
406 if (!reload_completed
|| frame_pointer_needed
|| get_frame_size () != 0)
409 /* Copied from output_function_epilogue (). We should probably create a
410 separate layout routine to perform the common work. */
412 for (regno
= 0 ; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
413 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
419 /* This function generates the assembly code for function exit,
420 on machines that need it. Args are same as for FUNCTION_PROLOGUE.
422 The function epilogue should not depend on the current stack pointer!
423 It should use the frame pointer only, if there is a frame pointer.
424 This is mandatory because of alloca; we also take advantage of it to
425 omit stack adjustments before returning. */
428 output_function_epilogue (stream
, size
)
433 register int mask
, fmask
;
435 int offset
, foffset
, fpoffset
;
436 extern char call_used_regs
[];
437 int fsize
= (size
+ 3) & -4;
439 rtx insn
= get_last_insn ();
440 int restore_from_sp
= 0;
442 /* If the last insn was a BARRIER, we don't have to write any code. */
443 if (GET_CODE (insn
) == NOTE
)
444 insn
= prev_nonnote_insn (insn
);
445 if (insn
&& GET_CODE (insn
) == BARRIER
)
447 /* Output just a no-op so that debuggers don't get confused
448 about which function the pc is in at this address. */
449 asm_fprintf (stream
, "\tnop\n");
453 #ifdef FUNCTION_BLOCK_PROFILER_EXIT
454 if (profile_block_flag
== 2)
456 FUNCTION_BLOCK_PROFILER_EXIT (stream
);
460 #ifdef FUNCTION_EXTRA_EPILOGUE
461 FUNCTION_EXTRA_EPILOGUE (stream
, size
);
463 nregs
= 0; fmask
= 0; fpoffset
= 0;
464 #ifdef SUPPORT_SUN_FPA
465 for (regno
= 24 ; regno
< 56 ; regno
++)
466 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
468 fpoffset
= nregs
* 8;
473 for (regno
= 16; regno
< 24; regno
++)
474 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
477 fmask
|= 1 << (23 - regno
);
480 foffset
= fpoffset
+ nregs
* 12;
482 if (frame_pointer_needed
)
483 regs_ever_live
[FRAME_POINTER_REGNUM
] = 0;
484 for (regno
= 0; regno
< 16; regno
++)
485 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
490 offset
= foffset
+ nregs
* 4;
491 /* FIXME : leaf_function_p below is too strong.
492 What we really need to know there is if there could be pending
493 stack adjustment needed at that point. */
494 restore_from_sp
= ! frame_pointer_needed
495 || (! current_function_calls_alloca
&& leaf_function_p ());
496 if (offset
+ fsize
>= 0x8000
498 && (mask
|| fmask
|| fpoffset
))
501 asm_fprintf (stream
, "\t%Omove.l %0I%d,%Ra1\n", -fsize
);
503 asm_fprintf (stream
, "\tmovel %0I%d,%Ra1\n", -fsize
);
507 if (TARGET_5200
|| nregs
<= 2)
509 /* Restore each separately in the same order moveml does.
510 Using two movel instructions instead of a single moveml
511 is about 15% faster for the 68020 and 68030 at no expense
516 /* Undo the work from above. */
517 for (i
= 0; i
< 16; i
++)
523 asm_fprintf (stream
, "\t%Omove.l -%d(%s,%Ra1.l),%s\n",
525 reg_names
[FRAME_POINTER_REGNUM
],
528 asm_fprintf (stream
, "\tmovel %s@(-%d,%Ra1:l),%s\n",
529 reg_names
[FRAME_POINTER_REGNUM
],
530 offset
+ fsize
, reg_names
[i
]);
533 else if (restore_from_sp
)
536 asm_fprintf (stream
, "\t%Omove.l (%Rsp)+,%s\n",
539 asm_fprintf (stream
, "\tmovel %Rsp@+,%s\n",
546 asm_fprintf (stream
, "\t%Omove.l -%d(%s),%s\n",
548 reg_names
[FRAME_POINTER_REGNUM
],
551 asm_fprintf (stream
, "\tmovel %s@(-%d),%s\n",
552 reg_names
[FRAME_POINTER_REGNUM
],
553 offset
+ fsize
, reg_names
[i
]);
564 asm_fprintf (stream
, "\tmovm.l -%d(%s,%Ra1.l),%0I0x%x\n",
566 reg_names
[FRAME_POINTER_REGNUM
],
569 asm_fprintf (stream
, "\tmoveml %s@(-%d,%Ra1:l),%0I0x%x\n",
570 reg_names
[FRAME_POINTER_REGNUM
],
571 offset
+ fsize
, mask
);
574 else if (restore_from_sp
)
577 asm_fprintf (stream
, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask
);
579 asm_fprintf (stream
, "\tmoveml %Rsp@+,%0I0x%x\n", mask
);
585 asm_fprintf (stream
, "\tmovm.l -%d(%s),%0I0x%x\n",
587 reg_names
[FRAME_POINTER_REGNUM
],
590 asm_fprintf (stream
, "\tmoveml %s@(-%d),%0I0x%x\n",
591 reg_names
[FRAME_POINTER_REGNUM
],
592 offset
+ fsize
, mask
);
601 asm_fprintf (stream
, "\tfmovm -%d(%s,%Ra1.l),%0I0x%x\n",
603 reg_names
[FRAME_POINTER_REGNUM
],
606 asm_fprintf (stream
, "\tfmovem %s@(-%d,%Ra1:l),%0I0x%x\n",
607 reg_names
[FRAME_POINTER_REGNUM
],
608 foffset
+ fsize
, fmask
);
611 else if (restore_from_sp
)
614 asm_fprintf (stream
, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask
);
616 asm_fprintf (stream
, "\tfmovem %Rsp@+,%0I0x%x\n", fmask
);
622 asm_fprintf (stream
, "\tfmovm -%d(%s),%0I0x%x\n",
624 reg_names
[FRAME_POINTER_REGNUM
],
627 asm_fprintf (stream
, "\tfmovem %s@(-%d),%0I0x%x\n",
628 reg_names
[FRAME_POINTER_REGNUM
],
629 foffset
+ fsize
, fmask
);
634 for (regno
= 55; regno
>= 24; regno
--)
635 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
640 asm_fprintf (stream
, "\tfpmovd -%d(%s,%Ra1.l), %s\n",
642 reg_names
[FRAME_POINTER_REGNUM
],
645 asm_fprintf (stream
, "\tfpmoved %s@(-%d,%Ra1:l), %s\n",
646 reg_names
[FRAME_POINTER_REGNUM
],
647 fpoffset
+ fsize
, reg_names
[regno
]);
650 else if (restore_from_sp
)
653 asm_fprintf (stream
, "\tfpmovd (%Rsp)+,%s\n",
656 asm_fprintf (stream
, "\tfpmoved %Rsp@+, %s\n",
663 asm_fprintf (stream
, "\tfpmovd -%d(%s), %s\n",
665 reg_names
[FRAME_POINTER_REGNUM
],
668 asm_fprintf (stream
, "\tfpmoved %s@(-%d), %s\n",
669 reg_names
[FRAME_POINTER_REGNUM
],
670 fpoffset
+ fsize
, reg_names
[regno
]);
675 if (frame_pointer_needed
)
676 fprintf (stream
, "\tunlk %s\n",
677 reg_names
[FRAME_POINTER_REGNUM
]);
686 asm_fprintf (stream
, "\taddq.w %OI%d,%Rsp\n", fsize
+ 4);
688 asm_fprintf (stream
, "\taddqw %OI%d,%Rsp\n", fsize
+ 4);
694 asm_fprintf (stream
, "\taddq.l %OI%d,%Rsp\n", fsize
+ 4);
696 asm_fprintf (stream
, "\taddql %OI%d,%Rsp\n", fsize
+ 4);
700 else if (fsize
+ 4 <= 16 && TARGET_CPU32
)
702 /* On the CPU32 it is faster to use two addqw instructions to
703 add a small integer (8 < N <= 16) to a register. */
705 asm_fprintf (stream
, "\taddq.w %OI8,%Rsp\n\taddq.w %OI%d,%Rsp\n",
708 asm_fprintf (stream
, "\taddqw %OI8,%Rsp\n\taddqw %OI%d,%Rsp\n",
713 #endif /* NO_ADDSUB_Q */
714 if (fsize
+ 4 < 0x8000)
718 /* asm_fprintf() cannot handle %. */
720 asm_fprintf (stream
, "\tadd.w %0I%d,%Rsp\n", fsize
+ 4);
722 asm_fprintf (stream
, "\taddw %0I%d,%Rsp\n", fsize
+ 4);
727 /* asm_fprintf() cannot handle %. */
729 asm_fprintf (stream
, "\tlea (%d,%Rsp),%Rsp\n", fsize
+ 4);
731 asm_fprintf (stream
, "\tlea %Rsp@(%d),%Rsp\n", fsize
+ 4);
737 /* asm_fprintf() cannot handle %. */
739 asm_fprintf (stream
, "\tadd.l %0I%d,%Rsp\n", fsize
+ 4);
741 asm_fprintf (stream
, "\taddl %0I%d,%Rsp\n", fsize
+ 4);
745 if (current_function_pops_args
)
746 asm_fprintf (stream
, "\trtd %0I%d\n", current_function_pops_args
);
748 fprintf (stream
, "\trts\n");
751 /* Similar to general_operand, but exclude stack_pointer_rtx. */
754 not_sp_operand (op
, mode
)
756 enum machine_mode mode
;
758 return op
!= stack_pointer_rtx
&& general_operand (op
, mode
);
761 /* Return TRUE if X is a valid comparison operator for the dbcc
764 Note it rejects floating point comparison operators.
765 (In the future we could use Fdbcc).
767 It also rejects some comparisons when CC_NO_OVERFLOW is set. */
770 valid_dbcc_comparison_p (x
, mode
)
772 enum machine_mode mode
;
774 switch (GET_CODE (x
))
776 case EQ
: case NE
: case GTU
: case LTU
:
780 /* Reject some when CC_NO_OVERFLOW is set. This may be over
782 case GT
: case LT
: case GE
: case LE
:
783 return ! (cc_prev_status
.flags
& CC_NO_OVERFLOW
);
789 /* Return non-zero if flags are currently in the 68881 flag register. */
793 /* We could add support for these in the future */
794 return cc_status
.flags
& CC_IN_68881
;
797 /* Output a dbCC; jCC sequence. Note we do not handle the
798 floating point version of this sequence (Fdbcc). We also
799 do not handle alternative conditions when CC_NO_OVERFLOW is
800 set. It is assumed that valid_dbcc_comparison_p and flags_in_68881 will
801 kick those out before we get here. */
803 output_dbcc_and_branch (operands
)
806 switch (GET_CODE (operands
[3]))
810 output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands
);
812 output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands
);
818 output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands
);
820 output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands
);
826 output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands
);
828 output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands
);
834 output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands
);
836 output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands
);
842 output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands
);
844 output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands
);
850 output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands
);
852 output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands
);
858 output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands
);
860 output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands
);
866 output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands
);
868 output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands
);
874 output_asm_insn ("dble %0,%l1\n\tjble %l2", operands
);
876 output_asm_insn ("dble %0,%l1\n\tjle %l2", operands
);
882 output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands
);
884 output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands
);
892 /* If the decrement is to be done in SImode, then we have
893 to compensate for the fact that dbcc decrements in HImode. */
894 switch (GET_MODE (operands
[0]))
898 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands
);
900 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands
);
913 output_scc_di(op
, operand1
, operand2
, dest
)
920 enum rtx_code op_code
= GET_CODE (op
);
922 /* The m68k cmp.l instruction requires operand1 to be a reg as used
923 below. Swap the operands and change the op if these requirements
924 are not fulfilled. */
925 if (GET_CODE (operand2
) == REG
&& GET_CODE (operand1
) != REG
)
931 op_code
= swap_condition (op_code
);
933 loperands
[0] = operand1
;
934 if (GET_CODE (operand1
) == REG
)
935 loperands
[1] = gen_rtx (REG
, SImode
, REGNO (operand1
) + 1);
937 loperands
[1] = adj_offsettable_operand (operand1
, 4);
938 if (operand2
!= const0_rtx
)
940 loperands
[2] = operand2
;
941 if (GET_CODE (operand2
) == REG
)
942 loperands
[3] = gen_rtx (REG
, SImode
, REGNO (operand2
) + 1);
944 loperands
[3] = adj_offsettable_operand (operand2
, 4);
946 loperands
[4] = gen_label_rtx();
947 if (operand2
!= const0_rtx
)
950 output_asm_insn ("cmp%.l %0,%2\n\tjbne %l4\n\tcmp%.l %1,%3", loperands
);
952 output_asm_insn ("cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1", loperands
);
956 output_asm_insn ("cmp%.l %0,%2\n\tjne %l4\n\tcmp%.l %1,%3", loperands
);
958 output_asm_insn ("cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1", loperands
);
963 output_asm_insn ("tst%.l %0\n\tjbne %l4\n\ttst%.l %1", loperands
);
965 output_asm_insn ("tst%.l %0\n\tjne %l4\n\ttst%.l %1", loperands
);
972 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
973 CODE_LABEL_NUMBER (loperands
[4]));
974 output_asm_insn ("seq %5", loperands
);
978 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
979 CODE_LABEL_NUMBER (loperands
[4]));
980 output_asm_insn ("sne %5", loperands
);
984 loperands
[6] = gen_label_rtx();
986 output_asm_insn ("shi %5\n\tjbra %l6", loperands
);
988 output_asm_insn ("shi %5\n\tjra %l6", loperands
);
990 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
991 CODE_LABEL_NUMBER (loperands
[4]));
992 output_asm_insn ("sgt %5", loperands
);
993 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
994 CODE_LABEL_NUMBER (loperands
[6]));
998 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
999 CODE_LABEL_NUMBER (loperands
[4]));
1000 output_asm_insn ("shi %5", loperands
);
1004 loperands
[6] = gen_label_rtx();
1006 output_asm_insn ("scs %5\n\tjbra %l6", loperands
);
1008 output_asm_insn ("scs %5\n\tjra %l6", loperands
);
1010 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1011 CODE_LABEL_NUMBER (loperands
[4]));
1012 output_asm_insn ("slt %5", loperands
);
1013 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1014 CODE_LABEL_NUMBER (loperands
[6]));
1018 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1019 CODE_LABEL_NUMBER (loperands
[4]));
1020 output_asm_insn ("scs %5", loperands
);
1024 loperands
[6] = gen_label_rtx();
1026 output_asm_insn ("scc %5\n\tjbra %l6", loperands
);
1028 output_asm_insn ("scc %5\n\tjra %l6", loperands
);
1030 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1031 CODE_LABEL_NUMBER (loperands
[4]));
1032 output_asm_insn ("sge %5", loperands
);
1033 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1034 CODE_LABEL_NUMBER (loperands
[6]));
1038 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1039 CODE_LABEL_NUMBER (loperands
[4]));
1040 output_asm_insn ("scc %5", loperands
);
1044 loperands
[6] = gen_label_rtx();
1046 output_asm_insn ("sls %5\n\tjbra %l6", loperands
);
1048 output_asm_insn ("sls %5\n\tjra %l6", loperands
);
1050 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1051 CODE_LABEL_NUMBER (loperands
[4]));
1052 output_asm_insn ("sle %5", loperands
);
1053 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1054 CODE_LABEL_NUMBER (loperands
[6]));
1058 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
1059 CODE_LABEL_NUMBER (loperands
[4]));
1060 output_asm_insn ("sls %5", loperands
);
1070 output_btst (operands
, countop
, dataop
, insn
, signpos
)
1072 rtx countop
, dataop
;
1076 operands
[0] = countop
;
1077 operands
[1] = dataop
;
1079 if (GET_CODE (countop
) == CONST_INT
)
1081 register int count
= INTVAL (countop
);
1082 /* If COUNT is bigger than size of storage unit in use,
1083 advance to the containing unit of same size. */
1084 if (count
> signpos
)
1086 int offset
= (count
& ~signpos
) / 8;
1087 count
= count
& signpos
;
1088 operands
[1] = dataop
= adj_offsettable_operand (dataop
, offset
);
1090 if (count
== signpos
)
1091 cc_status
.flags
= CC_NOT_POSITIVE
| CC_Z_IN_NOT_N
;
1093 cc_status
.flags
= CC_NOT_NEGATIVE
| CC_Z_IN_NOT_N
;
1095 /* These three statements used to use next_insns_test_no...
1096 but it appears that this should do the same job. */
1098 && next_insn_tests_no_inequality (insn
))
1101 && next_insn_tests_no_inequality (insn
))
1104 && next_insn_tests_no_inequality (insn
))
1107 cc_status
.flags
= CC_NOT_NEGATIVE
;
1109 return "btst %0,%1";
1112 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
1113 reference and a constant. */
1116 symbolic_operand (op
, mode
)
1118 enum machine_mode mode
;
1120 switch (GET_CODE (op
))
1128 return ((GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
1129 || GET_CODE (XEXP (op
, 0)) == LABEL_REF
)
1130 && GET_CODE (XEXP (op
, 1)) == CONST_INT
);
1132 #if 0 /* Deleted, with corresponding change in m68k.h,
1133 so as to fit the specs. No CONST_DOUBLE is ever symbolic. */
1135 return GET_MODE (op
) == mode
;
1143 /* Check for sign_extend or zero_extend. Used for bit-count operands. */
1146 extend_operator(x
, mode
)
1148 enum machine_mode mode
;
1150 if (mode
!= VOIDmode
&& GET_MODE(x
) != mode
)
1152 switch (GET_CODE(x
))
1163 /* Legitimize PIC addresses. If the address is already
1164 position-independent, we return ORIG. Newly generated
1165 position-independent addresses go to REG. If we need more
1166 than one register, we lose.
1168 An address is legitimized by making an indirect reference
1169 through the Global Offset Table with the name of the symbol
1172 The assembler and linker are responsible for placing the
1173 address of the symbol in the GOT. The function prologue
1174 is responsible for initializing a5 to the starting address
1177 The assembler is also responsible for translating a symbol name
1178 into a constant displacement from the start of the GOT.
1180 A quick example may make things a little clearer:
1182 When not generating PIC code to store the value 12345 into _foo
1183 we would generate the following code:
1187 When generating PIC two transformations are made. First, the compiler
1188 loads the address of foo into a register. So the first transformation makes:
1193 The code in movsi will intercept the lea instruction and call this
1194 routine which will transform the instructions into:
1196 movel a5@(_foo:w), a0
1200 That (in a nutshell) is how *all* symbol and label references are
1204 legitimize_pic_address (orig
, mode
, reg
)
1206 enum machine_mode mode
;
1210 /* First handle a simple SYMBOL_REF or LABEL_REF */
1211 if (GET_CODE (orig
) == SYMBOL_REF
|| GET_CODE (orig
) == LABEL_REF
)
1216 pic_ref
= gen_rtx (MEM
, Pmode
,
1217 gen_rtx (PLUS
, Pmode
,
1218 pic_offset_table_rtx
, orig
));
1219 current_function_uses_pic_offset_table
= 1;
1220 RTX_UNCHANGING_P (pic_ref
) = 1;
1221 emit_move_insn (reg
, pic_ref
);
1224 else if (GET_CODE (orig
) == CONST
)
1228 /* Make sure this is CONST has not already been legitimized */
1229 if (GET_CODE (XEXP (orig
, 0)) == PLUS
1230 && XEXP (XEXP (orig
, 0), 0) == pic_offset_table_rtx
)
1236 /* legitimize both operands of the PLUS */
1237 if (GET_CODE (XEXP (orig
, 0)) == PLUS
)
1239 base
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 0), Pmode
, reg
);
1240 orig
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 1), Pmode
,
1241 base
== reg
? 0 : reg
);
1245 if (GET_CODE (orig
) == CONST_INT
)
1246 return plus_constant_for_output (base
, INTVAL (orig
));
1247 pic_ref
= gen_rtx (PLUS
, Pmode
, base
, orig
);
1248 /* Likewise, should we set special REG_NOTEs here? */
1254 typedef enum { MOVL
, SWAP
, NEGW
, NOTW
, NOTB
, MOVQ
} CONST_METHOD
;
1256 #define USE_MOVQ(i) ((unsigned)((i) + 128) <= 255)
1259 const_method (constant
)
1265 i
= INTVAL (constant
);
1269 /* The Coldfire doesn't have byte or word operations. */
1270 /* FIXME: This may not be useful for the m68060 either */
1273 /* if -256 < N < 256 but N is not in range for a moveq
1274 N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */
1275 if (USE_MOVQ (i
^ 0xff))
1277 /* Likewise, try with not.w */
1278 if (USE_MOVQ (i
^ 0xffff))
1280 /* This is the only value where neg.w is useful */
1283 /* Try also with swap */
1285 if (USE_MOVQ ((u
>> 16) | (u
<< 16)))
1288 /* Otherwise, use move.l */
1292 const_int_cost (constant
)
1295 switch (const_method (constant
))
1298 /* Constants between -128 and 127 are cheap due to moveq */
1304 /* Constants easily generated by moveq + not.b/not.w/neg.w/swap */
1314 output_move_const_into_data_reg (operands
)
1319 i
= INTVAL (operands
[1]);
1320 switch (const_method (operands
[1]))
1323 #if defined (MOTOROLA) && !defined (CRDS)
1324 return "moveq%.l %1,%0";
1326 return "moveq %1,%0";
1329 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
, i
^ 0xff);
1330 #if defined (MOTOROLA) && !defined (CRDS)
1331 return "moveq%.l %1,%0\n\tnot%.b %0";
1333 return "moveq %1,%0\n\tnot%.b %0";
1336 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
, i
^ 0xffff);
1337 #if defined (MOTOROLA) && !defined (CRDS)
1338 return "moveq%.l %1,%0\n\tnot%.w %0";
1340 return "moveq %1,%0\n\tnot%.w %0";
1343 #if defined (MOTOROLA) && !defined (CRDS)
1344 return "moveq%.l %#-128,%0\n\tneg%.w %0";
1346 return "moveq %#-128,%0\n\tneg%.w %0";
1352 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
, (u
<< 16) | (u
>> 16));
1353 #if defined (MOTOROLA) && !defined (CRDS)
1354 return "moveq%.l %1,%0\n\tswap %0";
1356 return "moveq %1,%0\n\tswap %0";
1360 return "move%.l %1,%0";
1367 output_move_simode_const (operands
)
1370 if (operands
[1] == const0_rtx
1371 && (DATA_REG_P (operands
[0])
1372 || GET_CODE (operands
[0]) == MEM
)
1373 /* clr insns on 68000 read before writing.
1374 This isn't so on the 68010, but we have no TARGET_68010. */
1376 || !(GET_CODE (operands
[0]) == MEM
1377 && MEM_VOLATILE_P (operands
[0]))))
1379 else if (DATA_REG_P (operands
[0]))
1380 return output_move_const_into_data_reg (operands
);
1381 else if (ADDRESS_REG_P (operands
[0])
1382 && INTVAL (operands
[1]) < 0x8000
1383 && INTVAL (operands
[1]) >= -0x8000)
1384 return "move%.w %1,%0";
1385 else if (GET_CODE (operands
[0]) == MEM
1386 && GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
1387 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
1388 && INTVAL (operands
[1]) < 0x8000
1389 && INTVAL (operands
[1]) >= -0x8000)
1391 return "move%.l %1,%0";
1394 /* Return the best assembler insn template
1395 for moving operands[1] into operands[0] as a fullword. */
1398 singlemove_string (operands
)
1401 #ifdef SUPPORT_SUN_FPA
1402 if (FPA_REG_P (operands
[0]) || FPA_REG_P (operands
[1]))
1403 return "fpmoves %1,%0";
1405 if (GET_CODE (operands
[1]) == CONST_INT
)
1406 return output_move_simode_const (operands
);
1407 return "move%.l %1,%0";
1411 /* Output assembler code to perform a doubleword move insn
1412 with operands OPERANDS. */
1415 output_move_double (operands
)
1420 REGOP
, OFFSOP
, MEMOP
, PUSHOP
, POPOP
, CNSTOP
, RNDOP
1425 rtx addreg0
= 0, addreg1
= 0;
1426 int dest_overlapped_low
= 0;
1427 int size
= GET_MODE_SIZE (GET_MODE (operands
[0]));
1432 /* First classify both operands. */
1434 if (REG_P (operands
[0]))
1436 else if (offsettable_memref_p (operands
[0]))
1438 else if (GET_CODE (XEXP (operands
[0], 0)) == POST_INC
)
1440 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
)
1442 else if (GET_CODE (operands
[0]) == MEM
)
1447 if (REG_P (operands
[1]))
1449 else if (CONSTANT_P (operands
[1]))
1451 else if (offsettable_memref_p (operands
[1]))
1453 else if (GET_CODE (XEXP (operands
[1], 0)) == POST_INC
)
1455 else if (GET_CODE (XEXP (operands
[1], 0)) == PRE_DEC
)
1457 else if (GET_CODE (operands
[1]) == MEM
)
1462 /* Check for the cases that the operand constraints are not
1463 supposed to allow to happen. Abort if we get one,
1464 because generating code for these cases is painful. */
1466 if (optype0
== RNDOP
|| optype1
== RNDOP
)
1469 /* If one operand is decrementing and one is incrementing
1470 decrement the former register explicitly
1471 and change that operand into ordinary indexing. */
1473 if (optype0
== PUSHOP
&& optype1
== POPOP
)
1475 operands
[0] = XEXP (XEXP (operands
[0], 0), 0);
1477 output_asm_insn ("sub%.l %#12,%0", operands
);
1479 output_asm_insn ("subq%.l %#8,%0", operands
);
1480 if (GET_MODE (operands
[1]) == XFmode
)
1481 operands
[0] = gen_rtx (MEM
, XFmode
, operands
[0]);
1482 else if (GET_MODE (operands
[0]) == DFmode
)
1483 operands
[0] = gen_rtx (MEM
, DFmode
, operands
[0]);
1485 operands
[0] = gen_rtx (MEM
, DImode
, operands
[0]);
1488 if (optype0
== POPOP
&& optype1
== PUSHOP
)
1490 operands
[1] = XEXP (XEXP (operands
[1], 0), 0);
1492 output_asm_insn ("sub%.l %#12,%1", operands
);
1494 output_asm_insn ("subq%.l %#8,%1", operands
);
1495 if (GET_MODE (operands
[1]) == XFmode
)
1496 operands
[1] = gen_rtx (MEM
, XFmode
, operands
[1]);
1497 else if (GET_MODE (operands
[1]) == DFmode
)
1498 operands
[1] = gen_rtx (MEM
, DFmode
, operands
[1]);
1500 operands
[1] = gen_rtx (MEM
, DImode
, operands
[1]);
1504 /* If an operand is an unoffsettable memory ref, find a register
1505 we can increment temporarily to make it refer to the second word. */
1507 if (optype0
== MEMOP
)
1508 addreg0
= find_addr_reg (XEXP (operands
[0], 0));
1510 if (optype1
== MEMOP
)
1511 addreg1
= find_addr_reg (XEXP (operands
[1], 0));
1513 /* Ok, we can do one word at a time.
1514 Normally we do the low-numbered word first,
1515 but if either operand is autodecrementing then we
1516 do the high-numbered word first.
1518 In either case, set up in LATEHALF the operands to use
1519 for the high-numbered word and in some cases alter the
1520 operands in OPERANDS to be suitable for the low-numbered word. */
1524 if (optype0
== REGOP
)
1526 latehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 2);
1527 middlehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 1);
1529 else if (optype0
== OFFSOP
)
1531 middlehalf
[0] = adj_offsettable_operand (operands
[0], 4);
1532 latehalf
[0] = adj_offsettable_operand (operands
[0], size
- 4);
1536 middlehalf
[0] = operands
[0];
1537 latehalf
[0] = operands
[0];
1540 if (optype1
== REGOP
)
1542 latehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 2);
1543 middlehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 1);
1545 else if (optype1
== OFFSOP
)
1547 middlehalf
[1] = adj_offsettable_operand (operands
[1], 4);
1548 latehalf
[1] = adj_offsettable_operand (operands
[1], size
- 4);
1550 else if (optype1
== CNSTOP
)
1552 if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
1557 REAL_VALUE_FROM_CONST_DOUBLE (r
, operands
[1]);
1558 REAL_VALUE_TO_TARGET_LONG_DOUBLE (r
, l
);
1559 operands
[1] = GEN_INT (l
[0]);
1560 middlehalf
[1] = GEN_INT (l
[1]);
1561 latehalf
[1] = GEN_INT (l
[2]);
1563 else if (CONSTANT_P (operands
[1]))
1565 /* actually, no non-CONST_DOUBLE constant should ever
1568 if (GET_CODE (operands
[1]) == CONST_INT
&& INTVAL (operands
[1]) < 0)
1569 latehalf
[1] = constm1_rtx
;
1571 latehalf
[1] = const0_rtx
;
1576 middlehalf
[1] = operands
[1];
1577 latehalf
[1] = operands
[1];
1581 /* size is not 12: */
1583 if (optype0
== REGOP
)
1584 latehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 1);
1585 else if (optype0
== OFFSOP
)
1586 latehalf
[0] = adj_offsettable_operand (operands
[0], size
- 4);
1588 latehalf
[0] = operands
[0];
1590 if (optype1
== REGOP
)
1591 latehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 1);
1592 else if (optype1
== OFFSOP
)
1593 latehalf
[1] = adj_offsettable_operand (operands
[1], size
- 4);
1594 else if (optype1
== CNSTOP
)
1595 split_double (operands
[1], &operands
[1], &latehalf
[1]);
1597 latehalf
[1] = operands
[1];
1600 /* If insn is effectively movd N(sp),-(sp) then we will do the
1601 high word first. We should use the adjusted operand 1 (which is N+4(sp))
1602 for the low word as well, to compensate for the first decrement of sp. */
1603 if (optype0
== PUSHOP
1604 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
1605 && reg_overlap_mentioned_p (stack_pointer_rtx
, operands
[1]))
1606 operands
[1] = middlehalf
[1] = latehalf
[1];
1608 /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
1609 if the upper part of reg N does not appear in the MEM, arrange to
1610 emit the move late-half first. Otherwise, compute the MEM address
1611 into the upper part of N and use that as a pointer to the memory
1613 if (optype0
== REGOP
1614 && (optype1
== OFFSOP
|| optype1
== MEMOP
))
1616 rtx testlow
= gen_rtx (REG
, SImode
, REGNO (operands
[0]));
1618 if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0))
1619 && reg_overlap_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
1621 /* If both halves of dest are used in the src memory address,
1622 compute the address into latehalf of dest.
1623 Note that this can't happen if the dest is two data regs. */
1625 xops
[0] = latehalf
[0];
1626 xops
[1] = XEXP (operands
[1], 0);
1627 output_asm_insn ("lea %a1,%0", xops
);
1628 if( GET_MODE (operands
[1]) == XFmode
)
1630 operands
[1] = gen_rtx (MEM
, XFmode
, latehalf
[0]);
1631 middlehalf
[1] = adj_offsettable_operand (operands
[1], size
-8);
1632 latehalf
[1] = adj_offsettable_operand (operands
[1], size
-4);
1636 operands
[1] = gen_rtx (MEM
, DImode
, latehalf
[0]);
1637 latehalf
[1] = adj_offsettable_operand (operands
[1], size
-4);
1641 && reg_overlap_mentioned_p (middlehalf
[0],
1642 XEXP (operands
[1], 0)))
1644 /* Check for two regs used by both source and dest.
1645 Note that this can't happen if the dest is all data regs.
1646 It can happen if the dest is d6, d7, a0.
1647 But in that case, latehalf is an addr reg, so
1648 the code at compadr does ok. */
1650 if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0))
1651 || reg_overlap_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
1654 /* JRV says this can't happen: */
1655 if (addreg0
|| addreg1
)
1658 /* Only the middle reg conflicts; simply put it last. */
1659 output_asm_insn (singlemove_string (operands
), operands
);
1660 output_asm_insn (singlemove_string (latehalf
), latehalf
);
1661 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
1664 else if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0)))
1665 /* If the low half of dest is mentioned in the source memory
1666 address, the arrange to emit the move late half first. */
1667 dest_overlapped_low
= 1;
1670 /* If one or both operands autodecrementing,
1671 do the two words, high-numbered first. */
1673 /* Likewise, the first move would clobber the source of the second one,
1674 do them in the other order. This happens only for registers;
1675 such overlap can't happen in memory unless the user explicitly
1676 sets it up, and that is an undefined circumstance. */
1678 if (optype0
== PUSHOP
|| optype1
== PUSHOP
1679 || (optype0
== REGOP
&& optype1
== REGOP
1680 && ((middlehalf
[1] && REGNO (operands
[0]) == REGNO (middlehalf
[1]))
1681 || REGNO (operands
[0]) == REGNO (latehalf
[1])))
1682 || dest_overlapped_low
)
1684 /* Make any unoffsettable addresses point at high-numbered word. */
1688 output_asm_insn ("addq%.l %#8,%0", &addreg0
);
1690 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
1695 output_asm_insn ("addq%.l %#8,%0", &addreg1
);
1697 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
1701 output_asm_insn (singlemove_string (latehalf
), latehalf
);
1703 /* Undo the adds we just did. */
1705 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
1707 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
1711 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
1713 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
1715 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
1718 /* Do low-numbered word. */
1719 return singlemove_string (operands
);
1722 /* Normal case: do the two words, low-numbered first. */
1724 output_asm_insn (singlemove_string (operands
), operands
);
1726 /* Do the middle one of the three words for long double */
1730 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
1732 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
1734 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
1737 /* Make any unoffsettable addresses point at high-numbered word. */
1739 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
1741 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
1744 output_asm_insn (singlemove_string (latehalf
), latehalf
);
1746 /* Undo the adds we just did. */
1750 output_asm_insn ("subq%.l %#8,%0", &addreg0
);
1752 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
1757 output_asm_insn ("subq%.l %#8,%0", &addreg1
);
1759 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
1765 /* Return a REG that occurs in ADDR with coefficient 1.
1766 ADDR can be effectively incremented by incrementing REG. */
1769 find_addr_reg (addr
)
1772 while (GET_CODE (addr
) == PLUS
)
1774 if (GET_CODE (XEXP (addr
, 0)) == REG
)
1775 addr
= XEXP (addr
, 0);
1776 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
1777 addr
= XEXP (addr
, 1);
1778 else if (CONSTANT_P (XEXP (addr
, 0)))
1779 addr
= XEXP (addr
, 1);
1780 else if (CONSTANT_P (XEXP (addr
, 1)))
1781 addr
= XEXP (addr
, 0);
1785 if (GET_CODE (addr
) == REG
)
1790 /* Store in cc_status the expressions that the condition codes will
1791 describe after execution of an instruction whose pattern is EXP.
1792 Do not alter them if the instruction would not alter the cc's. */
1794 /* On the 68000, all the insns to store in an address register fail to
1795 set the cc's. However, in some cases these instructions can make it
1796 possibly invalid to use the saved cc's. In those cases we clear out
1797 some or all of the saved cc's so they won't be used. */
1799 notice_update_cc (exp
, insn
)
1803 /* If the cc is being set from the fpa and the expression is not an
1804 explicit floating point test instruction (which has code to deal with
1805 this), reinit the CC. */
1806 if (((cc_status
.value1
&& FPA_REG_P (cc_status
.value1
))
1807 || (cc_status
.value2
&& FPA_REG_P (cc_status
.value2
)))
1808 && !(GET_CODE (exp
) == PARALLEL
1809 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
1810 && XEXP (XVECEXP (exp
, 0, 0), 0) == cc0_rtx
))
1814 else if (GET_CODE (exp
) == SET
)
1816 if (GET_CODE (SET_SRC (exp
)) == CALL
)
1820 else if (ADDRESS_REG_P (SET_DEST (exp
)))
1822 if (cc_status
.value1
1823 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value1
))
1824 cc_status
.value1
= 0;
1825 if (cc_status
.value2
1826 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value2
))
1827 cc_status
.value2
= 0;
1829 else if (!FP_REG_P (SET_DEST (exp
))
1830 && SET_DEST (exp
) != cc0_rtx
1831 && (FP_REG_P (SET_SRC (exp
))
1832 || GET_CODE (SET_SRC (exp
)) == FIX
1833 || GET_CODE (SET_SRC (exp
)) == FLOAT_TRUNCATE
1834 || GET_CODE (SET_SRC (exp
)) == FLOAT_EXTEND
))
1838 /* A pair of move insns doesn't produce a useful overall cc. */
1839 else if (!FP_REG_P (SET_DEST (exp
))
1840 && !FP_REG_P (SET_SRC (exp
))
1841 && GET_MODE_SIZE (GET_MODE (SET_SRC (exp
))) > 4
1842 && (GET_CODE (SET_SRC (exp
)) == REG
1843 || GET_CODE (SET_SRC (exp
)) == MEM
1844 || GET_CODE (SET_SRC (exp
)) == CONST_DOUBLE
))
1848 else if (GET_CODE (SET_SRC (exp
)) == CALL
)
1852 else if (XEXP (exp
, 0) != pc_rtx
)
1854 cc_status
.flags
= 0;
1855 cc_status
.value1
= XEXP (exp
, 0);
1856 cc_status
.value2
= XEXP (exp
, 1);
1859 else if (GET_CODE (exp
) == PARALLEL
1860 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
)
1862 if (ADDRESS_REG_P (XEXP (XVECEXP (exp
, 0, 0), 0)))
1864 else if (XEXP (XVECEXP (exp
, 0, 0), 0) != pc_rtx
)
1866 cc_status
.flags
= 0;
1867 cc_status
.value1
= XEXP (XVECEXP (exp
, 0, 0), 0);
1868 cc_status
.value2
= XEXP (XVECEXP (exp
, 0, 0), 1);
1873 if (cc_status
.value2
!= 0
1874 && ADDRESS_REG_P (cc_status
.value2
)
1875 && GET_MODE (cc_status
.value2
) == QImode
)
1877 if (cc_status
.value2
!= 0
1878 && !(cc_status
.value1
&& FPA_REG_P (cc_status
.value1
)))
1879 switch (GET_CODE (cc_status
.value2
))
1881 case PLUS
: case MINUS
: case MULT
:
1882 case DIV
: case UDIV
: case MOD
: case UMOD
: case NEG
:
1883 #if 0 /* These instructions always clear the overflow bit */
1884 case ASHIFT
: case ASHIFTRT
: case LSHIFTRT
:
1885 case ROTATE
: case ROTATERT
:
1887 if (GET_MODE (cc_status
.value2
) != VOIDmode
)
1888 cc_status
.flags
|= CC_NO_OVERFLOW
;
1891 /* (SET r1 (ZERO_EXTEND r2)) on this machine
1892 ends with a move insn moving r2 in r2's mode.
1893 Thus, the cc's are set for r2.
1894 This can set N bit spuriously. */
1895 cc_status
.flags
|= CC_NOT_NEGATIVE
;
1897 if (cc_status
.value1
&& GET_CODE (cc_status
.value1
) == REG
1899 && reg_overlap_mentioned_p (cc_status
.value1
, cc_status
.value2
))
1900 cc_status
.value2
= 0;
1901 if (((cc_status
.value1
&& FP_REG_P (cc_status
.value1
))
1902 || (cc_status
.value2
&& FP_REG_P (cc_status
.value2
)))
1903 && !((cc_status
.value1
&& FPA_REG_P (cc_status
.value1
))
1904 || (cc_status
.value2
&& FPA_REG_P (cc_status
.value2
))))
1905 cc_status
.flags
= CC_IN_68881
;
1909 output_move_const_double (operands
)
1912 #ifdef SUPPORT_SUN_FPA
1913 if (TARGET_FPA
&& FPA_REG_P (operands
[0]))
1915 int code
= standard_sun_fpa_constant_p (operands
[1]);
1919 static char buf
[40];
1921 sprintf (buf
, "fpmove%%.d %%%%%d,%%0", code
& 0x1ff);
1924 return "fpmove%.d %1,%0";
1929 int code
= standard_68881_constant_p (operands
[1]);
1933 static char buf
[40];
1935 sprintf (buf
, "fmovecr %%#0x%x,%%0", code
& 0xff);
1938 return "fmove%.d %1,%0";
1943 output_move_const_single (operands
)
1946 #ifdef SUPPORT_SUN_FPA
1949 int code
= standard_sun_fpa_constant_p (operands
[1]);
1953 static char buf
[40];
1955 sprintf (buf
, "fpmove%%.s %%%%%d,%%0", code
& 0x1ff);
1958 return "fpmove%.s %1,%0";
1961 #endif /* defined SUPPORT_SUN_FPA */
1963 int code
= standard_68881_constant_p (operands
[1]);
1967 static char buf
[40];
1969 sprintf (buf
, "fmovecr %%#0x%x,%%0", code
& 0xff);
1972 return "fmove%.s %f1,%0";
1976 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1977 from the "fmovecr" instruction.
1978 The value, anded with 0xff, gives the code to use in fmovecr
1979 to get the desired constant. */
1981 /* This code has been fixed for cross-compilation. */
1983 static int inited_68881_table
= 0;
1985 char *strings_68881
[7] = {
1995 int codes_68881
[7] = {
2005 REAL_VALUE_TYPE values_68881
[7];
2007 /* Set up values_68881 array by converting the decimal values
2008 strings_68881 to binary. */
2015 enum machine_mode mode
;
2018 for (i
= 0; i
< 7; i
++)
2022 r
= REAL_VALUE_ATOF (strings_68881
[i
], mode
);
2023 values_68881
[i
] = r
;
2025 inited_68881_table
= 1;
2029 standard_68881_constant_p (x
)
2034 enum machine_mode mode
;
2036 #ifdef NO_ASM_FMOVECR
2040 /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */
2044 #ifndef REAL_ARITHMETIC
2045 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2046 if (! flag_pretend_float
)
2051 if (! inited_68881_table
)
2052 init_68881_table ();
2054 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
2056 for (i
= 0; i
< 6; i
++)
2058 if (REAL_VALUES_EQUAL (r
, values_68881
[i
]))
2059 return (codes_68881
[i
]);
2062 if (GET_MODE (x
) == SFmode
)
2065 if (REAL_VALUES_EQUAL (r
, values_68881
[6]))
2066 return (codes_68881
[6]);
2068 /* larger powers of ten in the constants ram are not used
2069 because they are not equal to a `double' C constant. */
2073 /* If X is a floating-point constant, return the logarithm of X base 2,
2074 or 0 if X is not a power of 2. */
2077 floating_exact_log2 (x
)
2080 REAL_VALUE_TYPE r
, r1
;
2083 #ifndef REAL_ARITHMETIC
2084 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2085 if (! flag_pretend_float
)
2090 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
2092 if (REAL_VALUES_LESS (r
, dconst0
))
2097 while (REAL_VALUES_LESS (r1
, r
))
2099 r1
= REAL_VALUE_LDEXP (dconst1
, i
);
2100 if (REAL_VALUES_EQUAL (r1
, r
))
2107 #ifdef SUPPORT_SUN_FPA
2108 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
2109 from the Sun FPA's constant RAM.
2110 The value returned, anded with 0x1ff, gives the code to use in fpmove
2111 to get the desired constant. */
2113 static int inited_FPA_table
= 0;
2115 char *strings_FPA
[38] = {
2116 /* small rationals */
2129 /* Decimal equivalents of double precision values */
2130 "2.718281828459045091", /* D_E */
2131 "6.283185307179586477", /* 2 pi */
2132 "3.141592653589793116", /* D_PI */
2133 "1.570796326794896619", /* pi/2 */
2134 "1.414213562373095145", /* D_SQRT2 */
2135 "0.7071067811865475244", /* 1/sqrt(2) */
2136 "-1.570796326794896619", /* -pi/2 */
2137 "1.442695040888963387", /* D_LOG2ofE */
2138 "3.321928024887362182", /* D_LOG2of10 */
2139 "0.6931471805599452862", /* D_LOGEof2 */
2140 "2.302585092994045901", /* D_LOGEof10 */
2141 "0.3010299956639811980", /* D_LOG10of2 */
2142 "0.4342944819032518167", /* D_LOG10ofE */
2143 /* Decimal equivalents of single precision values */
2144 "2.718281745910644531", /* S_E */
2145 "6.283185307179586477", /* 2 pi */
2146 "3.141592741012573242", /* S_PI */
2147 "1.570796326794896619", /* pi/2 */
2148 "1.414213538169860840", /* S_SQRT2 */
2149 "0.7071067811865475244", /* 1/sqrt(2) */
2150 "-1.570796326794896619", /* -pi/2 */
2151 "1.442695021629333496", /* S_LOG2ofE */
2152 "3.321928024291992188", /* S_LOG2of10 */
2153 "0.6931471824645996094", /* S_LOGEof2 */
2154 "2.302585124969482442", /* S_LOGEof10 */
2155 "0.3010300099849700928", /* S_LOG10of2 */
2156 "0.4342944920063018799", /* S_LOG10ofE */
2160 int codes_FPA
[38] = {
2161 /* small rationals */
2174 /* double precision */
2188 /* single precision */
2204 REAL_VALUE_TYPE values_FPA
[38];
2206 /* This code has been fixed for cross-compilation. */
2211 enum machine_mode mode
;
2216 for (i
= 0; i
< 38; i
++)
2220 r
= REAL_VALUE_ATOF (strings_FPA
[i
], mode
);
2223 inited_FPA_table
= 1;
2228 standard_sun_fpa_constant_p (x
)
2234 #ifndef REAL_ARITHMETIC
2235 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2236 if (! flag_pretend_float
)
2241 if (! inited_FPA_table
)
2244 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
2246 for (i
=0; i
<12; i
++)
2248 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
2249 return (codes_FPA
[i
]);
2252 if (GET_MODE (x
) == SFmode
)
2254 for (i
=25; i
<38; i
++)
2256 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
2257 return (codes_FPA
[i
]);
2262 for (i
=12; i
<25; i
++)
2264 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
2265 return (codes_FPA
[i
]);
2270 #endif /* define SUPPORT_SUN_FPA */
2272 /* A C compound statement to output to stdio stream STREAM the
2273 assembler syntax for an instruction operand X. X is an RTL
2276 CODE is a value that can be used to specify one of several ways
2277 of printing the operand. It is used when identical operands
2278 must be printed differently depending on the context. CODE
2279 comes from the `%' specification that was used to request
2280 printing of the operand. If the specification was just `%DIGIT'
2281 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
2282 is the ASCII code for LTR.
2284 If X is a register, this macro should print the register's name.
2285 The names can be found in an array `reg_names' whose type is
2286 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
2288 When the machine description has a specification `%PUNCT' (a `%'
2289 followed by a punctuation character), this macro is called with
2290 a null pointer for X and the punctuation character for CODE.
2292 The m68k specific codes are:
2294 '.' for dot needed in Motorola-style opcode names.
2295 '-' for an operand pushing on the stack:
2296 sp@-, -(sp) or -(%sp) depending on the style of syntax.
2297 '+' for an operand pushing on the stack:
2298 sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
2299 '@' for a reference to the top word on the stack:
2300 sp@, (sp) or (%sp) depending on the style of syntax.
2301 '#' for an immediate operand prefix (# in MIT and Motorola syntax
2302 but & in SGS syntax).
2303 '!' for the cc register (used in an `and to cc' insn).
2304 '$' for the letter `s' in an op code, but only on the 68040.
2305 '&' for the letter `d' in an op code, but only on the 68040.
2306 '/' for register prefix needed by longlong.h.
2308 'b' for byte insn (no effect, on the Sun; this is for the ISI).
2309 'd' to force memory addressing to be absolute, not relative.
2310 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
2311 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
2312 than directly). Second part of 'y' below.
2313 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
2314 or print pair of registers as rx:ry.
2315 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
2316 CONST_DOUBLE's as SunFPA constant RAM registers if
2317 possible, so it should not be used except for the SunFPA.
2322 print_operand (file
, op
, letter
)
2323 FILE *file
; /* file to write to */
2324 rtx op
; /* operand to print */
2325 int letter
; /* %<letter> or 0 */
2332 asm_fprintf (file
, ".");
2335 else if (letter
== '#')
2337 asm_fprintf (file
, "%0I");
2339 else if (letter
== '-')
2342 asm_fprintf (file
, "-(%Rsp)");
2344 asm_fprintf (file
, "%Rsp@-");
2347 else if (letter
== '+')
2350 asm_fprintf (file
, "(%Rsp)+");
2352 asm_fprintf (file
, "%Rsp@+");
2355 else if (letter
== '@')
2358 asm_fprintf (file
, "(%Rsp)");
2360 asm_fprintf (file
, "%Rsp@");
2363 else if (letter
== '!')
2365 asm_fprintf (file
, "%Rfpcr");
2367 else if (letter
== '$')
2369 if (TARGET_68040_ONLY
)
2371 fprintf (file
, "s");
2374 else if (letter
== '&')
2376 if (TARGET_68040_ONLY
)
2378 fprintf (file
, "d");
2381 else if (letter
== '/')
2383 asm_fprintf (file
, "%R");
2385 else if (GET_CODE (op
) == REG
)
2387 #ifdef SUPPORT_SUN_FPA
2389 && (letter
== 'y' || letter
== 'x')
2390 && GET_MODE (op
) == DFmode
)
2392 fprintf (file
, "%s:%s", reg_names
[REGNO (op
)],
2393 reg_names
[REGNO (op
)+1]);
2399 /* Print out the second register name of a register pair.
2400 I.e., R (6) => 7. */
2401 fputs (reg_names
[REGNO (op
) + 1], file
);
2403 fputs (reg_names
[REGNO (op
)], file
);
2406 else if (GET_CODE (op
) == MEM
)
2408 output_address (XEXP (op
, 0));
2409 if (letter
== 'd' && ! TARGET_68020
2410 && CONSTANT_ADDRESS_P (XEXP (op
, 0))
2411 && !(GET_CODE (XEXP (op
, 0)) == CONST_INT
2412 && INTVAL (XEXP (op
, 0)) < 0x8000
2413 && INTVAL (XEXP (op
, 0)) >= -0x8000))
2416 fprintf (file
, ".l");
2418 fprintf (file
, ":l");
2422 #ifdef SUPPORT_SUN_FPA
2423 else if ((letter
== 'y' || letter
== 'w')
2424 && GET_CODE (op
) == CONST_DOUBLE
2425 && (i
= standard_sun_fpa_constant_p (op
)))
2427 fprintf (file
, "%%%d", i
& 0x1ff);
2430 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == SFmode
)
2433 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2434 ASM_OUTPUT_FLOAT_OPERAND (letter
, file
, r
);
2436 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == XFmode
)
2439 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2440 ASM_OUTPUT_LONG_DOUBLE_OPERAND (file
, r
);
2442 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == DFmode
)
2445 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2446 ASM_OUTPUT_DOUBLE_OPERAND (file
, r
);
2450 asm_fprintf (file
, "%0I"); output_addr_const (file
, op
);
2455 /* A C compound statement to output to stdio stream STREAM the
2456 assembler syntax for an instruction operand that is a memory
2457 reference whose address is ADDR. ADDR is an RTL expression.
2459 Note that this contains a kludge that knows that the only reason
2460 we have an address (plus (label_ref...) (reg...)) when not generating
2461 PIC code is in the insn before a tablejump, and we know that m68k.md
2462 generates a label LInnn: on such an insn.
2464 It is possible for PIC to generate a (plus (label_ref...) (reg...))
2465 and we handle that just like we would a (plus (symbol_ref...) (reg...)).
2467 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
2468 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
2469 we want. This difference can be accommodated by using an assembler
2470 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
2471 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
2472 macro. See m68k/sgs.h for an example; for versions without the bug.
2473 Some assemblers refuse all the above solutions. The workaround is to
2474 emit "K(pc,d0.l*2)" with K being a small constant known to give the
2477 They also do not like things like "pea 1.w", so we simple leave off
2478 the .w on small constants.
2480 This routine is responsible for distinguishing between -fpic and -fPIC
2481 style relocations in an address. When generating -fpic code the
2482 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating
2483 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
2485 #ifndef ASM_OUTPUT_CASE_FETCH
2488 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2489 asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
2491 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2492 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
2495 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2496 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
2498 #endif /* ASM_OUTPUT_CASE_FETCH */
2501 print_operand_address (file
, addr
)
2505 register rtx reg1
, reg2
, breg
, ireg
;
2508 switch (GET_CODE (addr
))
2512 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
2514 fprintf (file
, "%s@", reg_names
[REGNO (addr
)]);
2519 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
2521 fprintf (file
, "%s@-", reg_names
[REGNO (XEXP (addr
, 0))]);
2526 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
2528 fprintf (file
, "%s@+", reg_names
[REGNO (XEXP (addr
, 0))]);
2532 reg1
= reg2
= ireg
= breg
= offset
= 0;
2533 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0)))
2535 offset
= XEXP (addr
, 0);
2536 addr
= XEXP (addr
, 1);
2538 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1)))
2540 offset
= XEXP (addr
, 1);
2541 addr
= XEXP (addr
, 0);
2543 if (GET_CODE (addr
) != PLUS
)
2547 else if (GET_CODE (XEXP (addr
, 0)) == SIGN_EXTEND
)
2549 reg1
= XEXP (addr
, 0);
2550 addr
= XEXP (addr
, 1);
2552 else if (GET_CODE (XEXP (addr
, 1)) == SIGN_EXTEND
)
2554 reg1
= XEXP (addr
, 1);
2555 addr
= XEXP (addr
, 0);
2557 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
2559 reg1
= XEXP (addr
, 0);
2560 addr
= XEXP (addr
, 1);
2562 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
2564 reg1
= XEXP (addr
, 1);
2565 addr
= XEXP (addr
, 0);
2567 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
2569 reg1
= XEXP (addr
, 0);
2570 addr
= XEXP (addr
, 1);
2572 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
2574 reg1
= XEXP (addr
, 1);
2575 addr
= XEXP (addr
, 0);
2577 if (GET_CODE (addr
) == REG
|| GET_CODE (addr
) == MULT
2578 || GET_CODE (addr
) == SIGN_EXTEND
)
2590 #if 0 /* for OLD_INDEXING */
2591 else if (GET_CODE (addr
) == PLUS
)
2593 if (GET_CODE (XEXP (addr
, 0)) == REG
)
2595 reg2
= XEXP (addr
, 0);
2596 addr
= XEXP (addr
, 1);
2598 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
2600 reg2
= XEXP (addr
, 1);
2601 addr
= XEXP (addr
, 0);
2613 if ((reg1
&& (GET_CODE (reg1
) == SIGN_EXTEND
2614 || GET_CODE (reg1
) == MULT
))
2615 || (reg2
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2
))))
2620 else if (reg1
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1
)))
2625 if (ireg
!= 0 && breg
== 0 && GET_CODE (addr
) == LABEL_REF
2626 && ! (flag_pic
&& ireg
== pic_offset_table_rtx
))
2629 if (GET_CODE (ireg
) == MULT
)
2631 scale
= INTVAL (XEXP (ireg
, 1));
2632 ireg
= XEXP (ireg
, 0);
2634 if (GET_CODE (ireg
) == SIGN_EXTEND
)
2636 ASM_OUTPUT_CASE_FETCH (file
,
2637 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2638 reg_names
[REGNO (XEXP (ireg
, 0))]);
2639 fprintf (file
, "w");
2643 ASM_OUTPUT_CASE_FETCH (file
,
2644 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2645 reg_names
[REGNO (ireg
)]);
2646 fprintf (file
, "l");
2651 fprintf (file
, "*%d", scale
);
2653 fprintf (file
, ":%d", scale
);
2659 if (breg
!= 0 && ireg
== 0 && GET_CODE (addr
) == LABEL_REF
2660 && ! (flag_pic
&& breg
== pic_offset_table_rtx
))
2662 ASM_OUTPUT_CASE_FETCH (file
,
2663 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2664 reg_names
[REGNO (breg
)]);
2665 fprintf (file
, "l)");
2668 if (ireg
!= 0 || breg
!= 0)
2675 if (! flag_pic
&& addr
&& GET_CODE (addr
) == LABEL_REF
)
2682 output_addr_const (file
, addr
);
2683 if (flag_pic
&& (breg
== pic_offset_table_rtx
))
2684 fprintf (file
, "@GOT");
2686 fprintf (file
, "(%s", reg_names
[REGNO (breg
)]);
2692 fprintf (file
, "%s@(", reg_names
[REGNO (breg
)]);
2695 output_addr_const (file
, addr
);
2696 if ((flag_pic
== 1) && (breg
== pic_offset_table_rtx
))
2697 fprintf (file
, ":w");
2698 if ((flag_pic
== 2) && (breg
== pic_offset_table_rtx
))
2699 fprintf (file
, ":l");
2701 if (addr
!= 0 && ireg
!= 0)
2706 if (ireg
!= 0 && GET_CODE (ireg
) == MULT
)
2708 scale
= INTVAL (XEXP (ireg
, 1));
2709 ireg
= XEXP (ireg
, 0);
2711 if (ireg
!= 0 && GET_CODE (ireg
) == SIGN_EXTEND
)
2714 fprintf (file
, "%s.w", reg_names
[REGNO (XEXP (ireg
, 0))]);
2716 fprintf (file
, "%s:w", reg_names
[REGNO (XEXP (ireg
, 0))]);
2722 fprintf (file
, "%s.l", reg_names
[REGNO (ireg
)]);
2724 fprintf (file
, "%s:l", reg_names
[REGNO (ireg
)]);
2730 fprintf (file
, "*%d", scale
);
2732 fprintf (file
, ":%d", scale
);
2738 else if (reg1
!= 0 && GET_CODE (addr
) == LABEL_REF
2739 && ! (flag_pic
&& reg1
== pic_offset_table_rtx
))
2741 ASM_OUTPUT_CASE_FETCH (file
,
2742 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2743 reg_names
[REGNO (reg1
)]);
2744 fprintf (file
, "l)");
2747 /* FALL-THROUGH (is this really what we want? */
2749 if (GET_CODE (addr
) == CONST_INT
2750 && INTVAL (addr
) < 0x8000
2751 && INTVAL (addr
) >= -0x8000)
2755 /* Many SGS assemblers croak on size specifiers for constants. */
2756 fprintf (file
, "%d", INTVAL (addr
));
2758 fprintf (file
, "%d.w", INTVAL (addr
));
2761 fprintf (file
, "%d:w", INTVAL (addr
));
2766 output_addr_const (file
, addr
);
2772 /* Check for cases where a clr insns can be omitted from code using
2773 strict_low_part sets. For example, the second clrl here is not needed:
2774 clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
2776 MODE is the mode of this STRICT_LOW_PART set. FIRST_INSN is the clear
2777 insn we are checking for redundancy. TARGET is the register set by the
2781 strict_low_part_peephole_ok (mode
, first_insn
, target
)
2782 enum machine_mode mode
;
2788 p
= prev_nonnote_insn (first_insn
);
2792 /* If it isn't an insn, then give up. */
2793 if (GET_CODE (p
) != INSN
)
2796 if (reg_set_p (target
, p
))
2798 rtx set
= single_set (p
);
2801 /* If it isn't an easy to recognize insn, then give up. */
2805 dest
= SET_DEST (set
);
2807 /* If this sets the entire target register to zero, then our
2808 first_insn is redundant. */
2809 if (rtx_equal_p (dest
, target
)
2810 && SET_SRC (set
) == const0_rtx
)
2812 else if (GET_CODE (dest
) == STRICT_LOW_PART
2813 && GET_CODE (XEXP (dest
, 0)) == REG
2814 && REGNO (XEXP (dest
, 0)) == REGNO (target
)
2815 && (GET_MODE_SIZE (GET_MODE (XEXP (dest
, 0)))
2816 <= GET_MODE_SIZE (mode
)))
2817 /* This is a strict low part set which modifies less than
2818 we are using, so it is safe. */
2824 p
= prev_nonnote_insn (p
);
2831 /* Accept integer operands in the range 0..0xffffffff. We have to check the
2832 range carefully since this predicate is used in DImode contexts. Also, we
2833 need some extra crud to make it work when hosted on 64-bit machines. */
2836 const_uint32_operand (op
, mode
)
2838 enum machine_mode mode
;
2840 #if HOST_BITS_PER_WIDE_INT > 32
2841 /* All allowed constants will fit a CONST_INT. */
2842 return (GET_CODE (op
) == CONST_INT
2843 && (INTVAL (op
) >= 0 && INTVAL (op
) <= 0xffffffffL
));
2845 return ((GET_CODE (op
) == CONST_INT
&& INTVAL (op
) >= 0)
2846 || (GET_CODE (op
) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (op
) == 0));
2850 /* Accept integer operands in the range -0x80000000..0x7fffffff. We have
2851 to check the range carefully since this predicate is used in DImode
2855 const_sint32_operand (op
, mode
)
2857 enum machine_mode mode
;
2859 /* All allowed constants will fit a CONST_INT. */
2860 return (GET_CODE (op
) == CONST_INT
2861 && (INTVAL (op
) >= (-0x7fffffff - 1) && INTVAL (op
) <= 0x7fffffff));