1 /* Subroutines for insn-output.c for Motorola 68000 family.
2 Copyright (C) 1987, 1993, 1994, 1995 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
22 /* Some output-actions in m68k.md need these. */
27 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "insn-flags.h"
33 #include "insn-attr.h"
35 /* Needed for use_return_insn. */
38 #ifdef SUPPORT_SUN_FPA
40 /* Index into this array by (register number >> 3) to find the
41 smallest class which contains that register. */
42 enum reg_class regno_reg_class
[]
43 = { DATA_REGS
, ADDR_REGS
, FP_REGS
,
44 LO_FPA_REGS
, LO_FPA_REGS
, FPA_REGS
, FPA_REGS
};
46 #endif /* defined SUPPORT_SUN_FPA */
48 /* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
49 if SGS_SWITCH_TABLE. */
50 int switch_table_difference_label_flag
;
52 static rtx
find_addr_reg ();
53 rtx
legitimize_pic_address ();
56 /* Emit a (use pic_offset_table_rtx) if we used PIC relocation in the
57 function at any time during the compilation process. In the future
58 we should try and eliminate the USE if we can easily determine that
59 all PIC references were deleted from the current function. That would
60 save an address register */
65 if (flag_pic
&& current_function_uses_pic_offset_table
)
67 rtx insn
= gen_rtx (USE
, VOIDmode
, pic_offset_table_rtx
);
68 emit_insn_after (insn
, get_insns ());
74 /* This function generates the assembly code for function entry.
75 STREAM is a stdio stream to output the code to.
76 SIZE is an int: how many units of temporary storage to allocate.
77 Refer to the array `regs_ever_live' to determine which registers
78 to save; `regs_ever_live[I]' is nonzero if register number I
79 is ever used in the function. This function is responsible for
80 knowing which registers should not be saved even if used. */
83 /* Note that the order of the bit mask for fmovem is the opposite
84 of the order for movem! */
88 output_function_prologue (stream
, size
)
93 register int mask
= 0;
94 int num_saved_regs
= 0;
95 extern char call_used_regs
[];
96 int fsize
= (size
+ 3) & -4;
99 if (frame_pointer_needed
)
101 if (fsize
== 0 && TARGET_68040
)
103 /* on the 68040, pea + move is faster than link.w 0 */
105 asm_fprintf (stream
, "\tpea (%s)\n\tmove.l %s,%s\n",
106 reg_names
[FRAME_POINTER_REGNUM
], reg_names
[STACK_POINTER_REGNUM
],
107 reg_names
[FRAME_POINTER_REGNUM
]);
109 asm_fprintf (stream
, "\tpea %s@\n\tmovel %s,%s\n",
110 reg_names
[FRAME_POINTER_REGNUM
], reg_names
[STACK_POINTER_REGNUM
],
111 reg_names
[FRAME_POINTER_REGNUM
]);
114 else if (fsize
< 0x8000)
117 asm_fprintf (stream
, "\tlink.w %s,%0I%d\n",
118 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
120 asm_fprintf (stream
, "\tlink %s,%0I%d\n",
121 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
124 else if (TARGET_68020
)
127 asm_fprintf (stream
, "\tlink.l %s,%0I%d\n",
128 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
130 asm_fprintf (stream
, "\tlink %s,%0I%d\n",
131 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
136 /* Adding negative number is faster on the 68040. */
138 asm_fprintf (stream
, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
139 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
141 asm_fprintf (stream
, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
142 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
148 /* Adding negative number is faster on the 68040. */
149 if (fsize
+ 4 < 0x8000)
151 /* asm_fprintf() cannot handle %. */
153 asm_fprintf (stream
, "\tadd.w %0I%d,%Rsp\n", - (fsize
+ 4));
155 asm_fprintf (stream
, "\taddw %0I%d,%Rsp\n", - (fsize
+ 4));
160 /* asm_fprintf() cannot handle %. */
162 asm_fprintf (stream
, "\tadd.l %0I%d,%Rsp\n", - (fsize
+ 4));
164 asm_fprintf (stream
, "\taddl %0I%d,%Rsp\n", - (fsize
+ 4));
168 #ifdef SUPPORT_SUN_FPA
169 for (regno
= 24; regno
< 56; regno
++)
170 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
173 asm_fprintf (stream
, "\tfpmovd %s,-(%Rsp)\n",
176 asm_fprintf (stream
, "\tfpmoved %s,%Rsp@-\n",
181 for (regno
= 16; regno
< 24; regno
++)
182 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
183 mask
|= 1 << (regno
- 16);
184 if ((mask
& 0xff) != 0)
187 asm_fprintf (stream
, "\tfmovm %0I0x%x,-(%Rsp)\n", mask
& 0xff);
189 asm_fprintf (stream
, "\tfmovem %0I0x%x,%Rsp@-\n", mask
& 0xff);
193 for (regno
= 0; regno
< 16; regno
++)
194 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
196 mask
|= 1 << (15 - regno
);
199 if (frame_pointer_needed
)
201 mask
&= ~ (1 << (15 - FRAME_POINTER_REGNUM
));
206 fprintf (stream
, "\ttstl sp@(%d)\n", NEED_PROBE
- num_saved_regs
* 4);
209 if (num_saved_regs
<= 2)
211 /* Store each separately in the same order moveml uses.
212 Using two movel instructions instead of a single moveml
213 is about 15% faster for the 68020 and 68030 at no expense
218 /* Undo the work from above. */
219 for (i
= 0; i
< 16; i
++)
223 "\t%Omove.l %s,-(%Rsp)\n",
225 "\tmovel %s,%Rsp@-\n",
232 asm_fprintf (stream
, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask
);
234 asm_fprintf (stream
, "\tmoveml %0I0x%x,%Rsp@-\n", mask
);
237 if (flag_pic
&& current_function_uses_pic_offset_table
)
240 asm_fprintf (stream
, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
241 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
243 asm_fprintf (stream
, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
244 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
245 asm_fprintf (stream
, "\tlea %Rpc@(0,%s:l),%s\n",
246 reg_names
[PIC_OFFSET_TABLE_REGNUM
],
247 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
252 /* Return true if this function's epilogue can be output as RTL. */
259 if (!reload_completed
|| frame_pointer_needed
|| get_frame_size () != 0)
262 /* Copied from output_function_epilogue (). We should probably create a
263 separate layout routine to perform the common work. */
265 for (regno
= 0 ; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
266 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
272 /* This function generates the assembly code for function exit,
273 on machines that need it. Args are same as for FUNCTION_PROLOGUE.
275 The function epilogue should not depend on the current stack pointer!
276 It should use the frame pointer only, if there is a frame pointer.
277 This is mandatory because of alloca; we also take advantage of it to
278 omit stack adjustments before returning. */
281 output_function_epilogue (stream
, size
)
286 register int mask
, fmask
;
288 int offset
, foffset
, fpoffset
;
289 extern char call_used_regs
[];
290 int fsize
= (size
+ 3) & -4;
292 rtx insn
= get_last_insn ();
294 /* If the last insn was a BARRIER, we don't have to write any code. */
295 if (GET_CODE (insn
) == NOTE
)
296 insn
= prev_nonnote_insn (insn
);
297 if (insn
&& GET_CODE (insn
) == BARRIER
)
299 /* Output just a no-op so that debuggers don't get confused
300 about which function the pc is in at this address. */
301 asm_fprintf (stream
, "\tnop\n");
305 #ifdef FUNCTION_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))
2184 fprintf (file
, ":l");
2187 #ifdef SUPPORT_SUN_FPA
2188 else if ((letter
== 'y' || letter
== 'w')
2189 && GET_CODE (op
) == CONST_DOUBLE
2190 && (i
= standard_sun_fpa_constant_p (op
)))
2192 fprintf (file
, "%%%d", i
& 0x1ff);
2195 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == SFmode
)
2198 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2199 ASM_OUTPUT_FLOAT_OPERAND (letter
, file
, r
);
2201 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == XFmode
)
2204 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2205 ASM_OUTPUT_LONG_DOUBLE_OPERAND (file
, r
);
2207 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == DFmode
)
2210 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
2211 ASM_OUTPUT_DOUBLE_OPERAND (file
, r
);
2215 asm_fprintf (file
, "%0I"); output_addr_const (file
, op
);
2220 /* A C compound statement to output to stdio stream STREAM the
2221 assembler syntax for an instruction operand that is a memory
2222 reference whose address is ADDR. ADDR is an RTL expression.
2224 Note that this contains a kludge that knows that the only reason
2225 we have an address (plus (label_ref...) (reg...)) when not generating
2226 PIC code is in the insn before a tablejump, and we know that m68k.md
2227 generates a label LInnn: on such an insn.
2229 It is possible for PIC to generate a (plus (label_ref...) (reg...))
2230 and we handle that just like we would a (plus (symbol_ref...) (reg...)).
2232 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
2233 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
2234 we want. This difference can be accommodated by using an assembler
2235 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
2236 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
2237 macro. See m68k/sgs.h for an example; for versions without the bug.
2238 Some assemblers refuse all the above solutions. The workaround is to
2239 emit "K(pc,d0.l*2)" with K being a small constant known to give the
2242 They also do not like things like "pea 1.w", so we simple leave off
2243 the .w on small constants.
2245 This routine is responsible for distinguishing between -fpic and -fPIC
2246 style relocations in an address. When generating -fpic code the
2247 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating
2248 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
2250 #ifndef ASM_OUTPUT_CASE_FETCH
2253 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2254 asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
2256 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2257 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
2260 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2261 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
2263 #endif /* ASM_OUTPUT_CASE_FETCH */
2266 print_operand_address (file
, addr
)
2270 register rtx reg1
, reg2
, breg
, ireg
;
2273 switch (GET_CODE (addr
))
2277 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
2279 fprintf (file
, "%s@", reg_names
[REGNO (addr
)]);
2284 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
2286 fprintf (file
, "%s@-", reg_names
[REGNO (XEXP (addr
, 0))]);
2291 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
2293 fprintf (file
, "%s@+", reg_names
[REGNO (XEXP (addr
, 0))]);
2297 reg1
= reg2
= ireg
= breg
= offset
= 0;
2298 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0)))
2300 offset
= XEXP (addr
, 0);
2301 addr
= XEXP (addr
, 1);
2303 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1)))
2305 offset
= XEXP (addr
, 1);
2306 addr
= XEXP (addr
, 0);
2308 if (GET_CODE (addr
) != PLUS
)
2312 else if (GET_CODE (XEXP (addr
, 0)) == SIGN_EXTEND
)
2314 reg1
= XEXP (addr
, 0);
2315 addr
= XEXP (addr
, 1);
2317 else if (GET_CODE (XEXP (addr
, 1)) == SIGN_EXTEND
)
2319 reg1
= XEXP (addr
, 1);
2320 addr
= XEXP (addr
, 0);
2322 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
2324 reg1
= XEXP (addr
, 0);
2325 addr
= XEXP (addr
, 1);
2327 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
2329 reg1
= XEXP (addr
, 1);
2330 addr
= XEXP (addr
, 0);
2332 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
2334 reg1
= XEXP (addr
, 0);
2335 addr
= XEXP (addr
, 1);
2337 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
2339 reg1
= XEXP (addr
, 1);
2340 addr
= XEXP (addr
, 0);
2342 if (GET_CODE (addr
) == REG
|| GET_CODE (addr
) == MULT
2343 || GET_CODE (addr
) == SIGN_EXTEND
)
2355 #if 0 /* for OLD_INDEXING */
2356 else if (GET_CODE (addr
) == PLUS
)
2358 if (GET_CODE (XEXP (addr
, 0)) == REG
)
2360 reg2
= XEXP (addr
, 0);
2361 addr
= XEXP (addr
, 1);
2363 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
2365 reg2
= XEXP (addr
, 1);
2366 addr
= XEXP (addr
, 0);
2378 if ((reg1
&& (GET_CODE (reg1
) == SIGN_EXTEND
2379 || GET_CODE (reg1
) == MULT
))
2380 || (reg2
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2
))))
2385 else if (reg1
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1
)))
2390 if (ireg
!= 0 && breg
== 0 && GET_CODE (addr
) == LABEL_REF
2391 && ! (flag_pic
&& ireg
== pic_offset_table_rtx
))
2394 if (GET_CODE (ireg
) == MULT
)
2396 scale
= INTVAL (XEXP (ireg
, 1));
2397 ireg
= XEXP (ireg
, 0);
2399 if (GET_CODE (ireg
) == SIGN_EXTEND
)
2401 ASM_OUTPUT_CASE_FETCH (file
,
2402 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2403 reg_names
[REGNO (XEXP (ireg
, 0))]);
2404 fprintf (file
, "w");
2408 ASM_OUTPUT_CASE_FETCH (file
,
2409 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2410 reg_names
[REGNO (ireg
)]);
2411 fprintf (file
, "l");
2416 fprintf (file
, "*%d", scale
);
2418 fprintf (file
, ":%d", scale
);
2424 if (breg
!= 0 && ireg
== 0 && GET_CODE (addr
) == LABEL_REF
2425 && ! (flag_pic
&& breg
== pic_offset_table_rtx
))
2427 ASM_OUTPUT_CASE_FETCH (file
,
2428 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2429 reg_names
[REGNO (breg
)]);
2430 fprintf (file
, "l)");
2433 if (ireg
!= 0 || breg
!= 0)
2440 if (! flag_pic
&& addr
&& GET_CODE (addr
) == LABEL_REF
)
2447 output_addr_const (file
, addr
);
2448 if (flag_pic
&& (breg
== pic_offset_table_rtx
))
2449 fprintf (file
, "@GOT");
2451 fprintf (file
, "(%s", reg_names
[REGNO (breg
)]);
2457 fprintf (file
, "%s@(", reg_names
[REGNO (breg
)]);
2460 output_addr_const (file
, addr
);
2461 if ((flag_pic
== 1) && (breg
== pic_offset_table_rtx
))
2462 fprintf (file
, ":w");
2463 if ((flag_pic
== 2) && (breg
== pic_offset_table_rtx
))
2464 fprintf (file
, ":l");
2466 if (addr
!= 0 && ireg
!= 0)
2471 if (ireg
!= 0 && GET_CODE (ireg
) == MULT
)
2473 scale
= INTVAL (XEXP (ireg
, 1));
2474 ireg
= XEXP (ireg
, 0);
2476 if (ireg
!= 0 && GET_CODE (ireg
) == SIGN_EXTEND
)
2479 fprintf (file
, "%s.w", reg_names
[REGNO (XEXP (ireg
, 0))]);
2481 fprintf (file
, "%s:w", reg_names
[REGNO (XEXP (ireg
, 0))]);
2487 fprintf (file
, "%s.l", reg_names
[REGNO (ireg
)]);
2489 fprintf (file
, "%s:l", reg_names
[REGNO (ireg
)]);
2495 fprintf (file
, "*%d", scale
);
2497 fprintf (file
, ":%d", scale
);
2503 else if (reg1
!= 0 && GET_CODE (addr
) == LABEL_REF
2504 && ! (flag_pic
&& reg1
== pic_offset_table_rtx
))
2506 ASM_OUTPUT_CASE_FETCH (file
,
2507 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2508 reg_names
[REGNO (reg1
)]);
2509 fprintf (file
, "l)");
2512 /* FALL-THROUGH (is this really what we want? */
2514 if (GET_CODE (addr
) == CONST_INT
2515 && INTVAL (addr
) < 0x8000
2516 && INTVAL (addr
) >= -0x8000)
2520 /* Many SGS assemblers croak on size specifiers for constants. */
2521 fprintf (file
, "%d", INTVAL (addr
));
2523 fprintf (file
, "%d.w", INTVAL (addr
));
2526 fprintf (file
, "%d:w", INTVAL (addr
));
2531 output_addr_const (file
, addr
);
2537 /* Check for cases where a clr insns can be omitted from code using
2538 strict_low_part sets. For example, the second clrl here is not needed:
2539 clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
2541 MODE is the mode of this STRICT_LOW_PART set. FIRST_INSN is the clear
2542 insn we are checking for redundancy. TARGET is the register set by the
2546 strict_low_part_peephole_ok (mode
, first_insn
, target
)
2547 enum machine_mode mode
;
2553 p
= prev_nonnote_insn (first_insn
);
2557 /* If it isn't an insn, then give up. */
2558 if (GET_CODE (p
) != INSN
)
2561 if (reg_set_p (target
, p
))
2563 rtx set
= single_set (p
);
2566 /* If it isn't an easy to recognize insn, then give up. */
2570 dest
= SET_DEST (set
);
2572 /* If this sets the entire target register to zero, then our
2573 first_insn is redundant. */
2574 if (rtx_equal_p (dest
, target
)
2575 && SET_SRC (set
) == const0_rtx
)
2577 else if (GET_CODE (dest
) == STRICT_LOW_PART
2578 && GET_CODE (XEXP (dest
, 0)) == REG
2579 && REGNO (XEXP (dest
, 0)) == REGNO (target
)
2580 && (GET_MODE_SIZE (GET_MODE (XEXP (dest
, 0)))
2581 <= GET_MODE_SIZE (mode
)))
2582 /* This is a strict low part set which modifies less than
2583 we are using, so it is safe. */
2589 p
= prev_nonnote_insn (p
);
2596 /* Accept integer operands in the range 0..0xffffffff. We have to check the
2597 range carefully since this predicate is used in DImode contexts. Also, we
2598 need some extra crud to make it work when hosted on 64-bit machines. */
2601 const_uint32_operand (op
, mode
)
2603 enum machine_mode mode
;
2605 #if HOST_BITS_PER_WIDE_INT > 32
2606 /* All allowed constants will fit a CONST_INT. */
2607 return (GET_CODE (op
) == CONST_INT
2608 && (INTVAL (op
) >= 0 && INTVAL (op
) <= 0xffffffffL
));
2610 return ((GET_CODE (op
) == CONST_INT
&& INTVAL (op
) >= 0)
2611 || (GET_CODE (op
) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (op
) == 0));
2615 /* Accept integer operands in the range -0x80000000..0x7fffffff. We have
2616 to check the range carefully since this predicate is used in DImode
2620 const_sint32_operand (op
, mode
)
2622 enum machine_mode mode
;
2624 /* All allowed constants will fit a CONST_INT. */
2625 return (GET_CODE (op
) == CONST_INT
2626 && (INTVAL (op
) >= (-0x7fffffff - 1) && INTVAL (op
) <= 0x7fffffff));