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 mode
!= HImode
&& mode
!= QImode
&& general_operand (op
, mode
);
453 return GET_MODE_CLASS (mode
) == MODE_FLOAT
&& op
== CONST0_RTX (mode
);
456 return mode
== QImode
|| mode
== HImode
|| add_operand (op
, mode
);
462 /* Return 1 if OP is a SYMBOL_REF for a function known to be in this
466 current_file_function_operand (op
, mode
)
468 enum machine_mode mode
;
470 return (GET_CODE (op
) == SYMBOL_REF
471 && ! profile_flag
&& ! profile_block_flag
472 && (SYMBOL_REF_FLAG (op
)
473 || op
== XEXP (DECL_RTL (current_function_decl
), 0)));
476 /* Return 1 if OP is a valid operand for the MEM of a CALL insn. */
479 call_operand (op
, mode
)
481 enum machine_mode mode
;
486 return (GET_CODE (op
) == SYMBOL_REF
487 || (GET_CODE (op
) == REG
&& REGNO (op
) == 27));
490 /* Return 1 if OP is a valid Alpha comparison operator. Here we know which
491 comparisons are valid in which insn. */
494 alpha_comparison_operator (op
, mode
)
496 enum machine_mode mode
;
498 enum rtx_code code
= GET_CODE (op
);
500 if (mode
!= GET_MODE (op
) || GET_RTX_CLASS (code
) != '<')
503 return (code
== EQ
|| code
== LE
|| code
== LT
504 || (mode
== DImode
&& (code
== LEU
|| code
== LTU
)));
507 /* Return 1 if OP is a signed comparison operation. */
510 signed_comparison_operator (op
, mode
)
512 enum machine_mode mode
;
514 switch (GET_CODE (op
))
516 case EQ
: case NE
: case LE
: case LT
: case GE
: case GT
:
523 /* Return 1 if this is a divide or modulus operator. */
526 divmod_operator (op
, mode
)
528 enum machine_mode mode
;
530 switch (GET_CODE (op
))
532 case DIV
: case MOD
: case UDIV
: case UMOD
:
539 /* Return 1 if this memory address is a known aligned register plus
540 a constant. It must be a valid address. This means that we can do
541 this as an aligned reference plus some offset.
543 Take into account what reload will do.
545 We could say that out-of-range stack slots are alignable, but that would
546 complicate get_aligned_mem and it isn't worth the trouble since few
547 functions have large stack space. */
550 aligned_memory_operand (op
, mode
)
552 enum machine_mode mode
;
554 if (GET_CODE (op
) == SUBREG
)
556 if (GET_MODE (op
) != mode
)
558 op
= SUBREG_REG (op
);
559 mode
= GET_MODE (op
);
562 if (reload_in_progress
&& GET_CODE (op
) == REG
563 && REGNO (op
) >= FIRST_PSEUDO_REGISTER
)
564 op
= reg_equiv_mem
[REGNO (op
)];
566 if (GET_CODE (op
) != MEM
|| GET_MODE (op
) != mode
567 || ! memory_address_p (mode
, XEXP (op
, 0)))
572 if (GET_CODE (op
) == PLUS
)
575 return (GET_CODE (op
) == REG
576 && REGNO_POINTER_ALIGN (REGNO (op
)) >= 4);
579 /* Similar, but return 1 if OP is a MEM which is not alignable. */
582 unaligned_memory_operand (op
, mode
)
584 enum machine_mode mode
;
586 if (GET_CODE (op
) == SUBREG
)
588 if (GET_MODE (op
) != mode
)
590 op
= SUBREG_REG (op
);
591 mode
= GET_MODE (op
);
594 if (reload_in_progress
&& GET_CODE (op
) == REG
595 && REGNO (op
) >= FIRST_PSEUDO_REGISTER
)
596 op
= reg_equiv_mem
[REGNO (op
)];
598 if (GET_CODE (op
) != MEM
|| GET_MODE (op
) != mode
)
603 if (! memory_address_p (mode
, op
))
606 if (GET_CODE (op
) == PLUS
)
609 return (GET_CODE (op
) != REG
610 || REGNO_POINTER_ALIGN (REGNO (op
)) < 4);
613 /* Return 1 if OP is either a register or an unaligned memory location. */
616 reg_or_unaligned_mem_operand (op
, mode
)
618 enum machine_mode mode
;
620 return register_operand (op
, mode
) || unaligned_memory_operand (op
, mode
);
623 /* Return 1 if OP is any memory location. During reload a pseudo matches. */
626 any_memory_operand (op
, mode
)
628 enum machine_mode mode
;
630 return (GET_CODE (op
) == MEM
631 || (GET_CODE (op
) == SUBREG
&& GET_CODE (SUBREG_REG (op
)) == REG
)
632 || (reload_in_progress
&& GET_CODE (op
) == REG
633 && REGNO (op
) >= FIRST_PSEUDO_REGISTER
)
634 || (reload_in_progress
&& GET_CODE (op
) == SUBREG
635 && GET_CODE (SUBREG_REG (op
)) == REG
636 && REGNO (SUBREG_REG (op
)) >= FIRST_PSEUDO_REGISTER
));
639 /* REF is an alignable memory location. Place an aligned SImode
640 reference into *PALIGNED_MEM and the number of bits to shift into
644 get_aligned_mem (ref
, paligned_mem
, pbitnum
)
646 rtx
*paligned_mem
, *pbitnum
;
649 HOST_WIDE_INT offset
= 0;
651 if (GET_CODE (ref
) == SUBREG
)
653 offset
= SUBREG_WORD (ref
) * UNITS_PER_WORD
;
654 if (BYTES_BIG_ENDIAN
)
655 offset
-= (MIN (UNITS_PER_WORD
, GET_MODE_SIZE (GET_MODE (ref
)))
656 - MIN (UNITS_PER_WORD
,
657 GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref
)))));
658 ref
= SUBREG_REG (ref
);
661 if (GET_CODE (ref
) == REG
)
662 ref
= reg_equiv_mem
[REGNO (ref
)];
664 if (reload_in_progress
)
665 base
= find_replacement (&XEXP (ref
, 0));
667 base
= XEXP (ref
, 0);
669 if (GET_CODE (base
) == PLUS
)
670 offset
+= INTVAL (XEXP (base
, 1)), base
= XEXP (base
, 0);
672 *paligned_mem
= gen_rtx (MEM
, SImode
,
673 plus_constant (base
, offset
& ~3));
674 MEM_IN_STRUCT_P (*paligned_mem
) = MEM_IN_STRUCT_P (ref
);
675 MEM_VOLATILE_P (*paligned_mem
) = MEM_VOLATILE_P (ref
);
676 RTX_UNCHANGING_P (*paligned_mem
) = RTX_UNCHANGING_P (ref
);
678 *pbitnum
= GEN_INT ((offset
& 3) * 8);
681 /* Similar, but just get the address. Handle the two reload cases.
682 Add EXTRA_OFFSET to the address we return. */
685 get_unaligned_address (ref
, extra_offset
)
690 HOST_WIDE_INT offset
= 0;
692 if (GET_CODE (ref
) == SUBREG
)
694 offset
= SUBREG_WORD (ref
) * UNITS_PER_WORD
;
695 if (BYTES_BIG_ENDIAN
)
696 offset
-= (MIN (UNITS_PER_WORD
, GET_MODE_SIZE (GET_MODE (ref
)))
697 - MIN (UNITS_PER_WORD
,
698 GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref
)))));
699 ref
= SUBREG_REG (ref
);
702 if (GET_CODE (ref
) == REG
)
703 ref
= reg_equiv_mem
[REGNO (ref
)];
705 if (reload_in_progress
)
706 base
= find_replacement (&XEXP (ref
, 0));
708 base
= XEXP (ref
, 0);
710 if (GET_CODE (base
) == PLUS
)
711 offset
+= INTVAL (XEXP (base
, 1)), base
= XEXP (base
, 0);
713 return plus_constant (base
, offset
+ extra_offset
);
716 /* Subfunction of the following function. Update the flags of any MEM
717 found in part of X. */
720 alpha_set_memflags_1 (x
, in_struct_p
, volatile_p
, unchanging_p
)
722 int in_struct_p
, volatile_p
, unchanging_p
;
726 switch (GET_CODE (x
))
730 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
731 alpha_set_memflags_1 (XVECEXP (x
, 0, i
), in_struct_p
, volatile_p
,
736 alpha_set_memflags_1 (PATTERN (x
), in_struct_p
, volatile_p
,
741 alpha_set_memflags_1 (SET_DEST (x
), in_struct_p
, volatile_p
,
743 alpha_set_memflags_1 (SET_SRC (x
), in_struct_p
, volatile_p
,
748 MEM_IN_STRUCT_P (x
) = in_struct_p
;
749 MEM_VOLATILE_P (x
) = volatile_p
;
750 RTX_UNCHANGING_P (x
) = unchanging_p
;
755 /* Given INSN, which is either an INSN or a SEQUENCE generated to
756 perform a memory operation, look for any MEMs in either a SET_DEST or
757 a SET_SRC and copy the in-struct, unchanging, and volatile flags from
758 REF into each of the MEMs found. If REF is not a MEM, don't do
762 alpha_set_memflags (insn
, ref
)
766 /* Note that it is always safe to get these flags, though they won't
767 be what we think if REF is not a MEM. */
768 int in_struct_p
= MEM_IN_STRUCT_P (ref
);
769 int volatile_p
= MEM_VOLATILE_P (ref
);
770 int unchanging_p
= RTX_UNCHANGING_P (ref
);
772 if (GET_CODE (ref
) != MEM
773 || (! in_struct_p
&& ! volatile_p
&& ! unchanging_p
))
776 alpha_set_memflags_1 (insn
, in_struct_p
, volatile_p
, unchanging_p
);
779 /* Try to output insns to set TARGET equal to the constant C if it can be
780 done in less than N insns. Do all computations in MODE. Returns the place
781 where the output has been placed if it can be done and the insns have been
782 emitted. If it would take more than N insns, zero is returned and no
783 insns and emitted. */
786 alpha_emit_set_const (target
, mode
, c
, n
)
788 enum machine_mode mode
;
795 /* Try 1 insn, then 2, then up to N. */
796 for (i
= 1; i
<= n
; i
++)
797 if ((pat
= alpha_emit_set_const_1 (target
, mode
, c
, i
)) != 0)
803 /* Internal routine for the above to check for N or below insns. */
806 alpha_emit_set_const_1 (target
, mode
, c
, n
)
808 enum machine_mode mode
;
812 HOST_WIDE_INT
new = c
;
814 /* Use a pseudo if highly optimizing and still generating RTL. */
816 = (flag_expensive_optimizations
&& rtx_equal_function_value_matters
820 #if HOST_BITS_PER_WIDE_INT == 64
821 /* We are only called for SImode and DImode. If this is SImode, ensure that
822 we are sign extended to a full word. This does not make any sense when
823 cross-compiling on a narrow machine. */
826 c
= (c
& 0xffffffff) - 2 * (c
& 0x80000000);
829 /* If this is a sign-extended 32-bit constant, we can do this in at most
830 three insns, so do it if we have enough insns left. We always have
831 a sign-extended 32-bit constant when compiling on a narrow machine.
832 Note that we cannot handle the constant 0x80000000. */
834 if ((HOST_BITS_PER_WIDE_INT
!= 64
835 || c
>> 31 == -1 || c
>> 31 == 0)
838 HOST_WIDE_INT low
= (c
& 0xffff) - 2 * (c
& 0x8000);
839 HOST_WIDE_INT tmp1
= c
- low
;
841 = ((tmp1
>> 16) & 0xffff) - 2 * ((tmp1
>> 16) & 0x8000);
842 HOST_WIDE_INT extra
= 0;
844 /* If HIGH will be interpreted as negative but the constant is
845 positive, we must adjust it to do two ldha insns. */
847 if ((high
& 0x8000) != 0 && c
>= 0)
851 high
= ((tmp1
>> 16) & 0xffff) - 2 * ((tmp1
>> 16) & 0x8000);
854 if (c
== low
|| (low
== 0 && extra
== 0))
855 return copy_to_suggested_reg (GEN_INT (c
), target
, mode
);
856 else if (n
>= 2 + (extra
!= 0))
858 temp
= copy_to_suggested_reg (GEN_INT (low
), subtarget
, mode
);
861 temp
= expand_binop (mode
, add_optab
, temp
, GEN_INT (extra
<< 16),
862 subtarget
, 0, OPTAB_WIDEN
);
864 return expand_binop (mode
, add_optab
, temp
, GEN_INT (high
<< 16),
865 target
, 0, OPTAB_WIDEN
);
869 /* If we couldn't do it that way, try some other methods. But if we have
870 no instructions left, don't bother. Likewise, if this is SImode and
871 we can't make pseudos, we can't do anything since the expand_binop
872 and expand_unop calls will widen and try to make pseudos. */
875 || (mode
== SImode
&& ! rtx_equal_function_value_matters
))
878 #if HOST_BITS_PER_WIDE_INT == 64
879 /* First, see if can load a value into the target that is the same as the
880 constant except that all bytes that are 0 are changed to be 0xff. If we
881 can, then we can do a ZAPNOT to obtain the desired constant. */
883 for (i
= 0; i
< 64; i
+= 8)
884 if ((new & ((HOST_WIDE_INT
) 0xff << i
)) == 0)
885 new |= (HOST_WIDE_INT
) 0xff << i
;
887 /* We are only called for SImode and DImode. If this is SImode, ensure that
888 we are sign extended to a full word. */
891 new = (new & 0xffffffff) - 2 * (new & 0x80000000);
894 && (temp
= alpha_emit_set_const (subtarget
, mode
, new, n
- 1)) != 0)
895 return expand_binop (mode
, and_optab
, temp
, GEN_INT (c
| ~ new),
896 target
, 0, OPTAB_WIDEN
);
899 /* Next, see if we can load a related constant and then shift and possibly
900 negate it to get the constant we want. Try this once each increasing
903 for (i
= 1; i
< n
; i
++)
905 /* First try complementing. */
906 if ((temp
= alpha_emit_set_const (subtarget
, mode
, ~ c
, i
)) != 0)
907 return expand_unop (mode
, one_cmpl_optab
, temp
, target
, 0);
909 /* Next try to form a constant and do a left shift. We can do this
910 if some low-order bits are zero; the exact_log2 call below tells
911 us that information. The bits we are shifting out could be any
912 value, but here we'll just try the 0- and sign-extended forms of
913 the constant. To try to increase the chance of having the same
914 constant in more than one insn, start at the highest number of
915 bits to shift, but try all possibilities in case a ZAPNOT will
918 if ((bits
= exact_log2 (c
& - c
)) > 0)
919 for (; bits
> 0; bits
--)
920 if ((temp
= (alpha_emit_set_const
922 (unsigned HOST_WIDE_INT
) c
>> bits
, i
))) != 0
923 || ((temp
= (alpha_emit_set_const
925 ((unsigned HOST_WIDE_INT
) c
) >> bits
, i
)))
927 return expand_binop (mode
, ashl_optab
, temp
, GEN_INT (bits
),
928 target
, 0, OPTAB_WIDEN
);
930 /* Now try high-order zero bits. Here we try the shifted-in bits as
931 all zero and all ones. Be careful to avoid shifting outside the
932 mode and to avoid shifting outside the host wide int size. */
934 if ((bits
= (MIN (HOST_BITS_PER_WIDE_INT
, GET_MODE_SIZE (mode
) * 8)
935 - floor_log2 (c
) - 1)) > 0)
936 for (; bits
> 0; bits
--)
937 if ((temp
= alpha_emit_set_const (subtarget
, mode
,
939 || ((temp
= (alpha_emit_set_const
941 ((c
<< bits
) | (((HOST_WIDE_INT
) 1 << bits
) - 1)),
944 return expand_binop (mode
, lshr_optab
, temp
, GEN_INT (bits
),
945 target
, 1, OPTAB_WIDEN
);
947 /* Now try high-order 1 bits. We get that with a sign-extension.
948 But one bit isn't enough here. Be careful to avoid shifting outside
949 the mode and to avoid shifting outside the host wide int size. */
951 if ((bits
= (MIN (HOST_BITS_PER_WIDE_INT
, GET_MODE_SIZE (mode
) * 8)
952 - floor_log2 (~ c
) - 2)) > 0)
953 for (; bits
> 0; bits
--)
954 if ((temp
= alpha_emit_set_const (subtarget
, mode
,
956 || ((temp
= (alpha_emit_set_const
958 ((c
<< bits
) | (((HOST_WIDE_INT
) 1 << bits
) - 1)),
961 return expand_binop (mode
, ashr_optab
, temp
, GEN_INT (bits
),
962 target
, 0, OPTAB_WIDEN
);
968 #if HOST_BITS_PER_WIDE_INT == 64
969 /* Having failed to find a 3 insn sequence in alpha_emit_set_const,
970 fall back to a straight forward decomposition. We do this to avoid
971 exponential run times encountered when looking for longer sequences
972 with alpha_emit_set_const. */
975 alpha_emit_set_long_const (target
, c
)
979 /* Use a pseudo if highly optimizing and still generating RTL. */
981 = (flag_expensive_optimizations
&& rtx_equal_function_value_matters
983 HOST_WIDE_INT d1
, d2
, d3
, d4
;
986 /* Decompose the entire word */
987 d1
= ((c
& 0xffff) ^ 0x8000) - 0x8000;
989 d2
= ((c
& 0xffffffff) ^ 0x80000000) - 0x80000000;
991 d3
= ((c
& 0xffff) ^ 0x8000) - 0x8000;
993 d4
= ((c
& 0xffffffff) ^ 0x80000000) - 0x80000000;
998 /* Construct the high word */
1000 r
= copy_to_suggested_reg (GEN_INT (d4
), subtarget
, DImode
);
1002 r
= copy_to_suggested_reg (GEN_INT (d3
), subtarget
, DImode
);
1004 r
= expand_binop (DImode
, add_optab
, GEN_INT (d3
), GEN_INT (d4
),
1005 subtarget
, 0, OPTAB_WIDEN
);
1007 /* Shift it into place */
1008 r
= expand_binop (DImode
, ashl_optab
, r
, GEN_INT (32),
1009 subtarget
, 0, OPTAB_WIDEN
);
1011 /* Add in the low word */
1013 r
= expand_binop (DImode
, add_optab
, r
, GEN_INT (d2
),
1014 subtarget
, 0, OPTAB_WIDEN
);
1016 r
= expand_binop (DImode
, add_optab
, r
, GEN_INT (d1
),
1017 subtarget
, 0, OPTAB_WIDEN
);
1020 r
= copy_to_suggested_reg(r
, target
, DImode
);
1024 #endif /* HOST_BITS_PER_WIDE_INT == 64 */
1026 /* Rewrite a comparison against zero CMP of the form
1027 (CODE (cc0) (const_int 0)) so it can be written validly in
1028 a conditional move (if_then_else CMP ...).
1029 If both of the operands that set cc0 are non-zero we must emit
1030 an insn to perform the compare (it can't be done within
1031 the conditional move). */
1033 alpha_emit_conditional_move (cmp
, mode
)
1035 enum machine_mode mode
;
1037 enum rtx_code code
= GET_CODE (cmp
);
1038 rtx op0
= alpha_compare_op0
;
1039 rtx op1
= alpha_compare_op1
;
1040 enum machine_mode cmp_mode
1041 = (GET_MODE (op0
) == VOIDmode
? DImode
: GET_MODE (op0
));
1042 enum machine_mode cmp_op_mode
= alpha_compare_fp_p
? DFmode
: DImode
;
1045 if (alpha_compare_fp_p
!= FLOAT_MODE_P (mode
))
1048 /* We may be able to use a conditional move directly.
1049 This avoids emitting spurious compares. */
1050 if (signed_comparison_operator (cmp
, cmp_op_mode
)
1051 && (op0
== CONST0_RTX (cmp_mode
) || op1
== CONST0_RTX (cmp_mode
)))
1052 return gen_rtx (code
, VOIDmode
, op0
, op1
);
1054 /* We can't put the comparison insides a conditional move;
1055 emit a compare instruction and put that inside the
1056 conditional move. Make sure we emit only comparisons we have;
1057 swap or reverse as necessary. */
1061 case EQ
: case LE
: case LT
: case LEU
: case LTU
:
1062 /* We have these compares: */
1066 /* This must be reversed. */
1067 code
= reverse_condition (code
);
1070 case GE
: case GT
: case GEU
: case GTU
:
1071 /* These must be swapped. Make sure the new first operand is in
1073 code
= swap_condition (code
);
1074 tem
= op0
, op0
= op1
, op1
= tem
;
1075 op0
= force_reg (cmp_mode
, op0
);
1082 tem
= gen_reg_rtx (cmp_op_mode
);
1083 emit_move_insn (tem
, gen_rtx (code
, cmp_op_mode
, op0
, op1
));
1084 return gen_rtx (code
== NE
? EQ
: NE
, VOIDmode
, tem
,
1085 CONST0_RTX (cmp_op_mode
));
1088 /* Adjust the cost of a scheduling dependency. Return the new cost of
1089 a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
1092 alpha_adjust_cost (insn
, link
, dep_insn
, cost
)
1100 /* If the dependence is an anti-dependence, there is no cost. For an
1101 output dependence, there is sometimes a cost, but it doesn't seem
1102 worth handling those few cases. */
1104 if (REG_NOTE_KIND (link
) != 0)
1107 /* EV5 costs are as given in alpha.md; exceptions are given here. */
1108 if (alpha_cpu
== PROCESSOR_EV5
)
1110 /* And the lord DEC sayeth: "A special bypass provides an effective
1111 latency of 0 cycles for an ICMP or ILOG insn producing the test
1112 operand of an IBR or CMOV insn." */
1113 if (recog_memoized (dep_insn
) >= 0
1114 && (get_attr_type (dep_insn
) == TYPE_ICMP
1115 || get_attr_type (dep_insn
) == TYPE_ILOG
)
1116 && recog_memoized (insn
) >= 0
1117 && (get_attr_type (insn
) == TYPE_IBR
1118 || (get_attr_type (insn
) == TYPE_CMOV
1119 && !((set
= single_set (dep_insn
)) != 0
1120 && GET_CODE (PATTERN (insn
)) == SET
1121 && GET_CODE (SET_SRC (PATTERN (insn
))) == IF_THEN_ELSE
1122 && (rtx_equal_p (SET_DEST (set
),
1123 XEXP (SET_SRC (PATTERN (insn
)), 1))
1124 || rtx_equal_p (SET_DEST (set
),
1125 XEXP (SET_SRC (PATTERN (insn
)), 2)))))))
1130 /* If INSN is a store insn and DEP_INSN is setting the data being stored,
1131 we can sometimes lower the cost. */
1133 if (recog_memoized (insn
) >= 0 && get_attr_type (insn
) == TYPE_ST
1134 && (set
= single_set (dep_insn
)) != 0
1135 && GET_CODE (PATTERN (insn
)) == SET
1136 && rtx_equal_p (SET_DEST (set
), SET_SRC (PATTERN (insn
))))
1137 switch (get_attr_type (dep_insn
))
1140 /* No savings here. */
1145 /* In these cases, we save one cycle. */
1149 /* In all other cases, we save two cycles. */
1150 return MAX (0, cost
- 4);
1153 /* Another case that needs adjustment is an arithmetic or logical
1154 operation. It's cost is usually one cycle, but we default it to
1155 two in the MD file. The only case that it is actually two is
1156 for the address in loads and stores. */
1158 if (recog_memoized (dep_insn
) >= 0
1159 && (get_attr_type (dep_insn
) == TYPE_IADD
1160 || get_attr_type (dep_insn
) == TYPE_ILOG
))
1161 switch (get_attr_type (insn
))
1171 /* The final case is when a compare feeds into an integer branch. The cost
1172 is only one cycle in that case. */
1174 if (recog_memoized (dep_insn
) >= 0
1175 && get_attr_type (dep_insn
) == TYPE_ICMP
1176 && recog_memoized (insn
) >= 0
1177 && get_attr_type (insn
) == TYPE_IBR
)
1180 /* Otherwise, return the default cost. */
1185 /* Print an operand. Recognize special options, documented below. */
1188 print_operand (file
, x
, code
)
1198 /* Generates fp-rounding mode suffix: nothing for normal, 'c' for
1199 chopped, 'm' for minus-infinity, and 'd' for dynamic rounding
1200 mode. alpha_fprm controls which suffix is generated. */
1203 case ALPHA_FPRM_NORM
:
1205 case ALPHA_FPRM_MINF
:
1208 case ALPHA_FPRM_CHOP
:
1211 case ALPHA_FPRM_DYN
:
1218 /* Generates trap-mode suffix for instructions that accept the su
1219 suffix only (cmpt et al). */
1220 if (alpha_tp
== ALPHA_TP_INSN
)
1225 /* Generates trap-mode suffix for instructions that accept the u, su,
1226 and sui suffix. This is the bulk of the IEEE floating point
1227 instructions (addt et al). */
1238 case ALPHA_FPTM_SUI
:
1239 fputs ("sui", file
);
1245 /* Generates trap-mode suffix for instructions that accept the sui
1246 suffix (cvtqt and cvtqs). */
1249 case ALPHA_FPTM_N
: case ALPHA_FPTM_U
:
1250 case ALPHA_FPTM_SU
: /* cvtqt/cvtqs can't cause underflow */
1252 case ALPHA_FPTM_SUI
:
1253 fputs ("sui", file
);
1259 /* If this operand is the constant zero, write it as "$31". */
1260 if (GET_CODE (x
) == REG
)
1261 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1262 else if (x
== CONST0_RTX (GET_MODE (x
)))
1263 fprintf (file
, "$31");
1265 output_operand_lossage ("invalid %%r value");
1270 /* Similar, but for floating-point. */
1271 if (GET_CODE (x
) == REG
)
1272 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1273 else if (x
== CONST0_RTX (GET_MODE (x
)))
1274 fprintf (file
, "$f31");
1276 output_operand_lossage ("invalid %%R value");
1281 /* Write the 1's complement of a constant. */
1282 if (GET_CODE (x
) != CONST_INT
)
1283 output_operand_lossage ("invalid %%N value");
1285 fprintf (file
, "%ld", ~ INTVAL (x
));
1289 /* Write 1 << C, for a constant C. */
1290 if (GET_CODE (x
) != CONST_INT
)
1291 output_operand_lossage ("invalid %%P value");
1293 fprintf (file
, "%ld", (HOST_WIDE_INT
) 1 << INTVAL (x
));
1297 /* Write the high-order 16 bits of a constant, sign-extended. */
1298 if (GET_CODE (x
) != CONST_INT
)
1299 output_operand_lossage ("invalid %%h value");
1301 fprintf (file
, "%ld", INTVAL (x
) >> 16);
1305 /* Write the low-order 16 bits of a constant, sign-extended. */
1306 if (GET_CODE (x
) != CONST_INT
)
1307 output_operand_lossage ("invalid %%L value");
1309 fprintf (file
, "%ld", (INTVAL (x
) & 0xffff) - 2 * (INTVAL (x
) & 0x8000));
1313 /* Write mask for ZAP insn. */
1314 if (GET_CODE (x
) == CONST_DOUBLE
)
1316 HOST_WIDE_INT mask
= 0;
1317 HOST_WIDE_INT value
;
1319 value
= CONST_DOUBLE_LOW (x
);
1320 for (i
= 0; i
< HOST_BITS_PER_WIDE_INT
/ HOST_BITS_PER_CHAR
;
1325 value
= CONST_DOUBLE_HIGH (x
);
1326 for (i
= 0; i
< HOST_BITS_PER_WIDE_INT
/ HOST_BITS_PER_CHAR
;
1329 mask
|= (1 << (i
+ sizeof (int)));
1331 fprintf (file
, "%ld", mask
& 0xff);
1334 else if (GET_CODE (x
) == CONST_INT
)
1336 HOST_WIDE_INT mask
= 0, value
= INTVAL (x
);
1338 for (i
= 0; i
< 8; i
++, value
>>= 8)
1342 fprintf (file
, "%ld", mask
);
1345 output_operand_lossage ("invalid %%m value");
1349 /* 'b', 'w', or 'l' as the value of the constant. */
1350 if (GET_CODE (x
) != CONST_INT
1351 || (INTVAL (x
) != 8 && INTVAL (x
) != 16 && INTVAL (x
) != 32))
1352 output_operand_lossage ("invalid %%M value");
1354 fprintf (file
, "%s",
1355 INTVAL (x
) == 8 ? "b" : INTVAL (x
) == 16 ? "w" : "l");
1359 /* Similar, except do it from the mask. */
1360 if (GET_CODE (x
) == CONST_INT
&& INTVAL (x
) == 0xff)
1361 fprintf (file
, "b");
1362 else if (GET_CODE (x
) == CONST_INT
&& INTVAL (x
) == 0xffff)
1363 fprintf (file
, "w");
1364 #if HOST_BITS_PER_WIDE_INT == 32
1365 else if (GET_CODE (x
) == CONST_DOUBLE
1366 && CONST_DOUBLE_HIGH (x
) == 0
1367 && CONST_DOUBLE_LOW (x
) == -1)
1368 fprintf (file
, "l");
1370 else if (GET_CODE (x
) == CONST_INT
&& INTVAL (x
) == 0xffffffff)
1371 fprintf (file
, "l");
1374 output_operand_lossage ("invalid %%U value");
1378 /* Write the constant value divided by 8. */
1379 if (GET_CODE (x
) != CONST_INT
1380 && (unsigned HOST_WIDE_INT
) INTVAL (x
) >= 64
1381 && (INTVAL (x
) & 7) != 8)
1382 output_operand_lossage ("invalid %%s value");
1384 fprintf (file
, "%ld", INTVAL (x
) / 8);
1388 /* Same, except compute (64 - c) / 8 */
1390 if (GET_CODE (x
) != CONST_INT
1391 && (unsigned HOST_WIDE_INT
) INTVAL (x
) >= 64
1392 && (INTVAL (x
) & 7) != 8)
1393 output_operand_lossage ("invalid %%s value");
1395 fprintf (file
, "%ld", (64 - INTVAL (x
)) / 8);
1399 /* Write out comparison name. */
1400 if (GET_RTX_CLASS (GET_CODE (x
)) != '<')
1401 output_operand_lossage ("invalid %%C value");
1403 if (GET_CODE (x
) == LEU
)
1404 fprintf (file
, "ule");
1405 else if (GET_CODE (x
) == LTU
)
1406 fprintf (file
, "ult");
1408 fprintf (file
, "%s", GET_RTX_NAME (GET_CODE (x
)));
1412 /* Similar, but write reversed code. We can't get an unsigned code
1414 if (GET_RTX_CLASS (GET_CODE (x
)) != '<')
1415 output_operand_lossage ("invalid %%D value");
1417 fprintf (file
, "%s", GET_RTX_NAME (reverse_condition (GET_CODE (x
))));
1421 /* Similar to `c', but swap. We can't get unsigned here either. */
1422 if (GET_RTX_CLASS (GET_CODE (x
)) != '<')
1423 output_operand_lossage ("invalid %%D value");
1425 fprintf (file
, "%s", GET_RTX_NAME (swap_condition (GET_CODE (x
))));
1429 /* Similar, but reverse and swap. We can't get unsigned here either. */
1430 if (GET_RTX_CLASS (GET_CODE (x
)) != '<')
1431 output_operand_lossage ("invalid %%D value");
1433 fprintf (file
, "%s",
1434 GET_RTX_NAME (swap_condition (reverse_condition ((GET_CODE (x
))))));
1438 /* Write the divide or modulus operator. */
1439 switch (GET_CODE (x
))
1442 fprintf (file
, "div%s", GET_MODE (x
) == SImode
? "l" : "q");
1445 fprintf (file
, "div%su", GET_MODE (x
) == SImode
? "l" : "q");
1448 fprintf (file
, "rem%s", GET_MODE (x
) == SImode
? "l" : "q");
1451 fprintf (file
, "rem%su", GET_MODE (x
) == SImode
? "l" : "q");
1454 output_operand_lossage ("invalid %%E value");
1460 /* Write "_u" for unaligned access. */
1461 if (GET_CODE (x
) == MEM
&& GET_CODE (XEXP (x
, 0)) == AND
)
1462 fprintf (file
, "_u");
1466 if (GET_CODE (x
) == REG
)
1467 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1468 else if (GET_CODE (x
) == MEM
)
1469 output_address (XEXP (x
, 0));
1471 output_addr_const (file
, x
);
1475 output_operand_lossage ("invalid %%xn code");
1479 /* Do what is necessary for `va_start'. The argument is ignored;
1480 We look at the current function to determine if stdarg or varargs
1481 is used and fill in an initial va_list. A pointer to this constructor
1485 alpha_builtin_saveregs (arglist
)
1488 rtx block
, addr
, argsize
;
1489 tree fntype
= TREE_TYPE (current_function_decl
);
1490 int stdarg
= (TYPE_ARG_TYPES (fntype
) != 0
1491 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype
)))
1492 != void_type_node
));
1494 /* Compute the current position into the args, taking into account
1495 both registers and memory. Both of these are already included in
1496 current_function_args_info. */
1498 argsize
= GEN_INT (current_function_args_info
* UNITS_PER_WORD
);
1500 /* SETUP_INCOMING_VARARGS moves the starting address base up by 48,
1501 storing fp arg registers in the first 48 bytes, and the integer arg
1502 registers in the next 48 bytes. This is only done, however, if any
1503 integer registers need to be stored.
1505 If no integer registers need be stored, then we must subtract 48 in
1506 order to account for the integer arg registers which are counted in
1507 argsize above, but which are not actually stored on the stack. */
1509 addr
= (current_function_args_info
<= 5 + stdarg
1510 ? plus_constant (virtual_incoming_args_rtx
, 6 * UNITS_PER_WORD
)
1511 : plus_constant (virtual_incoming_args_rtx
, - (6 * UNITS_PER_WORD
)));
1513 addr
= force_operand (addr
, NULL_RTX
);
1515 /* Allocate the va_list constructor */
1516 block
= assign_stack_local (BLKmode
, 2 * UNITS_PER_WORD
, BITS_PER_WORD
);
1517 RTX_UNCHANGING_P (block
) = 1;
1518 RTX_UNCHANGING_P (XEXP (block
, 0)) = 1;
1520 /* Store the address of the first integer register in the __base member. */
1522 #ifdef POINTERS_EXTEND_UNSIGNED
1523 addr
= convert_memory_address (ptr_mode
, addr
);
1526 emit_move_insn (change_address (block
, ptr_mode
, XEXP (block
, 0)), addr
);
1528 /* Store the argsize as the __va_offset member. */
1529 emit_move_insn (change_address (block
, TYPE_MODE (integer_type_node
),
1530 plus_constant (XEXP (block
, 0),
1531 POINTER_SIZE
/BITS_PER_UNIT
)),
1534 /* Return the address of the va_list constructor, but don't put it in a
1535 register. Doing so would fail when not optimizing and produce worse
1536 code when optimizing. */
1537 return XEXP (block
, 0);
1540 /* This page contains routines that are used to determine what the function
1541 prologue and epilogue code will do and write them out. */
1543 /* Compute the size of the save area in the stack. */
1551 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1552 if (! fixed_regs
[i
] && ! call_used_regs
[i
] && regs_ever_live
[i
])
1555 /* If some registers were saved but not reg 26, reg 26 must also
1556 be saved, so leave space for it. */
1557 if (size
!= 0 && ! regs_ever_live
[26])
1560 /* Our size must be even (multiple of 16 bytes). */
1567 /* Return 1 if this function can directly return via $26. */
1572 return (reload_completed
&& alpha_sa_size () == 0
1573 && get_frame_size () == 0
1574 && current_function_outgoing_args_size
== 0
1575 && current_function_pretend_args_size
== 0);
1578 /* Write a version stamp. Don't write anything if we are running as a
1579 cross-compiler. Otherwise, use the versions in /usr/include/stamp.h. */
1581 #if !defined(CROSS_COMPILE) && !defined(_WIN32) && !defined(__linux__)
1586 alpha_write_verstamp (file
)
1590 fprintf (file
, "\t.verstamp %d %d\n", MS_STAMP
, LS_STAMP
);
1594 /* Write code to add constant C to register number IN_REG (possibly 31)
1595 and put the result into OUT_REG. Use TEMP_REG as a scratch register;
1596 usually this will be OUT_REG, but should not be if OUT_REG is
1597 STACK_POINTER_REGNUM, since it must be updated in a single instruction.
1598 Write the code to FILE. */
1601 add_long_const (file
, c
, in_reg
, out_reg
, temp_reg
)
1604 int in_reg
, out_reg
, temp_reg
;
1606 HOST_WIDE_INT low
= (c
& 0xffff) - 2 * (c
& 0x8000);
1607 HOST_WIDE_INT tmp1
= c
- low
;
1608 HOST_WIDE_INT high
= ((tmp1
>> 16) & 0xffff) - 2 * ((tmp1
>> 16) & 0x8000);
1609 HOST_WIDE_INT extra
= 0;
1611 /* We don't have code to write out constants larger than 32 bits. */
1612 #if HOST_BITS_PER_LONG_INT == 64
1613 if ((unsigned HOST_WIDE_INT
) c
>> 32 != 0)
1617 /* If HIGH will be interpreted as negative, we must adjust it to do two
1618 ldha insns. Note that we will never be building a negative constant
1625 high
= ((tmp1
>> 16) & 0xffff) - 2 * ((tmp1
>> 16) & 0x8000);
1630 int result_reg
= (extra
== 0 && high
== 0) ? out_reg
: temp_reg
;
1632 if (low
>= 0 && low
< 255)
1633 fprintf (file
, "\taddq $%d,%d,$%d\n", in_reg
, low
, result_reg
);
1635 fprintf (file
, "\tlda $%d,%d($%d)\n", result_reg
, low
, in_reg
);
1637 in_reg
= result_reg
;
1642 int result_reg
= (high
== 0) ? out_reg
: temp_reg
;
1644 fprintf (file
, "\tldah $%d,%d($%d)\n", result_reg
, extra
, in_reg
);
1645 in_reg
= result_reg
;
1649 fprintf (file
, "\tldah $%d,%d($%d)\n", out_reg
, high
, in_reg
);
1652 /* Write function prologue. */
1655 output_prolog (file
, size
)
1659 HOST_WIDE_INT out_args_size
1660 = ALPHA_ROUND (current_function_outgoing_args_size
);
1661 HOST_WIDE_INT sa_size
= alpha_sa_size ();
1662 HOST_WIDE_INT frame_size
1663 = (out_args_size
+ sa_size
1664 + ALPHA_ROUND (size
+ current_function_pretend_args_size
));
1665 HOST_WIDE_INT reg_offset
= out_args_size
;
1666 HOST_WIDE_INT start_reg_offset
= reg_offset
;
1667 HOST_WIDE_INT actual_start_reg_offset
= start_reg_offset
;
1668 int int_reg_save_area_size
= 0;
1670 unsigned reg_mask
= 0;
1673 /* Ecoff can handle multiple .file directives, so put out file and lineno.
1674 We have to do that before the .ent directive as we cannot switch
1675 files within procedures with native ecoff because line numbers are
1676 linked to procedure descriptors.
1677 Outputting the lineno helps debugging of one line functions as they
1678 would otherwise get no line number at all. Please note that we would
1679 like to put out last_linenum from final.c, but it is not accessible. */
1681 if (write_symbols
== SDB_DEBUG
)
1683 ASM_OUTPUT_SOURCE_FILENAME (file
,
1684 DECL_SOURCE_FILE (current_function_decl
));
1685 if (debug_info_level
!= DINFO_LEVEL_TERSE
)
1686 ASM_OUTPUT_SOURCE_LINE (file
,
1687 DECL_SOURCE_LINE (current_function_decl
));
1690 /* The assembly language programmer's guide states that the second argument
1691 to the .ent directive, the lex_level, is ignored by the assembler,
1692 so we might as well omit it. */
1694 if (!flag_inhibit_size_directive
)
1696 fprintf (file
, "\t.ent ");
1697 assemble_name (file
, alpha_function_name
);
1698 fprintf (file
, "\n");
1700 ASM_OUTPUT_LABEL (file
, alpha_function_name
);
1701 inside_function
= TRUE
;
1703 if (TARGET_IEEE_CONFORMANT
&& !flag_inhibit_size_directive
)
1704 /* Set flags in procedure descriptor to request IEEE-conformant
1705 math-library routines. The value we set it to is PDSC_EXC_IEEE
1706 (/usr/include/pdsc.h). */
1707 fprintf (file
, "\t.eflag 48\n");
1709 /* Set up offsets to alpha virtual arg/local debugging pointer. */
1711 alpha_auto_offset
= -frame_size
+ current_function_pretend_args_size
;
1712 alpha_arg_offset
= -frame_size
+ 48;
1714 /* If we need a GP (we have a LDSYM insn or a CALL_INSN), load it first.
1715 Even if we are a static function, we still need to do this in case
1716 our address is taken and passed to something like qsort.
1718 We never need a GP for Windows/NT. */
1720 alpha_function_needs_gp
= 0;
1722 #ifdef TARGET_PROFILING_NEEDS_GP
1724 alpha_function_needs_gp
= 1;
1727 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
1728 if ((GET_CODE (insn
) == CALL_INSN
)
1729 || (GET_RTX_CLASS (GET_CODE (insn
)) == 'i'
1730 && GET_CODE (PATTERN (insn
)) != USE
1731 && GET_CODE (PATTERN (insn
)) != CLOBBER
1732 && (get_attr_type (insn
) == TYPE_LDSYM
1733 || get_attr_type (insn
) == TYPE_ISUBR
)))
1735 alpha_function_needs_gp
= 1;
1739 if (TARGET_WINDOWS_NT
== 0)
1741 if (alpha_function_needs_gp
)
1742 fprintf (file
, "\tldgp $29,0($27)\n");
1744 /* Put a label after the GP load so we can enter the function at it. */
1745 assemble_name (file
, alpha_function_name
);
1746 fprintf (file
, "..ng:\n");
1749 /* Adjust the stack by the frame size. If the frame size is > 4096
1750 bytes, we need to be sure we probe somewhere in the first and last
1751 4096 bytes (we can probably get away without the latter test) and
1752 every 8192 bytes in between. If the frame size is > 32768, we
1753 do this in a loop. Otherwise, we generate the explicit probe
1756 Note that we are only allowed to adjust sp once in the prologue. */
1758 if (frame_size
< 32768)
1760 if (frame_size
> 4096)
1764 fprintf (file
, "\tstq $31,-%d($30)\n", probed
);
1766 while (probed
+ 8192 < frame_size
)
1767 fprintf (file
, "\tstq $31,-%d($30)\n", probed
+= 8192);
1769 /* We only have to do this probe if we aren't saving registers. */
1770 if (sa_size
== 0 && probed
+ 4096 < frame_size
)
1771 fprintf (file
, "\tstq $31,-%d($30)\n", frame_size
);
1774 if (frame_size
!= 0)
1775 fprintf (file
, "\tlda $30,-%d($30)\n", frame_size
);
1779 /* Here we generate code to set R4 to SP + 4096 and set R5 to the
1780 number of 8192 byte blocks to probe. We then probe each block
1781 in the loop and then set SP to the proper location. If the
1782 amount remaining is > 4096, we have to do one more probe if we
1783 are not saving any registers. */
1785 HOST_WIDE_INT blocks
= (frame_size
+ 4096) / 8192;
1786 HOST_WIDE_INT leftover
= frame_size
+ 4096 - blocks
* 8192;
1788 add_long_const (file
, blocks
, 31, 5, 5);
1790 fprintf (file
, "\tlda $4,4096($30)\n");
1792 assemble_name (file
, alpha_function_name
);
1793 fprintf (file
, "..sc:\n");
1795 fprintf (file
, "\tstq $31,-8192($4)\n");
1796 fprintf (file
, "\tsubq $5,1,$5\n");
1797 fprintf (file
, "\tlda $4,-8192($4)\n");
1799 fprintf (file
, "\tbne $5,");
1800 assemble_name (file
, alpha_function_name
);
1801 fprintf (file
, "..sc\n");
1803 if (leftover
> 4096 && sa_size
== 0)
1804 fprintf (file
, "\tstq $31,-%d($4)\n", leftover
);
1806 fprintf (file
, "\tlda $30,-%d($4)\n", leftover
);
1809 /* Describe our frame. */
1810 if (!flag_inhibit_size_directive
)
1812 fprintf (file
, "\t.frame $%d,%d,$26,%d\n",
1813 (frame_pointer_needed
1814 ? HARD_FRAME_POINTER_REGNUM
: STACK_POINTER_REGNUM
),
1815 frame_size
, current_function_pretend_args_size
);
1818 /* Save register 26 if any other register needs to be saved. */
1821 reg_mask
|= 1 << 26;
1822 fprintf (file
, "\tstq $26,%d($30)\n", reg_offset
);
1824 int_reg_save_area_size
+= 8;
1827 /* Now save any other used integer registers required to be saved. */
1828 for (i
= 0; i
< 32; i
++)
1829 if (! fixed_regs
[i
] && ! call_used_regs
[i
] && regs_ever_live
[i
] && i
!= 26)
1832 fprintf (file
, "\tstq $%d,%d($30)\n", i
, reg_offset
);
1834 int_reg_save_area_size
+= 8;
1837 /* Print the register mask and do floating-point saves. */
1838 if (reg_mask
&& !flag_inhibit_size_directive
)
1839 fprintf (file
, "\t.mask 0x%x,%d\n", reg_mask
,
1840 actual_start_reg_offset
- frame_size
);
1842 start_reg_offset
= reg_offset
;
1845 for (i
= 0; i
< 32; i
++)
1846 if (! fixed_regs
[i
+ 32] && ! call_used_regs
[i
+ 32]
1847 && regs_ever_live
[i
+ 32])
1850 fprintf (file
, "\tstt $f%d,%d($30)\n", i
, reg_offset
);
1854 /* Print the floating-point mask, if we've saved any fp register. */
1855 if (reg_mask
&& !flag_inhibit_size_directive
)
1856 fprintf (file
, "\t.fmask 0x%x,%d\n", reg_mask
,
1857 actual_start_reg_offset
- frame_size
+ int_reg_save_area_size
);
1859 /* If we need a frame pointer, set it from the stack pointer. Note that
1860 this must always be the last instruction in the prologue. */
1861 if (frame_pointer_needed
)
1862 fprintf (file
, "\tbis $30,$30,$15\n");
1864 /* End the prologue and say if we used gp. */
1865 if (!flag_inhibit_size_directive
)
1866 fprintf (file
, "\t.prologue %d\n", alpha_function_needs_gp
);
1869 /* Write function epilogue. */
1872 output_epilog (file
, size
)
1876 rtx insn
= get_last_insn ();
1877 HOST_WIDE_INT out_args_size
1878 = ALPHA_ROUND (current_function_outgoing_args_size
);
1879 HOST_WIDE_INT sa_size
= alpha_sa_size ();
1880 HOST_WIDE_INT frame_size
1881 = (out_args_size
+ sa_size
1882 + ALPHA_ROUND (size
+ current_function_pretend_args_size
));
1883 HOST_WIDE_INT reg_offset
= out_args_size
;
1884 HOST_WIDE_INT frame_size_from_reg_save
= frame_size
- reg_offset
;
1886 = frame_pointer_needed
&& regs_ever_live
[HARD_FRAME_POINTER_REGNUM
];
1889 /* If the last insn was a BARRIER, we don't have to write anything except
1890 the .end pseudo-op. */
1891 if (GET_CODE (insn
) == NOTE
)
1892 insn
= prev_nonnote_insn (insn
);
1893 if (insn
== 0 || GET_CODE (insn
) != BARRIER
)
1897 final_prescan_insn (NULL_RTX
, NULL_PTR
, 0);
1899 /* If we have a frame pointer, restore SP from it. */
1900 if (frame_pointer_needed
)
1901 fprintf (file
, "\tbis $15,$15,$30\n");
1903 /* Restore all the registers, starting with the return address
1907 fprintf (file
, "\tldq $26,%d($30)\n", reg_offset
);
1911 /* Now restore any other used integer registers that that we saved,
1912 except for FP if it is being used as FP, since it must be
1915 for (i
= 0; i
< 32; i
++)
1916 if (! fixed_regs
[i
] && ! call_used_regs
[i
] && regs_ever_live
[i
]
1919 if (i
== HARD_FRAME_POINTER_REGNUM
&& frame_pointer_needed
)
1920 fp_offset
= reg_offset
;
1922 fprintf (file
, "\tldq $%d,%d($30)\n", i
, reg_offset
);
1926 for (i
= 0; i
< 32; i
++)
1927 if (! fixed_regs
[i
+ 32] && ! call_used_regs
[i
+ 32]
1928 && regs_ever_live
[i
+ 32])
1930 fprintf (file
, "\tldt $f%d,%d($30)\n", i
, reg_offset
);
1934 /* If the stack size is large and we have a frame pointer, compute the
1935 size of the stack into a register because the old FP restore, stack
1936 pointer adjust, and return are required to be consecutive
1938 if (frame_size
> 32767 && restore_fp
)
1939 add_long_const (file
, frame_size
, 31, 1, 1);
1941 /* If we needed a frame pointer and we have to restore it, do it
1942 now. This must be done in one instruction immediately
1943 before the SP update. */
1944 if (restore_fp
&& fp_offset
)
1945 fprintf (file
, "\tldq $15,%d($30)\n", fp_offset
);
1947 /* Now update the stack pointer, if needed. Only one instruction must
1948 modify the stack pointer. It must be the last instruction in the
1949 sequence and must be an ADDQ or LDA instruction. If the frame
1950 pointer was loaded above, we may only put one instruction here. */
1952 if (frame_size
> 32768 && restore_fp
)
1953 fprintf (file
, "\taddq $1,$30,$30\n");
1955 add_long_const (file
, frame_size
, 30, 30, 1);
1957 /* Finally return to the caller. */
1958 fprintf (file
, "\tret $31,($26),1\n");
1961 /* End the function. */
1962 if (!flag_inhibit_size_directive
)
1964 fprintf (file
, "\t.end ");
1965 assemble_name (file
, alpha_function_name
);
1966 fprintf (file
, "\n");
1968 inside_function
= FALSE
;
1970 /* Show that we know this function if it is called again. */
1971 SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl
), 0)) = 1;
1974 /* Debugging support. */
1978 /* Count the number of sdb related labels are generated (to find block
1979 start and end boundaries). */
1981 int sdb_label_count
= 0;
1983 /* Next label # for each statement. */
1985 static int sym_lineno
= 0;
1987 /* Count the number of .file directives, so that .loc is up to date. */
1989 static int num_source_filenames
= 0;
1991 /* Name of the file containing the current function. */
1993 static char *current_function_file
= "";
1995 /* Offsets to alpha virtual arg/local debugging pointers. */
1997 long alpha_arg_offset
;
1998 long alpha_auto_offset
;
2000 /* Emit a new filename to a stream. */
2003 alpha_output_filename (stream
, name
)
2007 static int first_time
= TRUE
;
2008 char ltext_label_name
[100];
2013 ++num_source_filenames
;
2014 current_function_file
= name
;
2015 fprintf (stream
, "\t.file\t%d ", num_source_filenames
);
2016 output_quoted_string (stream
, name
);
2017 fprintf (stream
, "\n");
2018 if (!TARGET_GAS
&& write_symbols
== DBX_DEBUG
)
2019 fprintf (stream
, "\t#@stabs\n");
2022 else if (!TARGET_GAS
&& write_symbols
== DBX_DEBUG
)
2024 ASM_GENERATE_INTERNAL_LABEL (ltext_label_name
, "Ltext", 0);
2025 fprintf (stream
, "%s ", ASM_STABS_OP
);
2026 output_quoted_string (stream
, name
);
2027 fprintf (stream
, ",%d,0,0,%s\n", N_SOL
, <ext_label_name
[1]);
2030 else if (name
!= current_function_file
2031 && strcmp (name
, current_function_file
) != 0)
2033 if (inside_function
&& ! TARGET_GAS
)
2034 fprintf (stream
, "\t#.file\t%d ", num_source_filenames
);
2037 ++num_source_filenames
;
2038 current_function_file
= name
;
2039 fprintf (stream
, "\t.file\t%d ", num_source_filenames
);
2042 output_quoted_string (stream
, name
);
2043 fprintf (stream
, "\n");
2047 /* Emit a linenumber to a stream. */
2050 alpha_output_lineno (stream
, line
)
2054 if (TARGET_GAS
&& write_symbols
== DBX_DEBUG
)
2056 /* mips-tfile doesn't understand .stabd directives. */
2058 fprintf (stream
, "$LM%d:\n\t%s %d,0,%d,$LM%d\n",
2059 sym_lineno
, ASM_STABN_OP
, N_SLINE
, line
, sym_lineno
);
2062 fprintf (stream
, "\n\t.loc\t%d %d\n", num_source_filenames
, line
);
2065 /* Structure to show the current status of registers and memory. */
2067 struct shadow_summary
2070 unsigned long i
: 32; /* Mask of int regs */
2071 unsigned long fp
: 32; /* Mask of fp regs */
2072 unsigned long mem
: 1; /* mem == imem | fpmem */
2076 /* Summary the effects of expression X on the machine. Update SUM, a pointer
2077 to the summary structure. SET is nonzero if the insn is setting the
2078 object, otherwise zero. */
2081 summarize_insn (x
, sum
, set
)
2083 struct shadow_summary
*sum
;
2092 switch (GET_CODE (x
))
2094 /* ??? Note that this case would be incorrect if the Alpha had a
2095 ZERO_EXTRACT in SET_DEST. */
2097 summarize_insn (SET_SRC (x
), sum
, 0);
2098 summarize_insn (SET_DEST (x
), sum
, 1);
2102 summarize_insn (XEXP (x
, 0), sum
, 1);
2106 summarize_insn (XEXP (x
, 0), sum
, 0);
2110 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
2111 summarize_insn (XVECEXP (x
, 0, i
), sum
, 0);
2116 int regno
= REGNO (x
);
2117 unsigned long mask
= 1UL << (regno
% 32);
2119 if (regno
== 31 || regno
== 63)
2125 sum
->defd
.i
|= mask
;
2127 sum
->defd
.fp
|= mask
;
2132 sum
->used
.i
|= mask
;
2134 sum
->used
.fp
|= mask
;
2145 /* Find the regs used in memory address computation: */
2146 summarize_insn (XEXP (x
, 0), sum
, 0);
2150 summarize_insn (SUBREG_REG (x
), sum
, 0);
2153 case CONST_INT
: case CONST_DOUBLE
:
2154 case SYMBOL_REF
: case LABEL_REF
: case CONST
:
2157 /* Handle common unary and binary ops for efficiency. */
2158 case COMPARE
: case PLUS
: case MINUS
: case MULT
: case DIV
:
2159 case MOD
: case UDIV
: case UMOD
: case AND
: case IOR
:
2160 case XOR
: case ASHIFT
: case ROTATE
: case ASHIFTRT
: case LSHIFTRT
:
2161 case ROTATERT
: case SMIN
: case SMAX
: case UMIN
: case UMAX
:
2162 case NE
: case EQ
: case GE
: case GT
: case LE
:
2163 case LT
: case GEU
: case GTU
: case LEU
: case LTU
:
2164 summarize_insn (XEXP (x
, 0), sum
, 0);
2165 summarize_insn (XEXP (x
, 1), sum
, 0);
2168 case NEG
: case NOT
: case SIGN_EXTEND
: case ZERO_EXTEND
:
2169 case TRUNCATE
: case FLOAT_EXTEND
: case FLOAT_TRUNCATE
: case FLOAT
:
2170 case FIX
: case UNSIGNED_FLOAT
: case UNSIGNED_FIX
: case ABS
:
2171 case SQRT
: case FFS
:
2172 summarize_insn (XEXP (x
, 0), sum
, 0);
2176 format_ptr
= GET_RTX_FORMAT (GET_CODE (x
));
2177 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
2178 switch (format_ptr
[i
])
2181 summarize_insn (XEXP (x
, i
), sum
, 0);
2185 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
2186 summarize_insn (XVECEXP (x
, i
, j
), sum
, 0);
2195 /* This function is executed just prior to the output of assembler code for
2196 INSN to modify the extracted operands so they will be output differently.
2198 OPVEC is the vector containing the operands extracted from INSN, and
2199 NOPERANDS is the number of elements of the vector which contain meaningful
2200 data for this insn. The contents of this vector are what will be used to
2201 convert the insn template into assembler code, so you can change the
2202 assembler output by changing the contents of the vector.
2204 We use this function to ensure a sufficient number of `trapb' instructions
2205 are in the code when the user requests code with a trap precision of
2206 functions or instructions.
2208 In naive mode, when the user requests a trap-precision of "instruction", a
2209 trapb is needed after every instruction that may generate a trap (and after
2210 jsr/bsr instructions, because called functions may import a trap from the
2211 caller). This ensures that the code is resumption safe but it is also slow.
2213 When optimizations are turned on, we delay issuing a trapb as long as
2214 possible. In this context, a trap shadow is the sequence of instructions
2215 that starts with a (potentially) trap generating instruction and extends to
2216 the next trapb or call_pal instruction (but GCC never generates call_pal by
2217 itself). We can delay (and therefore sometimes omit) a trapb subject to the
2218 following conditions:
2220 (a) On entry to the trap shadow, if any Alpha register or memory location
2221 contains a value that is used as an operand value by some instruction in
2222 the trap shadow (live on entry), then no instruction in the trap shadow
2223 may modify the register or memory location.
2225 (b) Within the trap shadow, the computation of the base register for a
2226 memory load or store instruction may not involve using the result
2227 of an instruction that might generate an UNPREDICTABLE result.
2229 (c) Within the trap shadow, no register may be used more than once as a
2230 destination register. (This is to make life easier for the trap-handler.)
2232 (d) The trap shadow may not include any branch instructions.
2237 final_prescan_insn (insn
, opvec
, noperands
)
2242 static struct shadow_summary shadow
= {0, 0, 0, 0, 0};
2244 #define CLOSE_SHADOW \
2247 fputs ("\ttrapb\n", asm_out_file); \
2249 bzero ((char *) &shadow, sizeof shadow); \
2253 if (alpha_tp
== ALPHA_TP_PROG
)
2260 /* Generate one trapb before epilogue (indicated by INSN==0) */
2266 if (optimize
&& insn
!= 0)
2268 struct shadow_summary sum
= {0, 0, 0};
2270 switch (GET_CODE(insn
))
2273 summarize_insn (PATTERN (insn
), &sum
, 0);
2275 if ((sum
.defd
.i
& shadow
.defd
.i
)
2276 || (sum
.defd
.fp
& shadow
.defd
.fp
))
2278 /* (c) would be violated */
2283 /* Combine shadow with summary of current insn: */
2284 shadow
.used
.i
|= sum
.used
.i
;
2285 shadow
.used
.fp
|= sum
.used
.fp
;
2286 shadow
.used
.mem
|= sum
.used
.mem
;
2287 shadow
.defd
.i
|= sum
.defd
.i
;
2288 shadow
.defd
.fp
|= sum
.defd
.fp
;
2289 shadow
.defd
.mem
|= sum
.defd
.mem
;
2291 if ((sum
.defd
.i
& shadow
.used
.i
)
2292 || (sum
.defd
.fp
& shadow
.used
.fp
)
2293 || (sum
.defd
.mem
& shadow
.used
.mem
))
2295 /* (a) would be violated (also takes care of (b)). */
2296 if (get_attr_trap (insn
) == TRAP_YES
2297 && ((sum
.defd
.i
& sum
.used
.i
)
2298 || (sum
.defd
.fp
& sum
.used
.fp
)))
2321 if (insn
!= 0 && get_attr_trap (insn
) == TRAP_YES
)
2323 if (optimize
&& !trap_pending
&& GET_CODE (insn
) == INSN
)
2324 summarize_insn (PATTERN (insn
), &shadow
, 0);
2329 /* Check a floating-point value for validity for a particular machine mode. */
2331 static char *float_strings
[] =
2333 "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
2334 "-1.70141173319264430e+38",
2335 "2.93873587705571877e-39", /* 2^-128 */
2336 "-2.93873587705571877e-39"
2339 static REAL_VALUE_TYPE float_values
[4];
2340 static int inited_float_values
= 0;
2343 check_float_value (mode
, d
, overflow
)
2344 enum machine_mode mode
;
2349 if (TARGET_IEEE
|| TARGET_IEEE_CONFORMANT
|| TARGET_IEEE_WITH_INEXACT
)
2352 if (inited_float_values
== 0)
2355 for (i
= 0; i
< 4; i
++)
2356 float_values
[i
] = REAL_VALUE_ATOF (float_strings
[i
], DFmode
);
2358 inited_float_values
= 1;
2365 bcopy ((char *) d
, (char *) &r
, sizeof (REAL_VALUE_TYPE
));
2366 if (REAL_VALUES_LESS (float_values
[0], r
))
2368 bcopy ((char *) &float_values
[0], (char *) d
,
2369 sizeof (REAL_VALUE_TYPE
));
2372 else if (REAL_VALUES_LESS (r
, float_values
[1]))
2374 bcopy ((char *) &float_values
[1], (char *) d
,
2375 sizeof (REAL_VALUE_TYPE
));
2378 else if (REAL_VALUES_LESS (dconst0
, r
)
2379 && REAL_VALUES_LESS (r
, float_values
[2]))
2381 bcopy ((char *) &dconst0
, (char *) d
, sizeof (REAL_VALUE_TYPE
));
2384 else if (REAL_VALUES_LESS (r
, dconst0
)
2385 && REAL_VALUES_LESS (float_values
[3], r
))
2387 bcopy ((char *) &dconst0
, (char *) d
, sizeof (REAL_VALUE_TYPE
));