1 /* Subroutines for insn-output.c for Motorola 68000 family.
2 Copyright (C) 1987, 1993, 1994, 1995 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 /* Emit a (use pic_offset_table_rtx) if we used PIC relocation in the
57 function at any time during the compilation process. In the future
58 we should try and eliminate the USE if we can easily determine that
59 all PIC references were deleted from the current function. That would
60 save an address register */
65 if (flag_pic
&& current_function_uses_pic_offset_table
)
67 rtx insn
= gen_rtx (USE
, VOIDmode
, pic_offset_table_rtx
);
68 emit_insn_after (insn
, get_insns ());
74 /* This function generates the assembly code for function entry.
75 STREAM is a stdio stream to output the code to.
76 SIZE is an int: how many units of temporary storage to allocate.
77 Refer to the array `regs_ever_live' to determine which registers
78 to save; `regs_ever_live[I]' is nonzero if register number I
79 is ever used in the function. This function is responsible for
80 knowing which registers should not be saved even if used. */
83 /* Note that the order of the bit mask for fmovem is the opposite
84 of the order for movem! */
88 output_function_prologue (stream
, size
)
93 register int mask
= 0;
94 int num_saved_regs
= 0;
95 extern char call_used_regs
[];
96 int fsize
= (size
+ 3) & -4;
99 if (frame_pointer_needed
)
101 if (fsize
== 0 && TARGET_68040
)
103 /* on the 68040, pea + move is faster than link.w 0 */
105 asm_fprintf (stream
, "\tpea (%s)\n\tmove.l %s,%s\n",
106 reg_names
[FRAME_POINTER_REGNUM
], reg_names
[STACK_POINTER_REGNUM
],
107 reg_names
[FRAME_POINTER_REGNUM
]);
109 asm_fprintf (stream
, "\tpea %s@\n\tmovel %s,%s\n",
110 reg_names
[FRAME_POINTER_REGNUM
], reg_names
[STACK_POINTER_REGNUM
],
111 reg_names
[FRAME_POINTER_REGNUM
]);
114 else if (fsize
< 0x8000)
117 asm_fprintf (stream
, "\tlink.w %s,%0I%d\n",
118 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
120 asm_fprintf (stream
, "\tlink %s,%0I%d\n",
121 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
124 else if (TARGET_68020
)
127 asm_fprintf (stream
, "\tlink.l %s,%0I%d\n",
128 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
130 asm_fprintf (stream
, "\tlink %s,%0I%d\n",
131 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
136 /* Adding negative number is faster on the 68040. */
138 asm_fprintf (stream
, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
139 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
141 asm_fprintf (stream
, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
142 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
148 /* Adding negative number is faster on the 68040. */
149 if (fsize
+ 4 < 0x8000)
151 /* asm_fprintf() cannot handle %. */
153 asm_fprintf (stream
, "\tadd.w %0I%d,%Rsp\n", - (fsize
+ 4));
155 asm_fprintf (stream
, "\taddw %0I%d,%Rsp\n", - (fsize
+ 4));
160 /* asm_fprintf() cannot handle %. */
162 asm_fprintf (stream
, "\tadd.l %0I%d,%Rsp\n", - (fsize
+ 4));
164 asm_fprintf (stream
, "\taddl %0I%d,%Rsp\n", - (fsize
+ 4));
168 #ifdef SUPPORT_SUN_FPA
169 for (regno
= 24; regno
< 56; regno
++)
170 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
173 asm_fprintf (stream
, "\tfpmovd %s,-(%Rsp)\n",
176 asm_fprintf (stream
, "\tfpmoved %s,%Rsp@-\n",
181 for (regno
= 16; regno
< 24; regno
++)
182 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
183 mask
|= 1 << (regno
- 16);
184 if ((mask
& 0xff) != 0)
187 asm_fprintf (stream
, "\tfmovm %0I0x%x,-(%Rsp)\n", mask
& 0xff);
189 asm_fprintf (stream
, "\tfmovem %0I0x%x,%Rsp@-\n", mask
& 0xff);
193 for (regno
= 0; regno
< 16; regno
++)
194 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
196 mask
|= 1 << (15 - regno
);
199 if (frame_pointer_needed
)
201 mask
&= ~ (1 << (15 - FRAME_POINTER_REGNUM
));
206 fprintf (stream
, "\ttstl sp@(%d)\n", NEED_PROBE
- num_saved_regs
* 4);
209 if (num_saved_regs
<= 2)
211 /* Store each separately in the same order moveml uses.
212 Using two movel instructions instead of a single moveml
213 is about 15% faster for the 68020 and 68030 at no expense
218 /* Undo the work from above. */
219 for (i
= 0; i
< 16; i
++)
223 "\t%Omove.l %s,-(%Rsp)\n",
225 "\tmovel %s,%Rsp@-\n",
232 asm_fprintf (stream
, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask
);
234 asm_fprintf (stream
, "\tmoveml %0I0x%x,%Rsp@-\n", mask
);
237 if (flag_pic
&& current_function_uses_pic_offset_table
)
240 asm_fprintf (stream
, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
241 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
243 asm_fprintf (stream
, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
244 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
245 asm_fprintf (stream
, "\tlea %Rpc@(0,%s:l),%s\n",
246 reg_names
[PIC_OFFSET_TABLE_REGNUM
],
247 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
252 /* Return true if this function's epilogue can be output as RTL. */
259 if (!reload_completed
|| frame_pointer_needed
|| get_frame_size () != 0)
262 /* Copied from output_function_epilogue (). We should probably create a
263 separate layout routine to perform the common work. */
265 for (regno
= 0 ; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
266 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
272 /* This function generates the assembly code for function exit,
273 on machines that need it. Args are same as for FUNCTION_PROLOGUE.
275 The function epilogue should not depend on the current stack pointer!
276 It should use the frame pointer only, if there is a frame pointer.
277 This is mandatory because of alloca; we also take advantage of it to
278 omit stack adjustments before returning. */
281 output_function_epilogue (stream
, size
)
286 register int mask
, fmask
;
288 int offset
, foffset
, fpoffset
;
289 extern char call_used_regs
[];
290 int fsize
= (size
+ 3) & -4;
292 rtx insn
= get_last_insn ();
294 /* If the last insn was a BARRIER, we don't have to write any code. */
295 if (GET_CODE (insn
) == NOTE
)
296 insn
= prev_nonnote_insn (insn
);
297 if (insn
&& GET_CODE (insn
) == BARRIER
)
299 /* Output just a no-op so that debuggers don't get confused
300 about which function the pc is in at this address. */
301 asm_fprintf (stream
, "\tnop\n");
305 #ifdef FUNCTION_EXTRA_EPILOGUE
306 FUNCTION_EXTRA_EPILOGUE (stream
, size
);
308 nregs
= 0; fmask
= 0; fpoffset
= 0;
309 #ifdef SUPPORT_SUN_FPA
310 for (regno
= 24 ; regno
< 56 ; regno
++)
311 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
313 fpoffset
= nregs
* 8;
316 for (regno
= 16; regno
< 24; regno
++)
317 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
320 fmask
|= 1 << (23 - regno
);
322 foffset
= fpoffset
+ nregs
* 12;
324 if (frame_pointer_needed
)
325 regs_ever_live
[FRAME_POINTER_REGNUM
] = 0;
326 for (regno
= 0; regno
< 16; regno
++)
327 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
332 offset
= foffset
+ nregs
* 4;
333 if (offset
+ fsize
>= 0x8000
334 && frame_pointer_needed
335 && (mask
|| fmask
|| fpoffset
))
338 asm_fprintf (stream
, "\t%Omove.l %0I%d,%Ra1\n", -fsize
);
340 asm_fprintf (stream
, "\tmovel %0I%d,%Ra1\n", -fsize
);
346 /* Restore each separately in the same order moveml does.
347 Using two movel instructions instead of a single moveml
348 is about 15% faster for the 68020 and 68030 at no expense
353 /* Undo the work from above. */
354 for (i
= 0; i
< 16; i
++)
360 asm_fprintf (stream
, "\t%Omove.l -%d(%s,%Ra1.l),%s\n",
362 reg_names
[FRAME_POINTER_REGNUM
],
365 asm_fprintf (stream
, "\tmovel %s@(-%d,%Ra1:l),%s\n",
366 reg_names
[FRAME_POINTER_REGNUM
],
367 offset
+ fsize
, reg_names
[i
]);
370 else if (! frame_pointer_needed
)
373 asm_fprintf (stream
, "\t%Omove.l (%Rsp)+,%s\n",
376 asm_fprintf (stream
, "\tmovel %Rsp@+,%s\n",
383 asm_fprintf (stream
, "\t%Omove.l -%d(%s),%s\n",
385 reg_names
[FRAME_POINTER_REGNUM
],
388 asm_fprintf (stream
, "\tmovel %s@(-%d),%s\n",
389 reg_names
[FRAME_POINTER_REGNUM
],
390 offset
+ fsize
, reg_names
[i
]);
401 asm_fprintf (stream
, "\tmovm.l -%d(%s,%Ra1.l),%0I0x%x\n",
403 reg_names
[FRAME_POINTER_REGNUM
],
406 asm_fprintf (stream
, "\tmoveml %s@(-%d,%Ra1:l),%0I0x%x\n",
407 reg_names
[FRAME_POINTER_REGNUM
],
408 offset
+ fsize
, mask
);
411 else if (! frame_pointer_needed
)
414 asm_fprintf (stream
, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask
);
416 asm_fprintf (stream
, "\tmoveml %Rsp@+,%0I0x%x\n", mask
);
422 asm_fprintf (stream
, "\tmovm.l -%d(%s),%0I0x%x\n",
424 reg_names
[FRAME_POINTER_REGNUM
],
427 asm_fprintf (stream
, "\tmoveml %s@(-%d),%0I0x%x\n",
428 reg_names
[FRAME_POINTER_REGNUM
],
429 offset
+ fsize
, mask
);
438 asm_fprintf (stream
, "\tfmovm -%d(%s,%Ra1.l),%0I0x%x\n",
440 reg_names
[FRAME_POINTER_REGNUM
],
443 asm_fprintf (stream
, "\tfmovem %s@(-%d,%Ra1:l),%0I0x%x\n",
444 reg_names
[FRAME_POINTER_REGNUM
],
445 foffset
+ fsize
, fmask
);
448 else if (! frame_pointer_needed
)
451 asm_fprintf (stream
, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask
);
453 asm_fprintf (stream
, "\tfmovem %Rsp@+,%0I0x%x\n", fmask
);
459 asm_fprintf (stream
, "\tfmovm -%d(%s),%0I0x%x\n",
461 reg_names
[FRAME_POINTER_REGNUM
],
464 asm_fprintf (stream
, "\tfmovem %s@(-%d),%0I0x%x\n",
465 reg_names
[FRAME_POINTER_REGNUM
],
466 foffset
+ fsize
, fmask
);
471 for (regno
= 55; regno
>= 24; regno
--)
472 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
477 asm_fprintf (stream
, "\tfpmovd -%d(%s,%Ra1.l), %s\n",
479 reg_names
[FRAME_POINTER_REGNUM
],
482 asm_fprintf (stream
, "\tfpmoved %s@(-%d,%Ra1:l), %s\n",
483 reg_names
[FRAME_POINTER_REGNUM
],
484 fpoffset
+ fsize
, reg_names
[regno
]);
487 else if (! frame_pointer_needed
)
490 asm_fprintf (stream
, "\tfpmovd (%Rsp)+,%s\n",
493 asm_fprintf (stream
, "\tfpmoved %Rsp@+, %s\n",
500 asm_fprintf (stream
, "\tfpmovd -%d(%s), %s\n",
502 reg_names
[FRAME_POINTER_REGNUM
],
505 asm_fprintf (stream
, "\tfpmoved %s@(-%d), %s\n",
506 reg_names
[FRAME_POINTER_REGNUM
],
507 fpoffset
+ fsize
, reg_names
[regno
]);
512 if (frame_pointer_needed
)
513 fprintf (stream
, "\tunlk %s\n",
514 reg_names
[FRAME_POINTER_REGNUM
]);
517 if (fsize
+ 4 < 0x8000)
519 /* asm_fprintf() cannot handle %. */
521 asm_fprintf (stream
, "\tadd.w %0I%d,%Rsp\n", fsize
+ 4);
523 asm_fprintf (stream
, "\taddw %0I%d,%Rsp\n", fsize
+ 4);
528 /* asm_fprintf() cannot handle %. */
530 asm_fprintf (stream
, "\tadd.l %0I%d,%Rsp\n", fsize
+ 4);
532 asm_fprintf (stream
, "\taddl %0I%d,%Rsp\n", fsize
+ 4);
536 if (current_function_pops_args
)
537 asm_fprintf (stream
, "\trtd %0I%d\n", current_function_pops_args
);
539 fprintf (stream
, "\trts\n");
542 /* Similar to general_operand, but exclude stack_pointer_rtx. */
545 not_sp_operand (op
, mode
)
547 enum machine_mode mode
;
549 return op
!= stack_pointer_rtx
&& general_operand (op
, mode
);
552 /* Return TRUE if X is a valid comparison operator for the dbcc
555 Note it rejects floating point comparison operators.
556 (In the future we could use Fdbcc).
558 It also rejects some comparisons when CC_NO_OVERFLOW is set. */
561 valid_dbcc_comparison_p (x
, mode
)
563 enum machine_mode mode
;
565 /* We could add support for these in the future */
566 if (cc_prev_status
.flags
& CC_IN_68881
)
569 switch (GET_CODE (x
))
572 case EQ
: case NE
: case GTU
: case LTU
:
576 /* Reject some when CC_NO_OVERFLOW is set. This may be over
578 case GT
: case LT
: case GE
: case LE
:
579 return ! (cc_prev_status
.flags
& CC_NO_OVERFLOW
);
585 /* Output a dbCC; jCC sequence. Note we do not handle the
586 floating point version of this sequence (Fdbcc). We also
587 do not handle alternative conditions when CC_NO_OVERFLOW is
588 set. It is assumed that valid_dbcc_comparison_p will kick
589 those out before we get here. */
591 output_dbcc_and_branch (operands
)
595 switch (GET_CODE (operands
[3]))
599 output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands
);
601 output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands
);
607 output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands
);
609 output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands
);
615 output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands
);
617 output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands
);
623 output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands
);
625 output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands
);
631 output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands
);
633 output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands
);
639 output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands
);
641 output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands
);
647 output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands
);
649 output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands
);
655 output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands
);
657 output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands
);
663 output_asm_insn ("dble %0,%l1\n\tjble %l2", operands
);
665 output_asm_insn ("dble %0,%l1\n\tjle %l2", operands
);
671 output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands
);
673 output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands
);
681 /* If the decrement is to be done in SImode, then we have
682 to compensate for the fact that dbcc decrements in HImode. */
683 switch (GET_MODE (operands
[0]))
687 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands
);
689 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands
);
702 output_scc_di(op
, operand1
, operand2
, dest
)
709 enum rtx_code op_code
= GET_CODE (op
);
711 /* The m68k cmp.l instruction requires operand1 to be a reg as used
712 below. Swap the operands and change the op if these requirements
713 are not fulfilled. */
714 if (GET_CODE (operand2
) == REG
&& GET_CODE (operand1
) != REG
)
720 op_code
= swap_condition (op_code
);
722 loperands
[0] = operand1
;
723 if (GET_CODE (operand1
) == REG
)
724 loperands
[1] = gen_rtx (REG
, SImode
, REGNO (operand1
) + 1);
726 loperands
[1] = adj_offsettable_operand (operand1
, 4);
727 if (operand2
!= const0_rtx
)
729 loperands
[2] = operand2
;
730 if (GET_CODE (operand2
) == REG
)
731 loperands
[3] = gen_rtx (REG
, SImode
, REGNO (operand2
) + 1);
733 loperands
[3] = adj_offsettable_operand (operand2
, 4);
735 loperands
[4] = gen_label_rtx();
736 if (operand2
!= const0_rtx
)
739 output_asm_insn ("cmp%.l %0,%2\n\tjbne %l4\n\tcmp%.l %1,%3", loperands
);
741 output_asm_insn ("cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1", loperands
);
745 output_asm_insn ("cmp%.l %0,%2\n\tjne %l4\n\tcmp%.l %1,%3", loperands
);
747 output_asm_insn ("cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1", loperands
);
752 output_asm_insn ("tst%.l %0\n\tjbne %l4\n\ttst%.l %1", loperands
);
754 output_asm_insn ("tst%.l %0\n\tjne %l4\n\ttst%.l %1", loperands
);
761 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
762 CODE_LABEL_NUMBER (loperands
[4]));
763 output_asm_insn ("seq %5", loperands
);
767 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
768 CODE_LABEL_NUMBER (loperands
[4]));
769 output_asm_insn ("sne %5", loperands
);
773 loperands
[6] = gen_label_rtx();
775 output_asm_insn ("shi %5\n\tjbra %l6", loperands
);
777 output_asm_insn ("shi %5\n\tjra %l6", loperands
);
779 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
780 CODE_LABEL_NUMBER (loperands
[4]));
781 output_asm_insn ("sgt %5", loperands
);
782 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
783 CODE_LABEL_NUMBER (loperands
[6]));
787 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
788 CODE_LABEL_NUMBER (loperands
[4]));
789 output_asm_insn ("shi %5", loperands
);
793 loperands
[6] = gen_label_rtx();
795 output_asm_insn ("scs %5\n\tjbra %l6", loperands
);
797 output_asm_insn ("scs %5\n\tjra %l6", loperands
);
799 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
800 CODE_LABEL_NUMBER (loperands
[4]));
801 output_asm_insn ("slt %5", loperands
);
802 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
803 CODE_LABEL_NUMBER (loperands
[6]));
807 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
808 CODE_LABEL_NUMBER (loperands
[4]));
809 output_asm_insn ("scs %5", loperands
);
813 loperands
[6] = gen_label_rtx();
815 output_asm_insn ("scc %5\n\tjbra %l6", loperands
);
817 output_asm_insn ("scc %5\n\tjra %l6", loperands
);
819 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
820 CODE_LABEL_NUMBER (loperands
[4]));
821 output_asm_insn ("sge %5", loperands
);
822 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
823 CODE_LABEL_NUMBER (loperands
[6]));
827 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
828 CODE_LABEL_NUMBER (loperands
[4]));
829 output_asm_insn ("scc %5", loperands
);
833 loperands
[6] = gen_label_rtx();
835 output_asm_insn ("sls %5\n\tjbra %l6", loperands
);
837 output_asm_insn ("sls %5\n\tjra %l6", loperands
);
839 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
840 CODE_LABEL_NUMBER (loperands
[4]));
841 output_asm_insn ("sle %5", loperands
);
842 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
843 CODE_LABEL_NUMBER (loperands
[6]));
847 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
848 CODE_LABEL_NUMBER (loperands
[4]));
849 output_asm_insn ("sls %5", loperands
);
859 output_btst (operands
, countop
, dataop
, insn
, signpos
)
865 operands
[0] = countop
;
866 operands
[1] = dataop
;
868 if (GET_CODE (countop
) == CONST_INT
)
870 register int count
= INTVAL (countop
);
871 /* If COUNT is bigger than size of storage unit in use,
872 advance to the containing unit of same size. */
875 int offset
= (count
& ~signpos
) / 8;
876 count
= count
& signpos
;
877 operands
[1] = dataop
= adj_offsettable_operand (dataop
, offset
);
879 if (count
== signpos
)
880 cc_status
.flags
= CC_NOT_POSITIVE
| CC_Z_IN_NOT_N
;
882 cc_status
.flags
= CC_NOT_NEGATIVE
| CC_Z_IN_NOT_N
;
884 /* These three statements used to use next_insns_test_no...
885 but it appears that this should do the same job. */
887 && next_insn_tests_no_inequality (insn
))
890 && next_insn_tests_no_inequality (insn
))
893 && next_insn_tests_no_inequality (insn
))
896 cc_status
.flags
= CC_NOT_NEGATIVE
;
901 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
902 reference and a constant. */
905 symbolic_operand (op
, mode
)
907 enum machine_mode mode
;
909 switch (GET_CODE (op
))
917 return ((GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
918 || GET_CODE (XEXP (op
, 0)) == LABEL_REF
)
919 && GET_CODE (XEXP (op
, 1)) == CONST_INT
);
921 #if 0 /* Deleted, with corresponding change in m68k.h,
922 so as to fit the specs. No CONST_DOUBLE is ever symbolic. */
924 return GET_MODE (op
) == mode
;
932 /* Check for sign_extend or zero_extend. Used for bit-count operands. */
935 extend_operator(x
, mode
)
937 enum machine_mode mode
;
939 if (mode
!= VOIDmode
&& GET_MODE(x
) != mode
)
952 /* Legitimize PIC addresses. If the address is already
953 position-independent, we return ORIG. Newly generated
954 position-independent addresses go to REG. If we need more
955 than one register, we lose.
957 An address is legitimized by making an indirect reference
958 through the Global Offset Table with the name of the symbol
961 The assembler and linker are responsible for placing the
962 address of the symbol in the GOT. The function prologue
963 is responsible for initializing a5 to the starting address
966 The assembler is also responsible for translating a symbol name
967 into a constant displacement from the start of the GOT.
969 A quick example may make things a little clearer:
971 When not generating PIC code to store the value 12345 into _foo
972 we would generate the following code:
976 When generating PIC two transformations are made. First, the compiler
977 loads the address of foo into a register. So the first transformation makes:
982 The code in movsi will intercept the lea instruction and call this
983 routine which will transform the instructions into:
985 movel a5@(_foo:w), a0
989 That (in a nutshell) is how *all* symbol and label references are
993 legitimize_pic_address (orig
, mode
, reg
)
995 enum machine_mode mode
;
999 /* First handle a simple SYMBOL_REF or LABEL_REF */
1000 if (GET_CODE (orig
) == SYMBOL_REF
|| GET_CODE (orig
) == LABEL_REF
)
1005 pic_ref
= gen_rtx (MEM
, Pmode
,
1006 gen_rtx (PLUS
, Pmode
,
1007 pic_offset_table_rtx
, orig
));
1008 current_function_uses_pic_offset_table
= 1;
1009 RTX_UNCHANGING_P (pic_ref
) = 1;
1010 emit_move_insn (reg
, pic_ref
);
1013 else if (GET_CODE (orig
) == CONST
)
1017 /* Make sure this is CONST has not already been legitimized */
1018 if (GET_CODE (XEXP (orig
, 0)) == PLUS
1019 && XEXP (XEXP (orig
, 0), 0) == pic_offset_table_rtx
)
1025 /* legitimize both operands of the PLUS */
1026 if (GET_CODE (XEXP (orig
, 0)) == PLUS
)
1028 base
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 0), Pmode
, reg
);
1029 orig
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 1), Pmode
,
1030 base
== reg
? 0 : reg
);
1034 if (GET_CODE (orig
) == CONST_INT
)
1035 return plus_constant_for_output (base
, INTVAL (orig
));
1036 pic_ref
= gen_rtx (PLUS
, Pmode
, base
, orig
);
1037 /* Likewise, should we set special REG_NOTEs here? */
1043 typedef enum { MOVL
, SWAP
, NEGW
, NOTW
, NOTB
, MOVQ
} CONST_METHOD
;
1048 return (i
>= -128 && i
<= 127);
1052 const_method (constant
)
1058 i
= INTVAL (constant
);
1061 /* if -256 < N < 256 but N is not in range for a moveq
1062 N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */
1063 if (use_movq (i
^ 0xff))
1065 /* Likewise, try with not.w */
1066 if (use_movq (i
^ 0xffff))
1068 /* This is the only value where neg.w is useful */
1071 /* Try also with swap */
1073 if (use_movq ((u
>> 16) | (u
<< 16)))
1075 /* Otherwise, use move.l */
1079 const_int_cost (constant
)
1082 switch (const_method (constant
))
1085 /* Constants between -128 and 127 are cheap due to moveq */
1091 /* Constants easily generated by moveq + not.b/not.w/neg.w/swap */
1101 output_move_const_into_data_reg (operands
)
1106 i
= INTVAL (operands
[1]);
1107 switch (const_method (operands
[1]))
1110 #if defined (MOTOROLA) && !defined (CRDS)
1111 return "moveq%.l %1,%0";
1113 return "moveq %1,%0";
1116 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
, i
^ 0xff);
1117 #if defined (MOTOROLA) && !defined (CRDS)
1118 return "moveq%.l %1,%0\n\tnot%.b %0";
1120 return "moveq %1,%0\n\tnot%.b %0";
1123 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
, i
^ 0xffff);
1124 #if defined (MOTOROLA) && !defined (CRDS)
1125 return "moveq%.l %1,%0\n\tnot%.w %0";
1127 return "moveq %1,%0\n\tnot%.w %0";
1130 #if defined (MOTOROLA) && !defined (CRDS)
1131 return "moveq%.l %#-128,%0\n\tneg%.w %0";
1133 return "moveq %#-128,%0\n\tneg%.w %0";
1139 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
, (u
<< 16) | (u
>> 16));
1140 #if defined (MOTOROLA) && !defined (CRDS)
1141 return "moveq%.l %1,%0\n\tswap %0";
1143 return "moveq %1,%0\n\tswap %0";
1147 return "move%.l %1,%0";
1153 /* Return the best assembler insn template
1154 for moving operands[1] into operands[0] as a fullword. */
1157 singlemove_string (operands
)
1160 #ifdef SUPPORT_SUN_FPA
1161 if (FPA_REG_P (operands
[0]) || FPA_REG_P (operands
[1]))
1162 return "fpmoves %1,%0";
1164 if (DATA_REG_P (operands
[0])
1165 && GET_CODE (operands
[1]) == CONST_INT
)
1166 return output_move_const_into_data_reg (operands
);
1167 if (operands
[1] != const0_rtx
)
1168 return "move%.l %1,%0";
1169 if (! ADDRESS_REG_P (operands
[0]))
1171 return "sub%.l %0,%0";
1175 /* Output assembler code to perform a doubleword move insn
1176 with operands OPERANDS. */
1179 output_move_double (operands
)
1184 REGOP
, OFFSOP
, MEMOP
, PUSHOP
, POPOP
, CNSTOP
, RNDOP
1189 rtx addreg0
= 0, addreg1
= 0;
1190 int dest_overlapped_low
= 0;
1191 int size
= GET_MODE_SIZE (GET_MODE (operands
[0]));
1196 /* First classify both operands. */
1198 if (REG_P (operands
[0]))
1200 else if (offsettable_memref_p (operands
[0]))
1202 else if (GET_CODE (XEXP (operands
[0], 0)) == POST_INC
)
1204 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
)
1206 else if (GET_CODE (operands
[0]) == MEM
)
1211 if (REG_P (operands
[1]))
1213 else if (CONSTANT_P (operands
[1]))
1215 else if (offsettable_memref_p (operands
[1]))
1217 else if (GET_CODE (XEXP (operands
[1], 0)) == POST_INC
)
1219 else if (GET_CODE (XEXP (operands
[1], 0)) == PRE_DEC
)
1221 else if (GET_CODE (operands
[1]) == MEM
)
1226 /* Check for the cases that the operand constraints are not
1227 supposed to allow to happen. Abort if we get one,
1228 because generating code for these cases is painful. */
1230 if (optype0
== RNDOP
|| optype1
== RNDOP
)
1233 /* If one operand is decrementing and one is incrementing
1234 decrement the former register explicitly
1235 and change that operand into ordinary indexing. */
1237 if (optype0
== PUSHOP
&& optype1
== POPOP
)
1239 operands
[0] = XEXP (XEXP (operands
[0], 0), 0);
1241 output_asm_insn ("sub%.l %#12,%0", operands
);
1243 output_asm_insn ("subq%.l %#8,%0", operands
);
1244 if (GET_MODE (operands
[1]) == XFmode
)
1245 operands
[0] = gen_rtx (MEM
, XFmode
, operands
[0]);
1246 else if (GET_MODE (operands
[0]) == DFmode
)
1247 operands
[0] = gen_rtx (MEM
, DFmode
, operands
[0]);
1249 operands
[0] = gen_rtx (MEM
, DImode
, operands
[0]);
1252 if (optype0
== POPOP
&& optype1
== PUSHOP
)
1254 operands
[1] = XEXP (XEXP (operands
[1], 0), 0);
1256 output_asm_insn ("sub%.l %#12,%1", operands
);
1258 output_asm_insn ("subq%.l %#8,%1", operands
);
1259 if (GET_MODE (operands
[1]) == XFmode
)
1260 operands
[1] = gen_rtx (MEM
, XFmode
, operands
[1]);
1261 else if (GET_MODE (operands
[1]) == DFmode
)
1262 operands
[1] = gen_rtx (MEM
, DFmode
, operands
[1]);
1264 operands
[1] = gen_rtx (MEM
, DImode
, operands
[1]);
1268 /* If an operand is an unoffsettable memory ref, find a register
1269 we can increment temporarily to make it refer to the second word. */
1271 if (optype0
== MEMOP
)
1272 addreg0
= find_addr_reg (XEXP (operands
[0], 0));
1274 if (optype1
== MEMOP
)
1275 addreg1
= find_addr_reg (XEXP (operands
[1], 0));
1277 /* Ok, we can do one word at a time.
1278 Normally we do the low-numbered word first,
1279 but if either operand is autodecrementing then we
1280 do the high-numbered word first.
1282 In either case, set up in LATEHALF the operands to use
1283 for the high-numbered word and in some cases alter the
1284 operands in OPERANDS to be suitable for the low-numbered word. */
1288 if (optype0
== REGOP
)
1290 latehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 2);
1291 middlehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 1);
1293 else if (optype0
== OFFSOP
)
1295 middlehalf
[0] = adj_offsettable_operand (operands
[0], 4);
1296 latehalf
[0] = adj_offsettable_operand (operands
[0], size
- 4);
1300 middlehalf
[0] = operands
[0];
1301 latehalf
[0] = operands
[0];
1304 if (optype1
== REGOP
)
1306 latehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 2);
1307 middlehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 1);
1309 else if (optype1
== OFFSOP
)
1311 middlehalf
[1] = adj_offsettable_operand (operands
[1], 4);
1312 latehalf
[1] = adj_offsettable_operand (operands
[1], size
- 4);
1314 else if (optype1
== CNSTOP
)
1316 if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
1321 REAL_VALUE_FROM_CONST_DOUBLE (r
, operands
[1]);
1322 REAL_VALUE_TO_TARGET_LONG_DOUBLE (r
, l
);
1323 operands
[1] = GEN_INT (l
[0]);
1324 middlehalf
[1] = GEN_INT (l
[1]);
1325 latehalf
[1] = GEN_INT (l
[2]);
1327 else if (CONSTANT_P (operands
[1]))
1329 /* actually, no non-CONST_DOUBLE constant should ever
1332 if (GET_CODE (operands
[1]) == CONST_INT
&& INTVAL (operands
[1]) < 0)
1333 latehalf
[1] = constm1_rtx
;
1335 latehalf
[1] = const0_rtx
;
1340 middlehalf
[1] = operands
[1];
1341 latehalf
[1] = operands
[1];
1345 /* size is not 12: */
1347 if (optype0
== REGOP
)
1348 latehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 1);
1349 else if (optype0
== OFFSOP
)
1350 latehalf
[0] = adj_offsettable_operand (operands
[0], size
- 4);
1352 latehalf
[0] = operands
[0];
1354 if (optype1
== REGOP
)
1355 latehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 1);
1356 else if (optype1
== OFFSOP
)
1357 latehalf
[1] = adj_offsettable_operand (operands
[1], size
- 4);
1358 else if (optype1
== CNSTOP
)
1359 split_double (operands
[1], &operands
[1], &latehalf
[1]);
1361 latehalf
[1] = operands
[1];
1364 /* If insn is effectively movd N(sp),-(sp) then we will do the
1365 high word first. We should use the adjusted operand 1 (which is N+4(sp))
1366 for the low word as well, to compensate for the first decrement of sp. */
1367 if (optype0
== PUSHOP
1368 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
1369 && reg_overlap_mentioned_p (stack_pointer_rtx
, operands
[1]))
1370 operands
[1] = middlehalf
[1] = latehalf
[1];
1372 /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
1373 if the upper part of reg N does not appear in the MEM, arrange to
1374 emit the move late-half first. Otherwise, compute the MEM address
1375 into the upper part of N and use that as a pointer to the memory
1377 if (optype0
== REGOP
1378 && (optype1
== OFFSOP
|| optype1
== MEMOP
))
1380 rtx testlow
= gen_rtx (REG
, SImode
, REGNO (operands
[0]));
1382 if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0))
1383 && reg_overlap_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
1385 /* If both halves of dest are used in the src memory address,
1386 compute the address into latehalf of dest.
1387 Note that this can't happen if the dest is two data regs. */
1389 xops
[0] = latehalf
[0];
1390 xops
[1] = XEXP (operands
[1], 0);
1391 output_asm_insn ("lea %a1,%0", xops
);
1392 if( GET_MODE (operands
[1]) == XFmode
)
1394 operands
[1] = gen_rtx (MEM
, XFmode
, latehalf
[0]);
1395 middlehalf
[1] = adj_offsettable_operand (operands
[1], size
-8);
1396 latehalf
[1] = adj_offsettable_operand (operands
[1], size
-4);
1400 operands
[1] = gen_rtx (MEM
, DImode
, latehalf
[0]);
1401 latehalf
[1] = adj_offsettable_operand (operands
[1], size
-4);
1405 && reg_overlap_mentioned_p (middlehalf
[0],
1406 XEXP (operands
[1], 0)))
1408 /* Check for two regs used by both source and dest.
1409 Note that this can't happen if the dest is all data regs.
1410 It can happen if the dest is d6, d7, a0.
1411 But in that case, latehalf is an addr reg, so
1412 the code at compadr does ok. */
1414 if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0))
1415 || reg_overlap_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
1418 /* JRV says this can't happen: */
1419 if (addreg0
|| addreg1
)
1422 /* Only the middle reg conflicts; simply put it last. */
1423 output_asm_insn (singlemove_string (operands
), operands
);
1424 output_asm_insn (singlemove_string (latehalf
), latehalf
);
1425 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
1428 else if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0)))
1429 /* If the low half of dest is mentioned in the source memory
1430 address, the arrange to emit the move late half first. */
1431 dest_overlapped_low
= 1;
1434 /* If one or both operands autodecrementing,
1435 do the two words, high-numbered first. */
1437 /* Likewise, the first move would clobber the source of the second one,
1438 do them in the other order. This happens only for registers;
1439 such overlap can't happen in memory unless the user explicitly
1440 sets it up, and that is an undefined circumstance. */
1442 if (optype0
== PUSHOP
|| optype1
== PUSHOP
1443 || (optype0
== REGOP
&& optype1
== REGOP
1444 && ((middlehalf
[1] && REGNO (operands
[0]) == REGNO (middlehalf
[1]))
1445 || REGNO (operands
[0]) == REGNO (latehalf
[1])))
1446 || dest_overlapped_low
)
1448 /* Make any unoffsettable addresses point at high-numbered word. */
1452 output_asm_insn ("addq%.l %#8,%0", &addreg0
);
1454 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
1459 output_asm_insn ("addq%.l %#8,%0", &addreg1
);
1461 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
1465 output_asm_insn (singlemove_string (latehalf
), latehalf
);
1467 /* Undo the adds we just did. */
1469 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
1471 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
1475 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
1477 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
1479 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
1482 /* Do low-numbered word. */
1483 return singlemove_string (operands
);
1486 /* Normal case: do the two words, low-numbered first. */
1488 output_asm_insn (singlemove_string (operands
), operands
);
1490 /* Do the middle one of the three words for long double */
1494 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
1496 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
1498 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
1501 /* Make any unoffsettable addresses point at high-numbered word. */
1503 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
1505 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
1508 output_asm_insn (singlemove_string (latehalf
), latehalf
);
1510 /* Undo the adds we just did. */
1514 output_asm_insn ("subq%.l %#8,%0", &addreg0
);
1516 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
1521 output_asm_insn ("subq%.l %#8,%0", &addreg1
);
1523 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
1529 /* Return a REG that occurs in ADDR with coefficient 1.
1530 ADDR can be effectively incremented by incrementing REG. */
1533 find_addr_reg (addr
)
1536 while (GET_CODE (addr
) == PLUS
)
1538 if (GET_CODE (XEXP (addr
, 0)) == REG
)
1539 addr
= XEXP (addr
, 0);
1540 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
1541 addr
= XEXP (addr
, 1);
1542 else if (CONSTANT_P (XEXP (addr
, 0)))
1543 addr
= XEXP (addr
, 1);
1544 else if (CONSTANT_P (XEXP (addr
, 1)))
1545 addr
= XEXP (addr
, 0);
1549 if (GET_CODE (addr
) == REG
)
1554 /* Store in cc_status the expressions that the condition codes will
1555 describe after execution of an instruction whose pattern is EXP.
1556 Do not alter them if the instruction would not alter the cc's. */
1558 /* On the 68000, all the insns to store in an address register fail to
1559 set the cc's. However, in some cases these instructions can make it
1560 possibly invalid to use the saved cc's. In those cases we clear out
1561 some or all of the saved cc's so they won't be used. */
1563 notice_update_cc (exp
, insn
)
1567 /* If the cc is being set from the fpa and the expression is not an
1568 explicit floating point test instruction (which has code to deal with
1569 this), reinit the CC. */
1570 if (((cc_status
.value1
&& FPA_REG_P (cc_status
.value1
))
1571 || (cc_status
.value2
&& FPA_REG_P (cc_status
.value2
)))
1572 && !(GET_CODE (exp
) == PARALLEL
1573 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
1574 && XEXP (XVECEXP (exp
, 0, 0), 0) == cc0_rtx
))
1578 else if (GET_CODE (exp
) == SET
)
1580 if (GET_CODE (SET_SRC (exp
)) == CALL
)
1584 else if (ADDRESS_REG_P (SET_DEST (exp
)))
1586 if (cc_status
.value1
1587 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value1
))
1588 cc_status
.value1
= 0;
1589 if (cc_status
.value2
1590 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value2
))
1591 cc_status
.value2
= 0;
1593 else if (!FP_REG_P (SET_DEST (exp
))
1594 && SET_DEST (exp
) != cc0_rtx
1595 && (FP_REG_P (SET_SRC (exp
))
1596 || GET_CODE (SET_SRC (exp
)) == FIX
1597 || GET_CODE (SET_SRC (exp
)) == FLOAT_TRUNCATE
1598 || GET_CODE (SET_SRC (exp
)) == FLOAT_EXTEND
))
1602 /* A pair of move insns doesn't produce a useful overall cc. */
1603 else if (!FP_REG_P (SET_DEST (exp
))
1604 && !FP_REG_P (SET_SRC (exp
))
1605 && GET_MODE_SIZE (GET_MODE (SET_SRC (exp
))) > 4
1606 && (GET_CODE (SET_SRC (exp
)) == REG
1607 || GET_CODE (SET_SRC (exp
)) == MEM
1608 || GET_CODE (SET_SRC (exp
)) == CONST_DOUBLE
))
1612 else if (GET_CODE (SET_SRC (exp
)) == CALL
)
1616 else if (XEXP (exp
, 0) != pc_rtx
)
1618 cc_status
.flags
= 0;
1619 cc_status
.value1
= XEXP (exp
, 0);
1620 cc_status
.value2
= XEXP (exp
, 1);
1623 else if (GET_CODE (exp
) == PARALLEL
1624 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
)
1626 if (ADDRESS_REG_P (XEXP (XVECEXP (exp
, 0, 0), 0)))
1628 else if (XEXP (XVECEXP (exp
, 0, 0), 0) != pc_rtx
)
1630 cc_status
.flags
= 0;
1631 cc_status
.value1
= XEXP (XVECEXP (exp
, 0, 0), 0);
1632 cc_status
.value2
= XEXP (XVECEXP (exp
, 0, 0), 1);
1637 if (cc_status
.value2
!= 0
1638 && ADDRESS_REG_P (cc_status
.value2
)
1639 && GET_MODE (cc_status
.value2
) == QImode
)
1641 if (cc_status
.value2
!= 0
1642 && !(cc_status
.value1
&& FPA_REG_P (cc_status
.value1
)))
1643 switch (GET_CODE (cc_status
.value2
))
1645 case PLUS
: case MINUS
: case MULT
:
1646 case DIV
: case UDIV
: case MOD
: case UMOD
: case NEG
:
1647 case ASHIFT
: case ASHIFTRT
: case LSHIFTRT
:
1648 case ROTATE
: case ROTATERT
:
1649 if (GET_MODE (cc_status
.value2
) != VOIDmode
)
1650 cc_status
.flags
|= CC_NO_OVERFLOW
;
1653 /* (SET r1 (ZERO_EXTEND r2)) on this machine
1654 ends with a move insn moving r2 in r2's mode.
1655 Thus, the cc's are set for r2.
1656 This can set N bit spuriously. */
1657 cc_status
.flags
|= CC_NOT_NEGATIVE
;
1659 if (cc_status
.value1
&& GET_CODE (cc_status
.value1
) == REG
1661 && reg_overlap_mentioned_p (cc_status
.value1
, cc_status
.value2
))
1662 cc_status
.value2
= 0;
1663 if (((cc_status
.value1
&& FP_REG_P (cc_status
.value1
))
1664 || (cc_status
.value2
&& FP_REG_P (cc_status
.value2
)))
1665 && !((cc_status
.value1
&& FPA_REG_P (cc_status
.value1
))
1666 || (cc_status
.value2
&& FPA_REG_P (cc_status
.value2
))))
1667 cc_status
.flags
= CC_IN_68881
;
1671 output_move_const_double (operands
)
1674 #ifdef SUPPORT_SUN_FPA
1675 if (TARGET_FPA
&& FPA_REG_P (operands
[0]))
1677 int code
= standard_sun_fpa_constant_p (operands
[1]);
1681 static char buf
[40];
1683 sprintf (buf
, "fpmove%%.d %%%%%d,%%0", code
& 0x1ff);
1686 return "fpmove%.d %1,%0";
1691 int code
= standard_68881_constant_p (operands
[1]);
1695 static char buf
[40];
1697 sprintf (buf
, "fmovecr %%#0x%x,%%0", code
& 0xff);
1700 return "fmove%.d %1,%0";
1705 output_move_const_single (operands
)
1708 #ifdef SUPPORT_SUN_FPA
1711 int code
= standard_sun_fpa_constant_p (operands
[1]);
1715 static char buf
[40];
1717 sprintf (buf
, "fpmove%%.s %%%%%d,%%0", code
& 0x1ff);
1720 return "fpmove%.s %1,%0";
1723 #endif /* defined SUPPORT_SUN_FPA */
1725 int code
= standard_68881_constant_p (operands
[1]);
1729 static char buf
[40];
1731 sprintf (buf
, "fmovecr %%#0x%x,%%0", code
& 0xff);
1734 return "fmove%.s %f1,%0";
1738 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1739 from the "fmovecr" instruction.
1740 The value, anded with 0xff, gives the code to use in fmovecr
1741 to get the desired constant. */
1743 /* This code has been fixed for cross-compilation. */
1745 static int inited_68881_table
= 0;
1747 char *strings_68881
[7] = {
1757 int codes_68881
[7] = {
1767 REAL_VALUE_TYPE values_68881
[7];
1769 /* Set up values_68881 array by converting the decimal values
1770 strings_68881 to binary. */
1777 enum machine_mode mode
;
1780 for (i
= 0; i
< 7; i
++)
1784 r
= REAL_VALUE_ATOF (strings_68881
[i
], mode
);
1785 values_68881
[i
] = r
;
1787 inited_68881_table
= 1;
1791 standard_68881_constant_p (x
)
1796 enum machine_mode mode
;
1798 #ifdef NO_ASM_FMOVECR
1802 /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */
1806 #ifndef REAL_ARITHMETIC
1807 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1808 if (! flag_pretend_float
)
1813 if (! inited_68881_table
)
1814 init_68881_table ();
1816 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1818 for (i
= 0; i
< 6; i
++)
1820 if (REAL_VALUES_EQUAL (r
, values_68881
[i
]))
1821 return (codes_68881
[i
]);
1824 if (GET_MODE (x
) == SFmode
)
1827 if (REAL_VALUES_EQUAL (r
, values_68881
[6]))
1828 return (codes_68881
[6]);
1830 /* larger powers of ten in the constants ram are not used
1831 because they are not equal to a `double' C constant. */
1835 /* If X is a floating-point constant, return the logarithm of X base 2,
1836 or 0 if X is not a power of 2. */
1839 floating_exact_log2 (x
)
1842 REAL_VALUE_TYPE r
, r1
;
1845 #ifndef REAL_ARITHMETIC
1846 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1847 if (! flag_pretend_float
)
1852 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1854 if (REAL_VALUES_LESS (r
, dconst0
))
1859 while (REAL_VALUES_LESS (r1
, r
))
1861 r1
= REAL_VALUE_LDEXP (dconst1
, i
);
1862 if (REAL_VALUES_EQUAL (r1
, r
))
1869 #ifdef SUPPORT_SUN_FPA
1870 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1871 from the Sun FPA's constant RAM.
1872 The value returned, anded with 0x1ff, gives the code to use in fpmove
1873 to get the desired constant. */
1875 static int inited_FPA_table
= 0;
1877 char *strings_FPA
[38] = {
1878 /* small rationals */
1891 /* Decimal equivalents of double precision values */
1892 "2.718281828459045091", /* D_E */
1893 "6.283185307179586477", /* 2 pi */
1894 "3.141592653589793116", /* D_PI */
1895 "1.570796326794896619", /* pi/2 */
1896 "1.414213562373095145", /* D_SQRT2 */
1897 "0.7071067811865475244", /* 1/sqrt(2) */
1898 "-1.570796326794896619", /* -pi/2 */
1899 "1.442695040888963387", /* D_LOG2ofE */
1900 "3.321928024887362182", /* D_LOG2of10 */
1901 "0.6931471805599452862", /* D_LOGEof2 */
1902 "2.302585092994045901", /* D_LOGEof10 */
1903 "0.3010299956639811980", /* D_LOG10of2 */
1904 "0.4342944819032518167", /* D_LOG10ofE */
1905 /* Decimal equivalents of single precision values */
1906 "2.718281745910644531", /* S_E */
1907 "6.283185307179586477", /* 2 pi */
1908 "3.141592741012573242", /* S_PI */
1909 "1.570796326794896619", /* pi/2 */
1910 "1.414213538169860840", /* S_SQRT2 */
1911 "0.7071067811865475244", /* 1/sqrt(2) */
1912 "-1.570796326794896619", /* -pi/2 */
1913 "1.442695021629333496", /* S_LOG2ofE */
1914 "3.321928024291992188", /* S_LOG2of10 */
1915 "0.6931471824645996094", /* S_LOGEof2 */
1916 "2.302585124969482442", /* S_LOGEof10 */
1917 "0.3010300099849700928", /* S_LOG10of2 */
1918 "0.4342944920063018799", /* S_LOG10ofE */
1922 int codes_FPA
[38] = {
1923 /* small rationals */
1936 /* double precision */
1950 /* single precision */
1966 REAL_VALUE_TYPE values_FPA
[38];
1968 /* This code has been fixed for cross-compilation. */
1973 enum machine_mode mode
;
1978 for (i
= 0; i
< 38; i
++)
1982 r
= REAL_VALUE_ATOF (strings_FPA
[i
], mode
);
1985 inited_FPA_table
= 1;
1990 standard_sun_fpa_constant_p (x
)
1996 #ifndef REAL_ARITHMETIC
1997 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1998 if (! flag_pretend_float
)
2003 if (! inited_FPA_table
)
2006 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
2008 for (i
=0; i
<12; i
++)
2010 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
2011 return (codes_FPA
[i
]);
2014 if (GET_MODE (x
) == SFmode
)
2016 for (i
=25; i
<38; i
++)
2018 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
2019 return (codes_FPA
[i
]);
2024 for (i
=12; i
<25; i
++)
2026 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
2027 return (codes_FPA
[i
]);
2032 #endif /* define SUPPORT_SUN_FPA */
2034 /* A C compound statement to output to stdio stream STREAM the
2035 assembler syntax for an instruction operand X. X is an RTL
2038 CODE is a value that can be used to specify one of several ways
2039 of printing the operand. It is used when identical operands
2040 must be printed differently depending on the context. CODE
2041 comes from the `%' specification that was used to request
2042 printing of the operand. If the specification was just `%DIGIT'
2043 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
2044 is the ASCII code for LTR.
2046 If X is a register, this macro should print the register's name.
2047 The names can be found in an array `reg_names' whose type is
2048 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
2050 When the machine description has a specification `%PUNCT' (a `%'
2051 followed by a punctuation character), this macro is called with
2052 a null pointer for X and the punctuation character for CODE.
2054 The m68k specific codes are:
2056 '.' for dot needed in Motorola-style opcode names.
2057 '-' for an operand pushing on the stack:
2058 sp@-, -(sp) or -(%sp) depending on the style of syntax.
2059 '+' for an operand pushing on the stack:
2060 sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
2061 '@' for a reference to the top word on the stack:
2062 sp@, (sp) or (%sp) depending on the style of syntax.
2063 '#' for an immediate operand prefix (# in MIT and Motorola syntax
2064 but & in SGS syntax).
2065 '!' for the cc register (used in an `and to cc' insn).
2066 '$' for the letter `s' in an op code, but only on the 68040.
2067 '&' for the letter `d' in an op code, but only on the 68040.
2068 '/' for register prefix needed by longlong.h.
2070 'b' for byte insn (no effect, on the Sun; this is for the ISI).
2071 'd' to force memory addressing to be absolute, not relative.
2072 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
2073 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
2074 than directly). Second part of 'y' below.
2075 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
2076 or print pair of registers as rx:ry.
2077 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
2078 CONST_DOUBLE's as SunFPA constant RAM registers if
2079 possible, so it should not be used except for the SunFPA.
2084 print_operand (file
, op
, letter
)
2085 FILE *file
; /* file to write to */
2086 rtx op
; /* operand to print */
2087 int letter
; /* %<letter> or 0 */
2094 asm_fprintf (file
, ".");
2097 else if (letter
== '#')
2099 asm_fprintf (file
, "%0I");
2101 else if (letter
== '-')
2104 asm_fprintf (file
, "-(%Rsp)");
2106 asm_fprintf (file
, "%Rsp@-");
2109 else if (letter
== '+')
2112 asm_fprintf (file
, "(%Rsp)+");
2114 asm_fprintf (file
, "%Rsp@+");
2117 else if (letter
== '@')
2120 asm_fprintf (file
, "(%Rsp)");
2122 asm_fprintf (file
, "%Rsp@");
2125 else if (letter
== '!')
2127 asm_fprintf (file
, "%Rfpcr");
2129 else if (letter
== '$')
2131 if (TARGET_68040_ONLY
)
2133 fprintf (file
, "s");
2136 else if (letter
== '&')
2138 if (TARGET_68040_ONLY
)
2140 fprintf (file
, "d");
2143 else if (letter
== '/')
2145 asm_fprintf (file
, "%R");
2147 else if (GET_CODE (op
) == REG
)
2149 #ifdef SUPPORT_SUN_FPA
2151 && (letter
== 'y' || letter
== 'x')
2152 && GET_MODE (op
) == DFmode
)
2154 fprintf (file
, "%s:%s", reg_names
[REGNO (op
)],
2155 reg_names
[REGNO (op
)+1]);
2161 /* Print out the second register name of a register pair.
2162 I.e., R (6) => 7. */
2163 fputs (reg_names
[REGNO (op
) + 1], file
);
2165 fputs (reg_names
[REGNO (op
)], file
);
2168 else if (GET_CODE (op
) == MEM
)
2170 output_address (XEXP (op
, 0));
2171 if (letter
== 'd' && ! TARGET_68020
2172 && CONSTANT_ADDRESS_P (XEXP (op
, 0))
2173 && !(GET_CODE (XEXP (op
, 0)) == CONST_INT
2174 && INTVAL (XEXP (op
, 0)) < 0x8000
2175 && INTVAL (XEXP (op
, 0)) >= -0x8000))
2177 fprintf (file
, ":l");
2180 #ifdef SUPPORT_SUN_FPA
2181 else if ((letter
== 'y' || letter
== 'w')
2182 && GET_CODE (op
) == CONST_DOUBLE
2183 && (i
= standard_sun_fpa_constant_p (op
)))
2185 fprintf (file
, "%%%d", i
& 0x1ff);
2188 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == SFmode
)
2191 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2192 ASM_OUTPUT_FLOAT_OPERAND (letter
, file
, r
);
2194 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == XFmode
)
2197 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2198 ASM_OUTPUT_LONG_DOUBLE_OPERAND (file
, r
);
2200 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == DFmode
)
2203 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2204 ASM_OUTPUT_DOUBLE_OPERAND (file
, r
);
2208 asm_fprintf (file
, "%0I"); output_addr_const (file
, op
);
2213 /* A C compound statement to output to stdio stream STREAM the
2214 assembler syntax for an instruction operand that is a memory
2215 reference whose address is ADDR. ADDR is an RTL expression.
2217 Note that this contains a kludge that knows that the only reason
2218 we have an address (plus (label_ref...) (reg...)) when not generating
2219 PIC code is in the insn before a tablejump, and we know that m68k.md
2220 generates a label LInnn: on such an insn.
2222 It is possible for PIC to generate a (plus (label_ref...) (reg...))
2223 and we handle that just like we would a (plus (symbol_ref...) (reg...)).
2225 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
2226 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
2227 we want. This difference can be accommodated by using an assembler
2228 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
2229 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
2230 macro. See m68k/sgs.h for an example; for versions without the bug.
2231 Some assemblers refuse all the above solutions. The workaround is to
2232 emit "K(pc,d0.l*2)" with K being a small constant known to give the
2235 They also do not like things like "pea 1.w", so we simple leave off
2236 the .w on small constants.
2238 This routine is responsible for distinguishing between -fpic and -fPIC
2239 style relocations in an address. When generating -fpic code the
2240 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating
2241 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
2243 #ifndef ASM_OUTPUT_CASE_FETCH
2246 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2247 asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
2249 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2250 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
2253 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2254 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
2256 #endif /* ASM_OUTPUT_CASE_FETCH */
2259 print_operand_address (file
, addr
)
2263 register rtx reg1
, reg2
, breg
, ireg
;
2266 switch (GET_CODE (addr
))
2270 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
2272 fprintf (file
, "%s@", reg_names
[REGNO (addr
)]);
2277 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
2279 fprintf (file
, "%s@-", reg_names
[REGNO (XEXP (addr
, 0))]);
2284 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
2286 fprintf (file
, "%s@+", reg_names
[REGNO (XEXP (addr
, 0))]);
2290 reg1
= reg2
= ireg
= breg
= offset
= 0;
2291 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0)))
2293 offset
= XEXP (addr
, 0);
2294 addr
= XEXP (addr
, 1);
2296 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1)))
2298 offset
= XEXP (addr
, 1);
2299 addr
= XEXP (addr
, 0);
2301 if (GET_CODE (addr
) != PLUS
)
2305 else if (GET_CODE (XEXP (addr
, 0)) == SIGN_EXTEND
)
2307 reg1
= XEXP (addr
, 0);
2308 addr
= XEXP (addr
, 1);
2310 else if (GET_CODE (XEXP (addr
, 1)) == SIGN_EXTEND
)
2312 reg1
= XEXP (addr
, 1);
2313 addr
= XEXP (addr
, 0);
2315 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
2317 reg1
= XEXP (addr
, 0);
2318 addr
= XEXP (addr
, 1);
2320 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
2322 reg1
= XEXP (addr
, 1);
2323 addr
= XEXP (addr
, 0);
2325 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
2327 reg1
= XEXP (addr
, 0);
2328 addr
= XEXP (addr
, 1);
2330 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
2332 reg1
= XEXP (addr
, 1);
2333 addr
= XEXP (addr
, 0);
2335 if (GET_CODE (addr
) == REG
|| GET_CODE (addr
) == MULT
2336 || GET_CODE (addr
) == SIGN_EXTEND
)
2348 #if 0 /* for OLD_INDEXING */
2349 else if (GET_CODE (addr
) == PLUS
)
2351 if (GET_CODE (XEXP (addr
, 0)) == REG
)
2353 reg2
= XEXP (addr
, 0);
2354 addr
= XEXP (addr
, 1);
2356 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
2358 reg2
= XEXP (addr
, 1);
2359 addr
= XEXP (addr
, 0);
2371 if ((reg1
&& (GET_CODE (reg1
) == SIGN_EXTEND
2372 || GET_CODE (reg1
) == MULT
))
2373 || (reg2
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2
))))
2378 else if (reg1
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1
)))
2383 if (ireg
!= 0 && breg
== 0 && GET_CODE (addr
) == LABEL_REF
2384 && ! (flag_pic
&& ireg
== pic_offset_table_rtx
))
2387 if (GET_CODE (ireg
) == MULT
)
2389 scale
= INTVAL (XEXP (ireg
, 1));
2390 ireg
= XEXP (ireg
, 0);
2392 if (GET_CODE (ireg
) == SIGN_EXTEND
)
2394 ASM_OUTPUT_CASE_FETCH (file
,
2395 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2396 reg_names
[REGNO (XEXP (ireg
, 0))]);
2397 fprintf (file
, "w");
2401 ASM_OUTPUT_CASE_FETCH (file
,
2402 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2403 reg_names
[REGNO (ireg
)]);
2404 fprintf (file
, "l");
2409 fprintf (file
, "*%d", scale
);
2411 fprintf (file
, ":%d", scale
);
2417 if (breg
!= 0 && ireg
== 0 && GET_CODE (addr
) == LABEL_REF
2418 && ! (flag_pic
&& breg
== pic_offset_table_rtx
))
2420 ASM_OUTPUT_CASE_FETCH (file
,
2421 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2422 reg_names
[REGNO (breg
)]);
2423 fprintf (file
, "l)");
2426 if (ireg
!= 0 || breg
!= 0)
2433 if (! flag_pic
&& addr
&& GET_CODE (addr
) == LABEL_REF
)
2440 output_addr_const (file
, addr
);
2441 if (flag_pic
&& (breg
== pic_offset_table_rtx
))
2442 fprintf (file
, "@GOT");
2444 fprintf (file
, "(%s", reg_names
[REGNO (breg
)]);
2450 fprintf (file
, "%s@(", reg_names
[REGNO (breg
)]);
2453 output_addr_const (file
, addr
);
2454 if ((flag_pic
== 1) && (breg
== pic_offset_table_rtx
))
2455 fprintf (file
, ":w");
2456 if ((flag_pic
== 2) && (breg
== pic_offset_table_rtx
))
2457 fprintf (file
, ":l");
2459 if (addr
!= 0 && ireg
!= 0)
2464 if (ireg
!= 0 && GET_CODE (ireg
) == MULT
)
2466 scale
= INTVAL (XEXP (ireg
, 1));
2467 ireg
= XEXP (ireg
, 0);
2469 if (ireg
!= 0 && GET_CODE (ireg
) == SIGN_EXTEND
)
2472 fprintf (file
, "%s.w", reg_names
[REGNO (XEXP (ireg
, 0))]);
2474 fprintf (file
, "%s:w", reg_names
[REGNO (XEXP (ireg
, 0))]);
2480 fprintf (file
, "%s.l", reg_names
[REGNO (ireg
)]);
2482 fprintf (file
, "%s:l", reg_names
[REGNO (ireg
)]);
2488 fprintf (file
, "*%d", scale
);
2490 fprintf (file
, ":%d", scale
);
2496 else if (reg1
!= 0 && GET_CODE (addr
) == LABEL_REF
2497 && ! (flag_pic
&& reg1
== pic_offset_table_rtx
))
2499 ASM_OUTPUT_CASE_FETCH (file
,
2500 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2501 reg_names
[REGNO (reg1
)]);
2502 fprintf (file
, "l)");
2505 /* FALL-THROUGH (is this really what we want? */
2507 if (GET_CODE (addr
) == CONST_INT
2508 && INTVAL (addr
) < 0x8000
2509 && INTVAL (addr
) >= -0x8000)
2513 /* Many SGS assemblers croak on size specifiers for constants. */
2514 fprintf (file
, "%d", INTVAL (addr
));
2516 fprintf (file
, "%d.w", INTVAL (addr
));
2519 fprintf (file
, "%d:w", INTVAL (addr
));
2524 output_addr_const (file
, addr
);
2530 /* Check for cases where a clr insns can be omitted from code using
2531 strict_low_part sets. For example, the second clrl here is not needed:
2532 clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
2534 MODE is the mode of this STRICT_LOW_PART set. FIRST_INSN is the clear
2535 insn we are checking for redundancy. TARGET is the register set by the
2539 strict_low_part_peephole_ok (mode
, first_insn
, target
)
2540 enum machine_mode mode
;
2546 p
= prev_nonnote_insn (first_insn
);
2550 /* If it isn't an insn, then give up. */
2551 if (GET_CODE (p
) != INSN
)
2554 if (reg_set_p (target
, p
))
2556 rtx set
= single_set (p
);
2559 /* If it isn't an easy to recognize insn, then give up. */
2563 dest
= SET_DEST (set
);
2565 /* If this sets the entire target register to zero, then our
2566 first_insn is redundant. */
2567 if (rtx_equal_p (dest
, target
)
2568 && SET_SRC (set
) == const0_rtx
)
2570 else if (GET_CODE (dest
) == STRICT_LOW_PART
2571 && GET_CODE (XEXP (dest
, 0)) == REG
2572 && REGNO (XEXP (dest
, 0)) == REGNO (target
)
2573 && (GET_MODE_SIZE (GET_MODE (XEXP (dest
, 0)))
2574 <= GET_MODE_SIZE (mode
)))
2575 /* This is a strict low part set which modifies less than
2576 we are using, so it is safe. */
2582 p
= prev_nonnote_insn (p
);
2589 /* Accept integer operands in the range 0..0xffffffff. We have to check the
2590 range carefully since this predicate is used in DImode contexts. Also, we
2591 need some extra crud to make it work when hosted on 64-bit machines. */
2594 const_uint32_operand (op
, mode
)
2596 enum machine_mode mode
;
2598 #if HOST_BITS_PER_WIDE_INT > 32
2599 /* All allowed constants will fit a CONST_INT. */
2600 return (GET_CODE (op
) == CONST_INT
2601 && (INTVAL (op
) >= 0 && INTVAL (op
) <= 0xffffffffL
));
2603 return ((GET_CODE (op
) == CONST_INT
&& INTVAL (op
) >= 0)
2604 || (GET_CODE (op
) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (op
) == 0));
2608 /* Accept integer operands in the range -0x80000000..0x7fffffff. We have
2609 to check the range carefully since this predicate is used in DImode
2613 const_sint32_operand (op
, mode
)
2615 enum machine_mode mode
;
2617 /* All allowed constants will fit a CONST_INT. */
2618 return (GET_CODE (op
) == CONST_INT
2619 && (INTVAL (op
) >= (-0x7fffffff - 1) && INTVAL (op
) <= 0x7fffffff));