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, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* Some output-actions in m68k.md need these. */
26 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "conditions.h"
30 #include "insn-flags.h"
32 #include "insn-attr.h"
34 /* Needed for use_return_insn. */
37 #ifdef SUPPORT_SUN_FPA
39 /* Index into this array by (register number >> 3) to find the
40 smallest class which contains that register. */
41 enum reg_class regno_reg_class
[]
42 = { DATA_REGS
, ADDR_REGS
, FP_REGS
,
43 LO_FPA_REGS
, LO_FPA_REGS
, FPA_REGS
, FPA_REGS
};
45 #endif /* defined SUPPORT_SUN_FPA */
47 /* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
48 if SGS_SWITCH_TABLE. */
49 int switch_table_difference_label_flag
;
51 static rtx
find_addr_reg ();
52 rtx
legitimize_pic_address ();
55 /* Emit a (use pic_offset_table_rtx) if we used PIC relocation in the
56 function at any time during the compilation process. In the future
57 we should try and eliminate the USE if we can easily determine that
58 all PIC references were deleted from the current function. That would
59 save an address register */
64 if (flag_pic
&& current_function_uses_pic_offset_table
)
65 emit_insn (gen_rtx (USE
, VOIDmode
, pic_offset_table_rtx
));
69 /* This function generates the assembly code for function entry.
70 STREAM is a stdio stream to output the code to.
71 SIZE is an int: how many units of temporary storage to allocate.
72 Refer to the array `regs_ever_live' to determine which registers
73 to save; `regs_ever_live[I]' is nonzero if register number I
74 is ever used in the function. This function is responsible for
75 knowing which registers should not be saved even if used. */
78 /* Note that the order of the bit mask for fmovem is the opposite
79 of the order for movem! */
83 output_function_prologue (stream
, size
)
88 register int mask
= 0;
89 int num_saved_regs
= 0;
90 extern char call_used_regs
[];
91 int fsize
= (size
+ 3) & -4;
94 if (frame_pointer_needed
)
96 if (fsize
== 0 && TARGET_68040
)
98 /* on the 68040, pea + move is faster than link.w 0 */
100 asm_fprintf (stream
, "\tpea (%s)\n\tmove.l %s,%s\n",
101 reg_names
[FRAME_POINTER_REGNUM
], reg_names
[STACK_POINTER_REGNUM
],
102 reg_names
[FRAME_POINTER_REGNUM
]);
104 asm_fprintf (stream
, "\tpea %s@\n\tmovel %s,%s\n",
105 reg_names
[FRAME_POINTER_REGNUM
], reg_names
[STACK_POINTER_REGNUM
],
106 reg_names
[FRAME_POINTER_REGNUM
]);
109 else if (fsize
< 0x8000)
112 asm_fprintf (stream
, "\tlink.w %s,%0I%d\n",
113 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
115 asm_fprintf (stream
, "\tlink %s,%0I%d\n",
116 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
119 else if (TARGET_68020
)
122 asm_fprintf (stream
, "\tlink.l %s,%0I%d\n",
123 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
125 asm_fprintf (stream
, "\tlink %s,%0I%d\n",
126 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
131 /* Adding negative number is faster on the 68040. */
133 asm_fprintf (stream
, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
134 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
136 asm_fprintf (stream
, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
137 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
143 /* Adding negative number is faster on the 68040. */
144 if (fsize
+ 4 < 0x8000)
146 /* asm_fprintf() cannot handle %. */
148 asm_fprintf (stream
, "\tadd.w %0I%d,%Rsp\n", - (fsize
+ 4));
150 asm_fprintf (stream
, "\taddw %0I%d,%Rsp\n", - (fsize
+ 4));
155 /* asm_fprintf() cannot handle %. */
157 asm_fprintf (stream
, "\tadd.l %0I%d,%Rsp\n", - (fsize
+ 4));
159 asm_fprintf (stream
, "\taddl %0I%d,%Rsp\n", - (fsize
+ 4));
163 #ifdef SUPPORT_SUN_FPA
164 for (regno
= 24; regno
< 56; regno
++)
165 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
168 asm_fprintf (stream
, "\tfpmovd %s,-(%Rsp)\n",
171 asm_fprintf (stream
, "\tfpmoved %s,%Rsp@-\n",
176 for (regno
= 16; regno
< 24; regno
++)
177 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
178 mask
|= 1 << (regno
- 16);
179 if ((mask
& 0xff) != 0)
182 asm_fprintf (stream
, "\tfmovm %0I0x%x,-(%Rsp)\n", mask
& 0xff);
184 asm_fprintf (stream
, "\tfmovem %0I0x%x,%Rsp@-\n", mask
& 0xff);
188 for (regno
= 0; regno
< 16; regno
++)
189 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
191 mask
|= 1 << (15 - regno
);
194 if (frame_pointer_needed
)
196 mask
&= ~ (1 << (15 - FRAME_POINTER_REGNUM
));
201 fprintf (stream
, "\ttstl sp@(%d)\n", NEED_PROBE
- num_saved_regs
* 4);
204 if (num_saved_regs
<= 2)
206 /* Store each separately in the same order moveml uses.
207 Using two movel instructions instead of a single moveml
208 is about 15% faster for the 68020 and 68030 at no expense
213 /* Undo the work from above. */
214 for (i
= 0; i
< 16; i
++)
218 "\t%Omove.l %s,-(%Rsp)\n",
220 "\tmovel %s,%Rsp@-\n",
227 asm_fprintf (stream
, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask
);
229 asm_fprintf (stream
, "\tmoveml %0I0x%x,%Rsp@-\n", mask
);
232 if (flag_pic
&& current_function_uses_pic_offset_table
)
235 asm_fprintf (stream
, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
236 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
238 asm_fprintf (stream
, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
239 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
240 asm_fprintf (stream
, "\tlea %Rpc@(0,%s:l),%s\n",
241 reg_names
[PIC_OFFSET_TABLE_REGNUM
],
242 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
247 /* Return true if this function's epilogue can be output as RTL. */
254 if (!reload_completed
|| frame_pointer_needed
|| get_frame_size () != 0)
257 /* Copied from output_function_epilogue (). We should probably create a
258 separate layout routine to perform the common work. */
260 for (regno
= 0 ; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
261 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
267 /* This function generates the assembly code for function exit,
268 on machines that need it. Args are same as for FUNCTION_PROLOGUE.
270 The function epilogue should not depend on the current stack pointer!
271 It should use the frame pointer only, if there is a frame pointer.
272 This is mandatory because of alloca; we also take advantage of it to
273 omit stack adjustments before returning. */
276 output_function_epilogue (stream
, size
)
281 register int mask
, fmask
;
283 int offset
, foffset
, fpoffset
;
284 extern char call_used_regs
[];
285 int fsize
= (size
+ 3) & -4;
287 rtx insn
= get_last_insn ();
289 /* If the last insn was a BARRIER, we don't have to write any code. */
290 if (GET_CODE (insn
) == NOTE
)
291 insn
= prev_nonnote_insn (insn
);
292 if (insn
&& GET_CODE (insn
) == BARRIER
)
294 /* Output just a no-op so that debuggers don't get confused
295 about which function the pc is in at this address. */
296 asm_fprintf (stream
, "\tnop\n");
300 #ifdef FUNCTION_EXTRA_EPILOGUE
301 FUNCTION_EXTRA_EPILOGUE (stream
, size
);
303 nregs
= 0; fmask
= 0; fpoffset
= 0;
304 #ifdef SUPPORT_SUN_FPA
305 for (regno
= 24 ; regno
< 56 ; regno
++)
306 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
308 fpoffset
= nregs
* 8;
311 for (regno
= 16; regno
< 24; regno
++)
312 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
315 fmask
|= 1 << (23 - regno
);
317 foffset
= fpoffset
+ nregs
* 12;
319 if (frame_pointer_needed
)
320 regs_ever_live
[FRAME_POINTER_REGNUM
] = 0;
321 for (regno
= 0; regno
< 16; regno
++)
322 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
327 offset
= foffset
+ nregs
* 4;
328 if (offset
+ fsize
>= 0x8000
329 && frame_pointer_needed
330 && (mask
|| fmask
|| fpoffset
))
333 asm_fprintf (stream
, "\t%Omove.l %0I%d,%Ra1\n", -fsize
);
335 asm_fprintf (stream
, "\tmovel %0I%d,%Ra1\n", -fsize
);
341 /* Restore each separately in the same order moveml does.
342 Using two movel instructions instead of a single moveml
343 is about 15% faster for the 68020 and 68030 at no expense
348 /* Undo the work from above. */
349 for (i
= 0; i
< 16; i
++)
355 asm_fprintf (stream
, "\t%Omove.l -%d(%s,%Ra1.l),%s\n",
357 reg_names
[FRAME_POINTER_REGNUM
],
360 asm_fprintf (stream
, "\tmovel %s@(-%d,%Ra1:l),%s\n",
361 reg_names
[FRAME_POINTER_REGNUM
],
362 offset
+ fsize
, reg_names
[i
]);
365 else if (! frame_pointer_needed
)
368 asm_fprintf (stream
, "\t%Omove.l (%Rsp)+,%s\n",
371 asm_fprintf (stream
, "\tmovel %Rsp@+,%s\n",
378 asm_fprintf (stream
, "\t%Omove.l -%d(%s),%s\n",
380 reg_names
[FRAME_POINTER_REGNUM
],
383 asm_fprintf (stream
, "\tmovel %s@(-%d),%s\n",
384 reg_names
[FRAME_POINTER_REGNUM
],
385 offset
+ fsize
, reg_names
[i
]);
396 asm_fprintf (stream
, "\tmovm.l -%d(%s,%Ra1.l),%0I0x%x\n",
398 reg_names
[FRAME_POINTER_REGNUM
],
401 asm_fprintf (stream
, "\tmoveml %s@(-%d,%Ra1:l),%0I0x%x\n",
402 reg_names
[FRAME_POINTER_REGNUM
],
403 offset
+ fsize
, mask
);
406 else if (! frame_pointer_needed
)
409 asm_fprintf (stream
, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask
);
411 asm_fprintf (stream
, "\tmoveml %Rsp@+,%0I0x%x\n", mask
);
417 asm_fprintf (stream
, "\tmovm.l -%d(%s),%0I0x%x\n",
419 reg_names
[FRAME_POINTER_REGNUM
],
422 asm_fprintf (stream
, "\tmoveml %s@(-%d),%0I0x%x\n",
423 reg_names
[FRAME_POINTER_REGNUM
],
424 offset
+ fsize
, mask
);
433 asm_fprintf (stream
, "\tfmovm -%d(%s,%Ra1.l),%0I0x%x\n",
435 reg_names
[FRAME_POINTER_REGNUM
],
438 asm_fprintf (stream
, "\tfmovem %s@(-%d,%Ra1:l),%0I0x%x\n",
439 reg_names
[FRAME_POINTER_REGNUM
],
440 foffset
+ fsize
, fmask
);
443 else if (! frame_pointer_needed
)
446 asm_fprintf (stream
, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask
);
448 asm_fprintf (stream
, "\tfmovem %Rsp@+,%0I0x%x\n", fmask
);
454 asm_fprintf (stream
, "\tfmovm -%d(%s),%0I0x%x\n",
456 reg_names
[FRAME_POINTER_REGNUM
],
459 asm_fprintf (stream
, "\tfmovem %s@(-%d),%0I0x%x\n",
460 reg_names
[FRAME_POINTER_REGNUM
],
461 foffset
+ fsize
, fmask
);
466 for (regno
= 55; regno
>= 24; regno
--)
467 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
472 asm_fprintf (stream
, "\tfpmovd -%d(%s,%Ra1.l), %s\n",
474 reg_names
[FRAME_POINTER_REGNUM
],
477 asm_fprintf (stream
, "\tfpmoved %s@(-%d,%Ra1:l), %s\n",
478 reg_names
[FRAME_POINTER_REGNUM
],
479 fpoffset
+ fsize
, reg_names
[regno
]);
482 else if (! frame_pointer_needed
)
485 asm_fprintf (stream
, "\tfpmovd (%Rsp)+,%s\n",
488 asm_fprintf (stream
, "\tfpmoved %Rsp@+, %s\n",
495 asm_fprintf (stream
, "\tfpmovd -%d(%s), %s\n",
497 reg_names
[FRAME_POINTER_REGNUM
],
500 asm_fprintf (stream
, "\tfpmoved %s@(-%d), %s\n",
501 reg_names
[FRAME_POINTER_REGNUM
],
502 fpoffset
+ fsize
, reg_names
[regno
]);
507 if (frame_pointer_needed
)
508 fprintf (stream
, "\tunlk %s\n",
509 reg_names
[FRAME_POINTER_REGNUM
]);
512 if (fsize
+ 4 < 0x8000)
514 /* asm_fprintf() cannot handle %. */
516 asm_fprintf (stream
, "\tadd.w %0I%d,%Rsp\n", fsize
+ 4);
518 asm_fprintf (stream
, "\taddw %0I%d,%Rsp\n", fsize
+ 4);
523 /* asm_fprintf() cannot handle %. */
525 asm_fprintf (stream
, "\tadd.l %0I%d,%Rsp\n", fsize
+ 4);
527 asm_fprintf (stream
, "\taddl %0I%d,%Rsp\n", fsize
+ 4);
531 if (current_function_pops_args
)
532 asm_fprintf (stream
, "\trtd %0I%d\n", current_function_pops_args
);
534 fprintf (stream
, "\trts\n");
537 /* Similar to general_operand, but exclude stack_pointer_rtx. */
540 not_sp_operand (op
, mode
)
542 enum machine_mode mode
;
544 return op
!= stack_pointer_rtx
&& general_operand (op
, mode
);
547 /* Return TRUE if X is a valid comparison operator for the dbcc
550 Note it rejects floating point comparison operators.
551 (In the future we could use Fdbcc).
553 It also rejects some comparisons when CC_NO_OVERFLOW is set. */
556 valid_dbcc_comparison_p (x
, mode
)
558 enum machine_mode mode
;
560 /* We could add support for these in the future */
561 if (cc_prev_status
.flags
& CC_IN_68881
)
564 switch (GET_CODE (x
))
567 case EQ
: case NE
: case GTU
: case LTU
:
571 /* Reject some when CC_NO_OVERFLOW is set. This may be over
573 case GT
: case LT
: case GE
: case LE
:
574 return ! (cc_prev_status
.flags
& CC_NO_OVERFLOW
);
580 /* Output a dbCC; jCC sequence. Note we do not handle the
581 floating point version of this sequence (Fdbcc). We also
582 do not handle alternative conditions when CC_NO_OVERFLOW is
583 set. It is assumed that valid_dbcc_comparison_p will kick
584 those out before we get here. */
586 output_dbcc_and_branch (operands
)
590 switch (GET_CODE (operands
[3]))
594 output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands
);
596 output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands
);
602 output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands
);
604 output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands
);
610 output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands
);
612 output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands
);
618 output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands
);
620 output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands
);
626 output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands
);
628 output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands
);
634 output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands
);
636 output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands
);
642 output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands
);
644 output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands
);
650 output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands
);
652 output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands
);
658 output_asm_insn ("dble %0,%l1\n\tjble %l2", operands
);
660 output_asm_insn ("dble %0,%l1\n\tjle %l2", operands
);
666 output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands
);
668 output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands
);
676 /* If the decrement is to be done in SImode, then we have
677 to compensate for the fact that dbcc decrements in HImode. */
678 switch (GET_MODE (operands
[0]))
682 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands
);
684 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands
);
697 output_scc_di(op
, operand1
, operand2
, dest
)
705 loperands
[0] = operand1
;
706 if (GET_CODE (operand1
) == REG
)
707 loperands
[1] = gen_rtx (REG
, SImode
, REGNO (operand1
) + 1);
709 loperands
[1] = adj_offsettable_operand (operand1
, 4);
710 if (operand2
!= const0_rtx
)
712 loperands
[2] = operand2
;
713 if (GET_CODE (operand2
) == REG
)
714 loperands
[3] = gen_rtx (REG
, SImode
, REGNO (operand2
) + 1);
716 loperands
[3] = adj_offsettable_operand (operand2
, 4);
718 loperands
[4] = gen_label_rtx();
719 if (operand2
!= const0_rtx
)
721 output_asm_insn ("cmp%.l %0,%2\n\tjbne %l4\n\tcmp%.l %1,%3", loperands
);
723 output_asm_insn ("cmp%.l %0,%2\n\tjne %l4\n\tcmp%.l %1,%3", loperands
);
727 output_asm_insn ("tst%.l %0\n\tjbne %l4\n\ttst%.l %1", loperands
);
729 output_asm_insn ("tst%.l %0\n\tjne %l4\n\ttst%.l %1", loperands
);
733 switch (GET_CODE (op
))
736 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
737 CODE_LABEL_NUMBER (loperands
[4]));
738 output_asm_insn ("seq %5", loperands
);
742 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
743 CODE_LABEL_NUMBER (loperands
[4]));
744 output_asm_insn ("sne %5", loperands
);
748 loperands
[6] = gen_label_rtx();
750 output_asm_insn ("shi %5\n\tjbra %l6", loperands
);
752 output_asm_insn ("shi %5\n\tjra %l6", loperands
);
754 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
755 CODE_LABEL_NUMBER (loperands
[4]));
756 output_asm_insn ("sgt %5", loperands
);
757 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
758 CODE_LABEL_NUMBER (loperands
[6]));
762 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
763 CODE_LABEL_NUMBER (loperands
[4]));
764 output_asm_insn ("shi %5", loperands
);
768 loperands
[6] = gen_label_rtx();
770 output_asm_insn ("scs %5\n\tjbra %l6", loperands
);
772 output_asm_insn ("scs %5\n\tjra %l6", loperands
);
774 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
775 CODE_LABEL_NUMBER (loperands
[4]));
776 output_asm_insn ("slt %5", loperands
);
777 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
778 CODE_LABEL_NUMBER (loperands
[6]));
782 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
783 CODE_LABEL_NUMBER (loperands
[4]));
784 output_asm_insn ("scs %5", loperands
);
788 loperands
[6] = gen_label_rtx();
790 output_asm_insn ("scc %5\n\tjbra %l6", loperands
);
792 output_asm_insn ("scc %5\n\tjra %l6", loperands
);
794 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
795 CODE_LABEL_NUMBER (loperands
[4]));
796 output_asm_insn ("sge %5", loperands
);
797 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
798 CODE_LABEL_NUMBER (loperands
[6]));
802 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
803 CODE_LABEL_NUMBER (loperands
[4]));
804 output_asm_insn ("scc %5", loperands
);
808 loperands
[6] = gen_label_rtx();
810 output_asm_insn ("sls %5\n\tjbra %l6", loperands
);
812 output_asm_insn ("sls %5\n\tjra %l6", loperands
);
814 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
815 CODE_LABEL_NUMBER (loperands
[4]));
816 output_asm_insn ("sle %5", loperands
);
817 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
818 CODE_LABEL_NUMBER (loperands
[6]));
822 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
823 CODE_LABEL_NUMBER (loperands
[4]));
824 output_asm_insn ("sls %5", loperands
);
834 output_btst (operands
, countop
, dataop
, insn
, signpos
)
840 operands
[0] = countop
;
841 operands
[1] = dataop
;
843 if (GET_CODE (countop
) == CONST_INT
)
845 register int count
= INTVAL (countop
);
846 /* If COUNT is bigger than size of storage unit in use,
847 advance to the containing unit of same size. */
850 int offset
= (count
& ~signpos
) / 8;
851 count
= count
& signpos
;
852 operands
[1] = dataop
= adj_offsettable_operand (dataop
, offset
);
854 if (count
== signpos
)
855 cc_status
.flags
= CC_NOT_POSITIVE
| CC_Z_IN_NOT_N
;
857 cc_status
.flags
= CC_NOT_NEGATIVE
| CC_Z_IN_NOT_N
;
859 /* These three statements used to use next_insns_test_no...
860 but it appears that this should do the same job. */
862 && next_insn_tests_no_inequality (insn
))
865 && next_insn_tests_no_inequality (insn
))
868 && next_insn_tests_no_inequality (insn
))
871 cc_status
.flags
= CC_NOT_NEGATIVE
;
876 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
877 reference and a constant. */
880 symbolic_operand (op
, mode
)
882 enum machine_mode mode
;
884 switch (GET_CODE (op
))
892 return ((GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
893 || GET_CODE (XEXP (op
, 0)) == LABEL_REF
)
894 && GET_CODE (XEXP (op
, 1)) == CONST_INT
);
896 #if 0 /* Deleted, with corresponding change in m68k.h,
897 so as to fit the specs. No CONST_DOUBLE is ever symbolic. */
899 return GET_MODE (op
) == mode
;
907 /* Check for sign_extend or zero_extend. Used for bit-count operands. */
910 extend_operator(x
, mode
)
912 enum machine_mode mode
;
914 if (mode
!= VOIDmode
&& GET_MODE(x
) != mode
)
927 /* Legitimize PIC addresses. If the address is already
928 position-independent, we return ORIG. Newly generated
929 position-independent addresses go to REG. If we need more
930 than one register, we lose.
932 An address is legitimized by making an indirect reference
933 through the Global Offset Table with the name of the symbol
936 The assembler and linker are responsible for placing the
937 address of the symbol in the GOT. The function prologue
938 is responsible for initializing a5 to the starting address
941 The assembler is also responsible for translating a symbol name
942 into a constant displacement from the start of the GOT.
944 A quick example may make things a little clearer:
946 When not generating PIC code to store the value 12345 into _foo
947 we would generate the following code:
951 When generating PIC two transformations are made. First, the compiler
952 loads the address of foo into a register. So the first transformation makes:
957 The code in movsi will intercept the lea instruction and call this
958 routine which will transform the instructions into:
960 movel a5@(_foo:w), a0
964 That (in a nutshell) is how *all* symbol and label references are
968 legitimize_pic_address (orig
, mode
, reg
)
970 enum machine_mode mode
;
974 /* First handle a simple SYMBOL_REF or LABEL_REF */
975 if (GET_CODE (orig
) == SYMBOL_REF
|| GET_CODE (orig
) == LABEL_REF
)
980 pic_ref
= gen_rtx (MEM
, Pmode
,
981 gen_rtx (PLUS
, Pmode
,
982 pic_offset_table_rtx
, orig
));
983 current_function_uses_pic_offset_table
= 1;
984 RTX_UNCHANGING_P (pic_ref
) = 1;
985 emit_move_insn (reg
, pic_ref
);
988 else if (GET_CODE (orig
) == CONST
)
992 /* Make sure this is CONST has not already been legitimized */
993 if (GET_CODE (XEXP (orig
, 0)) == PLUS
994 && XEXP (XEXP (orig
, 0), 0) == pic_offset_table_rtx
)
1000 /* legitimize both operands of the PLUS */
1001 if (GET_CODE (XEXP (orig
, 0)) == PLUS
)
1003 base
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 0), Pmode
, reg
);
1004 orig
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 1), Pmode
,
1005 base
== reg
? 0 : reg
);
1009 if (GET_CODE (orig
) == CONST_INT
)
1010 return plus_constant_for_output (base
, INTVAL (orig
));
1011 pic_ref
= gen_rtx (PLUS
, Pmode
, base
, orig
);
1012 /* Likewise, should we set special REG_NOTEs here? */
1018 typedef enum { MOVL
, SWAP
, NEGW
, NOTW
, NOTB
, MOVQ
} CONST_METHOD
;
1023 return (i
>= -128 && i
<= 127);
1027 const_method (constant
)
1033 i
= INTVAL (constant
);
1036 /* if -256 < N < 256 but N is not in range for a moveq
1037 N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */
1038 if (use_movq (i
^ 0xff))
1040 /* Likewise, try with not.w */
1041 if (use_movq (i
^ 0xffff))
1043 /* This is the only value where neg.w is useful */
1046 /* Try also with swap */
1048 if (use_movq ((u
>> 16) | (u
<< 16)))
1050 /* Otherwise, use move.l */
1054 const_int_cost (constant
)
1057 switch (const_method (constant
))
1060 /* Constants between -128 and 127 are cheap due to moveq */
1066 /* Constants easily generated by moveq + not.b/not.w/neg.w/swap */
1076 output_move_const_into_data_reg (operands
)
1081 i
= INTVAL (operands
[1]);
1082 switch (const_method (operands
[1]))
1085 #if defined (MOTOROLA) && !defined (CRDS)
1086 return "moveq%.l %1,%0";
1088 return "moveq %1,%0";
1091 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
, i
^ 0xff);
1092 #if defined (MOTOROLA) && !defined (CRDS)
1093 return "moveq%.l %1,%0\n\tnot%.b %0";
1095 return "moveq %1,%0\n\tnot%.b %0";
1098 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
, i
^ 0xffff);
1099 #if defined (MOTOROLA) && !defined (CRDS)
1100 return "moveq%.l %1,%0\n\tnot%.w %0";
1102 return "moveq %1,%0\n\tnot%.w %0";
1105 #if defined (MOTOROLA) && !defined (CRDS)
1106 return "moveq%.l %#-128,%0\n\tneg%.w %0";
1108 return "moveq %#-128,%0\n\tneg%.w %0";
1114 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
, (u
<< 16) | (u
>> 16));
1115 #if defined (MOTOROLA) && !defined (CRDS)
1116 return "moveq%.l %1,%0\n\tswap %0";
1118 return "moveq %1,%0\n\tswap %0";
1122 return "move%.l %1,%0";
1128 /* Return the best assembler insn template
1129 for moving operands[1] into operands[0] as a fullword. */
1132 singlemove_string (operands
)
1135 #ifdef SUPPORT_SUN_FPA
1136 if (FPA_REG_P (operands
[0]) || FPA_REG_P (operands
[1]))
1137 return "fpmoves %1,%0";
1139 if (DATA_REG_P (operands
[0])
1140 && GET_CODE (operands
[1]) == CONST_INT
)
1141 return output_move_const_into_data_reg (operands
);
1142 if (operands
[1] != const0_rtx
)
1143 return "move%.l %1,%0";
1144 if (! ADDRESS_REG_P (operands
[0]))
1146 return "sub%.l %0,%0";
1150 /* Output assembler code to perform a doubleword move insn
1151 with operands OPERANDS. */
1154 output_move_double (operands
)
1159 REGOP
, OFFSOP
, MEMOP
, PUSHOP
, POPOP
, CNSTOP
, RNDOP
1164 rtx addreg0
= 0, addreg1
= 0;
1165 int dest_overlapped_low
= 0;
1166 int size
= GET_MODE_SIZE (GET_MODE (operands
[0]));
1171 /* First classify both operands. */
1173 if (REG_P (operands
[0]))
1175 else if (offsettable_memref_p (operands
[0]))
1177 else if (GET_CODE (XEXP (operands
[0], 0)) == POST_INC
)
1179 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
)
1181 else if (GET_CODE (operands
[0]) == MEM
)
1186 if (REG_P (operands
[1]))
1188 else if (CONSTANT_P (operands
[1]))
1190 else if (offsettable_memref_p (operands
[1]))
1192 else if (GET_CODE (XEXP (operands
[1], 0)) == POST_INC
)
1194 else if (GET_CODE (XEXP (operands
[1], 0)) == PRE_DEC
)
1196 else if (GET_CODE (operands
[1]) == MEM
)
1201 /* Check for the cases that the operand constraints are not
1202 supposed to allow to happen. Abort if we get one,
1203 because generating code for these cases is painful. */
1205 if (optype0
== RNDOP
|| optype1
== RNDOP
)
1208 /* If one operand is decrementing and one is incrementing
1209 decrement the former register explicitly
1210 and change that operand into ordinary indexing. */
1212 if (optype0
== PUSHOP
&& optype1
== POPOP
)
1214 operands
[0] = XEXP (XEXP (operands
[0], 0), 0);
1216 output_asm_insn ("sub%.l %#12,%0", operands
);
1218 output_asm_insn ("subq%.l %#8,%0", operands
);
1219 if (GET_MODE (operands
[1]) == XFmode
)
1220 operands
[0] = gen_rtx (MEM
, XFmode
, operands
[0]);
1221 else if (GET_MODE (operands
[0]) == DFmode
)
1222 operands
[0] = gen_rtx (MEM
, DFmode
, operands
[0]);
1224 operands
[0] = gen_rtx (MEM
, DImode
, operands
[0]);
1227 if (optype0
== POPOP
&& optype1
== PUSHOP
)
1229 operands
[1] = XEXP (XEXP (operands
[1], 0), 0);
1231 output_asm_insn ("sub%.l %#12,%1", operands
);
1233 output_asm_insn ("subq%.l %#8,%1", operands
);
1234 if (GET_MODE (operands
[1]) == XFmode
)
1235 operands
[1] = gen_rtx (MEM
, XFmode
, operands
[1]);
1236 else if (GET_MODE (operands
[1]) == DFmode
)
1237 operands
[1] = gen_rtx (MEM
, DFmode
, operands
[1]);
1239 operands
[1] = gen_rtx (MEM
, DImode
, operands
[1]);
1243 /* If an operand is an unoffsettable memory ref, find a register
1244 we can increment temporarily to make it refer to the second word. */
1246 if (optype0
== MEMOP
)
1247 addreg0
= find_addr_reg (XEXP (operands
[0], 0));
1249 if (optype1
== MEMOP
)
1250 addreg1
= find_addr_reg (XEXP (operands
[1], 0));
1252 /* Ok, we can do one word at a time.
1253 Normally we do the low-numbered word first,
1254 but if either operand is autodecrementing then we
1255 do the high-numbered word first.
1257 In either case, set up in LATEHALF the operands to use
1258 for the high-numbered word and in some cases alter the
1259 operands in OPERANDS to be suitable for the low-numbered word. */
1263 if (optype0
== REGOP
)
1265 latehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 2);
1266 middlehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 1);
1268 else if (optype0
== OFFSOP
)
1270 middlehalf
[0] = adj_offsettable_operand (operands
[0], 4);
1271 latehalf
[0] = adj_offsettable_operand (operands
[0], size
- 4);
1275 middlehalf
[0] = operands
[0];
1276 latehalf
[0] = operands
[0];
1279 if (optype1
== REGOP
)
1281 latehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 2);
1282 middlehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 1);
1284 else if (optype1
== OFFSOP
)
1286 middlehalf
[1] = adj_offsettable_operand (operands
[1], 4);
1287 latehalf
[1] = adj_offsettable_operand (operands
[1], size
- 4);
1289 else if (optype1
== CNSTOP
)
1291 if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
1296 REAL_VALUE_FROM_CONST_DOUBLE (r
, operands
[1]);
1297 REAL_VALUE_TO_TARGET_LONG_DOUBLE (r
, l
);
1298 operands
[1] = GEN_INT (l
[0]);
1299 middlehalf
[1] = GEN_INT (l
[1]);
1300 latehalf
[1] = GEN_INT (l
[2]);
1302 else if (CONSTANT_P (operands
[1]))
1304 /* actually, no non-CONST_DOUBLE constant should ever
1307 if (GET_CODE (operands
[1]) == CONST_INT
&& INTVAL (operands
[1]) < 0)
1308 latehalf
[1] = constm1_rtx
;
1310 latehalf
[1] = const0_rtx
;
1315 middlehalf
[1] = operands
[1];
1316 latehalf
[1] = operands
[1];
1320 /* size is not 12: */
1322 if (optype0
== REGOP
)
1323 latehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 1);
1324 else if (optype0
== OFFSOP
)
1325 latehalf
[0] = adj_offsettable_operand (operands
[0], size
- 4);
1327 latehalf
[0] = operands
[0];
1329 if (optype1
== REGOP
)
1330 latehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 1);
1331 else if (optype1
== OFFSOP
)
1332 latehalf
[1] = adj_offsettable_operand (operands
[1], size
- 4);
1333 else if (optype1
== CNSTOP
)
1334 split_double (operands
[1], &operands
[1], &latehalf
[1]);
1336 latehalf
[1] = operands
[1];
1339 /* If insn is effectively movd N(sp),-(sp) then we will do the
1340 high word first. We should use the adjusted operand 1 (which is N+4(sp))
1341 for the low word as well, to compensate for the first decrement of sp. */
1342 if (optype0
== PUSHOP
1343 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
1344 && reg_overlap_mentioned_p (stack_pointer_rtx
, operands
[1]))
1345 operands
[1] = middlehalf
[1] = latehalf
[1];
1347 /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
1348 if the upper part of reg N does not appear in the MEM, arrange to
1349 emit the move late-half first. Otherwise, compute the MEM address
1350 into the upper part of N and use that as a pointer to the memory
1352 if (optype0
== REGOP
1353 && (optype1
== OFFSOP
|| optype1
== MEMOP
))
1355 rtx testlow
= gen_rtx (REG
, SImode
, REGNO (operands
[0]));
1357 if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0))
1358 && reg_overlap_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
1360 /* If both halves of dest are used in the src memory address,
1361 compute the address into latehalf of dest.
1362 Note that this can't happen if the dest is two data regs. */
1364 xops
[0] = latehalf
[0];
1365 xops
[1] = XEXP (operands
[1], 0);
1366 output_asm_insn ("lea %a1,%0", xops
);
1367 if( GET_MODE (operands
[1]) == XFmode
)
1369 operands
[1] = gen_rtx (MEM
, XFmode
, latehalf
[0]);
1370 middlehalf
[1] = adj_offsettable_operand (operands
[1], size
-8);
1371 latehalf
[1] = adj_offsettable_operand (operands
[1], size
-4);
1375 operands
[1] = gen_rtx (MEM
, DImode
, latehalf
[0]);
1376 latehalf
[1] = adj_offsettable_operand (operands
[1], size
-4);
1380 && reg_overlap_mentioned_p (middlehalf
[0],
1381 XEXP (operands
[1], 0)))
1383 /* Check for two regs used by both source and dest.
1384 Note that this can't happen if the dest is all data regs.
1385 It can happen if the dest is d6, d7, a0.
1386 But in that case, latehalf is an addr reg, so
1387 the code at compadr does ok. */
1389 if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0))
1390 || reg_overlap_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
1393 /* JRV says this can't happen: */
1394 if (addreg0
|| addreg1
)
1397 /* Only the middle reg conflicts; simply put it last. */
1398 output_asm_insn (singlemove_string (operands
), operands
);
1399 output_asm_insn (singlemove_string (latehalf
), latehalf
);
1400 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
1403 else if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0)))
1404 /* If the low half of dest is mentioned in the source memory
1405 address, the arrange to emit the move late half first. */
1406 dest_overlapped_low
= 1;
1409 /* If one or both operands autodecrementing,
1410 do the two words, high-numbered first. */
1412 /* Likewise, the first move would clobber the source of the second one,
1413 do them in the other order. This happens only for registers;
1414 such overlap can't happen in memory unless the user explicitly
1415 sets it up, and that is an undefined circumstance. */
1417 if (optype0
== PUSHOP
|| optype1
== PUSHOP
1418 || (optype0
== REGOP
&& optype1
== REGOP
1419 && ((middlehalf
[1] && REGNO (operands
[0]) == REGNO (middlehalf
[1]))
1420 || REGNO (operands
[0]) == REGNO (latehalf
[1])))
1421 || dest_overlapped_low
)
1423 /* Make any unoffsettable addresses point at high-numbered word. */
1427 output_asm_insn ("addq%.l %#8,%0", &addreg0
);
1429 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
1434 output_asm_insn ("addq%.l %#8,%0", &addreg1
);
1436 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
1440 output_asm_insn (singlemove_string (latehalf
), latehalf
);
1442 /* Undo the adds we just did. */
1444 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
1446 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
1450 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
1452 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
1454 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
1457 /* Do low-numbered word. */
1458 return singlemove_string (operands
);
1461 /* Normal case: do the two words, low-numbered first. */
1463 output_asm_insn (singlemove_string (operands
), operands
);
1465 /* Do the middle one of the three words for long double */
1469 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
1471 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
1473 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
1476 /* Make any unoffsettable addresses point at high-numbered word. */
1478 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
1480 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
1483 output_asm_insn (singlemove_string (latehalf
), latehalf
);
1485 /* Undo the adds we just did. */
1489 output_asm_insn ("subq%.l %#8,%0", &addreg0
);
1491 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
1496 output_asm_insn ("subq%.l %#8,%0", &addreg1
);
1498 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
1504 /* Return a REG that occurs in ADDR with coefficient 1.
1505 ADDR can be effectively incremented by incrementing REG. */
1508 find_addr_reg (addr
)
1511 while (GET_CODE (addr
) == PLUS
)
1513 if (GET_CODE (XEXP (addr
, 0)) == REG
)
1514 addr
= XEXP (addr
, 0);
1515 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
1516 addr
= XEXP (addr
, 1);
1517 else if (CONSTANT_P (XEXP (addr
, 0)))
1518 addr
= XEXP (addr
, 1);
1519 else if (CONSTANT_P (XEXP (addr
, 1)))
1520 addr
= XEXP (addr
, 0);
1524 if (GET_CODE (addr
) == REG
)
1529 /* Store in cc_status the expressions that the condition codes will
1530 describe after execution of an instruction whose pattern is EXP.
1531 Do not alter them if the instruction would not alter the cc's. */
1533 /* On the 68000, all the insns to store in an address register fail to
1534 set the cc's. However, in some cases these instructions can make it
1535 possibly invalid to use the saved cc's. In those cases we clear out
1536 some or all of the saved cc's so they won't be used. */
1538 notice_update_cc (exp
, insn
)
1542 /* If the cc is being set from the fpa and the expression is not an
1543 explicit floating point test instruction (which has code to deal with
1544 this), reinit the CC. */
1545 if (((cc_status
.value1
&& FPA_REG_P (cc_status
.value1
))
1546 || (cc_status
.value2
&& FPA_REG_P (cc_status
.value2
)))
1547 && !(GET_CODE (exp
) == PARALLEL
1548 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
1549 && XEXP (XVECEXP (exp
, 0, 0), 0) == cc0_rtx
))
1553 else if (GET_CODE (exp
) == SET
)
1555 if (GET_CODE (SET_SRC (exp
)) == CALL
)
1559 else if (ADDRESS_REG_P (SET_DEST (exp
)))
1561 if (cc_status
.value1
1562 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value1
))
1563 cc_status
.value1
= 0;
1564 if (cc_status
.value2
1565 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value2
))
1566 cc_status
.value2
= 0;
1568 else if (!FP_REG_P (SET_DEST (exp
))
1569 && SET_DEST (exp
) != cc0_rtx
1570 && (FP_REG_P (SET_SRC (exp
))
1571 || GET_CODE (SET_SRC (exp
)) == FIX
1572 || GET_CODE (SET_SRC (exp
)) == FLOAT_TRUNCATE
1573 || GET_CODE (SET_SRC (exp
)) == FLOAT_EXTEND
))
1577 /* A pair of move insns doesn't produce a useful overall cc. */
1578 else if (!FP_REG_P (SET_DEST (exp
))
1579 && !FP_REG_P (SET_SRC (exp
))
1580 && GET_MODE_SIZE (GET_MODE (SET_SRC (exp
))) > 4
1581 && (GET_CODE (SET_SRC (exp
)) == REG
1582 || GET_CODE (SET_SRC (exp
)) == MEM
1583 || GET_CODE (SET_SRC (exp
)) == CONST_DOUBLE
))
1587 else if (GET_CODE (SET_SRC (exp
)) == CALL
)
1591 else if (XEXP (exp
, 0) != pc_rtx
)
1593 cc_status
.flags
= 0;
1594 cc_status
.value1
= XEXP (exp
, 0);
1595 cc_status
.value2
= XEXP (exp
, 1);
1598 else if (GET_CODE (exp
) == PARALLEL
1599 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
)
1601 if (ADDRESS_REG_P (XEXP (XVECEXP (exp
, 0, 0), 0)))
1603 else if (XEXP (XVECEXP (exp
, 0, 0), 0) != pc_rtx
)
1605 cc_status
.flags
= 0;
1606 cc_status
.value1
= XEXP (XVECEXP (exp
, 0, 0), 0);
1607 cc_status
.value2
= XEXP (XVECEXP (exp
, 0, 0), 1);
1612 if (cc_status
.value2
!= 0
1613 && ADDRESS_REG_P (cc_status
.value2
)
1614 && GET_MODE (cc_status
.value2
) == QImode
)
1616 if (cc_status
.value2
!= 0
1617 && !(cc_status
.value1
&& FPA_REG_P (cc_status
.value1
)))
1618 switch (GET_CODE (cc_status
.value2
))
1620 case PLUS
: case MINUS
: case MULT
:
1621 case DIV
: case UDIV
: case MOD
: case UMOD
: case NEG
:
1622 case ASHIFT
: case ASHIFTRT
: case LSHIFTRT
:
1623 case ROTATE
: case ROTATERT
:
1624 if (GET_MODE (cc_status
.value2
) != VOIDmode
)
1625 cc_status
.flags
|= CC_NO_OVERFLOW
;
1628 /* (SET r1 (ZERO_EXTEND r2)) on this machine
1629 ends with a move insn moving r2 in r2's mode.
1630 Thus, the cc's are set for r2.
1631 This can set N bit spuriously. */
1632 cc_status
.flags
|= CC_NOT_NEGATIVE
;
1634 if (cc_status
.value1
&& GET_CODE (cc_status
.value1
) == REG
1636 && reg_overlap_mentioned_p (cc_status
.value1
, cc_status
.value2
))
1637 cc_status
.value2
= 0;
1638 if (((cc_status
.value1
&& FP_REG_P (cc_status
.value1
))
1639 || (cc_status
.value2
&& FP_REG_P (cc_status
.value2
)))
1640 && !((cc_status
.value1
&& FPA_REG_P (cc_status
.value1
))
1641 || (cc_status
.value2
&& FPA_REG_P (cc_status
.value2
))))
1642 cc_status
.flags
= CC_IN_68881
;
1646 output_move_const_double (operands
)
1649 #ifdef SUPPORT_SUN_FPA
1650 if (TARGET_FPA
&& FPA_REG_P (operands
[0]))
1652 int code
= standard_sun_fpa_constant_p (operands
[1]);
1656 static char buf
[40];
1658 sprintf (buf
, "fpmove%%.d %%%%%d,%%0", code
& 0x1ff);
1661 return "fpmove%.d %1,%0";
1666 int code
= standard_68881_constant_p (operands
[1]);
1670 static char buf
[40];
1672 sprintf (buf
, "fmovecr %%#0x%x,%%0", code
& 0xff);
1675 return "fmove%.d %1,%0";
1680 output_move_const_single (operands
)
1683 #ifdef SUPPORT_SUN_FPA
1686 int code
= standard_sun_fpa_constant_p (operands
[1]);
1690 static char buf
[40];
1692 sprintf (buf
, "fpmove%%.s %%%%%d,%%0", code
& 0x1ff);
1695 return "fpmove%.s %1,%0";
1698 #endif /* defined SUPPORT_SUN_FPA */
1700 int code
= standard_68881_constant_p (operands
[1]);
1704 static char buf
[40];
1706 sprintf (buf
, "fmovecr %%#0x%x,%%0", code
& 0xff);
1709 return "fmove%.s %f1,%0";
1713 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1714 from the "fmovecr" instruction.
1715 The value, anded with 0xff, gives the code to use in fmovecr
1716 to get the desired constant. */
1718 /* This code has been fixed for cross-compilation. */
1720 static int inited_68881_table
= 0;
1722 char *strings_68881
[7] = {
1732 int codes_68881
[7] = {
1742 REAL_VALUE_TYPE values_68881
[7];
1744 /* Set up values_68881 array by converting the decimal values
1745 strings_68881 to binary. */
1752 enum machine_mode mode
;
1755 for (i
= 0; i
< 7; i
++)
1759 r
= REAL_VALUE_ATOF (strings_68881
[i
], mode
);
1760 values_68881
[i
] = r
;
1762 inited_68881_table
= 1;
1766 standard_68881_constant_p (x
)
1771 enum machine_mode mode
;
1773 #ifdef NO_ASM_FMOVECR
1777 /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */
1781 #ifndef REAL_ARITHMETIC
1782 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1783 if (! flag_pretend_float
)
1788 if (! inited_68881_table
)
1789 init_68881_table ();
1791 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1793 for (i
= 0; i
< 6; i
++)
1795 if (REAL_VALUES_EQUAL (r
, values_68881
[i
]))
1796 return (codes_68881
[i
]);
1799 if (GET_MODE (x
) == SFmode
)
1802 if (REAL_VALUES_EQUAL (r
, values_68881
[6]))
1803 return (codes_68881
[6]);
1805 /* larger powers of ten in the constants ram are not used
1806 because they are not equal to a `double' C constant. */
1810 /* If X is a floating-point constant, return the logarithm of X base 2,
1811 or 0 if X is not a power of 2. */
1814 floating_exact_log2 (x
)
1817 REAL_VALUE_TYPE r
, r1
;
1820 #ifndef REAL_ARITHMETIC
1821 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1822 if (! flag_pretend_float
)
1827 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1829 if (REAL_VALUES_LESS (r
, dconst0
))
1834 while (REAL_VALUES_LESS (r1
, r
))
1836 r1
= REAL_VALUE_LDEXP (dconst1
, i
);
1837 if (REAL_VALUES_EQUAL (r1
, r
))
1844 #ifdef SUPPORT_SUN_FPA
1845 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1846 from the Sun FPA's constant RAM.
1847 The value returned, anded with 0x1ff, gives the code to use in fpmove
1848 to get the desired constant. */
1850 static int inited_FPA_table
= 0;
1852 char *strings_FPA
[38] = {
1853 /* small rationals */
1866 /* Decimal equivalents of double precision values */
1867 "2.718281828459045091", /* D_E */
1868 "6.283185307179586477", /* 2 pi */
1869 "3.141592653589793116", /* D_PI */
1870 "1.570796326794896619", /* pi/2 */
1871 "1.414213562373095145", /* D_SQRT2 */
1872 "0.7071067811865475244", /* 1/sqrt(2) */
1873 "-1.570796326794896619", /* -pi/2 */
1874 "1.442695040888963387", /* D_LOG2ofE */
1875 "3.321928024887362182", /* D_LOG2of10 */
1876 "0.6931471805599452862", /* D_LOGEof2 */
1877 "2.302585092994045901", /* D_LOGEof10 */
1878 "0.3010299956639811980", /* D_LOG10of2 */
1879 "0.4342944819032518167", /* D_LOG10ofE */
1880 /* Decimal equivalents of single precision values */
1881 "2.718281745910644531", /* S_E */
1882 "6.283185307179586477", /* 2 pi */
1883 "3.141592741012573242", /* S_PI */
1884 "1.570796326794896619", /* pi/2 */
1885 "1.414213538169860840", /* S_SQRT2 */
1886 "0.7071067811865475244", /* 1/sqrt(2) */
1887 "-1.570796326794896619", /* -pi/2 */
1888 "1.442695021629333496", /* S_LOG2ofE */
1889 "3.321928024291992188", /* S_LOG2of10 */
1890 "0.6931471824645996094", /* S_LOGEof2 */
1891 "2.302585124969482442", /* S_LOGEof10 */
1892 "0.3010300099849700928", /* S_LOG10of2 */
1893 "0.4342944920063018799", /* S_LOG10ofE */
1897 int codes_FPA
[38] = {
1898 /* small rationals */
1911 /* double precision */
1925 /* single precision */
1941 REAL_VALUE_TYPE values_FPA
[38];
1943 /* This code has been fixed for cross-compilation. */
1948 enum machine_mode mode
;
1953 for (i
= 0; i
< 38; i
++)
1957 r
= REAL_VALUE_ATOF (strings_FPA
[i
], mode
);
1960 inited_FPA_table
= 1;
1965 standard_sun_fpa_constant_p (x
)
1971 #ifndef REAL_ARITHMETIC
1972 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1973 if (! flag_pretend_float
)
1978 if (! inited_FPA_table
)
1981 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1983 for (i
=0; i
<12; i
++)
1985 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
1986 return (codes_FPA
[i
]);
1989 if (GET_MODE (x
) == SFmode
)
1991 for (i
=25; i
<38; i
++)
1993 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
1994 return (codes_FPA
[i
]);
1999 for (i
=12; i
<25; i
++)
2001 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
2002 return (codes_FPA
[i
]);
2007 #endif /* define SUPPORT_SUN_FPA */
2009 /* A C compound statement to output to stdio stream STREAM the
2010 assembler syntax for an instruction operand X. X is an RTL
2013 CODE is a value that can be used to specify one of several ways
2014 of printing the operand. It is used when identical operands
2015 must be printed differently depending on the context. CODE
2016 comes from the `%' specification that was used to request
2017 printing of the operand. If the specification was just `%DIGIT'
2018 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
2019 is the ASCII code for LTR.
2021 If X is a register, this macro should print the register's name.
2022 The names can be found in an array `reg_names' whose type is
2023 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
2025 When the machine description has a specification `%PUNCT' (a `%'
2026 followed by a punctuation character), this macro is called with
2027 a null pointer for X and the punctuation character for CODE.
2029 The m68k specific codes are:
2031 '.' for dot needed in Motorola-style opcode names.
2032 '-' for an operand pushing on the stack:
2033 sp@-, -(sp) or -(%sp) depending on the style of syntax.
2034 '+' for an operand pushing on the stack:
2035 sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
2036 '@' for a reference to the top word on the stack:
2037 sp@, (sp) or (%sp) depending on the style of syntax.
2038 '#' for an immediate operand prefix (# in MIT and Motorola syntax
2039 but & in SGS syntax).
2040 '!' for the cc register (used in an `and to cc' insn).
2041 '$' for the letter `s' in an op code, but only on the 68040.
2042 '&' for the letter `d' in an op code, but only on the 68040.
2043 '/' for register prefix needed by longlong.h.
2045 'b' for byte insn (no effect, on the Sun; this is for the ISI).
2046 'd' to force memory addressing to be absolute, not relative.
2047 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
2048 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
2049 than directly). Second part of 'y' below.
2050 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
2051 or print pair of registers as rx:ry.
2052 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
2053 CONST_DOUBLE's as SunFPA constant RAM registers if
2054 possible, so it should not be used except for the SunFPA.
2059 print_operand (file
, op
, letter
)
2060 FILE *file
; /* file to write to */
2061 rtx op
; /* operand to print */
2062 int letter
; /* %<letter> or 0 */
2069 asm_fprintf (file
, ".");
2072 else if (letter
== '#')
2074 asm_fprintf (file
, "%0I");
2076 else if (letter
== '-')
2079 asm_fprintf (file
, "-(%Rsp)");
2081 asm_fprintf (file
, "%Rsp@-");
2084 else if (letter
== '+')
2087 asm_fprintf (file
, "(%Rsp)+");
2089 asm_fprintf (file
, "%Rsp@+");
2092 else if (letter
== '@')
2095 asm_fprintf (file
, "(%Rsp)");
2097 asm_fprintf (file
, "%Rsp@");
2100 else if (letter
== '!')
2102 asm_fprintf (file
, "%Rfpcr");
2104 else if (letter
== '$')
2106 if (TARGET_68040_ONLY
)
2108 fprintf (file
, "s");
2111 else if (letter
== '&')
2113 if (TARGET_68040_ONLY
)
2115 fprintf (file
, "d");
2118 else if (letter
== '/')
2120 asm_fprintf (file
, "%R");
2122 else if (GET_CODE (op
) == REG
)
2124 #ifdef SUPPORT_SUN_FPA
2126 && (letter
== 'y' || letter
== 'x')
2127 && GET_MODE (op
) == DFmode
)
2129 fprintf (file
, "%s:%s", reg_names
[REGNO (op
)],
2130 reg_names
[REGNO (op
)+1]);
2136 /* Print out the second register name of a register pair.
2137 I.e., R (6) => 7. */
2138 fputs (reg_names
[REGNO (op
) + 1], file
);
2140 fputs (reg_names
[REGNO (op
)], file
);
2143 else if (GET_CODE (op
) == MEM
)
2145 output_address (XEXP (op
, 0));
2146 if (letter
== 'd' && ! TARGET_68020
2147 && CONSTANT_ADDRESS_P (XEXP (op
, 0))
2148 && !(GET_CODE (XEXP (op
, 0)) == CONST_INT
2149 && INTVAL (XEXP (op
, 0)) < 0x8000
2150 && INTVAL (XEXP (op
, 0)) >= -0x8000))
2152 fprintf (file
, ":l");
2155 #ifdef SUPPORT_SUN_FPA
2156 else if ((letter
== 'y' || letter
== 'w')
2157 && GET_CODE (op
) == CONST_DOUBLE
2158 && (i
= standard_sun_fpa_constant_p (op
)))
2160 fprintf (file
, "%%%d", i
& 0x1ff);
2163 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == SFmode
)
2166 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2167 ASM_OUTPUT_FLOAT_OPERAND (letter
, file
, r
);
2169 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == XFmode
)
2172 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2173 ASM_OUTPUT_LONG_DOUBLE_OPERAND (file
, r
);
2175 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == DFmode
)
2178 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2179 ASM_OUTPUT_DOUBLE_OPERAND (file
, r
);
2183 asm_fprintf (file
, "%0I"); output_addr_const (file
, op
);
2188 /* A C compound statement to output to stdio stream STREAM the
2189 assembler syntax for an instruction operand that is a memory
2190 reference whose address is ADDR. ADDR is an RTL expression.
2192 Note that this contains a kludge that knows that the only reason
2193 we have an address (plus (label_ref...) (reg...)) when not generating
2194 PIC code is in the insn before a tablejump, and we know that m68k.md
2195 generates a label LInnn: on such an insn.
2197 It is possible for PIC to generate a (plus (label_ref...) (reg...))
2198 and we handle that just like we would a (plus (symbol_ref...) (reg...)).
2200 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
2201 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
2202 we want. This difference can be accommodated by using an assembler
2203 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
2204 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
2205 macro. See m68k/sgs.h for an example; for versions without the bug.
2206 Some assemblers refuse all the above solutions. The workaround is to
2207 emit "K(pc,d0.l*2)" with K being a small constant known to give the
2210 They also do not like things like "pea 1.w", so we simple leave off
2211 the .w on small constants.
2213 This routine is responsible for distinguishing between -fpic and -fPIC
2214 style relocations in an address. When generating -fpic code the
2215 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating
2216 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
2218 #ifndef ASM_OUTPUT_CASE_FETCH
2221 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2222 asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
2224 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2225 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
2228 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2229 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
2231 #endif /* ASM_OUTPUT_CASE_FETCH */
2234 print_operand_address (file
, addr
)
2238 register rtx reg1
, reg2
, breg
, ireg
;
2241 switch (GET_CODE (addr
))
2245 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
2247 fprintf (file
, "%s@", reg_names
[REGNO (addr
)]);
2252 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
2254 fprintf (file
, "%s@-", reg_names
[REGNO (XEXP (addr
, 0))]);
2259 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
2261 fprintf (file
, "%s@+", reg_names
[REGNO (XEXP (addr
, 0))]);
2265 reg1
= reg2
= ireg
= breg
= offset
= 0;
2266 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0)))
2268 offset
= XEXP (addr
, 0);
2269 addr
= XEXP (addr
, 1);
2271 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1)))
2273 offset
= XEXP (addr
, 1);
2274 addr
= XEXP (addr
, 0);
2276 if (GET_CODE (addr
) != PLUS
)
2280 else if (GET_CODE (XEXP (addr
, 0)) == SIGN_EXTEND
)
2282 reg1
= XEXP (addr
, 0);
2283 addr
= XEXP (addr
, 1);
2285 else if (GET_CODE (XEXP (addr
, 1)) == SIGN_EXTEND
)
2287 reg1
= XEXP (addr
, 1);
2288 addr
= XEXP (addr
, 0);
2290 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
2292 reg1
= XEXP (addr
, 0);
2293 addr
= XEXP (addr
, 1);
2295 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
2297 reg1
= XEXP (addr
, 1);
2298 addr
= XEXP (addr
, 0);
2300 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
2302 reg1
= XEXP (addr
, 0);
2303 addr
= XEXP (addr
, 1);
2305 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
2307 reg1
= XEXP (addr
, 1);
2308 addr
= XEXP (addr
, 0);
2310 if (GET_CODE (addr
) == REG
|| GET_CODE (addr
) == MULT
2311 || GET_CODE (addr
) == SIGN_EXTEND
)
2323 #if 0 /* for OLD_INDEXING */
2324 else if (GET_CODE (addr
) == PLUS
)
2326 if (GET_CODE (XEXP (addr
, 0)) == REG
)
2328 reg2
= XEXP (addr
, 0);
2329 addr
= XEXP (addr
, 1);
2331 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
2333 reg2
= XEXP (addr
, 1);
2334 addr
= XEXP (addr
, 0);
2346 if ((reg1
&& (GET_CODE (reg1
) == SIGN_EXTEND
2347 || GET_CODE (reg1
) == MULT
))
2348 || (reg2
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2
))))
2353 else if (reg1
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1
)))
2358 if (ireg
!= 0 && breg
== 0 && GET_CODE (addr
) == LABEL_REF
2359 && ! (flag_pic
&& ireg
== pic_offset_table_rtx
))
2362 if (GET_CODE (ireg
) == MULT
)
2364 scale
= INTVAL (XEXP (ireg
, 1));
2365 ireg
= XEXP (ireg
, 0);
2367 if (GET_CODE (ireg
) == SIGN_EXTEND
)
2369 ASM_OUTPUT_CASE_FETCH (file
,
2370 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2371 reg_names
[REGNO (XEXP (ireg
, 0))]);
2372 fprintf (file
, "w");
2376 ASM_OUTPUT_CASE_FETCH (file
,
2377 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2378 reg_names
[REGNO (ireg
)]);
2379 fprintf (file
, "l");
2384 fprintf (file
, "*%d", scale
);
2386 fprintf (file
, ":%d", scale
);
2392 if (breg
!= 0 && ireg
== 0 && GET_CODE (addr
) == LABEL_REF
2393 && ! (flag_pic
&& breg
== pic_offset_table_rtx
))
2395 ASM_OUTPUT_CASE_FETCH (file
,
2396 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2397 reg_names
[REGNO (breg
)]);
2398 fprintf (file
, "l)");
2401 if (ireg
!= 0 || breg
!= 0)
2408 if (! flag_pic
&& addr
&& GET_CODE (addr
) == LABEL_REF
)
2415 output_addr_const (file
, addr
);
2416 if (flag_pic
&& (breg
== pic_offset_table_rtx
))
2417 fprintf (file
, "@GOT");
2419 fprintf (file
, "(%s", reg_names
[REGNO (breg
)]);
2425 fprintf (file
, "%s@(", reg_names
[REGNO (breg
)]);
2428 output_addr_const (file
, addr
);
2429 if ((flag_pic
== 1) && (breg
== pic_offset_table_rtx
))
2430 fprintf (file
, ":w");
2431 if ((flag_pic
== 2) && (breg
== pic_offset_table_rtx
))
2432 fprintf (file
, ":l");
2434 if (addr
!= 0 && ireg
!= 0)
2439 if (ireg
!= 0 && GET_CODE (ireg
) == MULT
)
2441 scale
= INTVAL (XEXP (ireg
, 1));
2442 ireg
= XEXP (ireg
, 0);
2444 if (ireg
!= 0 && GET_CODE (ireg
) == SIGN_EXTEND
)
2447 fprintf (file
, "%s.w", reg_names
[REGNO (XEXP (ireg
, 0))]);
2449 fprintf (file
, "%s:w", reg_names
[REGNO (XEXP (ireg
, 0))]);
2455 fprintf (file
, "%s.l", reg_names
[REGNO (ireg
)]);
2457 fprintf (file
, "%s:l", reg_names
[REGNO (ireg
)]);
2463 fprintf (file
, "*%d", scale
);
2465 fprintf (file
, ":%d", scale
);
2471 else if (reg1
!= 0 && GET_CODE (addr
) == LABEL_REF
2472 && ! (flag_pic
&& reg1
== pic_offset_table_rtx
))
2474 ASM_OUTPUT_CASE_FETCH (file
,
2475 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2476 reg_names
[REGNO (reg1
)]);
2477 fprintf (file
, "l)");
2480 /* FALL-THROUGH (is this really what we want? */
2482 if (GET_CODE (addr
) == CONST_INT
2483 && INTVAL (addr
) < 0x8000
2484 && INTVAL (addr
) >= -0x8000)
2488 /* Many SGS assemblers croak on size specifiers for constants. */
2489 fprintf (file
, "%d", INTVAL (addr
));
2491 fprintf (file
, "%d.w", INTVAL (addr
));
2494 fprintf (file
, "%d:w", INTVAL (addr
));
2499 output_addr_const (file
, addr
);
2505 /* Check for cases where a clr insns can be omitted from code using
2506 strict_low_part sets. For example, the second clrl here is not needed:
2507 clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
2509 MODE is the mode of this STRICT_LOW_PART set. FIRST_INSN is the clear
2510 insn we are checking for redundancy. TARGET is the register set by the
2514 strict_low_part_peephole_ok (mode
, first_insn
, target
)
2515 enum machine_mode mode
;
2521 p
= prev_nonnote_insn (first_insn
);
2525 /* If it isn't an insn, then give up. */
2526 if (GET_CODE (p
) != INSN
)
2529 if (reg_set_p (target
, p
))
2531 rtx set
= single_set (p
);
2534 /* If it isn't an easy to recognize insn, then give up. */
2538 dest
= SET_DEST (set
);
2540 /* If this sets the entire target register to zero, then our
2541 first_insn is redundant. */
2542 if (rtx_equal_p (dest
, target
)
2543 && SET_SRC (set
) == const0_rtx
)
2545 else if (GET_CODE (dest
) == STRICT_LOW_PART
2546 && GET_CODE (XEXP (dest
, 0)) == REG
2547 && REGNO (XEXP (dest
, 0)) == REGNO (target
)
2548 && (GET_MODE_SIZE (GET_MODE (XEXP (dest
, 0)))
2549 <= GET_MODE_SIZE (mode
)))
2550 /* This is a strict low part set which modifies less than
2551 we are using, so it is safe. */
2557 p
= prev_nonnote_insn (p
);
2564 /* Accept integer operands in the range 0..0xffffffff. We have to check the
2565 range carefully since this predicate is used in DImode contexts. Also, we
2566 need some extra crud to make it work when hosted on 64-bit machines. */
2569 const_uint32_operand (op
, mode
)
2571 enum machine_mode mode
;
2573 #if HOST_BITS_PER_WIDE_INT > 32
2574 /* All allowed constants will fit a CONST_INT. */
2575 return (GET_CODE (op
) == CONST_INT
2576 && (INTVAL (op
) >= 0 && INTVAL (op
) <= 0xffffffffL
));
2578 return ((GET_CODE (op
) == CONST_INT
&& INTVAL (op
) >= 0)
2579 || (GET_CODE (op
) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (op
) == 0));
2583 /* Accept integer operands in the range -0x80000000..0x7fffffff. We have
2584 to check the range carefully since this predicate is used in DImode
2588 const_sint32_operand (op
, mode
)
2590 enum machine_mode mode
;
2592 /* All allowed constants will fit a CONST_INT. */
2593 return (GET_CODE (op
) == CONST_INT
2594 && (INTVAL (op
) >= (-0x7fffffff - 1) && INTVAL (op
) <= 0x7fffffff));