1 /* Subroutines for insn-output.c for Motorola 68000 family.
2 Copyright (C) 1987, 1993, 1994, 1995, 1996 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_BLOCK_PROFILER_EXIT
306 if (profile_block_flag
== 2)
308 FUNCTION_BLOCK_PROFILER_EXIT (stream
);
312 #ifdef FUNCTION_EXTRA_EPILOGUE
313 FUNCTION_EXTRA_EPILOGUE (stream
, size
);
315 nregs
= 0; fmask
= 0; fpoffset
= 0;
316 #ifdef SUPPORT_SUN_FPA
317 for (regno
= 24 ; regno
< 56 ; regno
++)
318 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
320 fpoffset
= nregs
* 8;
323 for (regno
= 16; regno
< 24; regno
++)
324 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
327 fmask
|= 1 << (23 - regno
);
329 foffset
= fpoffset
+ nregs
* 12;
331 if (frame_pointer_needed
)
332 regs_ever_live
[FRAME_POINTER_REGNUM
] = 0;
333 for (regno
= 0; regno
< 16; regno
++)
334 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
339 offset
= foffset
+ nregs
* 4;
340 if (offset
+ fsize
>= 0x8000
341 && frame_pointer_needed
342 && (mask
|| fmask
|| fpoffset
))
345 asm_fprintf (stream
, "\t%Omove.l %0I%d,%Ra1\n", -fsize
);
347 asm_fprintf (stream
, "\tmovel %0I%d,%Ra1\n", -fsize
);
353 /* Restore each separately in the same order moveml does.
354 Using two movel instructions instead of a single moveml
355 is about 15% faster for the 68020 and 68030 at no expense
360 /* Undo the work from above. */
361 for (i
= 0; i
< 16; i
++)
367 asm_fprintf (stream
, "\t%Omove.l -%d(%s,%Ra1.l),%s\n",
369 reg_names
[FRAME_POINTER_REGNUM
],
372 asm_fprintf (stream
, "\tmovel %s@(-%d,%Ra1:l),%s\n",
373 reg_names
[FRAME_POINTER_REGNUM
],
374 offset
+ fsize
, reg_names
[i
]);
377 else if (! frame_pointer_needed
)
380 asm_fprintf (stream
, "\t%Omove.l (%Rsp)+,%s\n",
383 asm_fprintf (stream
, "\tmovel %Rsp@+,%s\n",
390 asm_fprintf (stream
, "\t%Omove.l -%d(%s),%s\n",
392 reg_names
[FRAME_POINTER_REGNUM
],
395 asm_fprintf (stream
, "\tmovel %s@(-%d),%s\n",
396 reg_names
[FRAME_POINTER_REGNUM
],
397 offset
+ fsize
, reg_names
[i
]);
408 asm_fprintf (stream
, "\tmovm.l -%d(%s,%Ra1.l),%0I0x%x\n",
410 reg_names
[FRAME_POINTER_REGNUM
],
413 asm_fprintf (stream
, "\tmoveml %s@(-%d,%Ra1:l),%0I0x%x\n",
414 reg_names
[FRAME_POINTER_REGNUM
],
415 offset
+ fsize
, mask
);
418 else if (! frame_pointer_needed
)
421 asm_fprintf (stream
, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask
);
423 asm_fprintf (stream
, "\tmoveml %Rsp@+,%0I0x%x\n", mask
);
429 asm_fprintf (stream
, "\tmovm.l -%d(%s),%0I0x%x\n",
431 reg_names
[FRAME_POINTER_REGNUM
],
434 asm_fprintf (stream
, "\tmoveml %s@(-%d),%0I0x%x\n",
435 reg_names
[FRAME_POINTER_REGNUM
],
436 offset
+ fsize
, mask
);
445 asm_fprintf (stream
, "\tfmovm -%d(%s,%Ra1.l),%0I0x%x\n",
447 reg_names
[FRAME_POINTER_REGNUM
],
450 asm_fprintf (stream
, "\tfmovem %s@(-%d,%Ra1:l),%0I0x%x\n",
451 reg_names
[FRAME_POINTER_REGNUM
],
452 foffset
+ fsize
, fmask
);
455 else if (! frame_pointer_needed
)
458 asm_fprintf (stream
, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask
);
460 asm_fprintf (stream
, "\tfmovem %Rsp@+,%0I0x%x\n", fmask
);
466 asm_fprintf (stream
, "\tfmovm -%d(%s),%0I0x%x\n",
468 reg_names
[FRAME_POINTER_REGNUM
],
471 asm_fprintf (stream
, "\tfmovem %s@(-%d),%0I0x%x\n",
472 reg_names
[FRAME_POINTER_REGNUM
],
473 foffset
+ fsize
, fmask
);
478 for (regno
= 55; regno
>= 24; regno
--)
479 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
484 asm_fprintf (stream
, "\tfpmovd -%d(%s,%Ra1.l), %s\n",
486 reg_names
[FRAME_POINTER_REGNUM
],
489 asm_fprintf (stream
, "\tfpmoved %s@(-%d,%Ra1:l), %s\n",
490 reg_names
[FRAME_POINTER_REGNUM
],
491 fpoffset
+ fsize
, reg_names
[regno
]);
494 else if (! frame_pointer_needed
)
497 asm_fprintf (stream
, "\tfpmovd (%Rsp)+,%s\n",
500 asm_fprintf (stream
, "\tfpmoved %Rsp@+, %s\n",
507 asm_fprintf (stream
, "\tfpmovd -%d(%s), %s\n",
509 reg_names
[FRAME_POINTER_REGNUM
],
512 asm_fprintf (stream
, "\tfpmoved %s@(-%d), %s\n",
513 reg_names
[FRAME_POINTER_REGNUM
],
514 fpoffset
+ fsize
, reg_names
[regno
]);
519 if (frame_pointer_needed
)
520 fprintf (stream
, "\tunlk %s\n",
521 reg_names
[FRAME_POINTER_REGNUM
]);
524 if (fsize
+ 4 < 0x8000)
526 /* asm_fprintf() cannot handle %. */
528 asm_fprintf (stream
, "\tadd.w %0I%d,%Rsp\n", fsize
+ 4);
530 asm_fprintf (stream
, "\taddw %0I%d,%Rsp\n", fsize
+ 4);
535 /* asm_fprintf() cannot handle %. */
537 asm_fprintf (stream
, "\tadd.l %0I%d,%Rsp\n", fsize
+ 4);
539 asm_fprintf (stream
, "\taddl %0I%d,%Rsp\n", fsize
+ 4);
543 if (current_function_pops_args
)
544 asm_fprintf (stream
, "\trtd %0I%d\n", current_function_pops_args
);
546 fprintf (stream
, "\trts\n");
549 /* Similar to general_operand, but exclude stack_pointer_rtx. */
552 not_sp_operand (op
, mode
)
554 enum machine_mode mode
;
556 return op
!= stack_pointer_rtx
&& general_operand (op
, mode
);
559 /* Return TRUE if X is a valid comparison operator for the dbcc
562 Note it rejects floating point comparison operators.
563 (In the future we could use Fdbcc).
565 It also rejects some comparisons when CC_NO_OVERFLOW is set. */
568 valid_dbcc_comparison_p (x
, mode
)
570 enum machine_mode mode
;
572 /* We could add support for these in the future */
573 if (cc_prev_status
.flags
& CC_IN_68881
)
576 switch (GET_CODE (x
))
579 case EQ
: case NE
: case GTU
: case LTU
:
583 /* Reject some when CC_NO_OVERFLOW is set. This may be over
585 case GT
: case LT
: case GE
: case LE
:
586 return ! (cc_prev_status
.flags
& CC_NO_OVERFLOW
);
592 /* Output a dbCC; jCC sequence. Note we do not handle the
593 floating point version of this sequence (Fdbcc). We also
594 do not handle alternative conditions when CC_NO_OVERFLOW is
595 set. It is assumed that valid_dbcc_comparison_p will kick
596 those out before we get here. */
598 output_dbcc_and_branch (operands
)
602 switch (GET_CODE (operands
[3]))
606 output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands
);
608 output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands
);
614 output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands
);
616 output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands
);
622 output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands
);
624 output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands
);
630 output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands
);
632 output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands
);
638 output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands
);
640 output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands
);
646 output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands
);
648 output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands
);
654 output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands
);
656 output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands
);
662 output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands
);
664 output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands
);
670 output_asm_insn ("dble %0,%l1\n\tjble %l2", operands
);
672 output_asm_insn ("dble %0,%l1\n\tjle %l2", operands
);
678 output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands
);
680 output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands
);
688 /* If the decrement is to be done in SImode, then we have
689 to compensate for the fact that dbcc decrements in HImode. */
690 switch (GET_MODE (operands
[0]))
694 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands
);
696 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands
);
709 output_scc_di(op
, operand1
, operand2
, dest
)
716 enum rtx_code op_code
= GET_CODE (op
);
718 /* The m68k cmp.l instruction requires operand1 to be a reg as used
719 below. Swap the operands and change the op if these requirements
720 are not fulfilled. */
721 if (GET_CODE (operand2
) == REG
&& GET_CODE (operand1
) != REG
)
727 op_code
= swap_condition (op_code
);
729 loperands
[0] = operand1
;
730 if (GET_CODE (operand1
) == REG
)
731 loperands
[1] = gen_rtx (REG
, SImode
, REGNO (operand1
) + 1);
733 loperands
[1] = adj_offsettable_operand (operand1
, 4);
734 if (operand2
!= const0_rtx
)
736 loperands
[2] = operand2
;
737 if (GET_CODE (operand2
) == REG
)
738 loperands
[3] = gen_rtx (REG
, SImode
, REGNO (operand2
) + 1);
740 loperands
[3] = adj_offsettable_operand (operand2
, 4);
742 loperands
[4] = gen_label_rtx();
743 if (operand2
!= const0_rtx
)
746 output_asm_insn ("cmp%.l %0,%2\n\tjbne %l4\n\tcmp%.l %1,%3", loperands
);
748 output_asm_insn ("cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1", loperands
);
752 output_asm_insn ("cmp%.l %0,%2\n\tjne %l4\n\tcmp%.l %1,%3", loperands
);
754 output_asm_insn ("cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1", loperands
);
759 output_asm_insn ("tst%.l %0\n\tjbne %l4\n\ttst%.l %1", loperands
);
761 output_asm_insn ("tst%.l %0\n\tjne %l4\n\ttst%.l %1", loperands
);
768 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
769 CODE_LABEL_NUMBER (loperands
[4]));
770 output_asm_insn ("seq %5", loperands
);
774 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
775 CODE_LABEL_NUMBER (loperands
[4]));
776 output_asm_insn ("sne %5", loperands
);
780 loperands
[6] = gen_label_rtx();
782 output_asm_insn ("shi %5\n\tjbra %l6", loperands
);
784 output_asm_insn ("shi %5\n\tjra %l6", loperands
);
786 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
787 CODE_LABEL_NUMBER (loperands
[4]));
788 output_asm_insn ("sgt %5", loperands
);
789 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
790 CODE_LABEL_NUMBER (loperands
[6]));
794 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
795 CODE_LABEL_NUMBER (loperands
[4]));
796 output_asm_insn ("shi %5", loperands
);
800 loperands
[6] = gen_label_rtx();
802 output_asm_insn ("scs %5\n\tjbra %l6", loperands
);
804 output_asm_insn ("scs %5\n\tjra %l6", loperands
);
806 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
807 CODE_LABEL_NUMBER (loperands
[4]));
808 output_asm_insn ("slt %5", loperands
);
809 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
810 CODE_LABEL_NUMBER (loperands
[6]));
814 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
815 CODE_LABEL_NUMBER (loperands
[4]));
816 output_asm_insn ("scs %5", loperands
);
820 loperands
[6] = gen_label_rtx();
822 output_asm_insn ("scc %5\n\tjbra %l6", loperands
);
824 output_asm_insn ("scc %5\n\tjra %l6", loperands
);
826 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
827 CODE_LABEL_NUMBER (loperands
[4]));
828 output_asm_insn ("sge %5", loperands
);
829 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
830 CODE_LABEL_NUMBER (loperands
[6]));
834 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
835 CODE_LABEL_NUMBER (loperands
[4]));
836 output_asm_insn ("scc %5", loperands
);
840 loperands
[6] = gen_label_rtx();
842 output_asm_insn ("sls %5\n\tjbra %l6", loperands
);
844 output_asm_insn ("sls %5\n\tjra %l6", loperands
);
846 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
847 CODE_LABEL_NUMBER (loperands
[4]));
848 output_asm_insn ("sle %5", loperands
);
849 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
850 CODE_LABEL_NUMBER (loperands
[6]));
854 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L",
855 CODE_LABEL_NUMBER (loperands
[4]));
856 output_asm_insn ("sls %5", loperands
);
866 output_btst (operands
, countop
, dataop
, insn
, signpos
)
872 operands
[0] = countop
;
873 operands
[1] = dataop
;
875 if (GET_CODE (countop
) == CONST_INT
)
877 register int count
= INTVAL (countop
);
878 /* If COUNT is bigger than size of storage unit in use,
879 advance to the containing unit of same size. */
882 int offset
= (count
& ~signpos
) / 8;
883 count
= count
& signpos
;
884 operands
[1] = dataop
= adj_offsettable_operand (dataop
, offset
);
886 if (count
== signpos
)
887 cc_status
.flags
= CC_NOT_POSITIVE
| CC_Z_IN_NOT_N
;
889 cc_status
.flags
= CC_NOT_NEGATIVE
| CC_Z_IN_NOT_N
;
891 /* These three statements used to use next_insns_test_no...
892 but it appears that this should do the same job. */
894 && next_insn_tests_no_inequality (insn
))
897 && next_insn_tests_no_inequality (insn
))
900 && next_insn_tests_no_inequality (insn
))
903 cc_status
.flags
= CC_NOT_NEGATIVE
;
908 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
909 reference and a constant. */
912 symbolic_operand (op
, mode
)
914 enum machine_mode mode
;
916 switch (GET_CODE (op
))
924 return ((GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
925 || GET_CODE (XEXP (op
, 0)) == LABEL_REF
)
926 && GET_CODE (XEXP (op
, 1)) == CONST_INT
);
928 #if 0 /* Deleted, with corresponding change in m68k.h,
929 so as to fit the specs. No CONST_DOUBLE is ever symbolic. */
931 return GET_MODE (op
) == mode
;
939 /* Check for sign_extend or zero_extend. Used for bit-count operands. */
942 extend_operator(x
, mode
)
944 enum machine_mode mode
;
946 if (mode
!= VOIDmode
&& GET_MODE(x
) != mode
)
959 /* Legitimize PIC addresses. If the address is already
960 position-independent, we return ORIG. Newly generated
961 position-independent addresses go to REG. If we need more
962 than one register, we lose.
964 An address is legitimized by making an indirect reference
965 through the Global Offset Table with the name of the symbol
968 The assembler and linker are responsible for placing the
969 address of the symbol in the GOT. The function prologue
970 is responsible for initializing a5 to the starting address
973 The assembler is also responsible for translating a symbol name
974 into a constant displacement from the start of the GOT.
976 A quick example may make things a little clearer:
978 When not generating PIC code to store the value 12345 into _foo
979 we would generate the following code:
983 When generating PIC two transformations are made. First, the compiler
984 loads the address of foo into a register. So the first transformation makes:
989 The code in movsi will intercept the lea instruction and call this
990 routine which will transform the instructions into:
992 movel a5@(_foo:w), a0
996 That (in a nutshell) is how *all* symbol and label references are
1000 legitimize_pic_address (orig
, mode
, reg
)
1002 enum machine_mode mode
;
1006 /* First handle a simple SYMBOL_REF or LABEL_REF */
1007 if (GET_CODE (orig
) == SYMBOL_REF
|| GET_CODE (orig
) == LABEL_REF
)
1012 pic_ref
= gen_rtx (MEM
, Pmode
,
1013 gen_rtx (PLUS
, Pmode
,
1014 pic_offset_table_rtx
, orig
));
1015 current_function_uses_pic_offset_table
= 1;
1016 RTX_UNCHANGING_P (pic_ref
) = 1;
1017 emit_move_insn (reg
, pic_ref
);
1020 else if (GET_CODE (orig
) == CONST
)
1024 /* Make sure this is CONST has not already been legitimized */
1025 if (GET_CODE (XEXP (orig
, 0)) == PLUS
1026 && XEXP (XEXP (orig
, 0), 0) == pic_offset_table_rtx
)
1032 /* legitimize both operands of the PLUS */
1033 if (GET_CODE (XEXP (orig
, 0)) == PLUS
)
1035 base
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 0), Pmode
, reg
);
1036 orig
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 1), Pmode
,
1037 base
== reg
? 0 : reg
);
1041 if (GET_CODE (orig
) == CONST_INT
)
1042 return plus_constant_for_output (base
, INTVAL (orig
));
1043 pic_ref
= gen_rtx (PLUS
, Pmode
, base
, orig
);
1044 /* Likewise, should we set special REG_NOTEs here? */
1050 typedef enum { MOVL
, SWAP
, NEGW
, NOTW
, NOTB
, MOVQ
} CONST_METHOD
;
1055 return (i
>= -128 && i
<= 127);
1059 const_method (constant
)
1065 i
= INTVAL (constant
);
1068 /* if -256 < N < 256 but N is not in range for a moveq
1069 N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */
1070 if (use_movq (i
^ 0xff))
1072 /* Likewise, try with not.w */
1073 if (use_movq (i
^ 0xffff))
1075 /* This is the only value where neg.w is useful */
1078 /* Try also with swap */
1080 if (use_movq ((u
>> 16) | (u
<< 16)))
1082 /* Otherwise, use move.l */
1086 const_int_cost (constant
)
1089 switch (const_method (constant
))
1092 /* Constants between -128 and 127 are cheap due to moveq */
1098 /* Constants easily generated by moveq + not.b/not.w/neg.w/swap */
1108 output_move_const_into_data_reg (operands
)
1113 i
= INTVAL (operands
[1]);
1114 switch (const_method (operands
[1]))
1117 #if defined (MOTOROLA) && !defined (CRDS)
1118 return "moveq%.l %1,%0";
1120 return "moveq %1,%0";
1123 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
, i
^ 0xff);
1124 #if defined (MOTOROLA) && !defined (CRDS)
1125 return "moveq%.l %1,%0\n\tnot%.b %0";
1127 return "moveq %1,%0\n\tnot%.b %0";
1130 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
, i
^ 0xffff);
1131 #if defined (MOTOROLA) && !defined (CRDS)
1132 return "moveq%.l %1,%0\n\tnot%.w %0";
1134 return "moveq %1,%0\n\tnot%.w %0";
1137 #if defined (MOTOROLA) && !defined (CRDS)
1138 return "moveq%.l %#-128,%0\n\tneg%.w %0";
1140 return "moveq %#-128,%0\n\tneg%.w %0";
1146 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
, (u
<< 16) | (u
>> 16));
1147 #if defined (MOTOROLA) && !defined (CRDS)
1148 return "moveq%.l %1,%0\n\tswap %0";
1150 return "moveq %1,%0\n\tswap %0";
1154 return "move%.l %1,%0";
1160 /* Return the best assembler insn template
1161 for moving operands[1] into operands[0] as a fullword. */
1164 singlemove_string (operands
)
1167 #ifdef SUPPORT_SUN_FPA
1168 if (FPA_REG_P (operands
[0]) || FPA_REG_P (operands
[1]))
1169 return "fpmoves %1,%0";
1171 if (DATA_REG_P (operands
[0])
1172 && GET_CODE (operands
[1]) == CONST_INT
)
1173 return output_move_const_into_data_reg (operands
);
1174 if (operands
[1] != const0_rtx
)
1175 return "move%.l %1,%0";
1176 if (! ADDRESS_REG_P (operands
[0]))
1178 return "sub%.l %0,%0";
1182 /* Output assembler code to perform a doubleword move insn
1183 with operands OPERANDS. */
1186 output_move_double (operands
)
1191 REGOP
, OFFSOP
, MEMOP
, PUSHOP
, POPOP
, CNSTOP
, RNDOP
1196 rtx addreg0
= 0, addreg1
= 0;
1197 int dest_overlapped_low
= 0;
1198 int size
= GET_MODE_SIZE (GET_MODE (operands
[0]));
1203 /* First classify both operands. */
1205 if (REG_P (operands
[0]))
1207 else if (offsettable_memref_p (operands
[0]))
1209 else if (GET_CODE (XEXP (operands
[0], 0)) == POST_INC
)
1211 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
)
1213 else if (GET_CODE (operands
[0]) == MEM
)
1218 if (REG_P (operands
[1]))
1220 else if (CONSTANT_P (operands
[1]))
1222 else if (offsettable_memref_p (operands
[1]))
1224 else if (GET_CODE (XEXP (operands
[1], 0)) == POST_INC
)
1226 else if (GET_CODE (XEXP (operands
[1], 0)) == PRE_DEC
)
1228 else if (GET_CODE (operands
[1]) == MEM
)
1233 /* Check for the cases that the operand constraints are not
1234 supposed to allow to happen. Abort if we get one,
1235 because generating code for these cases is painful. */
1237 if (optype0
== RNDOP
|| optype1
== RNDOP
)
1240 /* If one operand is decrementing and one is incrementing
1241 decrement the former register explicitly
1242 and change that operand into ordinary indexing. */
1244 if (optype0
== PUSHOP
&& optype1
== POPOP
)
1246 operands
[0] = XEXP (XEXP (operands
[0], 0), 0);
1248 output_asm_insn ("sub%.l %#12,%0", operands
);
1250 output_asm_insn ("subq%.l %#8,%0", operands
);
1251 if (GET_MODE (operands
[1]) == XFmode
)
1252 operands
[0] = gen_rtx (MEM
, XFmode
, operands
[0]);
1253 else if (GET_MODE (operands
[0]) == DFmode
)
1254 operands
[0] = gen_rtx (MEM
, DFmode
, operands
[0]);
1256 operands
[0] = gen_rtx (MEM
, DImode
, operands
[0]);
1259 if (optype0
== POPOP
&& optype1
== PUSHOP
)
1261 operands
[1] = XEXP (XEXP (operands
[1], 0), 0);
1263 output_asm_insn ("sub%.l %#12,%1", operands
);
1265 output_asm_insn ("subq%.l %#8,%1", operands
);
1266 if (GET_MODE (operands
[1]) == XFmode
)
1267 operands
[1] = gen_rtx (MEM
, XFmode
, operands
[1]);
1268 else if (GET_MODE (operands
[1]) == DFmode
)
1269 operands
[1] = gen_rtx (MEM
, DFmode
, operands
[1]);
1271 operands
[1] = gen_rtx (MEM
, DImode
, operands
[1]);
1275 /* If an operand is an unoffsettable memory ref, find a register
1276 we can increment temporarily to make it refer to the second word. */
1278 if (optype0
== MEMOP
)
1279 addreg0
= find_addr_reg (XEXP (operands
[0], 0));
1281 if (optype1
== MEMOP
)
1282 addreg1
= find_addr_reg (XEXP (operands
[1], 0));
1284 /* Ok, we can do one word at a time.
1285 Normally we do the low-numbered word first,
1286 but if either operand is autodecrementing then we
1287 do the high-numbered word first.
1289 In either case, set up in LATEHALF the operands to use
1290 for the high-numbered word and in some cases alter the
1291 operands in OPERANDS to be suitable for the low-numbered word. */
1295 if (optype0
== REGOP
)
1297 latehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 2);
1298 middlehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 1);
1300 else if (optype0
== OFFSOP
)
1302 middlehalf
[0] = adj_offsettable_operand (operands
[0], 4);
1303 latehalf
[0] = adj_offsettable_operand (operands
[0], size
- 4);
1307 middlehalf
[0] = operands
[0];
1308 latehalf
[0] = operands
[0];
1311 if (optype1
== REGOP
)
1313 latehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 2);
1314 middlehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 1);
1316 else if (optype1
== OFFSOP
)
1318 middlehalf
[1] = adj_offsettable_operand (operands
[1], 4);
1319 latehalf
[1] = adj_offsettable_operand (operands
[1], size
- 4);
1321 else if (optype1
== CNSTOP
)
1323 if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
1328 REAL_VALUE_FROM_CONST_DOUBLE (r
, operands
[1]);
1329 REAL_VALUE_TO_TARGET_LONG_DOUBLE (r
, l
);
1330 operands
[1] = GEN_INT (l
[0]);
1331 middlehalf
[1] = GEN_INT (l
[1]);
1332 latehalf
[1] = GEN_INT (l
[2]);
1334 else if (CONSTANT_P (operands
[1]))
1336 /* actually, no non-CONST_DOUBLE constant should ever
1339 if (GET_CODE (operands
[1]) == CONST_INT
&& INTVAL (operands
[1]) < 0)
1340 latehalf
[1] = constm1_rtx
;
1342 latehalf
[1] = const0_rtx
;
1347 middlehalf
[1] = operands
[1];
1348 latehalf
[1] = operands
[1];
1352 /* size is not 12: */
1354 if (optype0
== REGOP
)
1355 latehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 1);
1356 else if (optype0
== OFFSOP
)
1357 latehalf
[0] = adj_offsettable_operand (operands
[0], size
- 4);
1359 latehalf
[0] = operands
[0];
1361 if (optype1
== REGOP
)
1362 latehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 1);
1363 else if (optype1
== OFFSOP
)
1364 latehalf
[1] = adj_offsettable_operand (operands
[1], size
- 4);
1365 else if (optype1
== CNSTOP
)
1366 split_double (operands
[1], &operands
[1], &latehalf
[1]);
1368 latehalf
[1] = operands
[1];
1371 /* If insn is effectively movd N(sp),-(sp) then we will do the
1372 high word first. We should use the adjusted operand 1 (which is N+4(sp))
1373 for the low word as well, to compensate for the first decrement of sp. */
1374 if (optype0
== PUSHOP
1375 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
1376 && reg_overlap_mentioned_p (stack_pointer_rtx
, operands
[1]))
1377 operands
[1] = middlehalf
[1] = latehalf
[1];
1379 /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
1380 if the upper part of reg N does not appear in the MEM, arrange to
1381 emit the move late-half first. Otherwise, compute the MEM address
1382 into the upper part of N and use that as a pointer to the memory
1384 if (optype0
== REGOP
1385 && (optype1
== OFFSOP
|| optype1
== MEMOP
))
1387 rtx testlow
= gen_rtx (REG
, SImode
, REGNO (operands
[0]));
1389 if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0))
1390 && reg_overlap_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
1392 /* If both halves of dest are used in the src memory address,
1393 compute the address into latehalf of dest.
1394 Note that this can't happen if the dest is two data regs. */
1396 xops
[0] = latehalf
[0];
1397 xops
[1] = XEXP (operands
[1], 0);
1398 output_asm_insn ("lea %a1,%0", xops
);
1399 if( GET_MODE (operands
[1]) == XFmode
)
1401 operands
[1] = gen_rtx (MEM
, XFmode
, latehalf
[0]);
1402 middlehalf
[1] = adj_offsettable_operand (operands
[1], size
-8);
1403 latehalf
[1] = adj_offsettable_operand (operands
[1], size
-4);
1407 operands
[1] = gen_rtx (MEM
, DImode
, latehalf
[0]);
1408 latehalf
[1] = adj_offsettable_operand (operands
[1], size
-4);
1412 && reg_overlap_mentioned_p (middlehalf
[0],
1413 XEXP (operands
[1], 0)))
1415 /* Check for two regs used by both source and dest.
1416 Note that this can't happen if the dest is all data regs.
1417 It can happen if the dest is d6, d7, a0.
1418 But in that case, latehalf is an addr reg, so
1419 the code at compadr does ok. */
1421 if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0))
1422 || reg_overlap_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
1425 /* JRV says this can't happen: */
1426 if (addreg0
|| addreg1
)
1429 /* Only the middle reg conflicts; simply put it last. */
1430 output_asm_insn (singlemove_string (operands
), operands
);
1431 output_asm_insn (singlemove_string (latehalf
), latehalf
);
1432 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
1435 else if (reg_overlap_mentioned_p (testlow
, XEXP (operands
[1], 0)))
1436 /* If the low half of dest is mentioned in the source memory
1437 address, the arrange to emit the move late half first. */
1438 dest_overlapped_low
= 1;
1441 /* If one or both operands autodecrementing,
1442 do the two words, high-numbered first. */
1444 /* Likewise, the first move would clobber the source of the second one,
1445 do them in the other order. This happens only for registers;
1446 such overlap can't happen in memory unless the user explicitly
1447 sets it up, and that is an undefined circumstance. */
1449 if (optype0
== PUSHOP
|| optype1
== PUSHOP
1450 || (optype0
== REGOP
&& optype1
== REGOP
1451 && ((middlehalf
[1] && REGNO (operands
[0]) == REGNO (middlehalf
[1]))
1452 || REGNO (operands
[0]) == REGNO (latehalf
[1])))
1453 || dest_overlapped_low
)
1455 /* Make any unoffsettable addresses point at high-numbered word. */
1459 output_asm_insn ("addq%.l %#8,%0", &addreg0
);
1461 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
1466 output_asm_insn ("addq%.l %#8,%0", &addreg1
);
1468 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
1472 output_asm_insn (singlemove_string (latehalf
), latehalf
);
1474 /* Undo the adds we just did. */
1476 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
1478 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
1482 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
1484 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
1486 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
1489 /* Do low-numbered word. */
1490 return singlemove_string (operands
);
1493 /* Normal case: do the two words, low-numbered first. */
1495 output_asm_insn (singlemove_string (operands
), operands
);
1497 /* Do the middle one of the three words for long double */
1501 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
1503 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
1505 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
1508 /* Make any unoffsettable addresses point at high-numbered word. */
1510 output_asm_insn ("addq%.l %#4,%0", &addreg0
);
1512 output_asm_insn ("addq%.l %#4,%0", &addreg1
);
1515 output_asm_insn (singlemove_string (latehalf
), latehalf
);
1517 /* Undo the adds we just did. */
1521 output_asm_insn ("subq%.l %#8,%0", &addreg0
);
1523 output_asm_insn ("subq%.l %#4,%0", &addreg0
);
1528 output_asm_insn ("subq%.l %#8,%0", &addreg1
);
1530 output_asm_insn ("subq%.l %#4,%0", &addreg1
);
1536 /* Return a REG that occurs in ADDR with coefficient 1.
1537 ADDR can be effectively incremented by incrementing REG. */
1540 find_addr_reg (addr
)
1543 while (GET_CODE (addr
) == PLUS
)
1545 if (GET_CODE (XEXP (addr
, 0)) == REG
)
1546 addr
= XEXP (addr
, 0);
1547 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
1548 addr
= XEXP (addr
, 1);
1549 else if (CONSTANT_P (XEXP (addr
, 0)))
1550 addr
= XEXP (addr
, 1);
1551 else if (CONSTANT_P (XEXP (addr
, 1)))
1552 addr
= XEXP (addr
, 0);
1556 if (GET_CODE (addr
) == REG
)
1561 /* Store in cc_status the expressions that the condition codes will
1562 describe after execution of an instruction whose pattern is EXP.
1563 Do not alter them if the instruction would not alter the cc's. */
1565 /* On the 68000, all the insns to store in an address register fail to
1566 set the cc's. However, in some cases these instructions can make it
1567 possibly invalid to use the saved cc's. In those cases we clear out
1568 some or all of the saved cc's so they won't be used. */
1570 notice_update_cc (exp
, insn
)
1574 /* If the cc is being set from the fpa and the expression is not an
1575 explicit floating point test instruction (which has code to deal with
1576 this), reinit the CC. */
1577 if (((cc_status
.value1
&& FPA_REG_P (cc_status
.value1
))
1578 || (cc_status
.value2
&& FPA_REG_P (cc_status
.value2
)))
1579 && !(GET_CODE (exp
) == PARALLEL
1580 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
1581 && XEXP (XVECEXP (exp
, 0, 0), 0) == cc0_rtx
))
1585 else if (GET_CODE (exp
) == SET
)
1587 if (GET_CODE (SET_SRC (exp
)) == CALL
)
1591 else if (ADDRESS_REG_P (SET_DEST (exp
)))
1593 if (cc_status
.value1
1594 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value1
))
1595 cc_status
.value1
= 0;
1596 if (cc_status
.value2
1597 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value2
))
1598 cc_status
.value2
= 0;
1600 else if (!FP_REG_P (SET_DEST (exp
))
1601 && SET_DEST (exp
) != cc0_rtx
1602 && (FP_REG_P (SET_SRC (exp
))
1603 || GET_CODE (SET_SRC (exp
)) == FIX
1604 || GET_CODE (SET_SRC (exp
)) == FLOAT_TRUNCATE
1605 || GET_CODE (SET_SRC (exp
)) == FLOAT_EXTEND
))
1609 /* A pair of move insns doesn't produce a useful overall cc. */
1610 else if (!FP_REG_P (SET_DEST (exp
))
1611 && !FP_REG_P (SET_SRC (exp
))
1612 && GET_MODE_SIZE (GET_MODE (SET_SRC (exp
))) > 4
1613 && (GET_CODE (SET_SRC (exp
)) == REG
1614 || GET_CODE (SET_SRC (exp
)) == MEM
1615 || GET_CODE (SET_SRC (exp
)) == CONST_DOUBLE
))
1619 else if (GET_CODE (SET_SRC (exp
)) == CALL
)
1623 else if (XEXP (exp
, 0) != pc_rtx
)
1625 cc_status
.flags
= 0;
1626 cc_status
.value1
= XEXP (exp
, 0);
1627 cc_status
.value2
= XEXP (exp
, 1);
1630 else if (GET_CODE (exp
) == PARALLEL
1631 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
)
1633 if (ADDRESS_REG_P (XEXP (XVECEXP (exp
, 0, 0), 0)))
1635 else if (XEXP (XVECEXP (exp
, 0, 0), 0) != pc_rtx
)
1637 cc_status
.flags
= 0;
1638 cc_status
.value1
= XEXP (XVECEXP (exp
, 0, 0), 0);
1639 cc_status
.value2
= XEXP (XVECEXP (exp
, 0, 0), 1);
1644 if (cc_status
.value2
!= 0
1645 && ADDRESS_REG_P (cc_status
.value2
)
1646 && GET_MODE (cc_status
.value2
) == QImode
)
1648 if (cc_status
.value2
!= 0
1649 && !(cc_status
.value1
&& FPA_REG_P (cc_status
.value1
)))
1650 switch (GET_CODE (cc_status
.value2
))
1652 case PLUS
: case MINUS
: case MULT
:
1653 case DIV
: case UDIV
: case MOD
: case UMOD
: case NEG
:
1654 case ASHIFT
: case ASHIFTRT
: case LSHIFTRT
:
1655 case ROTATE
: case ROTATERT
:
1656 if (GET_MODE (cc_status
.value2
) != VOIDmode
)
1657 cc_status
.flags
|= CC_NO_OVERFLOW
;
1660 /* (SET r1 (ZERO_EXTEND r2)) on this machine
1661 ends with a move insn moving r2 in r2's mode.
1662 Thus, the cc's are set for r2.
1663 This can set N bit spuriously. */
1664 cc_status
.flags
|= CC_NOT_NEGATIVE
;
1666 if (cc_status
.value1
&& GET_CODE (cc_status
.value1
) == REG
1668 && reg_overlap_mentioned_p (cc_status
.value1
, cc_status
.value2
))
1669 cc_status
.value2
= 0;
1670 if (((cc_status
.value1
&& FP_REG_P (cc_status
.value1
))
1671 || (cc_status
.value2
&& FP_REG_P (cc_status
.value2
)))
1672 && !((cc_status
.value1
&& FPA_REG_P (cc_status
.value1
))
1673 || (cc_status
.value2
&& FPA_REG_P (cc_status
.value2
))))
1674 cc_status
.flags
= CC_IN_68881
;
1678 output_move_const_double (operands
)
1681 #ifdef SUPPORT_SUN_FPA
1682 if (TARGET_FPA
&& FPA_REG_P (operands
[0]))
1684 int code
= standard_sun_fpa_constant_p (operands
[1]);
1688 static char buf
[40];
1690 sprintf (buf
, "fpmove%%.d %%%%%d,%%0", code
& 0x1ff);
1693 return "fpmove%.d %1,%0";
1698 int code
= standard_68881_constant_p (operands
[1]);
1702 static char buf
[40];
1704 sprintf (buf
, "fmovecr %%#0x%x,%%0", code
& 0xff);
1707 return "fmove%.d %1,%0";
1712 output_move_const_single (operands
)
1715 #ifdef SUPPORT_SUN_FPA
1718 int code
= standard_sun_fpa_constant_p (operands
[1]);
1722 static char buf
[40];
1724 sprintf (buf
, "fpmove%%.s %%%%%d,%%0", code
& 0x1ff);
1727 return "fpmove%.s %1,%0";
1730 #endif /* defined SUPPORT_SUN_FPA */
1732 int code
= standard_68881_constant_p (operands
[1]);
1736 static char buf
[40];
1738 sprintf (buf
, "fmovecr %%#0x%x,%%0", code
& 0xff);
1741 return "fmove%.s %f1,%0";
1745 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1746 from the "fmovecr" instruction.
1747 The value, anded with 0xff, gives the code to use in fmovecr
1748 to get the desired constant. */
1750 /* This code has been fixed for cross-compilation. */
1752 static int inited_68881_table
= 0;
1754 char *strings_68881
[7] = {
1764 int codes_68881
[7] = {
1774 REAL_VALUE_TYPE values_68881
[7];
1776 /* Set up values_68881 array by converting the decimal values
1777 strings_68881 to binary. */
1784 enum machine_mode mode
;
1787 for (i
= 0; i
< 7; i
++)
1791 r
= REAL_VALUE_ATOF (strings_68881
[i
], mode
);
1792 values_68881
[i
] = r
;
1794 inited_68881_table
= 1;
1798 standard_68881_constant_p (x
)
1803 enum machine_mode mode
;
1805 #ifdef NO_ASM_FMOVECR
1809 /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */
1813 #ifndef REAL_ARITHMETIC
1814 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1815 if (! flag_pretend_float
)
1820 if (! inited_68881_table
)
1821 init_68881_table ();
1823 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1825 for (i
= 0; i
< 6; i
++)
1827 if (REAL_VALUES_EQUAL (r
, values_68881
[i
]))
1828 return (codes_68881
[i
]);
1831 if (GET_MODE (x
) == SFmode
)
1834 if (REAL_VALUES_EQUAL (r
, values_68881
[6]))
1835 return (codes_68881
[6]);
1837 /* larger powers of ten in the constants ram are not used
1838 because they are not equal to a `double' C constant. */
1842 /* If X is a floating-point constant, return the logarithm of X base 2,
1843 or 0 if X is not a power of 2. */
1846 floating_exact_log2 (x
)
1849 REAL_VALUE_TYPE r
, r1
;
1852 #ifndef REAL_ARITHMETIC
1853 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1854 if (! flag_pretend_float
)
1859 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1861 if (REAL_VALUES_LESS (r
, dconst0
))
1866 while (REAL_VALUES_LESS (r1
, r
))
1868 r1
= REAL_VALUE_LDEXP (dconst1
, i
);
1869 if (REAL_VALUES_EQUAL (r1
, r
))
1876 #ifdef SUPPORT_SUN_FPA
1877 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1878 from the Sun FPA's constant RAM.
1879 The value returned, anded with 0x1ff, gives the code to use in fpmove
1880 to get the desired constant. */
1882 static int inited_FPA_table
= 0;
1884 char *strings_FPA
[38] = {
1885 /* small rationals */
1898 /* Decimal equivalents of double precision values */
1899 "2.718281828459045091", /* D_E */
1900 "6.283185307179586477", /* 2 pi */
1901 "3.141592653589793116", /* D_PI */
1902 "1.570796326794896619", /* pi/2 */
1903 "1.414213562373095145", /* D_SQRT2 */
1904 "0.7071067811865475244", /* 1/sqrt(2) */
1905 "-1.570796326794896619", /* -pi/2 */
1906 "1.442695040888963387", /* D_LOG2ofE */
1907 "3.321928024887362182", /* D_LOG2of10 */
1908 "0.6931471805599452862", /* D_LOGEof2 */
1909 "2.302585092994045901", /* D_LOGEof10 */
1910 "0.3010299956639811980", /* D_LOG10of2 */
1911 "0.4342944819032518167", /* D_LOG10ofE */
1912 /* Decimal equivalents of single precision values */
1913 "2.718281745910644531", /* S_E */
1914 "6.283185307179586477", /* 2 pi */
1915 "3.141592741012573242", /* S_PI */
1916 "1.570796326794896619", /* pi/2 */
1917 "1.414213538169860840", /* S_SQRT2 */
1918 "0.7071067811865475244", /* 1/sqrt(2) */
1919 "-1.570796326794896619", /* -pi/2 */
1920 "1.442695021629333496", /* S_LOG2ofE */
1921 "3.321928024291992188", /* S_LOG2of10 */
1922 "0.6931471824645996094", /* S_LOGEof2 */
1923 "2.302585124969482442", /* S_LOGEof10 */
1924 "0.3010300099849700928", /* S_LOG10of2 */
1925 "0.4342944920063018799", /* S_LOG10ofE */
1929 int codes_FPA
[38] = {
1930 /* small rationals */
1943 /* double precision */
1957 /* single precision */
1973 REAL_VALUE_TYPE values_FPA
[38];
1975 /* This code has been fixed for cross-compilation. */
1980 enum machine_mode mode
;
1985 for (i
= 0; i
< 38; i
++)
1989 r
= REAL_VALUE_ATOF (strings_FPA
[i
], mode
);
1992 inited_FPA_table
= 1;
1997 standard_sun_fpa_constant_p (x
)
2003 #ifndef REAL_ARITHMETIC
2004 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2005 if (! flag_pretend_float
)
2010 if (! inited_FPA_table
)
2013 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
2015 for (i
=0; i
<12; i
++)
2017 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
2018 return (codes_FPA
[i
]);
2021 if (GET_MODE (x
) == SFmode
)
2023 for (i
=25; i
<38; i
++)
2025 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
2026 return (codes_FPA
[i
]);
2031 for (i
=12; i
<25; i
++)
2033 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
2034 return (codes_FPA
[i
]);
2039 #endif /* define SUPPORT_SUN_FPA */
2041 /* A C compound statement to output to stdio stream STREAM the
2042 assembler syntax for an instruction operand X. X is an RTL
2045 CODE is a value that can be used to specify one of several ways
2046 of printing the operand. It is used when identical operands
2047 must be printed differently depending on the context. CODE
2048 comes from the `%' specification that was used to request
2049 printing of the operand. If the specification was just `%DIGIT'
2050 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
2051 is the ASCII code for LTR.
2053 If X is a register, this macro should print the register's name.
2054 The names can be found in an array `reg_names' whose type is
2055 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
2057 When the machine description has a specification `%PUNCT' (a `%'
2058 followed by a punctuation character), this macro is called with
2059 a null pointer for X and the punctuation character for CODE.
2061 The m68k specific codes are:
2063 '.' for dot needed in Motorola-style opcode names.
2064 '-' for an operand pushing on the stack:
2065 sp@-, -(sp) or -(%sp) depending on the style of syntax.
2066 '+' for an operand pushing on the stack:
2067 sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
2068 '@' for a reference to the top word on the stack:
2069 sp@, (sp) or (%sp) depending on the style of syntax.
2070 '#' for an immediate operand prefix (# in MIT and Motorola syntax
2071 but & in SGS syntax).
2072 '!' for the cc register (used in an `and to cc' insn).
2073 '$' for the letter `s' in an op code, but only on the 68040.
2074 '&' for the letter `d' in an op code, but only on the 68040.
2075 '/' for register prefix needed by longlong.h.
2077 'b' for byte insn (no effect, on the Sun; this is for the ISI).
2078 'd' to force memory addressing to be absolute, not relative.
2079 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
2080 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
2081 than directly). Second part of 'y' below.
2082 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
2083 or print pair of registers as rx:ry.
2084 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
2085 CONST_DOUBLE's as SunFPA constant RAM registers if
2086 possible, so it should not be used except for the SunFPA.
2091 print_operand (file
, op
, letter
)
2092 FILE *file
; /* file to write to */
2093 rtx op
; /* operand to print */
2094 int letter
; /* %<letter> or 0 */
2101 asm_fprintf (file
, ".");
2104 else if (letter
== '#')
2106 asm_fprintf (file
, "%0I");
2108 else if (letter
== '-')
2111 asm_fprintf (file
, "-(%Rsp)");
2113 asm_fprintf (file
, "%Rsp@-");
2116 else if (letter
== '+')
2119 asm_fprintf (file
, "(%Rsp)+");
2121 asm_fprintf (file
, "%Rsp@+");
2124 else if (letter
== '@')
2127 asm_fprintf (file
, "(%Rsp)");
2129 asm_fprintf (file
, "%Rsp@");
2132 else if (letter
== '!')
2134 asm_fprintf (file
, "%Rfpcr");
2136 else if (letter
== '$')
2138 if (TARGET_68040_ONLY
)
2140 fprintf (file
, "s");
2143 else if (letter
== '&')
2145 if (TARGET_68040_ONLY
)
2147 fprintf (file
, "d");
2150 else if (letter
== '/')
2152 asm_fprintf (file
, "%R");
2154 else if (GET_CODE (op
) == REG
)
2156 #ifdef SUPPORT_SUN_FPA
2158 && (letter
== 'y' || letter
== 'x')
2159 && GET_MODE (op
) == DFmode
)
2161 fprintf (file
, "%s:%s", reg_names
[REGNO (op
)],
2162 reg_names
[REGNO (op
)+1]);
2168 /* Print out the second register name of a register pair.
2169 I.e., R (6) => 7. */
2170 fputs (reg_names
[REGNO (op
) + 1], file
);
2172 fputs (reg_names
[REGNO (op
)], file
);
2175 else if (GET_CODE (op
) == MEM
)
2177 output_address (XEXP (op
, 0));
2178 if (letter
== 'd' && ! TARGET_68020
2179 && CONSTANT_ADDRESS_P (XEXP (op
, 0))
2180 && !(GET_CODE (XEXP (op
, 0)) == CONST_INT
2181 && INTVAL (XEXP (op
, 0)) < 0x8000
2182 && INTVAL (XEXP (op
, 0)) >= -0x8000))
2185 fprintf (file
, ".l");
2187 fprintf (file
, ":l");
2191 #ifdef SUPPORT_SUN_FPA
2192 else if ((letter
== 'y' || letter
== 'w')
2193 && GET_CODE (op
) == CONST_DOUBLE
2194 && (i
= standard_sun_fpa_constant_p (op
)))
2196 fprintf (file
, "%%%d", i
& 0x1ff);
2199 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == SFmode
)
2202 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2203 ASM_OUTPUT_FLOAT_OPERAND (letter
, file
, r
);
2205 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == XFmode
)
2208 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2209 ASM_OUTPUT_LONG_DOUBLE_OPERAND (file
, r
);
2211 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == DFmode
)
2214 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2215 ASM_OUTPUT_DOUBLE_OPERAND (file
, r
);
2219 asm_fprintf (file
, "%0I"); output_addr_const (file
, op
);
2224 /* A C compound statement to output to stdio stream STREAM the
2225 assembler syntax for an instruction operand that is a memory
2226 reference whose address is ADDR. ADDR is an RTL expression.
2228 Note that this contains a kludge that knows that the only reason
2229 we have an address (plus (label_ref...) (reg...)) when not generating
2230 PIC code is in the insn before a tablejump, and we know that m68k.md
2231 generates a label LInnn: on such an insn.
2233 It is possible for PIC to generate a (plus (label_ref...) (reg...))
2234 and we handle that just like we would a (plus (symbol_ref...) (reg...)).
2236 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
2237 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
2238 we want. This difference can be accommodated by using an assembler
2239 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
2240 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
2241 macro. See m68k/sgs.h for an example; for versions without the bug.
2242 Some assemblers refuse all the above solutions. The workaround is to
2243 emit "K(pc,d0.l*2)" with K being a small constant known to give the
2246 They also do not like things like "pea 1.w", so we simple leave off
2247 the .w on small constants.
2249 This routine is responsible for distinguishing between -fpic and -fPIC
2250 style relocations in an address. When generating -fpic code the
2251 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating
2252 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
2254 #ifndef ASM_OUTPUT_CASE_FETCH
2257 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2258 asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
2260 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2261 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
2264 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2265 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
2267 #endif /* ASM_OUTPUT_CASE_FETCH */
2270 print_operand_address (file
, addr
)
2274 register rtx reg1
, reg2
, breg
, ireg
;
2277 switch (GET_CODE (addr
))
2281 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
2283 fprintf (file
, "%s@", reg_names
[REGNO (addr
)]);
2288 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
2290 fprintf (file
, "%s@-", reg_names
[REGNO (XEXP (addr
, 0))]);
2295 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
2297 fprintf (file
, "%s@+", reg_names
[REGNO (XEXP (addr
, 0))]);
2301 reg1
= reg2
= ireg
= breg
= offset
= 0;
2302 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0)))
2304 offset
= XEXP (addr
, 0);
2305 addr
= XEXP (addr
, 1);
2307 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1)))
2309 offset
= XEXP (addr
, 1);
2310 addr
= XEXP (addr
, 0);
2312 if (GET_CODE (addr
) != PLUS
)
2316 else if (GET_CODE (XEXP (addr
, 0)) == SIGN_EXTEND
)
2318 reg1
= XEXP (addr
, 0);
2319 addr
= XEXP (addr
, 1);
2321 else if (GET_CODE (XEXP (addr
, 1)) == SIGN_EXTEND
)
2323 reg1
= XEXP (addr
, 1);
2324 addr
= XEXP (addr
, 0);
2326 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
2328 reg1
= XEXP (addr
, 0);
2329 addr
= XEXP (addr
, 1);
2331 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
2333 reg1
= XEXP (addr
, 1);
2334 addr
= XEXP (addr
, 0);
2336 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
2338 reg1
= XEXP (addr
, 0);
2339 addr
= XEXP (addr
, 1);
2341 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
2343 reg1
= XEXP (addr
, 1);
2344 addr
= XEXP (addr
, 0);
2346 if (GET_CODE (addr
) == REG
|| GET_CODE (addr
) == MULT
2347 || GET_CODE (addr
) == SIGN_EXTEND
)
2359 #if 0 /* for OLD_INDEXING */
2360 else if (GET_CODE (addr
) == PLUS
)
2362 if (GET_CODE (XEXP (addr
, 0)) == REG
)
2364 reg2
= XEXP (addr
, 0);
2365 addr
= XEXP (addr
, 1);
2367 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
2369 reg2
= XEXP (addr
, 1);
2370 addr
= XEXP (addr
, 0);
2382 if ((reg1
&& (GET_CODE (reg1
) == SIGN_EXTEND
2383 || GET_CODE (reg1
) == MULT
))
2384 || (reg2
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2
))))
2389 else if (reg1
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1
)))
2394 if (ireg
!= 0 && breg
== 0 && GET_CODE (addr
) == LABEL_REF
2395 && ! (flag_pic
&& ireg
== pic_offset_table_rtx
))
2398 if (GET_CODE (ireg
) == MULT
)
2400 scale
= INTVAL (XEXP (ireg
, 1));
2401 ireg
= XEXP (ireg
, 0);
2403 if (GET_CODE (ireg
) == SIGN_EXTEND
)
2405 ASM_OUTPUT_CASE_FETCH (file
,
2406 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2407 reg_names
[REGNO (XEXP (ireg
, 0))]);
2408 fprintf (file
, "w");
2412 ASM_OUTPUT_CASE_FETCH (file
,
2413 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2414 reg_names
[REGNO (ireg
)]);
2415 fprintf (file
, "l");
2420 fprintf (file
, "*%d", scale
);
2422 fprintf (file
, ":%d", scale
);
2428 if (breg
!= 0 && ireg
== 0 && GET_CODE (addr
) == LABEL_REF
2429 && ! (flag_pic
&& breg
== pic_offset_table_rtx
))
2431 ASM_OUTPUT_CASE_FETCH (file
,
2432 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2433 reg_names
[REGNO (breg
)]);
2434 fprintf (file
, "l)");
2437 if (ireg
!= 0 || breg
!= 0)
2444 if (! flag_pic
&& addr
&& GET_CODE (addr
) == LABEL_REF
)
2451 output_addr_const (file
, addr
);
2452 if (flag_pic
&& (breg
== pic_offset_table_rtx
))
2453 fprintf (file
, "@GOT");
2455 fprintf (file
, "(%s", reg_names
[REGNO (breg
)]);
2461 fprintf (file
, "%s@(", reg_names
[REGNO (breg
)]);
2464 output_addr_const (file
, addr
);
2465 if ((flag_pic
== 1) && (breg
== pic_offset_table_rtx
))
2466 fprintf (file
, ":w");
2467 if ((flag_pic
== 2) && (breg
== pic_offset_table_rtx
))
2468 fprintf (file
, ":l");
2470 if (addr
!= 0 && ireg
!= 0)
2475 if (ireg
!= 0 && GET_CODE (ireg
) == MULT
)
2477 scale
= INTVAL (XEXP (ireg
, 1));
2478 ireg
= XEXP (ireg
, 0);
2480 if (ireg
!= 0 && GET_CODE (ireg
) == SIGN_EXTEND
)
2483 fprintf (file
, "%s.w", reg_names
[REGNO (XEXP (ireg
, 0))]);
2485 fprintf (file
, "%s:w", reg_names
[REGNO (XEXP (ireg
, 0))]);
2491 fprintf (file
, "%s.l", reg_names
[REGNO (ireg
)]);
2493 fprintf (file
, "%s:l", reg_names
[REGNO (ireg
)]);
2499 fprintf (file
, "*%d", scale
);
2501 fprintf (file
, ":%d", scale
);
2507 else if (reg1
!= 0 && GET_CODE (addr
) == LABEL_REF
2508 && ! (flag_pic
&& reg1
== pic_offset_table_rtx
))
2510 ASM_OUTPUT_CASE_FETCH (file
,
2511 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2512 reg_names
[REGNO (reg1
)]);
2513 fprintf (file
, "l)");
2516 /* FALL-THROUGH (is this really what we want? */
2518 if (GET_CODE (addr
) == CONST_INT
2519 && INTVAL (addr
) < 0x8000
2520 && INTVAL (addr
) >= -0x8000)
2524 /* Many SGS assemblers croak on size specifiers for constants. */
2525 fprintf (file
, "%d", INTVAL (addr
));
2527 fprintf (file
, "%d.w", INTVAL (addr
));
2530 fprintf (file
, "%d:w", INTVAL (addr
));
2535 output_addr_const (file
, addr
);
2541 /* Check for cases where a clr insns can be omitted from code using
2542 strict_low_part sets. For example, the second clrl here is not needed:
2543 clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
2545 MODE is the mode of this STRICT_LOW_PART set. FIRST_INSN is the clear
2546 insn we are checking for redundancy. TARGET is the register set by the
2550 strict_low_part_peephole_ok (mode
, first_insn
, target
)
2551 enum machine_mode mode
;
2557 p
= prev_nonnote_insn (first_insn
);
2561 /* If it isn't an insn, then give up. */
2562 if (GET_CODE (p
) != INSN
)
2565 if (reg_set_p (target
, p
))
2567 rtx set
= single_set (p
);
2570 /* If it isn't an easy to recognize insn, then give up. */
2574 dest
= SET_DEST (set
);
2576 /* If this sets the entire target register to zero, then our
2577 first_insn is redundant. */
2578 if (rtx_equal_p (dest
, target
)
2579 && SET_SRC (set
) == const0_rtx
)
2581 else if (GET_CODE (dest
) == STRICT_LOW_PART
2582 && GET_CODE (XEXP (dest
, 0)) == REG
2583 && REGNO (XEXP (dest
, 0)) == REGNO (target
)
2584 && (GET_MODE_SIZE (GET_MODE (XEXP (dest
, 0)))
2585 <= GET_MODE_SIZE (mode
)))
2586 /* This is a strict low part set which modifies less than
2587 we are using, so it is safe. */
2593 p
= prev_nonnote_insn (p
);
2600 /* Accept integer operands in the range 0..0xffffffff. We have to check the
2601 range carefully since this predicate is used in DImode contexts. Also, we
2602 need some extra crud to make it work when hosted on 64-bit machines. */
2605 const_uint32_operand (op
, mode
)
2607 enum machine_mode mode
;
2609 #if HOST_BITS_PER_WIDE_INT > 32
2610 /* All allowed constants will fit a CONST_INT. */
2611 return (GET_CODE (op
) == CONST_INT
2612 && (INTVAL (op
) >= 0 && INTVAL (op
) <= 0xffffffffL
));
2614 return ((GET_CODE (op
) == CONST_INT
&& INTVAL (op
) >= 0)
2615 || (GET_CODE (op
) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (op
) == 0));
2619 /* Accept integer operands in the range -0x80000000..0x7fffffff. We have
2620 to check the range carefully since this predicate is used in DImode
2624 const_sint32_operand (op
, mode
)
2626 enum machine_mode mode
;
2628 /* All allowed constants will fit a CONST_INT. */
2629 return (GET_CODE (op
) == CONST_INT
2630 && (INTVAL (op
) >= (-0x7fffffff - 1) && INTVAL (op
) <= 0x7fffffff));