1 /* Subroutines used for code generation on the DEC Alpha.
2 Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
3 Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
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"
41 /* Specify which cpu to schedule for. */
42 enum processor_type alpha_cpu
;
44 /* Specify how accurate floating-point traps need to be. */
46 enum alpha_trap_precision alpha_tp
;
48 /* Specify the floating-point rounding mode. */
50 enum alpha_fp_rounding_mode alpha_fprm
;
52 /* Specify which things cause traps. */
54 enum alpha_fp_trap_mode alpha_fptm
;
56 /* Strings decoded into the above options. */
57 char *alpha_cpu_string
; /* -mcpu=ev[4|5] */
58 char *alpha_tp_string
; /* -mtrap-precision=[p|s|i] */
59 char *alpha_fprm_string
; /* -mfp-rounding-mode=[n|m|c|d] */
60 char *alpha_fptm_string
; /* -mfp-trap-mode=[n|u|su|sui] */
62 /* Save information from a "cmpxx" operation until the branch or scc is
65 rtx alpha_compare_op0
, alpha_compare_op1
;
66 int alpha_compare_fp_p
;
68 /* Save the name of the current function as used by the assembler. This
69 is used by the epilogue. */
71 char *alpha_function_name
;
73 /* Non-zero if inside of a function, because the Alpha asm can't
74 handle .files inside of functions. */
76 static int inside_function
= FALSE
;
78 /* Non-zero if an instruction that may cause a trap is pending. */
80 static int trap_pending
= 0;
82 /* Nonzero if the current function needs gp. */
84 int alpha_function_needs_gp
;
86 extern char *version_string
;
87 extern int rtx_equal_function_value_matters
;
89 /* Declarations of static functions. */
90 static void alpha_set_memflags_1
PROTO((rtx
, int, int, int));
91 static rtx alpha_emit_set_const_1
PROTO((rtx
, enum machine_mode
,
93 static void add_long_const
PROTO((FILE *, HOST_WIDE_INT
, int, int, int));
95 /* Parse target option strings. */
100 alpha_cpu
= PROCESSOR_EV4
;
102 if (alpha_cpu_string
)
104 if (! strcmp (alpha_cpu_string
, "ev4")
105 || ! strcmp (alpha_cpu_string
, "21064"))
106 alpha_cpu
= PROCESSOR_EV4
;
107 else if (! strcmp (alpha_cpu_string
, "ev5")
108 || ! strcmp (alpha_cpu_string
, "21164"))
109 alpha_cpu
= PROCESSOR_EV5
;
111 error ("bad value `%s' for -mcpu switch", alpha_cpu_string
);
114 alpha_tp
= ALPHA_TP_PROG
;
115 alpha_fprm
= ALPHA_FPRM_NORM
;
116 alpha_fptm
= ALPHA_FPTM_N
;
120 alpha_tp
= ALPHA_TP_INSN
;
121 alpha_fptm
= ALPHA_FPTM_SU
;
124 if (TARGET_IEEE_WITH_INEXACT
)
126 alpha_tp
= ALPHA_TP_INSN
;
127 alpha_fptm
= ALPHA_FPTM_SUI
;
132 if (! strcmp (alpha_tp_string
, "p"))
133 alpha_tp
= ALPHA_TP_PROG
;
134 else if (! strcmp (alpha_tp_string
, "f"))
135 alpha_tp
= ALPHA_TP_FUNC
;
136 else if (! strcmp (alpha_tp_string
, "i"))
137 alpha_tp
= ALPHA_TP_INSN
;
139 error ("bad value `%s' for -mtrap-precision switch", alpha_tp_string
);
142 if (alpha_fprm_string
)
144 if (! strcmp (alpha_fprm_string
, "n"))
145 alpha_fprm
= ALPHA_FPRM_NORM
;
146 else if (! strcmp (alpha_fprm_string
, "m"))
147 alpha_fprm
= ALPHA_FPRM_MINF
;
148 else if (! strcmp (alpha_fprm_string
, "c"))
149 alpha_fprm
= ALPHA_FPRM_CHOP
;
150 else if (! strcmp (alpha_fprm_string
,"d"))
151 alpha_fprm
= ALPHA_FPRM_DYN
;
153 error ("bad value `%s' for -mfp-rounding-mode switch",
157 if (alpha_fptm_string
)
159 if (strcmp (alpha_fptm_string
, "n") == 0)
160 alpha_fptm
= ALPHA_FPTM_N
;
161 else if (strcmp (alpha_fptm_string
, "u") == 0)
162 alpha_fptm
= ALPHA_FPTM_U
;
163 else if (strcmp (alpha_fptm_string
, "su") == 0)
164 alpha_fptm
= ALPHA_FPTM_SU
;
165 else if (strcmp (alpha_fptm_string
, "sui") == 0)
166 alpha_fptm
= ALPHA_FPTM_SUI
;
168 error ("bad value `%s' for -mfp-trap-mode switch", alpha_fptm_string
);
171 /* Do some sanity checks on the above option. */
173 if ((alpha_fptm
== ALPHA_FPTM_SU
|| alpha_fptm
== ALPHA_FPTM_SUI
)
174 && alpha_tp
!= ALPHA_TP_INSN
)
176 warning ("fp software completion requires -mtrap-precision=i");
177 alpha_tp
= ALPHA_TP_INSN
;
181 /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */
189 for (i
= 0; i
< HOST_BITS_PER_WIDE_INT
/ HOST_BITS_PER_CHAR
;
191 if ((value
& 0xff) != 0 && (value
& 0xff) != 0xff)
197 /* Returns 1 if OP is either the constant zero or a register. If a
198 register, it must be in the proper mode unless MODE is VOIDmode. */
201 reg_or_0_operand (op
, mode
)
203 enum machine_mode mode
;
205 return op
== const0_rtx
|| register_operand (op
, mode
);
208 /* Return 1 if OP is a constant in the range of 0-63 (for a shift) or
212 reg_or_6bit_operand (op
, mode
)
214 enum machine_mode mode
;
216 return ((GET_CODE (op
) == CONST_INT
217 && (unsigned HOST_WIDE_INT
) INTVAL (op
) < 64)
218 || register_operand (op
, mode
));
222 /* Return 1 if OP is an 8-bit constant or any register. */
225 reg_or_8bit_operand (op
, mode
)
227 enum machine_mode mode
;
229 return ((GET_CODE (op
) == CONST_INT
230 && (unsigned HOST_WIDE_INT
) INTVAL (op
) < 0x100)
231 || register_operand (op
, mode
));
234 /* Return 1 if OP is an 8-bit constant. */
237 cint8_operand (op
, mode
)
239 enum machine_mode mode
;
241 return (GET_CODE (op
) == CONST_INT
242 && (unsigned HOST_WIDE_INT
) INTVAL (op
) < 0x100);
245 /* Return 1 if the operand is a valid second operand to an add insn. */
248 add_operand (op
, mode
)
250 enum machine_mode mode
;
252 if (GET_CODE (op
) == CONST_INT
)
253 return (CONST_OK_FOR_LETTER_P (INTVAL (op
), 'K')
254 || CONST_OK_FOR_LETTER_P (INTVAL (op
), 'L')
255 || CONST_OK_FOR_LETTER_P (INTVAL (op
), 'O'));
257 return register_operand (op
, mode
);
260 /* Return 1 if the operand is a valid second operand to a sign-extending
264 sext_add_operand (op
, mode
)
266 enum machine_mode mode
;
268 if (GET_CODE (op
) == CONST_INT
)
269 return ((unsigned HOST_WIDE_INT
) INTVAL (op
) < 255
270 || (unsigned HOST_WIDE_INT
) (- INTVAL (op
)) < 255);
272 return register_operand (op
, mode
);
275 /* Return 1 if OP is the constant 4 or 8. */
278 const48_operand (op
, mode
)
280 enum machine_mode mode
;
282 return (GET_CODE (op
) == CONST_INT
283 && (INTVAL (op
) == 4 || INTVAL (op
) == 8));
286 /* Return 1 if OP is a valid first operand to an AND insn. */
289 and_operand (op
, mode
)
291 enum machine_mode mode
;
293 if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == VOIDmode
)
294 return (zap_mask (CONST_DOUBLE_LOW (op
))
295 && zap_mask (CONST_DOUBLE_HIGH (op
)));
297 if (GET_CODE (op
) == CONST_INT
)
298 return ((unsigned HOST_WIDE_INT
) INTVAL (op
) < 0x100
299 || (unsigned HOST_WIDE_INT
) ~ INTVAL (op
) < 0x100
300 || zap_mask (INTVAL (op
)));
302 return register_operand (op
, mode
);
305 /* Return 1 if OP is a valid first operand to an IOR or XOR insn. */
308 or_operand (op
, mode
)
310 enum machine_mode mode
;
312 if (GET_CODE (op
) == CONST_INT
)
313 return ((unsigned HOST_WIDE_INT
) INTVAL (op
) < 0x100
314 || (unsigned HOST_WIDE_INT
) ~ INTVAL (op
) < 0x100);
316 return register_operand (op
, mode
);
319 /* Return 1 if OP is a constant that is the width, in bits, of an integral
320 mode smaller than DImode. */
323 mode_width_operand (op
, mode
)
325 enum machine_mode mode
;
327 return (GET_CODE (op
) == CONST_INT
328 && (INTVAL (op
) == 8 || INTVAL (op
) == 16 || INTVAL (op
) == 32));
331 /* Return 1 if OP is a constant that is the width of an integral machine mode
332 smaller than an integer. */
335 mode_mask_operand (op
, mode
)
337 enum machine_mode mode
;
339 #if HOST_BITS_PER_WIDE_INT == 32
340 if (GET_CODE (op
) == CONST_DOUBLE
)
341 return CONST_DOUBLE_HIGH (op
) == 0 && CONST_DOUBLE_LOW (op
) == -1;
344 return (GET_CODE (op
) == CONST_INT
345 && (INTVAL (op
) == 0xff
346 || INTVAL (op
) == 0xffff
347 #if HOST_BITS_PER_WIDE_INT == 64
348 || INTVAL (op
) == 0xffffffff
353 /* Return 1 if OP is a multiple of 8 less than 64. */
356 mul8_operand (op
, mode
)
358 enum machine_mode mode
;
360 return (GET_CODE (op
) == CONST_INT
361 && (unsigned HOST_WIDE_INT
) INTVAL (op
) < 64
362 && (INTVAL (op
) & 7) == 0);
365 /* Return 1 if OP is the constant zero in floating-point. */
368 fp0_operand (op
, mode
)
370 enum machine_mode mode
;
372 return (GET_MODE (op
) == mode
373 && GET_MODE_CLASS (mode
) == MODE_FLOAT
&& op
== CONST0_RTX (mode
));
376 /* Return 1 if OP is the floating-point constant zero or a register. */
379 reg_or_fp0_operand (op
, mode
)
381 enum machine_mode mode
;
383 return fp0_operand (op
, mode
) || register_operand (op
, mode
);
386 /* Return 1 if OP is a register or a constant integer. */
390 reg_or_cint_operand (op
, mode
)
392 enum machine_mode mode
;
394 return GET_CODE (op
) == CONST_INT
|| register_operand (op
, mode
);
397 /* Return 1 if OP is something that can be reloaded into a register;
398 if it is a MEM, it need not be valid. */
401 some_operand (op
, mode
)
403 enum machine_mode mode
;
405 if (mode
!= VOIDmode
&& GET_MODE (op
) != VOIDmode
&& mode
!= GET_MODE (op
))
408 switch (GET_CODE (op
))
410 case REG
: case MEM
: case CONST_DOUBLE
:
411 case CONST_INT
: case LABEL_REF
: case SYMBOL_REF
: case CONST
:
415 return some_operand (SUBREG_REG (op
), VOIDmode
);
421 /* Return 1 if OP is a valid operand for the source of a move insn. */
424 input_operand (op
, mode
)
426 enum machine_mode mode
;
428 if (mode
!= VOIDmode
&& GET_MODE (op
) != VOIDmode
&& mode
!= GET_MODE (op
))
431 if (GET_MODE_CLASS (mode
) == MODE_FLOAT
&& GET_MODE (op
) != mode
)
434 switch (GET_CODE (op
))
439 /* This handles both the Windows/NT and OSF cases. */
440 return mode
== ptr_mode
|| mode
== DImode
;
446 if (register_operand (op
, mode
))
448 /* ... fall through ... */
450 return (TARGET_BYTE_OPS
|| (mode
!= HImode
&& mode
!= QImode
)
451 && general_operand (op
, mode
));
454 return GET_MODE_CLASS (mode
) == MODE_FLOAT
&& op
== CONST0_RTX (mode
);
457 return mode
== QImode
|| mode
== HImode
|| add_operand (op
, mode
);
463 /* Return 1 if OP is a SYMBOL_REF for a function known to be in this
467 current_file_function_operand (op
, mode
)
469 enum machine_mode mode
;
471 return (GET_CODE (op
) == SYMBOL_REF
472 && ! profile_flag
&& ! profile_block_flag
473 && (SYMBOL_REF_FLAG (op
)
474 || op
== XEXP (DECL_RTL (current_function_decl
), 0)));
477 /* Return 1 if OP is a valid operand for the MEM of a CALL insn. */
480 call_operand (op
, mode
)
482 enum machine_mode mode
;
487 return (GET_CODE (op
) == SYMBOL_REF
488 || (GET_CODE (op
) == REG
&& REGNO (op
) == 27));
491 /* Return 1 if OP is a valid Alpha comparison operator. Here we know which
492 comparisons are valid in which insn. */
495 alpha_comparison_operator (op
, mode
)
497 enum machine_mode mode
;
499 enum rtx_code code
= GET_CODE (op
);
501 if (mode
!= GET_MODE (op
) || GET_RTX_CLASS (code
) != '<')
504 return (code
== EQ
|| code
== LE
|| code
== LT
505 || (mode
== DImode
&& (code
== LEU
|| code
== LTU
)));
508 /* Return 1 if OP is a valid Alpha swapped comparison operator. */
511 alpha_swapped_comparison_operator (op
, mode
)
513 enum machine_mode mode
;
515 enum rtx_code code
= GET_CODE (op
);
517 if (mode
!= GET_MODE (op
) || GET_RTX_CLASS (code
) != '<')
520 code
= swap_condition (code
);
521 return (code
== EQ
|| code
== LE
|| code
== LT
522 || (mode
== DImode
&& (code
== LEU
|| code
== LTU
)));
525 /* Return 1 if OP is a signed comparison operation. */
528 signed_comparison_operator (op
, mode
)
530 enum machine_mode mode
;
532 switch (GET_CODE (op
))
534 case EQ
: case NE
: case LE
: case LT
: case GE
: case GT
:
541 /* Return 1 if this is a divide or modulus operator. */
544 divmod_operator (op
, mode
)
546 enum machine_mode mode
;
548 switch (GET_CODE (op
))
550 case DIV
: case MOD
: case UDIV
: case UMOD
:
557 /* Return 1 if this memory address is a known aligned register plus
558 a constant. It must be a valid address. This means that we can do
559 this as an aligned reference plus some offset.
561 Take into account what reload will do.
563 We could say that out-of-range stack slots are alignable, but that would
564 complicate get_aligned_mem and it isn't worth the trouble since few
565 functions have large stack space. */
568 aligned_memory_operand (op
, mode
)
570 enum machine_mode mode
;
572 if (GET_CODE (op
) == SUBREG
)
574 if (GET_MODE (op
) != mode
)
576 op
= SUBREG_REG (op
);
577 mode
= GET_MODE (op
);
580 if (reload_in_progress
&& GET_CODE (op
) == REG
581 && REGNO (op
) >= FIRST_PSEUDO_REGISTER
)
582 op
= reg_equiv_mem
[REGNO (op
)];
584 if (GET_CODE (op
) != MEM
|| GET_MODE (op
) != mode
585 || ! memory_address_p (mode
, XEXP (op
, 0)))
590 if (GET_CODE (op
) == PLUS
)
593 return (GET_CODE (op
) == REG
594 && REGNO_POINTER_ALIGN (REGNO (op
)) >= 4);
597 /* Similar, but return 1 if OP is a MEM which is not alignable. */
600 unaligned_memory_operand (op
, mode
)
602 enum machine_mode mode
;
604 if (GET_CODE (op
) == SUBREG
)
606 if (GET_MODE (op
) != mode
)
608 op
= SUBREG_REG (op
);
609 mode
= GET_MODE (op
);
612 if (reload_in_progress
&& GET_CODE (op
) == REG
613 && REGNO (op
) >= FIRST_PSEUDO_REGISTER
)
614 op
= reg_equiv_mem
[REGNO (op
)];
616 if (GET_CODE (op
) != MEM
|| GET_MODE (op
) != mode
)
621 if (! memory_address_p (mode
, op
))
624 if (GET_CODE (op
) == PLUS
)
627 return (GET_CODE (op
) != REG
628 || REGNO_POINTER_ALIGN (REGNO (op
)) < 4);
631 /* Return 1 if OP is either a register or an unaligned memory location. */
634 reg_or_unaligned_mem_operand (op
, mode
)
636 enum machine_mode mode
;
638 return register_operand (op
, mode
) || unaligned_memory_operand (op
, mode
);
641 /* Return 1 if OP is any memory location. During reload a pseudo matches. */
644 any_memory_operand (op
, mode
)
646 enum machine_mode mode
;
648 return (GET_CODE (op
) == MEM
649 || (GET_CODE (op
) == SUBREG
&& GET_CODE (SUBREG_REG (op
)) == REG
)
650 || (reload_in_progress
&& GET_CODE (op
) == REG
651 && REGNO (op
) >= FIRST_PSEUDO_REGISTER
)
652 || (reload_in_progress
&& GET_CODE (op
) == SUBREG
653 && GET_CODE (SUBREG_REG (op
)) == REG
654 && REGNO (SUBREG_REG (op
)) >= FIRST_PSEUDO_REGISTER
));
657 /* REF is an alignable memory location. Place an aligned SImode
658 reference into *PALIGNED_MEM and the number of bits to shift into
662 get_aligned_mem (ref
, paligned_mem
, pbitnum
)
664 rtx
*paligned_mem
, *pbitnum
;
667 HOST_WIDE_INT offset
= 0;
669 if (GET_CODE (ref
) == SUBREG
)
671 offset
= SUBREG_WORD (ref
) * UNITS_PER_WORD
;
672 if (BYTES_BIG_ENDIAN
)
673 offset
-= (MIN (UNITS_PER_WORD
, GET_MODE_SIZE (GET_MODE (ref
)))
674 - MIN (UNITS_PER_WORD
,
675 GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref
)))));
676 ref
= SUBREG_REG (ref
);
679 if (GET_CODE (ref
) == REG
)
680 ref
= reg_equiv_mem
[REGNO (ref
)];
682 if (reload_in_progress
)
683 base
= find_replacement (&XEXP (ref
, 0));
685 base
= XEXP (ref
, 0);
687 if (GET_CODE (base
) == PLUS
)
688 offset
+= INTVAL (XEXP (base
, 1)), base
= XEXP (base
, 0);
690 *paligned_mem
= gen_rtx (MEM
, SImode
,
691 plus_constant (base
, offset
& ~3));
692 MEM_IN_STRUCT_P (*paligned_mem
) = MEM_IN_STRUCT_P (ref
);
693 MEM_VOLATILE_P (*paligned_mem
) = MEM_VOLATILE_P (ref
);
694 RTX_UNCHANGING_P (*paligned_mem
) = RTX_UNCHANGING_P (ref
);
696 *pbitnum
= GEN_INT ((offset
& 3) * 8);
699 /* Similar, but just get the address. Handle the two reload cases.
700 Add EXTRA_OFFSET to the address we return. */
703 get_unaligned_address (ref
, extra_offset
)
708 HOST_WIDE_INT offset
= 0;
710 if (GET_CODE (ref
) == SUBREG
)
712 offset
= SUBREG_WORD (ref
) * UNITS_PER_WORD
;
713 if (BYTES_BIG_ENDIAN
)
714 offset
-= (MIN (UNITS_PER_WORD
, GET_MODE_SIZE (GET_MODE (ref
)))
715 - MIN (UNITS_PER_WORD
,
716 GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref
)))));
717 ref
= SUBREG_REG (ref
);
720 if (GET_CODE (ref
) == REG
)
721 ref
= reg_equiv_mem
[REGNO (ref
)];
723 if (reload_in_progress
)
724 base
= find_replacement (&XEXP (ref
, 0));
726 base
= XEXP (ref
, 0);
728 if (GET_CODE (base
) == PLUS
)
729 offset
+= INTVAL (XEXP (base
, 1)), base
= XEXP (base
, 0);
731 return plus_constant (base
, offset
+ extra_offset
);
734 /* Subfunction of the following function. Update the flags of any MEM
735 found in part of X. */
738 alpha_set_memflags_1 (x
, in_struct_p
, volatile_p
, unchanging_p
)
740 int in_struct_p
, volatile_p
, unchanging_p
;
744 switch (GET_CODE (x
))
748 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
749 alpha_set_memflags_1 (XVECEXP (x
, 0, i
), in_struct_p
, volatile_p
,
754 alpha_set_memflags_1 (PATTERN (x
), in_struct_p
, volatile_p
,
759 alpha_set_memflags_1 (SET_DEST (x
), in_struct_p
, volatile_p
,
761 alpha_set_memflags_1 (SET_SRC (x
), in_struct_p
, volatile_p
,
766 MEM_IN_STRUCT_P (x
) = in_struct_p
;
767 MEM_VOLATILE_P (x
) = volatile_p
;
768 RTX_UNCHANGING_P (x
) = unchanging_p
;
773 /* Given INSN, which is either an INSN or a SEQUENCE generated to
774 perform a memory operation, look for any MEMs in either a SET_DEST or
775 a SET_SRC and copy the in-struct, unchanging, and volatile flags from
776 REF into each of the MEMs found. If REF is not a MEM, don't do
780 alpha_set_memflags (insn
, ref
)
784 /* Note that it is always safe to get these flags, though they won't
785 be what we think if REF is not a MEM. */
786 int in_struct_p
= MEM_IN_STRUCT_P (ref
);
787 int volatile_p
= MEM_VOLATILE_P (ref
);
788 int unchanging_p
= RTX_UNCHANGING_P (ref
);
790 if (GET_CODE (ref
) != MEM
791 || (! in_struct_p
&& ! volatile_p
&& ! unchanging_p
))
794 alpha_set_memflags_1 (insn
, in_struct_p
, volatile_p
, unchanging_p
);
797 /* Try to output insns to set TARGET equal to the constant C if it can be
798 done in less than N insns. Do all computations in MODE. Returns the place
799 where the output has been placed if it can be done and the insns have been
800 emitted. If it would take more than N insns, zero is returned and no
801 insns and emitted. */
804 alpha_emit_set_const (target
, mode
, c
, n
)
806 enum machine_mode mode
;
813 /* Try 1 insn, then 2, then up to N. */
814 for (i
= 1; i
<= n
; i
++)
815 if ((pat
= alpha_emit_set_const_1 (target
, mode
, c
, i
)) != 0)
821 /* Internal routine for the above to check for N or below insns. */
824 alpha_emit_set_const_1 (target
, mode
, c
, n
)
826 enum machine_mode mode
;
830 HOST_WIDE_INT
new = c
;
832 /* Use a pseudo if highly optimizing and still generating RTL. */
834 = (flag_expensive_optimizations
&& rtx_equal_function_value_matters
838 #if HOST_BITS_PER_WIDE_INT == 64
839 /* We are only called for SImode and DImode. If this is SImode, ensure that
840 we are sign extended to a full word. This does not make any sense when
841 cross-compiling on a narrow machine. */
844 c
= (c
& 0xffffffff) - 2 * (c
& 0x80000000);
847 /* If this is a sign-extended 32-bit constant, we can do this in at most
848 three insns, so do it if we have enough insns left. We always have
849 a sign-extended 32-bit constant when compiling on a narrow machine.
850 Note that we cannot handle the constant 0x80000000. */
852 if ((HOST_BITS_PER_WIDE_INT
!= 64
853 || c
>> 31 == -1 || c
>> 31 == 0)
856 HOST_WIDE_INT low
= (c
& 0xffff) - 2 * (c
& 0x8000);
857 HOST_WIDE_INT tmp1
= c
- low
;
859 = ((tmp1
>> 16) & 0xffff) - 2 * ((tmp1
>> 16) & 0x8000);
860 HOST_WIDE_INT extra
= 0;
862 /* If HIGH will be interpreted as negative but the constant is
863 positive, we must adjust it to do two ldha insns. */
865 if ((high
& 0x8000) != 0 && c
>= 0)
869 high
= ((tmp1
>> 16) & 0xffff) - 2 * ((tmp1
>> 16) & 0x8000);
872 if (c
== low
|| (low
== 0 && extra
== 0))
873 return copy_to_suggested_reg (GEN_INT (c
), target
, mode
);
874 else if (n
>= 2 + (extra
!= 0))
876 temp
= copy_to_suggested_reg (GEN_INT (low
), subtarget
, mode
);
879 temp
= expand_binop (mode
, add_optab
, temp
, GEN_INT (extra
<< 16),
880 subtarget
, 0, OPTAB_WIDEN
);
882 return expand_binop (mode
, add_optab
, temp
, GEN_INT (high
<< 16),
883 target
, 0, OPTAB_WIDEN
);
887 /* If we couldn't do it that way, try some other methods. But if we have
888 no instructions left, don't bother. Likewise, if this is SImode and
889 we can't make pseudos, we can't do anything since the expand_binop
890 and expand_unop calls will widen and try to make pseudos. */
893 || (mode
== SImode
&& ! rtx_equal_function_value_matters
))
896 #if HOST_BITS_PER_WIDE_INT == 64
897 /* First, see if can load a value into the target that is the same as the
898 constant except that all bytes that are 0 are changed to be 0xff. If we
899 can, then we can do a ZAPNOT to obtain the desired constant. */
901 for (i
= 0; i
< 64; i
+= 8)
902 if ((new & ((HOST_WIDE_INT
) 0xff << i
)) == 0)
903 new |= (HOST_WIDE_INT
) 0xff << i
;
905 /* We are only called for SImode and DImode. If this is SImode, ensure that
906 we are sign extended to a full word. */
909 new = (new & 0xffffffff) - 2 * (new & 0x80000000);
912 && (temp
= alpha_emit_set_const (subtarget
, mode
, new, n
- 1)) != 0)
913 return expand_binop (mode
, and_optab
, temp
, GEN_INT (c
| ~ new),
914 target
, 0, OPTAB_WIDEN
);
917 /* Next, see if we can load a related constant and then shift and possibly
918 negate it to get the constant we want. Try this once each increasing
921 for (i
= 1; i
< n
; i
++)
923 /* First try complementing. */
924 if ((temp
= alpha_emit_set_const (subtarget
, mode
, ~ c
, i
)) != 0)
925 return expand_unop (mode
, one_cmpl_optab
, temp
, target
, 0);
927 /* Next try to form a constant and do a left shift. We can do this
928 if some low-order bits are zero; the exact_log2 call below tells
929 us that information. The bits we are shifting out could be any
930 value, but here we'll just try the 0- and sign-extended forms of
931 the constant. To try to increase the chance of having the same
932 constant in more than one insn, start at the highest number of
933 bits to shift, but try all possibilities in case a ZAPNOT will
936 if ((bits
= exact_log2 (c
& - c
)) > 0)
937 for (; bits
> 0; bits
--)
938 if ((temp
= (alpha_emit_set_const
940 (unsigned HOST_WIDE_INT
) c
>> bits
, i
))) != 0
941 || ((temp
= (alpha_emit_set_const
943 ((unsigned HOST_WIDE_INT
) c
) >> bits
, i
)))
945 return expand_binop (mode
, ashl_optab
, temp
, GEN_INT (bits
),
946 target
, 0, OPTAB_WIDEN
);
948 /* Now try high-order zero bits. Here we try the shifted-in bits as
949 all zero and all ones. Be careful to avoid shifting outside the
950 mode and to avoid shifting outside the host wide int size. */
952 if ((bits
= (MIN (HOST_BITS_PER_WIDE_INT
, GET_MODE_SIZE (mode
) * 8)
953 - floor_log2 (c
) - 1)) > 0)
954 for (; bits
> 0; bits
--)
955 if ((temp
= alpha_emit_set_const (subtarget
, mode
,
957 || ((temp
= (alpha_emit_set_const
959 ((c
<< bits
) | (((HOST_WIDE_INT
) 1 << bits
) - 1)),
962 return expand_binop (mode
, lshr_optab
, temp
, GEN_INT (bits
),
963 target
, 1, OPTAB_WIDEN
);
965 /* Now try high-order 1 bits. We get that with a sign-extension.
966 But one bit isn't enough here. Be careful to avoid shifting outside
967 the mode and to avoid shifting outside the host wide int size. */
969 if ((bits
= (MIN (HOST_BITS_PER_WIDE_INT
, GET_MODE_SIZE (mode
) * 8)
970 - floor_log2 (~ c
) - 2)) > 0)
971 for (; bits
> 0; bits
--)
972 if ((temp
= alpha_emit_set_const (subtarget
, mode
,
974 || ((temp
= (alpha_emit_set_const
976 ((c
<< bits
) | (((HOST_WIDE_INT
) 1 << bits
) - 1)),
979 return expand_binop (mode
, ashr_optab
, temp
, GEN_INT (bits
),
980 target
, 0, OPTAB_WIDEN
);
986 #if HOST_BITS_PER_WIDE_INT == 64
987 /* Having failed to find a 3 insn sequence in alpha_emit_set_const,
988 fall back to a straight forward decomposition. We do this to avoid
989 exponential run times encountered when looking for longer sequences
990 with alpha_emit_set_const. */
993 alpha_emit_set_long_const (target
, c
)
997 /* Use a pseudo if highly optimizing and still generating RTL. */
999 = (flag_expensive_optimizations
&& rtx_equal_function_value_matters
1001 HOST_WIDE_INT d1
, d2
, d3
, d4
;
1004 /* Decompose the entire word */
1005 d1
= ((c
& 0xffff) ^ 0x8000) - 0x8000;
1007 d2
= ((c
& 0xffffffff) ^ 0x80000000) - 0x80000000;
1009 d3
= ((c
& 0xffff) ^ 0x8000) - 0x8000;
1011 d4
= ((c
& 0xffffffff) ^ 0x80000000) - 0x80000000;
1016 /* Construct the high word */
1018 r1
= copy_to_suggested_reg (GEN_INT (d4
), subtarget
, DImode
);
1020 r1
= copy_to_suggested_reg (GEN_INT (d3
), subtarget
, DImode
);
1022 r1
= expand_binop (DImode
, add_optab
, GEN_INT (d3
), GEN_INT (d4
),
1023 subtarget
, 0, OPTAB_WIDEN
);
1025 /* Shift it into place */
1026 r2
= expand_binop (DImode
, ashl_optab
, r1
, GEN_INT (32),
1027 subtarget
, 0, OPTAB_WIDEN
);
1029 if (subtarget
== 0 && d1
== d3
&& d2
== d4
)
1030 r1
= expand_binop (DImode
, add_optab
, r1
, r2
, subtarget
, 0, OPTAB_WIDEN
);
1035 /* Add in the low word */
1037 r1
= expand_binop (DImode
, add_optab
, r1
, GEN_INT (d2
),
1038 subtarget
, 0, OPTAB_WIDEN
);
1040 r1
= expand_binop (DImode
, add_optab
, r1
, GEN_INT (d1
),
1041 subtarget
, 0, OPTAB_WIDEN
);
1045 r1
= copy_to_suggested_reg(r1
, target
, DImode
);
1049 #endif /* HOST_BITS_PER_WIDE_INT == 64 */
1051 /* Rewrite a comparison against zero CMP of the form
1052 (CODE (cc0) (const_int 0)) so it can be written validly in
1053 a conditional move (if_then_else CMP ...).
1054 If both of the operands that set cc0 are non-zero we must emit
1055 an insn to perform the compare (it can't be done within
1056 the conditional move). */
1058 alpha_emit_conditional_move (cmp
, mode
)
1060 enum machine_mode mode
;
1062 enum rtx_code code
= GET_CODE (cmp
);
1063 enum rtx_code cmov_code
= NE
;
1064 rtx op0
= alpha_compare_op0
;
1065 rtx op1
= alpha_compare_op1
;
1066 enum machine_mode cmp_mode
1067 = (GET_MODE (op0
) == VOIDmode
? DImode
: GET_MODE (op0
));
1068 enum machine_mode cmp_op_mode
= alpha_compare_fp_p
? DFmode
: DImode
;
1071 if (alpha_compare_fp_p
!= FLOAT_MODE_P (mode
))
1074 /* We may be able to use a conditional move directly.
1075 This avoids emitting spurious compares. */
1076 if (signed_comparison_operator (cmp
, cmp_op_mode
)
1077 && (op0
== CONST0_RTX (cmp_mode
) || op1
== CONST0_RTX (cmp_mode
)))
1078 return gen_rtx (code
, VOIDmode
, op0
, op1
);
1080 /* We can't put the comparison insides a conditional move;
1081 emit a compare instruction and put that inside the
1082 conditional move. Make sure we emit only comparisons we have;
1083 swap or reverse as necessary. */
1087 case EQ
: case LE
: case LT
: case LEU
: case LTU
:
1088 /* We have these compares: */
1092 /* This must be reversed. */
1093 code
= reverse_condition (code
);
1097 case GE
: case GT
: case GEU
: case GTU
:
1098 /* These must be swapped. Make sure the new first operand is in
1100 code
= swap_condition (code
);
1101 tem
= op0
, op0
= op1
, op1
= tem
;
1102 op0
= force_reg (cmp_mode
, op0
);
1109 tem
= gen_reg_rtx (cmp_op_mode
);
1110 emit_move_insn (tem
, gen_rtx (code
, cmp_op_mode
, op0
, op1
));
1111 return gen_rtx (cmov_code
, VOIDmode
, tem
, CONST0_RTX (cmp_op_mode
));
1114 /* Adjust the cost of a scheduling dependency. Return the new cost of
1115 a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
1118 alpha_adjust_cost (insn
, link
, dep_insn
, cost
)
1126 /* If the dependence is an anti-dependence, there is no cost. For an
1127 output dependence, there is sometimes a cost, but it doesn't seem
1128 worth handling those few cases. */
1130 if (REG_NOTE_KIND (link
) != 0)
1133 /* EV5 costs are as given in alpha.md; exceptions are given here. */
1134 if (alpha_cpu
== PROCESSOR_EV5
)
1136 /* And the lord DEC sayeth: "A special bypass provides an effective
1137 latency of 0 cycles for an ICMP or ILOG insn producing the test
1138 operand of an IBR or CMOV insn." */
1139 if (recog_memoized (dep_insn
) >= 0
1140 && (get_attr_type (dep_insn
) == TYPE_ICMP
1141 || get_attr_type (dep_insn
) == TYPE_ILOG
)
1142 && recog_memoized (insn
) >= 0
1143 && (get_attr_type (insn
) == TYPE_IBR
1144 || (get_attr_type (insn
) == TYPE_CMOV
1145 && !((set
= single_set (dep_insn
)) != 0
1146 && GET_CODE (PATTERN (insn
)) == SET
1147 && GET_CODE (SET_SRC (PATTERN (insn
))) == IF_THEN_ELSE
1148 && (rtx_equal_p (SET_DEST (set
),
1149 XEXP (SET_SRC (PATTERN (insn
)), 1))
1150 || rtx_equal_p (SET_DEST (set
),
1151 XEXP (SET_SRC (PATTERN (insn
)), 2)))))))
1156 /* If INSN is a store insn and DEP_INSN is setting the data being stored,
1157 we can sometimes lower the cost. */
1159 if (recog_memoized (insn
) >= 0 && get_attr_type (insn
) == TYPE_ST
1160 && (set
= single_set (dep_insn
)) != 0
1161 && GET_CODE (PATTERN (insn
)) == SET
1162 && rtx_equal_p (SET_DEST (set
), SET_SRC (PATTERN (insn
))))
1163 switch (get_attr_type (dep_insn
))
1166 /* No savings here. */
1171 /* In these cases, we save one cycle. */
1175 /* In all other cases, we save two cycles. */
1176 return MAX (0, cost
- 4);
1179 /* Another case that needs adjustment is an arithmetic or logical
1180 operation. It's cost is usually one cycle, but we default it to
1181 two in the MD file. The only case that it is actually two is
1182 for the address in loads and stores. */
1184 if (recog_memoized (dep_insn
) >= 0
1185 && (get_attr_type (dep_insn
) == TYPE_IADD
1186 || get_attr_type (dep_insn
) == TYPE_ILOG
))
1187 switch (get_attr_type (insn
))
1197 /* The final case is when a compare feeds into an integer branch. The cost
1198 is only one cycle in that case. */
1200 if (recog_memoized (dep_insn
) >= 0
1201 && get_attr_type (dep_insn
) == TYPE_ICMP
1202 && recog_memoized (insn
) >= 0
1203 && get_attr_type (insn
) == TYPE_IBR
)
1206 /* Otherwise, return the default cost. */
1211 /* Print an operand. Recognize special options, documented below. */
1214 print_operand (file
, x
, code
)
1224 /* Generates fp-rounding mode suffix: nothing for normal, 'c' for
1225 chopped, 'm' for minus-infinity, and 'd' for dynamic rounding
1226 mode. alpha_fprm controls which suffix is generated. */
1229 case ALPHA_FPRM_NORM
:
1231 case ALPHA_FPRM_MINF
:
1234 case ALPHA_FPRM_CHOP
:
1237 case ALPHA_FPRM_DYN
:
1244 /* Generates trap-mode suffix for instructions that accept the su
1245 suffix only (cmpt et al). */
1246 if (alpha_tp
== ALPHA_TP_INSN
)
1251 /* Generates trap-mode suffix for instructions that accept the u, su,
1252 and sui suffix. This is the bulk of the IEEE floating point
1253 instructions (addt et al). */
1264 case ALPHA_FPTM_SUI
:
1265 fputs ("sui", file
);
1271 /* Generates trap-mode suffix for instructions that accept the sui
1272 suffix (cvtqt and cvtqs). */
1275 case ALPHA_FPTM_N
: case ALPHA_FPTM_U
:
1276 case ALPHA_FPTM_SU
: /* cvtqt/cvtqs can't cause underflow */
1278 case ALPHA_FPTM_SUI
:
1279 fputs ("sui", file
);
1285 /* If this operand is the constant zero, write it as "$31". */
1286 if (GET_CODE (x
) == REG
)
1287 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1288 else if (x
== CONST0_RTX (GET_MODE (x
)))
1289 fprintf (file
, "$31");
1291 output_operand_lossage ("invalid %%r value");
1296 /* Similar, but for floating-point. */
1297 if (GET_CODE (x
) == REG
)
1298 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1299 else if (x
== CONST0_RTX (GET_MODE (x
)))
1300 fprintf (file
, "$f31");
1302 output_operand_lossage ("invalid %%R value");
1307 /* Write the 1's complement of a constant. */
1308 if (GET_CODE (x
) != CONST_INT
)
1309 output_operand_lossage ("invalid %%N value");
1311 fprintf (file
, "%ld", ~ INTVAL (x
));
1315 /* Write 1 << C, for a constant C. */
1316 if (GET_CODE (x
) != CONST_INT
)
1317 output_operand_lossage ("invalid %%P value");
1319 fprintf (file
, "%ld", (HOST_WIDE_INT
) 1 << INTVAL (x
));
1323 /* Write the high-order 16 bits of a constant, sign-extended. */
1324 if (GET_CODE (x
) != CONST_INT
)
1325 output_operand_lossage ("invalid %%h value");
1327 fprintf (file
, "%ld", INTVAL (x
) >> 16);
1331 /* Write the low-order 16 bits of a constant, sign-extended. */
1332 if (GET_CODE (x
) != CONST_INT
)
1333 output_operand_lossage ("invalid %%L value");
1335 fprintf (file
, "%ld", (INTVAL (x
) & 0xffff) - 2 * (INTVAL (x
) & 0x8000));
1339 /* Write mask for ZAP insn. */
1340 if (GET_CODE (x
) == CONST_DOUBLE
)
1342 HOST_WIDE_INT mask
= 0;
1343 HOST_WIDE_INT value
;
1345 value
= CONST_DOUBLE_LOW (x
);
1346 for (i
= 0; i
< HOST_BITS_PER_WIDE_INT
/ HOST_BITS_PER_CHAR
;
1351 value
= CONST_DOUBLE_HIGH (x
);
1352 for (i
= 0; i
< HOST_BITS_PER_WIDE_INT
/ HOST_BITS_PER_CHAR
;
1355 mask
|= (1 << (i
+ sizeof (int)));
1357 fprintf (file
, "%ld", mask
& 0xff);
1360 else if (GET_CODE (x
) == CONST_INT
)
1362 HOST_WIDE_INT mask
= 0, value
= INTVAL (x
);
1364 for (i
= 0; i
< 8; i
++, value
>>= 8)
1368 fprintf (file
, "%ld", mask
);
1371 output_operand_lossage ("invalid %%m value");
1375 /* 'b', 'w', or 'l' as the value of the constant. */
1376 if (GET_CODE (x
) != CONST_INT
1377 || (INTVAL (x
) != 8 && INTVAL (x
) != 16 && INTVAL (x
) != 32))
1378 output_operand_lossage ("invalid %%M value");
1380 fprintf (file
, "%s",
1381 INTVAL (x
) == 8 ? "b" : INTVAL (x
) == 16 ? "w" : "l");
1385 /* Similar, except do it from the mask. */
1386 if (GET_CODE (x
) == CONST_INT
&& INTVAL (x
) == 0xff)
1387 fprintf (file
, "b");
1388 else if (GET_CODE (x
) == CONST_INT
&& INTVAL (x
) == 0xffff)
1389 fprintf (file
, "w");
1390 #if HOST_BITS_PER_WIDE_INT == 32
1391 else if (GET_CODE (x
) == CONST_DOUBLE
1392 && CONST_DOUBLE_HIGH (x
) == 0
1393 && CONST_DOUBLE_LOW (x
) == -1)
1394 fprintf (file
, "l");
1396 else if (GET_CODE (x
) == CONST_INT
&& INTVAL (x
) == 0xffffffff)
1397 fprintf (file
, "l");
1400 output_operand_lossage ("invalid %%U value");
1404 /* Write the constant value divided by 8. */
1405 if (GET_CODE (x
) != CONST_INT
1406 && (unsigned HOST_WIDE_INT
) INTVAL (x
) >= 64
1407 && (INTVAL (x
) & 7) != 8)
1408 output_operand_lossage ("invalid %%s value");
1410 fprintf (file
, "%ld", INTVAL (x
) / 8);
1414 /* Same, except compute (64 - c) / 8 */
1416 if (GET_CODE (x
) != CONST_INT
1417 && (unsigned HOST_WIDE_INT
) INTVAL (x
) >= 64
1418 && (INTVAL (x
) & 7) != 8)
1419 output_operand_lossage ("invalid %%s value");
1421 fprintf (file
, "%ld", (64 - INTVAL (x
)) / 8);
1424 case 'C': case 'D': case 'c': case 'd':
1425 /* Write out comparison name. */
1427 enum rtx_code c
= GET_CODE (x
);
1429 if (GET_RTX_CLASS (c
) != '<')
1430 output_operand_lossage ("invalid %%C value");
1433 c
= reverse_condition (c
);
1434 else if (code
== 'c')
1435 c
= swap_condition (c
);
1436 else if (code
== 'd')
1437 c
= swap_condition (reverse_condition (c
));
1440 fprintf (file
, "ule");
1442 fprintf (file
, "ult");
1444 fprintf (file
, "%s", GET_RTX_NAME (c
));
1449 /* Write the divide or modulus operator. */
1450 switch (GET_CODE (x
))
1453 fprintf (file
, "div%s", GET_MODE (x
) == SImode
? "l" : "q");
1456 fprintf (file
, "div%su", GET_MODE (x
) == SImode
? "l" : "q");
1459 fprintf (file
, "rem%s", GET_MODE (x
) == SImode
? "l" : "q");
1462 fprintf (file
, "rem%su", GET_MODE (x
) == SImode
? "l" : "q");
1465 output_operand_lossage ("invalid %%E value");
1471 /* Write "_u" for unaligned access. */
1472 if (GET_CODE (x
) == MEM
&& GET_CODE (XEXP (x
, 0)) == AND
)
1473 fprintf (file
, "_u");
1477 if (GET_CODE (x
) == REG
)
1478 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1479 else if (GET_CODE (x
) == MEM
)
1480 output_address (XEXP (x
, 0));
1482 output_addr_const (file
, x
);
1486 output_operand_lossage ("invalid %%xn code");
1490 /* Do what is necessary for `va_start'. The argument is ignored;
1491 We look at the current function to determine if stdarg or varargs
1492 is used and fill in an initial va_list. A pointer to this constructor
1496 alpha_builtin_saveregs (arglist
)
1499 rtx block
, addr
, argsize
;
1500 tree fntype
= TREE_TYPE (current_function_decl
);
1501 int stdarg
= (TYPE_ARG_TYPES (fntype
) != 0
1502 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype
)))
1503 != void_type_node
));
1505 /* Compute the current position into the args, taking into account
1506 both registers and memory. Both of these are already included in
1507 current_function_args_info. */
1509 argsize
= GEN_INT (current_function_args_info
* UNITS_PER_WORD
);
1511 /* SETUP_INCOMING_VARARGS moves the starting address base up by 48,
1512 storing fp arg registers in the first 48 bytes, and the integer arg
1513 registers in the next 48 bytes. This is only done, however, if any
1514 integer registers need to be stored.
1516 If no integer registers need be stored, then we must subtract 48 in
1517 order to account for the integer arg registers which are counted in
1518 argsize above, but which are not actually stored on the stack. */
1520 addr
= (current_function_args_info
<= 5 + stdarg
1521 ? plus_constant (virtual_incoming_args_rtx
, 6 * UNITS_PER_WORD
)
1522 : plus_constant (virtual_incoming_args_rtx
, - (6 * UNITS_PER_WORD
)));
1524 addr
= force_operand (addr
, NULL_RTX
);
1526 /* Allocate the va_list constructor */
1527 block
= assign_stack_local (BLKmode
, 2 * UNITS_PER_WORD
, BITS_PER_WORD
);
1528 RTX_UNCHANGING_P (block
) = 1;
1529 RTX_UNCHANGING_P (XEXP (block
, 0)) = 1;
1531 /* Store the address of the first integer register in the __base member. */
1533 #ifdef POINTERS_EXTEND_UNSIGNED
1534 addr
= convert_memory_address (ptr_mode
, addr
);
1537 emit_move_insn (change_address (block
, ptr_mode
, XEXP (block
, 0)), addr
);
1539 /* Store the argsize as the __va_offset member. */
1540 emit_move_insn (change_address (block
, TYPE_MODE (integer_type_node
),
1541 plus_constant (XEXP (block
, 0),
1542 POINTER_SIZE
/BITS_PER_UNIT
)),
1545 /* Return the address of the va_list constructor, but don't put it in a
1546 register. Doing so would fail when not optimizing and produce worse
1547 code when optimizing. */
1548 return XEXP (block
, 0);
1551 /* This page contains routines that are used to determine what the function
1552 prologue and epilogue code will do and write them out. */
1554 /* Compute the size of the save area in the stack. */
1562 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1563 if (! fixed_regs
[i
] && ! call_used_regs
[i
] && regs_ever_live
[i
])
1566 /* If some registers were saved but not reg 26, reg 26 must also
1567 be saved, so leave space for it. */
1568 if (size
!= 0 && ! regs_ever_live
[26])
1571 /* Our size must be even (multiple of 16 bytes). */
1578 /* Return 1 if this function can directly return via $26. */
1583 return (reload_completed
&& alpha_sa_size () == 0
1584 && get_frame_size () == 0
1585 && current_function_outgoing_args_size
== 0
1586 && current_function_pretend_args_size
== 0);
1589 /* Write a version stamp. Don't write anything if we are running as a
1590 cross-compiler. Otherwise, use the versions in /usr/include/stamp.h. */
1592 #if !defined(CROSS_COMPILE) && !defined(_WIN32) && !defined(__linux__)
1597 alpha_write_verstamp (file
)
1601 fprintf (file
, "\t.verstamp %d %d\n", MS_STAMP
, LS_STAMP
);
1605 /* Write code to add constant C to register number IN_REG (possibly 31)
1606 and put the result into OUT_REG. Use TEMP_REG as a scratch register;
1607 usually this will be OUT_REG, but should not be if OUT_REG is
1608 STACK_POINTER_REGNUM, since it must be updated in a single instruction.
1609 Write the code to FILE. */
1612 add_long_const (file
, c
, in_reg
, out_reg
, temp_reg
)
1615 int in_reg
, out_reg
, temp_reg
;
1617 HOST_WIDE_INT low
= (c
& 0xffff) - 2 * (c
& 0x8000);
1618 HOST_WIDE_INT tmp1
= c
- low
;
1619 HOST_WIDE_INT high
= ((tmp1
>> 16) & 0xffff) - 2 * ((tmp1
>> 16) & 0x8000);
1620 HOST_WIDE_INT extra
= 0;
1622 /* We don't have code to write out constants larger than 32 bits. */
1623 #if HOST_BITS_PER_LONG_INT == 64
1624 if ((unsigned HOST_WIDE_INT
) c
>> 32 != 0)
1628 /* If HIGH will be interpreted as negative, we must adjust it to do two
1629 ldha insns. Note that we will never be building a negative constant
1636 high
= ((tmp1
>> 16) & 0xffff) - 2 * ((tmp1
>> 16) & 0x8000);
1641 int result_reg
= (extra
== 0 && high
== 0) ? out_reg
: temp_reg
;
1643 if (low
>= 0 && low
< 255)
1644 fprintf (file
, "\taddq $%d,%d,$%d\n", in_reg
, low
, result_reg
);
1646 fprintf (file
, "\tlda $%d,%d($%d)\n", result_reg
, low
, in_reg
);
1648 in_reg
= result_reg
;
1653 int result_reg
= (high
== 0) ? out_reg
: temp_reg
;
1655 fprintf (file
, "\tldah $%d,%d($%d)\n", result_reg
, extra
, in_reg
);
1656 in_reg
= result_reg
;
1660 fprintf (file
, "\tldah $%d,%d($%d)\n", out_reg
, high
, in_reg
);
1663 /* Write function prologue. */
1666 output_prolog (file
, size
)
1670 HOST_WIDE_INT out_args_size
1671 = ALPHA_ROUND (current_function_outgoing_args_size
);
1672 HOST_WIDE_INT sa_size
= alpha_sa_size ();
1673 HOST_WIDE_INT frame_size
1674 = (out_args_size
+ sa_size
1675 + ALPHA_ROUND (size
+ current_function_pretend_args_size
));
1676 HOST_WIDE_INT reg_offset
= out_args_size
;
1677 HOST_WIDE_INT start_reg_offset
= reg_offset
;
1678 HOST_WIDE_INT actual_start_reg_offset
= start_reg_offset
;
1679 int int_reg_save_area_size
= 0;
1681 unsigned reg_mask
= 0;
1684 /* Ecoff can handle multiple .file directives, so put out file and lineno.
1685 We have to do that before the .ent directive as we cannot switch
1686 files within procedures with native ecoff because line numbers are
1687 linked to procedure descriptors.
1688 Outputting the lineno helps debugging of one line functions as they
1689 would otherwise get no line number at all. Please note that we would
1690 like to put out last_linenum from final.c, but it is not accessible. */
1692 if (write_symbols
== SDB_DEBUG
)
1694 ASM_OUTPUT_SOURCE_FILENAME (file
,
1695 DECL_SOURCE_FILE (current_function_decl
));
1696 if (debug_info_level
!= DINFO_LEVEL_TERSE
)
1697 ASM_OUTPUT_SOURCE_LINE (file
,
1698 DECL_SOURCE_LINE (current_function_decl
));
1701 /* The assembly language programmer's guide states that the second argument
1702 to the .ent directive, the lex_level, is ignored by the assembler,
1703 so we might as well omit it. */
1705 if (!flag_inhibit_size_directive
)
1707 fprintf (file
, "\t.ent ");
1708 assemble_name (file
, alpha_function_name
);
1709 fprintf (file
, "\n");
1711 ASM_OUTPUT_LABEL (file
, alpha_function_name
);
1712 inside_function
= TRUE
;
1714 if (TARGET_IEEE_CONFORMANT
&& !flag_inhibit_size_directive
)
1715 /* Set flags in procedure descriptor to request IEEE-conformant
1716 math-library routines. The value we set it to is PDSC_EXC_IEEE
1717 (/usr/include/pdsc.h). */
1718 fprintf (file
, "\t.eflag 48\n");
1720 /* Set up offsets to alpha virtual arg/local debugging pointer. */
1722 alpha_auto_offset
= -frame_size
+ current_function_pretend_args_size
;
1723 alpha_arg_offset
= -frame_size
+ 48;
1725 /* If we need a GP (we have a LDSYM insn or a CALL_INSN), load it first.
1726 Even if we are a static function, we still need to do this in case
1727 our address is taken and passed to something like qsort.
1729 We never need a GP for Windows/NT. */
1731 alpha_function_needs_gp
= 0;
1733 #ifdef TARGET_PROFILING_NEEDS_GP
1735 alpha_function_needs_gp
= 1;
1738 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
1739 if ((GET_CODE (insn
) == CALL_INSN
)
1740 || (GET_RTX_CLASS (GET_CODE (insn
)) == 'i'
1741 && GET_CODE (PATTERN (insn
)) != USE
1742 && GET_CODE (PATTERN (insn
)) != CLOBBER
1743 && (get_attr_type (insn
) == TYPE_LDSYM
1744 || get_attr_type (insn
) == TYPE_ISUBR
)))
1746 alpha_function_needs_gp
= 1;
1750 if (TARGET_WINDOWS_NT
== 0)
1752 if (alpha_function_needs_gp
)
1753 fprintf (file
, "\tldgp $29,0($27)\n");
1755 /* Put a label after the GP load so we can enter the function at it. */
1756 assemble_name (file
, alpha_function_name
);
1757 fprintf (file
, "..ng:\n");
1760 /* Adjust the stack by the frame size. If the frame size is > 4096
1761 bytes, we need to be sure we probe somewhere in the first and last
1762 4096 bytes (we can probably get away without the latter test) and
1763 every 8192 bytes in between. If the frame size is > 32768, we
1764 do this in a loop. Otherwise, we generate the explicit probe
1767 Note that we are only allowed to adjust sp once in the prologue. */
1769 if (frame_size
< 32768)
1771 if (frame_size
> 4096)
1775 fprintf (file
, "\tstq $31,-%d($30)\n", probed
);
1777 while (probed
+ 8192 < frame_size
)
1778 fprintf (file
, "\tstq $31,-%d($30)\n", probed
+= 8192);
1780 /* We only have to do this probe if we aren't saving registers. */
1781 if (sa_size
== 0 && probed
+ 4096 < frame_size
)
1782 fprintf (file
, "\tstq $31,-%d($30)\n", frame_size
);
1785 if (frame_size
!= 0)
1786 fprintf (file
, "\tlda $30,-%d($30)\n", frame_size
);
1790 /* Here we generate code to set R4 to SP + 4096 and set R5 to the
1791 number of 8192 byte blocks to probe. We then probe each block
1792 in the loop and then set SP to the proper location. If the
1793 amount remaining is > 4096, we have to do one more probe if we
1794 are not saving any registers. */
1796 HOST_WIDE_INT blocks
= (frame_size
+ 4096) / 8192;
1797 HOST_WIDE_INT leftover
= frame_size
+ 4096 - blocks
* 8192;
1799 add_long_const (file
, blocks
, 31, 5, 5);
1801 fprintf (file
, "\tlda $4,4096($30)\n");
1803 assemble_name (file
, alpha_function_name
);
1804 fprintf (file
, "..sc:\n");
1806 fprintf (file
, "\tstq $31,-8192($4)\n");
1807 fprintf (file
, "\tsubq $5,1,$5\n");
1808 fprintf (file
, "\tlda $4,-8192($4)\n");
1810 fprintf (file
, "\tbne $5,");
1811 assemble_name (file
, alpha_function_name
);
1812 fprintf (file
, "..sc\n");
1814 if (leftover
> 4096 && sa_size
== 0)
1815 fprintf (file
, "\tstq $31,-%d($4)\n", leftover
);
1817 fprintf (file
, "\tlda $30,-%d($4)\n", leftover
);
1820 /* Describe our frame. */
1821 if (!flag_inhibit_size_directive
)
1823 fprintf (file
, "\t.frame $%d,%d,$26,%d\n",
1824 (frame_pointer_needed
1825 ? HARD_FRAME_POINTER_REGNUM
: STACK_POINTER_REGNUM
),
1826 frame_size
, current_function_pretend_args_size
);
1829 /* Save register 26 if any other register needs to be saved. */
1832 reg_mask
|= 1 << 26;
1833 fprintf (file
, "\tstq $26,%d($30)\n", reg_offset
);
1835 int_reg_save_area_size
+= 8;
1838 /* Now save any other used integer registers required to be saved. */
1839 for (i
= 0; i
< 32; i
++)
1840 if (! fixed_regs
[i
] && ! call_used_regs
[i
] && regs_ever_live
[i
] && i
!= 26)
1843 fprintf (file
, "\tstq $%d,%d($30)\n", i
, reg_offset
);
1845 int_reg_save_area_size
+= 8;
1848 /* Print the register mask and do floating-point saves. */
1849 if (reg_mask
&& !flag_inhibit_size_directive
)
1850 fprintf (file
, "\t.mask 0x%x,%d\n", reg_mask
,
1851 actual_start_reg_offset
- frame_size
);
1853 start_reg_offset
= reg_offset
;
1856 for (i
= 0; i
< 32; i
++)
1857 if (! fixed_regs
[i
+ 32] && ! call_used_regs
[i
+ 32]
1858 && regs_ever_live
[i
+ 32])
1861 fprintf (file
, "\tstt $f%d,%d($30)\n", i
, reg_offset
);
1865 /* Print the floating-point mask, if we've saved any fp register. */
1866 if (reg_mask
&& !flag_inhibit_size_directive
)
1867 fprintf (file
, "\t.fmask 0x%x,%d\n", reg_mask
,
1868 actual_start_reg_offset
- frame_size
+ int_reg_save_area_size
);
1870 /* If we need a frame pointer, set it from the stack pointer. Note that
1871 this must always be the last instruction in the prologue. */
1872 if (frame_pointer_needed
)
1873 fprintf (file
, "\tbis $30,$30,$15\n");
1875 /* End the prologue and say if we used gp. */
1876 if (!flag_inhibit_size_directive
)
1877 fprintf (file
, "\t.prologue %d\n", alpha_function_needs_gp
);
1880 /* Write function epilogue. */
1883 output_epilog (file
, size
)
1887 rtx insn
= get_last_insn ();
1888 HOST_WIDE_INT out_args_size
1889 = ALPHA_ROUND (current_function_outgoing_args_size
);
1890 HOST_WIDE_INT sa_size
= alpha_sa_size ();
1891 HOST_WIDE_INT frame_size
1892 = (out_args_size
+ sa_size
1893 + ALPHA_ROUND (size
+ current_function_pretend_args_size
));
1894 HOST_WIDE_INT reg_offset
= out_args_size
;
1895 HOST_WIDE_INT frame_size_from_reg_save
= frame_size
- reg_offset
;
1897 = frame_pointer_needed
&& regs_ever_live
[HARD_FRAME_POINTER_REGNUM
];
1900 /* If the last insn was a BARRIER, we don't have to write anything except
1901 the .end pseudo-op. */
1902 if (GET_CODE (insn
) == NOTE
)
1903 insn
= prev_nonnote_insn (insn
);
1904 if (insn
== 0 || GET_CODE (insn
) != BARRIER
)
1908 final_prescan_insn (NULL_RTX
, NULL_PTR
, 0);
1910 /* If we have a frame pointer, restore SP from it. */
1911 if (frame_pointer_needed
)
1912 fprintf (file
, "\tbis $15,$15,$30\n");
1914 /* Restore all the registers, starting with the return address
1918 fprintf (file
, "\tldq $26,%d($30)\n", reg_offset
);
1922 /* Now restore any other used integer registers that that we saved,
1923 except for FP if it is being used as FP, since it must be
1926 for (i
= 0; i
< 32; i
++)
1927 if (! fixed_regs
[i
] && ! call_used_regs
[i
] && regs_ever_live
[i
]
1930 if (i
== HARD_FRAME_POINTER_REGNUM
&& frame_pointer_needed
)
1931 fp_offset
= reg_offset
;
1933 fprintf (file
, "\tldq $%d,%d($30)\n", i
, reg_offset
);
1937 for (i
= 0; i
< 32; i
++)
1938 if (! fixed_regs
[i
+ 32] && ! call_used_regs
[i
+ 32]
1939 && regs_ever_live
[i
+ 32])
1941 fprintf (file
, "\tldt $f%d,%d($30)\n", i
, reg_offset
);
1945 /* If the stack size is large and we have a frame pointer, compute the
1946 size of the stack into a register because the old FP restore, stack
1947 pointer adjust, and return are required to be consecutive
1949 if (frame_size
> 32767 && restore_fp
)
1950 add_long_const (file
, frame_size
, 31, 1, 1);
1952 /* If we needed a frame pointer and we have to restore it, do it
1953 now. This must be done in one instruction immediately
1954 before the SP update. */
1955 if (restore_fp
&& fp_offset
)
1956 fprintf (file
, "\tldq $15,%d($30)\n", fp_offset
);
1958 /* Now update the stack pointer, if needed. Only one instruction must
1959 modify the stack pointer. It must be the last instruction in the
1960 sequence and must be an ADDQ or LDA instruction. If the frame
1961 pointer was loaded above, we may only put one instruction here. */
1963 if (frame_size
> 32768 && restore_fp
)
1964 fprintf (file
, "\taddq $1,$30,$30\n");
1966 add_long_const (file
, frame_size
, 30, 30, 1);
1968 /* Finally return to the caller. */
1969 fprintf (file
, "\tret $31,($26),1\n");
1972 /* End the function. */
1973 if (!flag_inhibit_size_directive
)
1975 fprintf (file
, "\t.end ");
1976 assemble_name (file
, alpha_function_name
);
1977 fprintf (file
, "\n");
1979 inside_function
= FALSE
;
1981 /* Show that we know this function if it is called again. */
1982 SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl
), 0)) = 1;
1985 /* Debugging support. */
1989 /* Count the number of sdb related labels are generated (to find block
1990 start and end boundaries). */
1992 int sdb_label_count
= 0;
1994 /* Next label # for each statement. */
1996 static int sym_lineno
= 0;
1998 /* Count the number of .file directives, so that .loc is up to date. */
2000 static int num_source_filenames
= 0;
2002 /* Name of the file containing the current function. */
2004 static char *current_function_file
= "";
2006 /* Offsets to alpha virtual arg/local debugging pointers. */
2008 long alpha_arg_offset
;
2009 long alpha_auto_offset
;
2011 /* Emit a new filename to a stream. */
2014 alpha_output_filename (stream
, name
)
2018 static int first_time
= TRUE
;
2019 char ltext_label_name
[100];
2024 ++num_source_filenames
;
2025 current_function_file
= name
;
2026 fprintf (stream
, "\t.file\t%d ", num_source_filenames
);
2027 output_quoted_string (stream
, name
);
2028 fprintf (stream
, "\n");
2029 if (!TARGET_GAS
&& write_symbols
== DBX_DEBUG
)
2030 fprintf (stream
, "\t#@stabs\n");
2033 else if (write_symbols
== DBX_DEBUG
)
2035 ASM_GENERATE_INTERNAL_LABEL (ltext_label_name
, "Ltext", 0);
2036 fprintf (stream
, "%s ", ASM_STABS_OP
);
2037 output_quoted_string (stream
, name
);
2038 fprintf (stream
, ",%d,0,0,%s\n", N_SOL
, <ext_label_name
[1]);
2041 else if (name
!= current_function_file
2042 && strcmp (name
, current_function_file
) != 0)
2044 if (inside_function
&& ! TARGET_GAS
)
2045 fprintf (stream
, "\t#.file\t%d ", num_source_filenames
);
2048 ++num_source_filenames
;
2049 current_function_file
= name
;
2050 fprintf (stream
, "\t.file\t%d ", num_source_filenames
);
2053 output_quoted_string (stream
, name
);
2054 fprintf (stream
, "\n");
2058 /* Emit a linenumber to a stream. */
2061 alpha_output_lineno (stream
, line
)
2065 if (write_symbols
== DBX_DEBUG
)
2067 /* mips-tfile doesn't understand .stabd directives. */
2069 fprintf (stream
, "$LM%d:\n\t%s %d,0,%d,$LM%d\n",
2070 sym_lineno
, ASM_STABN_OP
, N_SLINE
, line
, sym_lineno
);
2073 fprintf (stream
, "\n\t.loc\t%d %d\n", num_source_filenames
, line
);
2076 /* Structure to show the current status of registers and memory. */
2078 struct shadow_summary
2081 unsigned long i
: 32; /* Mask of int regs */
2082 unsigned long fp
: 32; /* Mask of fp regs */
2083 unsigned long mem
: 1; /* mem == imem | fpmem */
2087 /* Summary the effects of expression X on the machine. Update SUM, a pointer
2088 to the summary structure. SET is nonzero if the insn is setting the
2089 object, otherwise zero. */
2092 summarize_insn (x
, sum
, set
)
2094 struct shadow_summary
*sum
;
2103 switch (GET_CODE (x
))
2105 /* ??? Note that this case would be incorrect if the Alpha had a
2106 ZERO_EXTRACT in SET_DEST. */
2108 summarize_insn (SET_SRC (x
), sum
, 0);
2109 summarize_insn (SET_DEST (x
), sum
, 1);
2113 summarize_insn (XEXP (x
, 0), sum
, 1);
2117 summarize_insn (XEXP (x
, 0), sum
, 0);
2121 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
2122 summarize_insn (XVECEXP (x
, 0, i
), sum
, 0);
2127 int regno
= REGNO (x
);
2128 unsigned long mask
= 1UL << (regno
% 32);
2130 if (regno
== 31 || regno
== 63)
2136 sum
->defd
.i
|= mask
;
2138 sum
->defd
.fp
|= mask
;
2143 sum
->used
.i
|= mask
;
2145 sum
->used
.fp
|= mask
;
2156 /* Find the regs used in memory address computation: */
2157 summarize_insn (XEXP (x
, 0), sum
, 0);
2161 summarize_insn (SUBREG_REG (x
), sum
, 0);
2164 case CONST_INT
: case CONST_DOUBLE
:
2165 case SYMBOL_REF
: case LABEL_REF
: case CONST
:
2168 /* Handle common unary and binary ops for efficiency. */
2169 case COMPARE
: case PLUS
: case MINUS
: case MULT
: case DIV
:
2170 case MOD
: case UDIV
: case UMOD
: case AND
: case IOR
:
2171 case XOR
: case ASHIFT
: case ROTATE
: case ASHIFTRT
: case LSHIFTRT
:
2172 case ROTATERT
: case SMIN
: case SMAX
: case UMIN
: case UMAX
:
2173 case NE
: case EQ
: case GE
: case GT
: case LE
:
2174 case LT
: case GEU
: case GTU
: case LEU
: case LTU
:
2175 summarize_insn (XEXP (x
, 0), sum
, 0);
2176 summarize_insn (XEXP (x
, 1), sum
, 0);
2179 case NEG
: case NOT
: case SIGN_EXTEND
: case ZERO_EXTEND
:
2180 case TRUNCATE
: case FLOAT_EXTEND
: case FLOAT_TRUNCATE
: case FLOAT
:
2181 case FIX
: case UNSIGNED_FLOAT
: case UNSIGNED_FIX
: case ABS
:
2182 case SQRT
: case FFS
:
2183 summarize_insn (XEXP (x
, 0), sum
, 0);
2187 format_ptr
= GET_RTX_FORMAT (GET_CODE (x
));
2188 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
2189 switch (format_ptr
[i
])
2192 summarize_insn (XEXP (x
, i
), sum
, 0);
2196 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
2197 summarize_insn (XVECEXP (x
, i
, j
), sum
, 0);
2206 /* This function is executed just prior to the output of assembler code for
2207 INSN to modify the extracted operands so they will be output differently.
2209 OPVEC is the vector containing the operands extracted from INSN, and
2210 NOPERANDS is the number of elements of the vector which contain meaningful
2211 data for this insn. The contents of this vector are what will be used to
2212 convert the insn template into assembler code, so you can change the
2213 assembler output by changing the contents of the vector.
2215 We use this function to ensure a sufficient number of `trapb' instructions
2216 are in the code when the user requests code with a trap precision of
2217 functions or instructions.
2219 In naive mode, when the user requests a trap-precision of "instruction", a
2220 trapb is needed after every instruction that may generate a trap (and after
2221 jsr/bsr instructions, because called functions may import a trap from the
2222 caller). This ensures that the code is resumption safe but it is also slow.
2224 When optimizations are turned on, we delay issuing a trapb as long as
2225 possible. In this context, a trap shadow is the sequence of instructions
2226 that starts with a (potentially) trap generating instruction and extends to
2227 the next trapb or call_pal instruction (but GCC never generates call_pal by
2228 itself). We can delay (and therefore sometimes omit) a trapb subject to the
2229 following conditions:
2231 (a) On entry to the trap shadow, if any Alpha register or memory location
2232 contains a value that is used as an operand value by some instruction in
2233 the trap shadow (live on entry), then no instruction in the trap shadow
2234 may modify the register or memory location.
2236 (b) Within the trap shadow, the computation of the base register for a
2237 memory load or store instruction may not involve using the result
2238 of an instruction that might generate an UNPREDICTABLE result.
2240 (c) Within the trap shadow, no register may be used more than once as a
2241 destination register. (This is to make life easier for the trap-handler.)
2243 (d) The trap shadow may not include any branch instructions.
2248 final_prescan_insn (insn
, opvec
, noperands
)
2253 static struct shadow_summary shadow
= {0, 0, 0, 0, 0};
2255 #define CLOSE_SHADOW \
2258 fputs ("\ttrapb\n", asm_out_file); \
2260 bzero ((char *) &shadow, sizeof shadow); \
2264 if (alpha_tp
== ALPHA_TP_PROG
)
2271 /* Generate one trapb before epilogue (indicated by INSN==0) */
2277 if (optimize
&& insn
!= 0)
2279 struct shadow_summary sum
= {0, 0, 0};
2281 switch (GET_CODE(insn
))
2284 summarize_insn (PATTERN (insn
), &sum
, 0);
2286 if ((sum
.defd
.i
& shadow
.defd
.i
)
2287 || (sum
.defd
.fp
& shadow
.defd
.fp
))
2289 /* (c) would be violated */
2294 /* Combine shadow with summary of current insn: */
2295 shadow
.used
.i
|= sum
.used
.i
;
2296 shadow
.used
.fp
|= sum
.used
.fp
;
2297 shadow
.used
.mem
|= sum
.used
.mem
;
2298 shadow
.defd
.i
|= sum
.defd
.i
;
2299 shadow
.defd
.fp
|= sum
.defd
.fp
;
2300 shadow
.defd
.mem
|= sum
.defd
.mem
;
2302 if ((sum
.defd
.i
& shadow
.used
.i
)
2303 || (sum
.defd
.fp
& shadow
.used
.fp
)
2304 || (sum
.defd
.mem
& shadow
.used
.mem
))
2306 /* (a) would be violated (also takes care of (b)). */
2307 if (get_attr_trap (insn
) == TRAP_YES
2308 && ((sum
.defd
.i
& sum
.used
.i
)
2309 || (sum
.defd
.fp
& sum
.used
.fp
)))
2332 if (insn
!= 0 && get_attr_trap (insn
) == TRAP_YES
)
2334 if (optimize
&& !trap_pending
&& GET_CODE (insn
) == INSN
)
2335 summarize_insn (PATTERN (insn
), &shadow
, 0);
2340 /* Check a floating-point value for validity for a particular machine mode. */
2342 static char *float_strings
[] =
2344 "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
2345 "-1.70141173319264430e+38",
2346 "2.93873587705571877e-39", /* 2^-128 */
2347 "-2.93873587705571877e-39"
2350 static REAL_VALUE_TYPE float_values
[4];
2351 static int inited_float_values
= 0;
2354 check_float_value (mode
, d
, overflow
)
2355 enum machine_mode mode
;
2360 if (TARGET_IEEE
|| TARGET_IEEE_CONFORMANT
|| TARGET_IEEE_WITH_INEXACT
)
2363 if (inited_float_values
== 0)
2366 for (i
= 0; i
< 4; i
++)
2367 float_values
[i
] = REAL_VALUE_ATOF (float_strings
[i
], DFmode
);
2369 inited_float_values
= 1;
2376 bcopy ((char *) d
, (char *) &r
, sizeof (REAL_VALUE_TYPE
));
2377 if (REAL_VALUES_LESS (float_values
[0], r
))
2379 bcopy ((char *) &float_values
[0], (char *) d
,
2380 sizeof (REAL_VALUE_TYPE
));
2383 else if (REAL_VALUES_LESS (r
, float_values
[1]))
2385 bcopy ((char *) &float_values
[1], (char *) d
,
2386 sizeof (REAL_VALUE_TYPE
));
2389 else if (REAL_VALUES_LESS (dconst0
, r
)
2390 && REAL_VALUES_LESS (r
, float_values
[2]))
2392 bcopy ((char *) &dconst0
, (char *) d
, sizeof (REAL_VALUE_TYPE
));
2395 else if (REAL_VALUES_LESS (r
, dconst0
)
2396 && REAL_VALUES_LESS (float_values
[3], r
))
2398 bcopy ((char *) &dconst0
, (char *) d
, sizeof (REAL_VALUE_TYPE
));