1 /* Subroutines used for code generation on the DEC Alpha.
2 Copyright (C) 1992, 93-99, 2000 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"
47 extern int rtx_equal_function_value_matters
;
49 /* Specify which cpu to schedule for. */
51 enum processor_type alpha_cpu
;
52 static const char * const alpha_cpu_name
[] =
57 /* Specify how accurate floating-point traps need to be. */
59 enum alpha_trap_precision alpha_tp
;
61 /* Specify the floating-point rounding mode. */
63 enum alpha_fp_rounding_mode alpha_fprm
;
65 /* Specify which things cause traps. */
67 enum alpha_fp_trap_mode alpha_fptm
;
69 /* Strings decoded into the above options. */
71 const char *alpha_cpu_string
; /* -mcpu= */
72 const char *alpha_tp_string
; /* -mtrap-precision=[p|s|i] */
73 const char *alpha_fprm_string
; /* -mfp-rounding-mode=[n|m|c|d] */
74 const char *alpha_fptm_string
; /* -mfp-trap-mode=[n|u|su|sui] */
75 const char *alpha_mlat_string
; /* -mmemory-latency= */
77 /* Save information from a "cmpxx" operation until the branch or scc is
80 struct alpha_compare alpha_compare
;
82 /* Non-zero if inside of a function, because the Alpha asm can't
83 handle .files inside of functions. */
85 static int inside_function
= FALSE
;
87 /* The number of cycles of latency we should assume on memory reads. */
89 int alpha_memory_latency
= 3;
91 /* Whether the function needs the GP. */
93 static int alpha_function_needs_gp
;
95 /* The alias set for prologue/epilogue register save/restore. */
97 static int alpha_sr_alias_set
;
99 /* Declarations of static functions. */
100 static void alpha_set_memflags_1
101 PARAMS ((rtx
, int, int, int));
102 static rtx alpha_emit_set_const_1
103 PARAMS ((rtx
, enum machine_mode
, HOST_WIDE_INT
, int));
104 static void alpha_expand_unaligned_load_words
105 PARAMS ((rtx
*out_regs
, rtx smem
, HOST_WIDE_INT words
, HOST_WIDE_INT ofs
));
106 static void alpha_expand_unaligned_store_words
107 PARAMS ((rtx
*out_regs
, rtx smem
, HOST_WIDE_INT words
, HOST_WIDE_INT ofs
));
108 static void alpha_sa_mask
109 PARAMS ((unsigned long *imaskP
, unsigned long *fmaskP
));
110 static int alpha_does_function_need_gp
112 static void alpha_init_machine_status
113 PARAMS ((struct function
*p
));
114 static void alpha_mark_machine_status
115 PARAMS ((struct function
*p
));
116 static int alpha_ra_ever_killed
118 static rtx set_frame_related_p
120 static const char *alpha_lookup_xfloating_lib_func
121 PARAMS ((enum rtx_code
));
122 static int alpha_compute_xfloating_mode_arg
123 PARAMS ((enum rtx_code
, enum alpha_fp_rounding_mode
));
124 static void alpha_emit_xfloating_libcall
125 PARAMS ((const char *, rtx
, rtx
[], int, rtx
));
126 static rtx alpha_emit_xfloating_compare
127 PARAMS ((enum rtx_code
, rtx
, rtx
));
129 /* Get the number of args of a function in one of two ways. */
131 #define NUM_ARGS current_function_args_info.num_args
133 #define NUM_ARGS current_function_args_info
139 /* Parse target option strings. */
144 alpha_tp
= ALPHA_TP_PROG
;
145 alpha_fprm
= ALPHA_FPRM_NORM
;
146 alpha_fptm
= ALPHA_FPTM_N
;
150 alpha_tp
= ALPHA_TP_INSN
;
151 alpha_fptm
= ALPHA_FPTM_SU
;
154 if (TARGET_IEEE_WITH_INEXACT
)
156 alpha_tp
= ALPHA_TP_INSN
;
157 alpha_fptm
= ALPHA_FPTM_SUI
;
162 if (! strcmp (alpha_tp_string
, "p"))
163 alpha_tp
= ALPHA_TP_PROG
;
164 else if (! strcmp (alpha_tp_string
, "f"))
165 alpha_tp
= ALPHA_TP_FUNC
;
166 else if (! strcmp (alpha_tp_string
, "i"))
167 alpha_tp
= ALPHA_TP_INSN
;
169 error ("bad value `%s' for -mtrap-precision switch", alpha_tp_string
);
172 if (alpha_fprm_string
)
174 if (! strcmp (alpha_fprm_string
, "n"))
175 alpha_fprm
= ALPHA_FPRM_NORM
;
176 else if (! strcmp (alpha_fprm_string
, "m"))
177 alpha_fprm
= ALPHA_FPRM_MINF
;
178 else if (! strcmp (alpha_fprm_string
, "c"))
179 alpha_fprm
= ALPHA_FPRM_CHOP
;
180 else if (! strcmp (alpha_fprm_string
,"d"))
181 alpha_fprm
= ALPHA_FPRM_DYN
;
183 error ("bad value `%s' for -mfp-rounding-mode switch",
187 if (alpha_fptm_string
)
189 if (strcmp (alpha_fptm_string
, "n") == 0)
190 alpha_fptm
= ALPHA_FPTM_N
;
191 else if (strcmp (alpha_fptm_string
, "u") == 0)
192 alpha_fptm
= ALPHA_FPTM_U
;
193 else if (strcmp (alpha_fptm_string
, "su") == 0)
194 alpha_fptm
= ALPHA_FPTM_SU
;
195 else if (strcmp (alpha_fptm_string
, "sui") == 0)
196 alpha_fptm
= ALPHA_FPTM_SUI
;
198 error ("bad value `%s' for -mfp-trap-mode switch", alpha_fptm_string
);
202 = TARGET_CPU_DEFAULT
& MASK_CPU_EV6
? PROCESSOR_EV6
203 : (TARGET_CPU_DEFAULT
& MASK_CPU_EV5
? PROCESSOR_EV5
: PROCESSOR_EV4
);
205 if (alpha_cpu_string
)
207 if (! strcmp (alpha_cpu_string
, "ev4")
208 || ! strcmp (alpha_cpu_string
, "ev45")
209 || ! strcmp (alpha_cpu_string
, "21064"))
211 alpha_cpu
= PROCESSOR_EV4
;
212 target_flags
&= ~ (MASK_BWX
| MASK_MAX
| MASK_FIX
| MASK_CIX
);
214 else if (! strcmp (alpha_cpu_string
, "ev5")
215 || ! strcmp (alpha_cpu_string
, "21164"))
217 alpha_cpu
= PROCESSOR_EV5
;
218 target_flags
&= ~ (MASK_BWX
| MASK_MAX
| MASK_FIX
| MASK_CIX
);
220 else if (! strcmp (alpha_cpu_string
, "ev56")
221 || ! strcmp (alpha_cpu_string
, "21164a"))
223 alpha_cpu
= PROCESSOR_EV5
;
224 target_flags
|= MASK_BWX
;
225 target_flags
&= ~ (MASK_MAX
| MASK_FIX
| MASK_CIX
);
227 else if (! strcmp (alpha_cpu_string
, "pca56")
228 || ! strcmp (alpha_cpu_string
, "21164PC")
229 || ! strcmp (alpha_cpu_string
, "21164pc"))
231 alpha_cpu
= PROCESSOR_EV5
;
232 target_flags
|= MASK_BWX
| MASK_MAX
;
233 target_flags
&= ~ (MASK_FIX
| MASK_CIX
);
235 else if (! strcmp (alpha_cpu_string
, "ev6")
236 || ! strcmp (alpha_cpu_string
, "21264"))
238 alpha_cpu
= PROCESSOR_EV6
;
239 target_flags
|= MASK_BWX
| MASK_MAX
| MASK_FIX
;
240 target_flags
&= ~ (MASK_CIX
);
242 else if (! strcmp (alpha_cpu_string
, "ev67")
243 || ! strcmp (alpha_cpu_string
, "21264a"))
245 alpha_cpu
= PROCESSOR_EV6
;
246 target_flags
|= MASK_BWX
| MASK_MAX
| MASK_FIX
| MASK_CIX
;
249 error ("bad value `%s' for -mcpu switch", alpha_cpu_string
);
252 /* Do some sanity checks on the above options. */
254 if ((alpha_fptm
== ALPHA_FPTM_SU
|| alpha_fptm
== ALPHA_FPTM_SUI
)
255 && alpha_tp
!= ALPHA_TP_INSN
&& alpha_cpu
!= PROCESSOR_EV6
)
257 warning ("fp software completion requires -mtrap-precision=i");
258 alpha_tp
= ALPHA_TP_INSN
;
261 if (alpha_cpu
== PROCESSOR_EV6
)
263 /* Except for EV6 pass 1 (not released), we always have precise
264 arithmetic traps. Which means we can do software completion
265 without minding trap shadows. */
266 alpha_tp
= ALPHA_TP_PROG
;
269 if (TARGET_FLOAT_VAX
)
271 if (alpha_fprm
== ALPHA_FPRM_MINF
|| alpha_fprm
== ALPHA_FPRM_DYN
)
273 warning ("rounding mode not supported for VAX floats");
274 alpha_fprm
= ALPHA_FPRM_NORM
;
276 if (alpha_fptm
== ALPHA_FPTM_SUI
)
278 warning ("trap mode not supported for VAX floats");
279 alpha_fptm
= ALPHA_FPTM_SU
;
287 if (!alpha_mlat_string
)
288 alpha_mlat_string
= "L1";
290 if (ISDIGIT ((unsigned char)alpha_mlat_string
[0])
291 && (lat
= strtol (alpha_mlat_string
, &end
, 10), *end
== '\0'))
293 else if ((alpha_mlat_string
[0] == 'L' || alpha_mlat_string
[0] == 'l')
294 && ISDIGIT ((unsigned char)alpha_mlat_string
[1])
295 && alpha_mlat_string
[2] == '\0')
297 static int const cache_latency
[][4] =
299 { 3, 30, -1 }, /* ev4 -- Bcache is a guess */
300 { 2, 12, 38 }, /* ev5 -- Bcache from PC164 LMbench numbers */
301 { 3, 13, -1 }, /* ev6 -- Ho hum, doesn't exist yet */
304 lat
= alpha_mlat_string
[1] - '0';
305 if (lat
< 0 || lat
> 3 || cache_latency
[alpha_cpu
][lat
-1] == -1)
307 warning ("L%d cache latency unknown for %s",
308 lat
, alpha_cpu_name
[alpha_cpu
]);
312 lat
= cache_latency
[alpha_cpu
][lat
-1];
314 else if (! strcmp (alpha_mlat_string
, "main"))
316 /* Most current memories have about 370ns latency. This is
317 a reasonable guess for a fast cpu. */
322 warning ("bad value `%s' for -mmemory-latency", alpha_mlat_string
);
326 alpha_memory_latency
= lat
;
329 /* Default the definition of "small data" to 8 bytes. */
333 /* Acquire a unique set number for our register saves and restores. */
334 alpha_sr_alias_set
= new_alias_set ();
336 /* Set up function hooks. */
337 init_machine_status
= alpha_init_machine_status
;
338 mark_machine_status
= alpha_mark_machine_status
;
341 /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */
349 for (i
= 0; i
< HOST_BITS_PER_WIDE_INT
/ HOST_BITS_PER_CHAR
;
351 if ((value
& 0xff) != 0 && (value
& 0xff) != 0xff)
357 /* Returns 1 if OP is either the constant zero or a register. If a
358 register, it must be in the proper mode unless MODE is VOIDmode. */
361 reg_or_0_operand (op
, mode
)
363 enum machine_mode mode
;
365 return op
== const0_rtx
|| register_operand (op
, mode
);
368 /* Return 1 if OP is a constant in the range of 0-63 (for a shift) or
372 reg_or_6bit_operand (op
, mode
)
374 enum machine_mode mode
;
376 return ((GET_CODE (op
) == CONST_INT
377 && (unsigned HOST_WIDE_INT
) INTVAL (op
) < 64)
378 || register_operand (op
, mode
));
382 /* Return 1 if OP is an 8-bit constant or any register. */
385 reg_or_8bit_operand (op
, mode
)
387 enum machine_mode mode
;
389 return ((GET_CODE (op
) == CONST_INT
390 && (unsigned HOST_WIDE_INT
) INTVAL (op
) < 0x100)
391 || register_operand (op
, mode
));
394 /* Return 1 if OP is an 8-bit constant. */
397 cint8_operand (op
, mode
)
399 enum machine_mode mode ATTRIBUTE_UNUSED
;
401 return ((GET_CODE (op
) == CONST_INT
402 && (unsigned HOST_WIDE_INT
) INTVAL (op
) < 0x100));
405 /* Return 1 if the operand is a valid second operand to an add insn. */
408 add_operand (op
, mode
)
410 enum machine_mode mode
;
412 if (GET_CODE (op
) == CONST_INT
)
413 /* Constraints I, J, O and P are covered by K. */
414 return (CONST_OK_FOR_LETTER_P (INTVAL (op
), 'K')
415 || CONST_OK_FOR_LETTER_P (INTVAL (op
), 'L'));
417 return register_operand (op
, mode
);
420 /* Return 1 if the operand is a valid second operand to a sign-extending
424 sext_add_operand (op
, mode
)
426 enum machine_mode mode
;
428 if (GET_CODE (op
) == CONST_INT
)
429 return (CONST_OK_FOR_LETTER_P (INTVAL (op
), 'I')
430 || CONST_OK_FOR_LETTER_P (INTVAL (op
), 'O'));
432 return reg_not_elim_operand (op
, mode
);
435 /* Return 1 if OP is the constant 4 or 8. */
438 const48_operand (op
, mode
)
440 enum machine_mode mode ATTRIBUTE_UNUSED
;
442 return (GET_CODE (op
) == CONST_INT
443 && (INTVAL (op
) == 4 || INTVAL (op
) == 8));
446 /* Return 1 if OP is a valid first operand to an AND insn. */
449 and_operand (op
, mode
)
451 enum machine_mode mode
;
453 if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == VOIDmode
)
454 return (zap_mask (CONST_DOUBLE_LOW (op
))
455 && zap_mask (CONST_DOUBLE_HIGH (op
)));
457 if (GET_CODE (op
) == CONST_INT
)
458 return ((unsigned HOST_WIDE_INT
) INTVAL (op
) < 0x100
459 || (unsigned HOST_WIDE_INT
) ~ INTVAL (op
) < 0x100
460 || zap_mask (INTVAL (op
)));
462 return register_operand (op
, mode
);
465 /* Return 1 if OP is a valid first operand to an IOR or XOR insn. */
468 or_operand (op
, mode
)
470 enum machine_mode mode
;
472 if (GET_CODE (op
) == CONST_INT
)
473 return ((unsigned HOST_WIDE_INT
) INTVAL (op
) < 0x100
474 || (unsigned HOST_WIDE_INT
) ~ INTVAL (op
) < 0x100);
476 return register_operand (op
, mode
);
479 /* Return 1 if OP is a constant that is the width, in bits, of an integral
480 mode smaller than DImode. */
483 mode_width_operand (op
, mode
)
485 enum machine_mode mode ATTRIBUTE_UNUSED
;
487 return (GET_CODE (op
) == CONST_INT
488 && (INTVAL (op
) == 8 || INTVAL (op
) == 16
489 || INTVAL (op
) == 32 || INTVAL (op
) == 64));
492 /* Return 1 if OP is a constant that is the width of an integral machine mode
493 smaller than an integer. */
496 mode_mask_operand (op
, mode
)
498 enum machine_mode mode ATTRIBUTE_UNUSED
;
500 #if HOST_BITS_PER_WIDE_INT == 32
501 if (GET_CODE (op
) == CONST_DOUBLE
)
502 return (CONST_DOUBLE_LOW (op
) == -1
503 && (CONST_DOUBLE_HIGH (op
) == -1
504 || CONST_DOUBLE_HIGH (op
) == 0));
506 if (GET_CODE (op
) == CONST_DOUBLE
)
507 return (CONST_DOUBLE_LOW (op
) == -1 && CONST_DOUBLE_HIGH (op
) == 0);
510 return (GET_CODE (op
) == CONST_INT
511 && (INTVAL (op
) == 0xff
512 || INTVAL (op
) == 0xffff
513 || INTVAL (op
) == (HOST_WIDE_INT
)0xffffffff
514 #if HOST_BITS_PER_WIDE_INT == 64
520 /* Return 1 if OP is a multiple of 8 less than 64. */
523 mul8_operand (op
, mode
)
525 enum machine_mode mode ATTRIBUTE_UNUSED
;
527 return (GET_CODE (op
) == CONST_INT
528 && (unsigned HOST_WIDE_INT
) INTVAL (op
) < 64
529 && (INTVAL (op
) & 7) == 0);
532 /* Return 1 if OP is the constant zero in floating-point. */
535 fp0_operand (op
, mode
)
537 enum machine_mode mode
;
539 return (GET_MODE (op
) == mode
540 && GET_MODE_CLASS (mode
) == MODE_FLOAT
&& op
== CONST0_RTX (mode
));
543 /* Return 1 if OP is the floating-point constant zero or a register. */
546 reg_or_fp0_operand (op
, mode
)
548 enum machine_mode mode
;
550 return fp0_operand (op
, mode
) || register_operand (op
, mode
);
553 /* Return 1 if OP is a hard floating-point register. */
556 hard_fp_register_operand (op
, mode
)
558 enum machine_mode mode
;
560 return ((GET_CODE (op
) == REG
&& REGNO_REG_CLASS (REGNO (op
)) == FLOAT_REGS
)
561 || (GET_CODE (op
) == SUBREG
562 && hard_fp_register_operand (SUBREG_REG (op
), mode
)));
565 /* Return 1 if OP is a register or a constant integer. */
569 reg_or_cint_operand (op
, mode
)
571 enum machine_mode mode
;
573 return (GET_CODE (op
) == CONST_INT
574 || register_operand (op
, mode
));
577 /* Return 1 if OP is something that can be reloaded into a register;
578 if it is a MEM, it need not be valid. */
581 some_operand (op
, mode
)
583 enum machine_mode mode
;
585 if (mode
!= VOIDmode
&& GET_MODE (op
) != VOIDmode
&& mode
!= GET_MODE (op
))
588 switch (GET_CODE (op
))
590 case REG
: case MEM
: case CONST_DOUBLE
: case CONST_INT
: case LABEL_REF
:
591 case SYMBOL_REF
: case CONST
:
595 return some_operand (SUBREG_REG (op
), VOIDmode
);
604 /* Likewise, but don't accept constants. */
607 some_ni_operand (op
, mode
)
609 enum machine_mode mode
;
611 if (GET_MODE (op
) != mode
&& mode
!= VOIDmode
)
614 if (GET_CODE (op
) == SUBREG
)
615 op
= SUBREG_REG (op
);
617 return (GET_CODE (op
) == REG
|| GET_CODE (op
) == MEM
);
620 /* Return 1 if OP is a valid operand for the source of a move insn. */
623 input_operand (op
, mode
)
625 enum machine_mode mode
;
627 if (mode
!= VOIDmode
&& GET_MODE (op
) != VOIDmode
&& mode
!= GET_MODE (op
))
630 if (GET_MODE_CLASS (mode
) == MODE_FLOAT
&& GET_MODE (op
) != mode
)
633 switch (GET_CODE (op
))
638 /* This handles both the Windows/NT and OSF cases. */
639 return mode
== ptr_mode
|| mode
== DImode
;
646 if (register_operand (op
, mode
))
648 /* ... fall through ... */
650 return ((TARGET_BWX
|| (mode
!= HImode
&& mode
!= QImode
))
651 && general_operand (op
, mode
));
654 return GET_MODE_CLASS (mode
) == MODE_FLOAT
&& op
== CONST0_RTX (mode
);
657 return mode
== QImode
|| mode
== HImode
|| add_operand (op
, mode
);
669 /* Return 1 if OP is a SYMBOL_REF for a function known to be in this
673 current_file_function_operand (op
, mode
)
675 enum machine_mode mode ATTRIBUTE_UNUSED
;
677 return (GET_CODE (op
) == SYMBOL_REF
678 && ! profile_flag
&& ! profile_block_flag
679 && (SYMBOL_REF_FLAG (op
)
680 || op
== XEXP (DECL_RTL (current_function_decl
), 0)));
683 /* Return 1 if OP is a valid operand for the MEM of a CALL insn. */
686 call_operand (op
, mode
)
688 enum machine_mode mode
;
693 return (GET_CODE (op
) == SYMBOL_REF
694 || (GET_CODE (op
) == REG
695 && (TARGET_OPEN_VMS
|| TARGET_WINDOWS_NT
|| REGNO (op
) == 27)));
698 /* Return 1 if OP is a valid Alpha comparison operator. Here we know which
699 comparisons are valid in which insn. */
702 alpha_comparison_operator (op
, mode
)
704 enum machine_mode mode
;
706 enum rtx_code code
= GET_CODE (op
);
708 if (mode
!= GET_MODE (op
) && mode
!= VOIDmode
)
711 return (code
== EQ
|| code
== LE
|| code
== LT
712 || (mode
== DImode
&& (code
== LEU
|| code
== LTU
)));
715 /* Return 1 if OP is a valid Alpha swapped comparison operator. */
718 alpha_swapped_comparison_operator (op
, mode
)
720 enum machine_mode mode
;
722 enum rtx_code code
= GET_CODE (op
);
724 if ((mode
!= GET_MODE (op
) && mode
!= VOIDmode
)
725 || GET_RTX_CLASS (code
) != '<')
728 code
= swap_condition (code
);
729 return (code
== EQ
|| code
== LE
|| code
== LT
730 || (mode
== DImode
&& (code
== LEU
|| code
== LTU
)));
733 /* Return 1 if OP is a signed comparison operation. */
736 signed_comparison_operator (op
, mode
)
738 enum machine_mode mode ATTRIBUTE_UNUSED
;
740 enum rtx_code code
= GET_CODE (op
);
742 if (mode
!= GET_MODE (op
) && mode
!= VOIDmode
)
745 return (code
== EQ
|| code
== NE
746 || code
== LE
|| code
== LT
747 || code
== GE
|| code
== GT
);
750 /* Return 1 if OP is a valid Alpha floating point comparison operator.
751 Here we know which comparisons are valid in which insn. */
754 alpha_fp_comparison_operator (op
, mode
)
756 enum machine_mode mode
;
758 enum rtx_code code
= GET_CODE (op
);
760 if (mode
!= GET_MODE (op
) && mode
!= VOIDmode
)
763 return (code
== EQ
|| code
== LE
|| code
== LT
|| code
== UNORDERED
);
766 /* Return 1 if this is a divide or modulus operator. */
769 divmod_operator (op
, mode
)
771 enum machine_mode mode ATTRIBUTE_UNUSED
;
773 switch (GET_CODE (op
))
775 case DIV
: case MOD
: case UDIV
: case UMOD
:
785 /* Return 1 if this memory address is a known aligned register plus
786 a constant. It must be a valid address. This means that we can do
787 this as an aligned reference plus some offset.
789 Take into account what reload will do. */
792 aligned_memory_operand (op
, mode
)
794 enum machine_mode mode
;
798 if (reload_in_progress
)
801 if (GET_CODE (tmp
) == SUBREG
)
802 tmp
= SUBREG_REG (tmp
);
803 if (GET_CODE (tmp
) == REG
804 && REGNO (tmp
) >= FIRST_PSEUDO_REGISTER
)
806 op
= reg_equiv_memory_loc
[REGNO (tmp
)];
812 if (GET_CODE (op
) != MEM
813 || GET_MODE (op
) != mode
)
817 /* LEGITIMIZE_RELOAD_ADDRESS creates (plus (plus reg const_hi) const_lo)
818 sorts of constructs. Dig for the real base register. */
819 if (reload_in_progress
820 && GET_CODE (op
) == PLUS
821 && GET_CODE (XEXP (op
, 0)) == PLUS
)
822 base
= XEXP (XEXP (op
, 0), 0);
825 if (! memory_address_p (mode
, op
))
827 base
= (GET_CODE (op
) == PLUS
? XEXP (op
, 0) : op
);
830 return (GET_CODE (base
) == REG
831 && REGNO_POINTER_ALIGN (REGNO (base
)) >= 4);
834 /* Similar, but return 1 if OP is a MEM which is not alignable. */
837 unaligned_memory_operand (op
, mode
)
839 enum machine_mode mode
;
843 if (reload_in_progress
)
846 if (GET_CODE (tmp
) == SUBREG
)
847 tmp
= SUBREG_REG (tmp
);
848 if (GET_CODE (tmp
) == REG
849 && REGNO (tmp
) >= FIRST_PSEUDO_REGISTER
)
851 op
= reg_equiv_memory_loc
[REGNO (tmp
)];
857 if (GET_CODE (op
) != MEM
858 || GET_MODE (op
) != mode
)
862 /* LEGITIMIZE_RELOAD_ADDRESS creates (plus (plus reg const_hi) const_lo)
863 sorts of constructs. Dig for the real base register. */
864 if (reload_in_progress
865 && GET_CODE (op
) == PLUS
866 && GET_CODE (XEXP (op
, 0)) == PLUS
)
867 base
= XEXP (XEXP (op
, 0), 0);
870 if (! memory_address_p (mode
, op
))
872 base
= (GET_CODE (op
) == PLUS
? XEXP (op
, 0) : op
);
875 return (GET_CODE (base
) == REG
876 && REGNO_POINTER_ALIGN (REGNO (base
)) < 4);
879 /* Return 1 if OP is either a register or an unaligned memory location. */
882 reg_or_unaligned_mem_operand (op
, mode
)
884 enum machine_mode mode
;
886 return register_operand (op
, mode
) || unaligned_memory_operand (op
, mode
);
889 /* Return 1 if OP is any memory location. During reload a pseudo matches. */
892 any_memory_operand (op
, mode
)
894 enum machine_mode mode ATTRIBUTE_UNUSED
;
896 return (GET_CODE (op
) == MEM
897 || (GET_CODE (op
) == SUBREG
&& GET_CODE (SUBREG_REG (op
)) == REG
)
898 || (reload_in_progress
&& GET_CODE (op
) == REG
899 && REGNO (op
) >= FIRST_PSEUDO_REGISTER
)
900 || (reload_in_progress
&& GET_CODE (op
) == SUBREG
901 && GET_CODE (SUBREG_REG (op
)) == REG
902 && REGNO (SUBREG_REG (op
)) >= FIRST_PSEUDO_REGISTER
));
905 /* Returns 1 if OP is not an eliminable register.
907 This exists to cure a pathological abort in the s8addq (et al) patterns,
909 long foo () { long t; bar(); return (long) &t * 26107; }
911 which run afoul of a hack in reload to cure a (presumably) similar
912 problem with lea-type instructions on other targets. But there is
913 one of us and many of them, so work around the problem by selectively
914 preventing combine from making the optimization. */
917 reg_not_elim_operand (op
, mode
)
919 enum machine_mode mode
;
922 if (GET_CODE (op
) == SUBREG
)
923 inner
= SUBREG_REG (op
);
924 if (inner
== frame_pointer_rtx
|| inner
== arg_pointer_rtx
)
927 return register_operand (op
, mode
);
930 /* Return 1 is OP is a memory location that is not a reference (using
931 an AND) to an unaligned location. Take into account what reload
935 normal_memory_operand (op
, mode
)
937 enum machine_mode mode ATTRIBUTE_UNUSED
;
939 if (reload_in_progress
)
942 if (GET_CODE (tmp
) == SUBREG
)
943 tmp
= SUBREG_REG (tmp
);
944 if (GET_CODE (tmp
) == REG
945 && REGNO (tmp
) >= FIRST_PSEUDO_REGISTER
)
947 op
= reg_equiv_memory_loc
[REGNO (tmp
)];
949 /* This may not have been assigned an equivalent address if it will
950 be eliminated. In that case, it doesn't matter what we do. */
956 return GET_CODE (op
) == MEM
&& GET_CODE (XEXP (op
, 0)) != AND
;
959 /* Accept a register, but not a subreg of any kind. This allows us to
960 avoid pathological cases in reload wrt data movement common in
961 int->fp conversion. */
964 reg_no_subreg_operand (op
, mode
)
966 enum machine_mode mode
;
968 if (GET_CODE (op
) == SUBREG
)
970 return register_operand (op
, mode
);
973 /* Recognize a addition operation that includes a constant. Used to
974 convince reload to canonize (plus (plus reg c1) c2) during register
978 addition_operation (op
, mode
)
980 enum machine_mode mode
;
982 if (GET_MODE (op
) != mode
&& mode
!= VOIDmode
)
984 if (GET_CODE (op
) == PLUS
985 && register_operand (XEXP (op
, 0), mode
)
986 && GET_CODE (XEXP (op
, 1)) == CONST_INT
987 && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (op
, 1)), 'K'))
992 /* Return 1 if this function can directly return via $26. */
997 return (! TARGET_OPEN_VMS
&& reload_completed
&& alpha_sa_size () == 0
998 && get_frame_size () == 0
999 && current_function_outgoing_args_size
== 0
1000 && current_function_pretend_args_size
== 0);
1003 /* REF is an alignable memory location. Place an aligned SImode
1004 reference into *PALIGNED_MEM and the number of bits to shift into
1005 *PBITNUM. SCRATCH is a free register for use in reloading out
1006 of range stack slots. */
1009 get_aligned_mem (ref
, paligned_mem
, pbitnum
)
1011 rtx
*paligned_mem
, *pbitnum
;
1014 HOST_WIDE_INT offset
= 0;
1016 if (GET_CODE (ref
) != MEM
)
1019 if (reload_in_progress
1020 && ! memory_address_p (GET_MODE (ref
), XEXP (ref
, 0)))
1022 base
= find_replacement (&XEXP (ref
, 0));
1024 if (! memory_address_p (GET_MODE (ref
), base
))
1029 base
= XEXP (ref
, 0);
1032 if (GET_CODE (base
) == PLUS
)
1033 offset
+= INTVAL (XEXP (base
, 1)), base
= XEXP (base
, 0);
1035 *paligned_mem
= gen_rtx_MEM (SImode
, plus_constant (base
, offset
& ~3));
1036 MEM_COPY_ATTRIBUTES (*paligned_mem
, ref
);
1037 RTX_UNCHANGING_P (*paligned_mem
) = RTX_UNCHANGING_P (ref
);
1039 /* Sadly, we cannot use alias sets here because we may overlap other
1040 data in a different alias set. */
1041 /* MEM_ALIAS_SET (*paligned_mem) = MEM_ALIAS_SET (ref); */
1043 *pbitnum
= GEN_INT ((offset
& 3) * 8);
1046 /* Similar, but just get the address. Handle the two reload cases.
1047 Add EXTRA_OFFSET to the address we return. */
1050 get_unaligned_address (ref
, extra_offset
)
1055 HOST_WIDE_INT offset
= 0;
1057 if (GET_CODE (ref
) != MEM
)
1060 if (reload_in_progress
1061 && ! memory_address_p (GET_MODE (ref
), XEXP (ref
, 0)))
1063 base
= find_replacement (&XEXP (ref
, 0));
1065 if (! memory_address_p (GET_MODE (ref
), base
))
1070 base
= XEXP (ref
, 0);
1073 if (GET_CODE (base
) == PLUS
)
1074 offset
+= INTVAL (XEXP (base
, 1)), base
= XEXP (base
, 0);
1076 return plus_constant (base
, offset
+ extra_offset
);
1079 /* Loading and storing HImode or QImode values to and from memory
1080 usually requires a scratch register. The exceptions are loading
1081 QImode and HImode from an aligned address to a general register
1082 unless byte instructions are permitted.
1084 We also cannot load an unaligned address or a paradoxical SUBREG
1085 into an FP register.
1087 We also cannot do integral arithmetic into FP regs, as might result
1088 from register elimination into a DImode fp register. */
1091 secondary_reload_class (class, mode
, x
, in
)
1092 enum reg_class
class;
1093 enum machine_mode mode
;
1097 if ((mode
== QImode
|| mode
== HImode
) && ! TARGET_BWX
)
1099 if (GET_CODE (x
) == MEM
1100 || (GET_CODE (x
) == REG
&& REGNO (x
) >= FIRST_PSEUDO_REGISTER
)
1101 || (GET_CODE (x
) == SUBREG
1102 && (GET_CODE (SUBREG_REG (x
)) == MEM
1103 || (GET_CODE (SUBREG_REG (x
)) == REG
1104 && REGNO (SUBREG_REG (x
)) >= FIRST_PSEUDO_REGISTER
))))
1106 if (!in
|| !aligned_memory_operand(x
, mode
))
1107 return GENERAL_REGS
;
1111 if (class == FLOAT_REGS
)
1113 if (GET_CODE (x
) == MEM
&& GET_CODE (XEXP (x
, 0)) == AND
)
1114 return GENERAL_REGS
;
1116 if (GET_CODE (x
) == SUBREG
1117 && (GET_MODE_SIZE (GET_MODE (x
))
1118 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x
)))))
1119 return GENERAL_REGS
;
1121 if (in
&& INTEGRAL_MODE_P (mode
) && ! general_operand (x
, mode
))
1122 return GENERAL_REGS
;
1128 /* Subfunction of the following function. Update the flags of any MEM
1129 found in part of X. */
1132 alpha_set_memflags_1 (x
, in_struct_p
, volatile_p
, unchanging_p
)
1134 int in_struct_p
, volatile_p
, unchanging_p
;
1138 switch (GET_CODE (x
))
1142 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
1143 alpha_set_memflags_1 (XVECEXP (x
, 0, i
), in_struct_p
, volatile_p
,
1148 alpha_set_memflags_1 (PATTERN (x
), in_struct_p
, volatile_p
,
1153 alpha_set_memflags_1 (SET_DEST (x
), in_struct_p
, volatile_p
,
1155 alpha_set_memflags_1 (SET_SRC (x
), in_struct_p
, volatile_p
,
1160 MEM_IN_STRUCT_P (x
) = in_struct_p
;
1161 MEM_VOLATILE_P (x
) = volatile_p
;
1162 RTX_UNCHANGING_P (x
) = unchanging_p
;
1163 /* Sadly, we cannot use alias sets because the extra aliasing
1164 produced by the AND interferes. Given that two-byte quantities
1165 are the only thing we would be able to differentiate anyway,
1166 there does not seem to be any point in convoluting the early
1167 out of the alias check. */
1168 /* MEM_ALIAS_SET (x) = alias_set; */
1176 /* Given INSN, which is either an INSN or a SEQUENCE generated to
1177 perform a memory operation, look for any MEMs in either a SET_DEST or
1178 a SET_SRC and copy the in-struct, unchanging, and volatile flags from
1179 REF into each of the MEMs found. If REF is not a MEM, don't do
1183 alpha_set_memflags (insn
, ref
)
1187 int in_struct_p
, volatile_p
, unchanging_p
;
1189 if (GET_CODE (ref
) != MEM
)
1192 in_struct_p
= MEM_IN_STRUCT_P (ref
);
1193 volatile_p
= MEM_VOLATILE_P (ref
);
1194 unchanging_p
= RTX_UNCHANGING_P (ref
);
1196 /* This is only called from alpha.md, after having had something
1197 generated from one of the insn patterns. So if everything is
1198 zero, the pattern is already up-to-date. */
1199 if (! in_struct_p
&& ! volatile_p
&& ! unchanging_p
)
1202 alpha_set_memflags_1 (insn
, in_struct_p
, volatile_p
, unchanging_p
);
1205 /* Try to output insns to set TARGET equal to the constant C if it can be
1206 done in less than N insns. Do all computations in MODE. Returns the place
1207 where the output has been placed if it can be done and the insns have been
1208 emitted. If it would take more than N insns, zero is returned and no
1209 insns and emitted. */
1212 alpha_emit_set_const (target
, mode
, c
, n
)
1214 enum machine_mode mode
;
1221 /* Try 1 insn, then 2, then up to N. */
1222 for (i
= 1; i
<= n
; i
++)
1223 if ((pat
= alpha_emit_set_const_1 (target
, mode
, c
, i
)) != 0)
1229 /* Internal routine for the above to check for N or below insns. */
1232 alpha_emit_set_const_1 (target
, mode
, c
, n
)
1234 enum machine_mode mode
;
1238 HOST_WIDE_INT
new = c
;
1240 /* Use a pseudo if highly optimizing and still generating RTL. */
1242 = (flag_expensive_optimizations
&& rtx_equal_function_value_matters
1246 #if HOST_BITS_PER_WIDE_INT == 64
1247 /* We are only called for SImode and DImode. If this is SImode, ensure that
1248 we are sign extended to a full word. This does not make any sense when
1249 cross-compiling on a narrow machine. */
1252 c
= (c
& 0xffffffff) - 2 * (c
& 0x80000000);
1255 /* If this is a sign-extended 32-bit constant, we can do this in at most
1256 three insns, so do it if we have enough insns left. We always have
1257 a sign-extended 32-bit constant when compiling on a narrow machine. */
1259 if (HOST_BITS_PER_WIDE_INT
!= 64
1260 || c
>> 31 == -1 || c
>> 31 == 0)
1262 HOST_WIDE_INT low
= (c
& 0xffff) - 2 * (c
& 0x8000);
1263 HOST_WIDE_INT tmp1
= c
- low
;
1265 = ((tmp1
>> 16) & 0xffff) - 2 * ((tmp1
>> 16) & 0x8000);
1266 HOST_WIDE_INT extra
= 0;
1268 /* If HIGH will be interpreted as negative but the constant is
1269 positive, we must adjust it to do two ldha insns. */
1271 if ((high
& 0x8000) != 0 && c
>= 0)
1275 high
= ((tmp1
>> 16) & 0xffff) - 2 * ((tmp1
>> 16) & 0x8000);
1278 if (c
== low
|| (low
== 0 && extra
== 0))
1280 /* We used to use copy_to_suggested_reg (GEN_INT (c), target, mode)
1281 but that meant that we can't handle INT_MIN on 32-bit machines
1282 (like NT/Alpha), because we recurse indefinitely through
1283 emit_move_insn to gen_movdi. So instead, since we know exactly
1284 what we want, create it explicitly. */
1287 target
= gen_reg_rtx (mode
);
1288 emit_insn (gen_rtx_SET (VOIDmode
, target
, GEN_INT (c
)));
1291 else if (n
>= 2 + (extra
!= 0))
1293 temp
= copy_to_suggested_reg (GEN_INT (low
), subtarget
, mode
);
1296 temp
= expand_binop (mode
, add_optab
, temp
, GEN_INT (extra
<< 16),
1297 subtarget
, 0, OPTAB_WIDEN
);
1299 return expand_binop (mode
, add_optab
, temp
, GEN_INT (high
<< 16),
1300 target
, 0, OPTAB_WIDEN
);
1304 /* If we couldn't do it that way, try some other methods. But if we have
1305 no instructions left, don't bother. Likewise, if this is SImode and
1306 we can't make pseudos, we can't do anything since the expand_binop
1307 and expand_unop calls will widen and try to make pseudos. */
1310 || (mode
== SImode
&& ! rtx_equal_function_value_matters
))
1313 #if HOST_BITS_PER_WIDE_INT == 64
1314 /* First, see if can load a value into the target that is the same as the
1315 constant except that all bytes that are 0 are changed to be 0xff. If we
1316 can, then we can do a ZAPNOT to obtain the desired constant. */
1318 for (i
= 0; i
< 64; i
+= 8)
1319 if ((new & ((HOST_WIDE_INT
) 0xff << i
)) == 0)
1320 new |= (HOST_WIDE_INT
) 0xff << i
;
1322 /* We are only called for SImode and DImode. If this is SImode, ensure that
1323 we are sign extended to a full word. */
1326 new = (new & 0xffffffff) - 2 * (new & 0x80000000);
1329 && (temp
= alpha_emit_set_const (subtarget
, mode
, new, n
- 1)) != 0)
1330 return expand_binop (mode
, and_optab
, temp
, GEN_INT (c
| ~ new),
1331 target
, 0, OPTAB_WIDEN
);
1334 /* Next, see if we can load a related constant and then shift and possibly
1335 negate it to get the constant we want. Try this once each increasing
1336 numbers of insns. */
1338 for (i
= 1; i
< n
; i
++)
1340 /* First try complementing. */
1341 if ((temp
= alpha_emit_set_const (subtarget
, mode
, ~ c
, i
)) != 0)
1342 return expand_unop (mode
, one_cmpl_optab
, temp
, target
, 0);
1344 /* Next try to form a constant and do a left shift. We can do this
1345 if some low-order bits are zero; the exact_log2 call below tells
1346 us that information. The bits we are shifting out could be any
1347 value, but here we'll just try the 0- and sign-extended forms of
1348 the constant. To try to increase the chance of having the same
1349 constant in more than one insn, start at the highest number of
1350 bits to shift, but try all possibilities in case a ZAPNOT will
1353 if ((bits
= exact_log2 (c
& - c
)) > 0)
1354 for (; bits
> 0; bits
--)
1355 if ((temp
= (alpha_emit_set_const
1357 (unsigned HOST_WIDE_INT
) (c
>> bits
), i
))) != 0
1358 || ((temp
= (alpha_emit_set_const
1360 ((unsigned HOST_WIDE_INT
) c
) >> bits
, i
)))
1362 return expand_binop (mode
, ashl_optab
, temp
, GEN_INT (bits
),
1363 target
, 0, OPTAB_WIDEN
);
1365 /* Now try high-order zero bits. Here we try the shifted-in bits as
1366 all zero and all ones. Be careful to avoid shifting outside the
1367 mode and to avoid shifting outside the host wide int size. */
1368 /* On narrow hosts, don't shift a 1 into the high bit, since we'll
1369 confuse the recursive call and set all of the high 32 bits. */
1371 if ((bits
= (MIN (HOST_BITS_PER_WIDE_INT
, GET_MODE_SIZE (mode
) * 8)
1372 - floor_log2 (c
) - 1 - (HOST_BITS_PER_WIDE_INT
< 64))) > 0)
1373 for (; bits
> 0; bits
--)
1374 if ((temp
= alpha_emit_set_const (subtarget
, mode
,
1376 || ((temp
= (alpha_emit_set_const
1378 ((c
<< bits
) | (((HOST_WIDE_INT
) 1 << bits
) - 1)),
1381 return expand_binop (mode
, lshr_optab
, temp
, GEN_INT (bits
),
1382 target
, 1, OPTAB_WIDEN
);
1384 /* Now try high-order 1 bits. We get that with a sign-extension.
1385 But one bit isn't enough here. Be careful to avoid shifting outside
1386 the mode and to avoid shifting outside the host wide int size. */
1388 if ((bits
= (MIN (HOST_BITS_PER_WIDE_INT
, GET_MODE_SIZE (mode
) * 8)
1389 - floor_log2 (~ c
) - 2)) > 0)
1390 for (; bits
> 0; bits
--)
1391 if ((temp
= alpha_emit_set_const (subtarget
, mode
,
1393 || ((temp
= (alpha_emit_set_const
1395 ((c
<< bits
) | (((HOST_WIDE_INT
) 1 << bits
) - 1)),
1398 return expand_binop (mode
, ashr_optab
, temp
, GEN_INT (bits
),
1399 target
, 0, OPTAB_WIDEN
);
1405 /* Having failed to find a 3 insn sequence in alpha_emit_set_const,
1406 fall back to a straight forward decomposition. We do this to avoid
1407 exponential run times encountered when looking for longer sequences
1408 with alpha_emit_set_const. */
1411 alpha_emit_set_long_const (target
, c1
, c2
)
1413 HOST_WIDE_INT c1
, c2
;
1415 HOST_WIDE_INT d1
, d2
, d3
, d4
;
1417 /* Decompose the entire word */
1418 #if HOST_BITS_PER_WIDE_INT >= 64
1419 if (c2
!= -(c1
< 0))
1421 d1
= ((c1
& 0xffff) ^ 0x8000) - 0x8000;
1423 d2
= ((c1
& 0xffffffff) ^ 0x80000000) - 0x80000000;
1424 c1
= (c1
- d2
) >> 32;
1425 d3
= ((c1
& 0xffff) ^ 0x8000) - 0x8000;
1427 d4
= ((c1
& 0xffffffff) ^ 0x80000000) - 0x80000000;
1431 d1
= ((c1
& 0xffff) ^ 0x8000) - 0x8000;
1433 d2
= ((c1
& 0xffffffff) ^ 0x80000000) - 0x80000000;
1437 d3
= ((c2
& 0xffff) ^ 0x8000) - 0x8000;
1439 d4
= ((c2
& 0xffffffff) ^ 0x80000000) - 0x80000000;
1444 /* Construct the high word */
1447 emit_move_insn (target
, GEN_INT (d4
));
1449 emit_move_insn (target
, gen_rtx_PLUS (DImode
, target
, GEN_INT (d3
)));
1452 emit_move_insn (target
, GEN_INT (d3
));
1454 /* Shift it into place */
1455 emit_move_insn (target
, gen_rtx_ASHIFT (DImode
, target
, GEN_INT (32)));
1457 /* Add in the low bits. */
1459 emit_move_insn (target
, gen_rtx_PLUS (DImode
, target
, GEN_INT (d2
)));
1461 emit_move_insn (target
, gen_rtx_PLUS (DImode
, target
, GEN_INT (d1
)));
1466 /* Generate an unsigned DImode to FP conversion. This is the same code
1467 optabs would emit if we didn't have TFmode patterns.
1469 For SFmode, this is the only construction I've found that can pass
1470 gcc.c-torture/execute/ieee/rbug.c. No scenario that uses DFmode
1471 intermediates will work, because you'll get intermediate rounding
1472 that ruins the end result. Some of this could be fixed by turning
1473 on round-to-positive-infinity, but that requires diddling the fpsr,
1474 which kills performance. I tried turning this around and converting
1475 to a negative number, so that I could turn on /m, but either I did
1476 it wrong or there's something else cause I wound up with the exact
1477 same single-bit error. There is a branch-less form of this same code:
1488 fcmoveq $f10,$f11,$f0
1490 I'm not using it because it's the same number of instructions as
1491 this branch-full form, and it has more serialized long latency
1492 instructions on the critical path.
1494 For DFmode, we can avoid rounding errors by breaking up the word
1495 into two pieces, converting them separately, and adding them back:
1497 LC0: .long 0,0x5f800000
1501 cpyse $f11,$f31,$f10
1502 cpyse $f31,$f11,$f11
1510 This doesn't seem to be a clear-cut win over the optabs form.
1511 It probably all depends on the distribution of numbers being
1512 converted -- in the optabs form, all but high-bit-set has a
1513 much lower minimum execution time. */
1516 alpha_emit_floatuns (operands
)
1519 rtx neglab
, donelab
, i0
, i1
, f0
, in
, out
;
1520 enum machine_mode mode
;
1524 mode
= GET_MODE (out
);
1525 neglab
= gen_label_rtx ();
1526 donelab
= gen_label_rtx ();
1527 i0
= gen_reg_rtx (DImode
);
1528 i1
= gen_reg_rtx (DImode
);
1529 f0
= gen_reg_rtx (mode
);
1531 emit_cmp_and_jump_insns (in
, const0_rtx
, LT
, const0_rtx
, DImode
, 0,
1534 emit_insn (gen_rtx_SET (VOIDmode
, out
, gen_rtx_FLOAT (mode
, in
)));
1535 emit_jump_insn (gen_jump (donelab
));
1537 emit_label (neglab
);
1539 emit_insn (gen_lshrdi3 (i0
, in
, const1_rtx
));
1540 emit_insn (gen_anddi3 (i1
, in
, const1_rtx
));
1541 emit_insn (gen_iordi3 (i0
, i0
, i1
));
1542 emit_insn (gen_rtx_SET (VOIDmode
, f0
, gen_rtx_FLOAT (mode
, i0
)));
1543 emit_insn (gen_rtx_SET (VOIDmode
, out
, gen_rtx_PLUS (mode
, f0
, f0
)));
1545 emit_label (donelab
);
1548 /* Generate the comparison for a conditional branch. */
1551 alpha_emit_conditional_branch (code
)
1554 enum rtx_code cmp_code
, branch_code
;
1555 enum machine_mode cmp_mode
, branch_mode
= VOIDmode
;
1556 rtx op0
= alpha_compare
.op0
, op1
= alpha_compare
.op1
;
1559 if (alpha_compare
.fp_p
&& GET_MODE (op0
) == TFmode
)
1561 if (! TARGET_HAS_XFLOATING_LIBS
)
1564 /* X_floating library comparison functions return
1568 Convert the compare against the raw return value. */
1570 op0
= alpha_emit_xfloating_compare (code
, op0
, op1
);
1572 alpha_compare
.fp_p
= 0;
1576 /* The general case: fold the comparison code to the types of compares
1577 that we have, choosing the branch as necessary. */
1580 case EQ
: case LE
: case LT
: case LEU
: case LTU
:
1582 /* We have these compares: */
1583 cmp_code
= code
, branch_code
= NE
;
1588 /* These must be reversed. */
1589 cmp_code
= reverse_condition (code
), branch_code
= EQ
;
1592 case GE
: case GT
: case GEU
: case GTU
:
1593 /* For FP, we swap them, for INT, we reverse them. */
1594 if (alpha_compare
.fp_p
)
1596 cmp_code
= swap_condition (code
);
1598 tem
= op0
, op0
= op1
, op1
= tem
;
1602 cmp_code
= reverse_condition (code
);
1611 if (alpha_compare
.fp_p
)
1616 /* When we are not as concerned about non-finite values, and we
1617 are comparing against zero, we can branch directly. */
1618 if (op1
== CONST0_RTX (DFmode
))
1619 cmp_code
= NIL
, branch_code
= code
;
1620 else if (op0
== CONST0_RTX (DFmode
))
1622 /* Undo the swap we probably did just above. */
1623 tem
= op0
, op0
= op1
, op1
= tem
;
1624 branch_code
= swap_condition (cmp_code
);
1630 /* ??? We mark the the branch mode to be CCmode to prevent the
1631 compare and branch from being combined, since the compare
1632 insn follows IEEE rules that the branch does not. */
1633 branch_mode
= CCmode
;
1640 /* The following optimizations are only for signed compares. */
1641 if (code
!= LEU
&& code
!= LTU
&& code
!= GEU
&& code
!= GTU
)
1643 /* Whee. Compare and branch against 0 directly. */
1644 if (op1
== const0_rtx
)
1645 cmp_code
= NIL
, branch_code
= code
;
1647 /* We want to use cmpcc/bcc when we can, since there is a zero delay
1648 bypass between logicals and br/cmov on EV5. But we don't want to
1649 force valid immediate constants into registers needlessly. */
1650 else if (GET_CODE (op1
) == CONST_INT
)
1652 HOST_WIDE_INT v
= INTVAL (op1
), n
= -v
;
1654 if (! CONST_OK_FOR_LETTER_P (v
, 'I')
1655 && (CONST_OK_FOR_LETTER_P (n
, 'K')
1656 || CONST_OK_FOR_LETTER_P (n
, 'L')))
1658 cmp_code
= PLUS
, branch_code
= code
;
1665 /* Force op0 into a register. */
1666 if (GET_CODE (op0
) != REG
)
1667 op0
= force_reg (cmp_mode
, op0
);
1669 /* Emit an initial compare instruction, if necessary. */
1671 if (cmp_code
!= NIL
)
1673 tem
= gen_reg_rtx (cmp_mode
);
1674 emit_move_insn (tem
, gen_rtx_fmt_ee (cmp_code
, cmp_mode
, op0
, op1
));
1677 /* Zero the operands. */
1678 memset (&alpha_compare
, 0, sizeof (alpha_compare
));
1680 /* Return the branch comparison. */
1681 return gen_rtx_fmt_ee (branch_code
, branch_mode
, tem
, CONST0_RTX (cmp_mode
));
1685 /* Rewrite a comparison against zero CMP of the form
1686 (CODE (cc0) (const_int 0)) so it can be written validly in
1687 a conditional move (if_then_else CMP ...).
1688 If both of the operands that set cc0 are non-zero we must emit
1689 an insn to perform the compare (it can't be done within
1690 the conditional move). */
1692 alpha_emit_conditional_move (cmp
, mode
)
1694 enum machine_mode mode
;
1696 enum rtx_code code
= GET_CODE (cmp
);
1697 enum rtx_code cmov_code
= NE
;
1698 rtx op0
= alpha_compare
.op0
;
1699 rtx op1
= alpha_compare
.op1
;
1700 int fp_p
= alpha_compare
.fp_p
;
1701 enum machine_mode cmp_mode
1702 = (GET_MODE (op0
) == VOIDmode
? DImode
: GET_MODE (op0
));
1703 enum machine_mode cmp_op_mode
= fp_p
? DFmode
: DImode
;
1704 enum machine_mode cmov_mode
= VOIDmode
;
1705 int local_fast_math
= flag_fast_math
;
1708 /* Zero the operands. */
1709 memset (&alpha_compare
, 0, sizeof (alpha_compare
));
1711 if (fp_p
!= FLOAT_MODE_P (mode
))
1713 enum rtx_code cmp_code
;
1718 /* If we have fp<->int register move instructions, do a cmov by
1719 performing the comparison in fp registers, and move the
1720 zero/non-zero value to integer registers, where we can then
1721 use a normal cmov, or vice-versa. */
1725 case EQ
: case LE
: case LT
: case LEU
: case LTU
:
1726 /* We have these compares. */
1727 cmp_code
= code
, code
= NE
;
1731 /* This must be reversed. */
1732 cmp_code
= EQ
, code
= EQ
;
1735 case GE
: case GT
: case GEU
: case GTU
:
1736 /* These must be swapped. */
1737 cmp_code
= swap_condition (code
);
1739 tem
= op0
, op0
= op1
, op1
= tem
;
1746 tem
= gen_reg_rtx (cmp_op_mode
);
1747 emit_insn (gen_rtx_SET (VOIDmode
, tem
,
1748 gen_rtx_fmt_ee (cmp_code
, cmp_op_mode
,
1751 cmp_mode
= cmp_op_mode
= fp_p
? DImode
: DFmode
;
1752 op0
= gen_lowpart (cmp_op_mode
, tem
);
1753 op1
= CONST0_RTX (cmp_op_mode
);
1755 local_fast_math
= 1;
1758 /* We may be able to use a conditional move directly.
1759 This avoids emitting spurious compares. */
1760 if (signed_comparison_operator (cmp
, VOIDmode
)
1761 && (!fp_p
|| local_fast_math
)
1762 && (op0
== CONST0_RTX (cmp_mode
) || op1
== CONST0_RTX (cmp_mode
)))
1763 return gen_rtx_fmt_ee (code
, VOIDmode
, op0
, op1
);
1765 /* We can't put the comparison insides a conditional move;
1766 emit a compare instruction and put that inside the
1767 conditional move. Make sure we emit only comparisons we have;
1768 swap or reverse as necessary. */
1772 case EQ
: case LE
: case LT
: case LEU
: case LTU
:
1773 /* We have these compares: */
1777 /* This must be reversed. */
1778 code
= reverse_condition (code
);
1782 case GE
: case GT
: case GEU
: case GTU
:
1783 /* These must be swapped. Make sure the new first operand is in
1785 code
= swap_condition (code
);
1786 tem
= op0
, op0
= op1
, op1
= tem
;
1787 op0
= force_reg (cmp_mode
, op0
);
1794 /* ??? We mark the branch mode to be CCmode to prevent the compare
1795 and cmov from being combined, since the compare insn follows IEEE
1796 rules that the cmov does not. */
1797 if (fp_p
&& !local_fast_math
)
1800 tem
= gen_reg_rtx (cmp_op_mode
);
1801 emit_move_insn (tem
, gen_rtx_fmt_ee (code
, cmp_op_mode
, op0
, op1
));
1802 return gen_rtx_fmt_ee (cmov_code
, cmov_mode
, tem
, CONST0_RTX (cmp_op_mode
));
1805 /* Look up the function X_floating library function name for the
1809 alpha_lookup_xfloating_lib_func (code
)
1818 static const struct xfloating_op vms_xfloating_ops
[] =
1820 { PLUS
, "OTS$ADD_X" },
1821 { MINUS
, "OTS$SUB_X" },
1822 { MULT
, "OTS$MUL_X" },
1823 { DIV
, "OTS$DIV_X" },
1824 { EQ
, "OTS$EQL_X" },
1825 { NE
, "OTS$NEQ_X" },
1826 { LT
, "OTS$LSS_X" },
1827 { LE
, "OTS$LEQ_X" },
1828 { GT
, "OTS$GTR_X" },
1829 { GE
, "OTS$GEQ_X" },
1830 { FIX
, "OTS$CVTXQ" },
1831 { FLOAT
, "OTS$CVTQX" },
1832 { UNSIGNED_FLOAT
, "OTS$CVTQUX" },
1833 { FLOAT_EXTEND
, "OTS$CVT_FLOAT_T_X" },
1834 { FLOAT_TRUNCATE
, "OTS$CVT_FLOAT_X_T" },
1837 static const struct xfloating_op osf_xfloating_ops
[] =
1839 { PLUS
, "_OtsAddX" },
1840 { MINUS
, "_OtsSubX" },
1841 { MULT
, "_OtsMulX" },
1842 { DIV
, "_OtsDivX" },
1849 { FIX
, "_OtsCvtXQ" },
1850 { FLOAT
, "_OtsCvtQX" },
1851 { UNSIGNED_FLOAT
, "_OtsCvtQUX" },
1852 { FLOAT_EXTEND
, "_OtsConvertFloatTX" },
1853 { FLOAT_TRUNCATE
, "_OtsConvertFloatXT" },
1856 const struct xfloating_op
*ops
;
1857 const long n
= sizeof(osf_xfloating_ops
) / sizeof(osf_xfloating_ops
[0]);
1860 /* How irritating. Nothing to key off for the table. Hardcode
1861 knowledge of the G_floating routines. */
1862 if (TARGET_FLOAT_VAX
)
1864 if (TARGET_OPEN_VMS
)
1866 if (code
== FLOAT_EXTEND
)
1867 return "OTS$CVT_FLOAT_G_X";
1868 if (code
== FLOAT_TRUNCATE
)
1869 return "OTS$CVT_FLOAT_X_G";
1873 if (code
== FLOAT_EXTEND
)
1874 return "_OtsConvertFloatGX";
1875 if (code
== FLOAT_TRUNCATE
)
1876 return "_OtsConvertFloatXG";
1880 if (TARGET_OPEN_VMS
)
1881 ops
= vms_xfloating_ops
;
1883 ops
= osf_xfloating_ops
;
1885 for (i
= 0; i
< n
; ++i
)
1886 if (ops
[i
].code
== code
)
1892 /* Most X_floating operations take the rounding mode as an argument.
1893 Compute that here. */
1896 alpha_compute_xfloating_mode_arg (code
, round
)
1898 enum alpha_fp_rounding_mode round
;
1904 case ALPHA_FPRM_NORM
:
1907 case ALPHA_FPRM_MINF
:
1910 case ALPHA_FPRM_CHOP
:
1913 case ALPHA_FPRM_DYN
:
1919 /* XXX For reference, round to +inf is mode = 3. */
1922 if (code
== FLOAT_TRUNCATE
&& alpha_fptm
== ALPHA_FPTM_N
)
1928 /* Emit an X_floating library function call.
1930 Note that these functions do not follow normal calling conventions:
1931 TFmode arguments are passed in two integer registers (as opposed to
1932 indirect); TFmode return values appear in R16+R17.
1934 FUNC is the function name to call.
1935 TARGET is where the output belongs.
1936 OPERANDS are the inputs.
1937 NOPERANDS is the count of inputs.
1938 EQUIV is the expression equivalent for the function.
1942 alpha_emit_xfloating_libcall (func
, target
, operands
, noperands
, equiv
)
1949 rtx usage
= NULL_RTX
, tmp
, reg
;
1954 for (i
= 0; i
< noperands
; ++i
)
1956 switch (GET_MODE (operands
[i
]))
1959 reg
= gen_rtx_REG (TFmode
, regno
);
1964 reg
= gen_rtx_REG (DFmode
, regno
+ 32);
1969 if (GET_CODE (operands
[i
]) != CONST_INT
)
1973 reg
= gen_rtx_REG (DImode
, regno
);
1981 emit_move_insn (reg
, operands
[i
]);
1982 usage
= alloc_EXPR_LIST (0, gen_rtx_USE (VOIDmode
, reg
), usage
);
1985 switch (GET_MODE (target
))
1988 reg
= gen_rtx_REG (TFmode
, 16);
1991 reg
= gen_rtx_REG (DFmode
, 32);
1994 reg
= gen_rtx_REG (DImode
, 0);
2000 tmp
= gen_rtx_MEM (QImode
, gen_rtx_SYMBOL_REF (Pmode
, (char *) func
));
2001 tmp
= emit_call_insn (gen_call_value (reg
, tmp
, const0_rtx
,
2002 const0_rtx
, const0_rtx
));
2003 CALL_INSN_FUNCTION_USAGE (tmp
) = usage
;
2008 emit_libcall_block (tmp
, target
, reg
, equiv
);
2011 /* Emit an X_floating library function call for arithmetic (+,-,*,/). */
2014 alpha_emit_xfloating_arith (code
, operands
)
2020 rtx out_operands
[3];
2022 func
= alpha_lookup_xfloating_lib_func (code
);
2023 mode
= alpha_compute_xfloating_mode_arg (code
, alpha_fprm
);
2025 out_operands
[0] = operands
[1];
2026 out_operands
[1] = operands
[2];
2027 out_operands
[2] = GEN_INT (mode
);
2028 alpha_emit_xfloating_libcall (func
, operands
[0], out_operands
, 3,
2029 gen_rtx_fmt_ee (code
, TFmode
, operands
[1],
2033 /* Emit an X_floating library function call for a comparison. */
2036 alpha_emit_xfloating_compare (code
, op0
, op1
)
2041 rtx out
, operands
[2];
2043 func
= alpha_lookup_xfloating_lib_func (code
);
2047 out
= gen_reg_rtx (DImode
);
2049 /* ??? Strange equiv cause what's actually returned is -1,0,1, not a
2050 proper boolean value. */
2051 alpha_emit_xfloating_libcall (func
, out
, operands
, 2,
2052 gen_rtx_COMPARE (TFmode
, op0
, op1
));
2057 /* Emit an X_floating library function call for a conversion. */
2060 alpha_emit_xfloating_cvt (code
, operands
)
2064 int noperands
= 1, mode
;
2065 rtx out_operands
[2];
2068 func
= alpha_lookup_xfloating_lib_func (code
);
2070 out_operands
[0] = operands
[1];
2075 mode
= alpha_compute_xfloating_mode_arg (code
, ALPHA_FPRM_CHOP
);
2076 out_operands
[1] = GEN_INT (mode
);
2079 case FLOAT_TRUNCATE
:
2080 mode
= alpha_compute_xfloating_mode_arg (code
, alpha_fprm
);
2081 out_operands
[1] = GEN_INT (mode
);
2088 alpha_emit_xfloating_libcall (func
, operands
[0], out_operands
, noperands
,
2089 gen_rtx_fmt_e (code
, GET_MODE (operands
[0]),
2094 alpha_split_tfmode_pair (operands
)
2097 if (GET_CODE (operands
[1]) == REG
)
2099 operands
[3] = gen_rtx_REG (DImode
, REGNO (operands
[1]) + 1);
2100 operands
[2] = gen_rtx_REG (DImode
, REGNO (operands
[1]));
2102 else if (GET_CODE (operands
[1]) == MEM
)
2104 operands
[3] = change_address (operands
[1], DImode
,
2105 plus_constant (XEXP (operands
[1], 0), 8));
2106 operands
[2] = change_address (operands
[1], DImode
, NULL_RTX
);
2108 else if (operands
[1] == CONST0_RTX (TFmode
))
2109 operands
[2] = operands
[3] = const0_rtx
;
2113 if (GET_CODE (operands
[0]) == REG
)
2115 operands
[1] = gen_rtx_REG (DImode
, REGNO (operands
[0]) + 1);
2116 operands
[0] = gen_rtx_REG (DImode
, REGNO (operands
[0]));
2118 else if (GET_CODE (operands
[0]) == MEM
)
2120 operands
[1] = change_address (operands
[0], DImode
,
2121 plus_constant (XEXP (operands
[0], 0), 8));
2122 operands
[0] = change_address (operands
[0], DImode
, NULL_RTX
);
2128 /* Use ext[wlq][lh] as the Architecture Handbook describes for extracting
2132 word: ldq_u r1,X(r11) ldq_u r1,X(r11)
2133 ldq_u r2,X+1(r11) ldq_u r2,X+1(r11)
2134 lda r3,X(r11) lda r3,X+2(r11)
2135 extwl r1,r3,r1 extql r1,r3,r1
2136 extwh r2,r3,r2 extqh r2,r3,r2
2137 or r1.r2.r1 or r1,r2,r1
2140 long: ldq_u r1,X(r11) ldq_u r1,X(r11)
2141 ldq_u r2,X+3(r11) ldq_u r2,X+3(r11)
2142 lda r3,X(r11) lda r3,X(r11)
2143 extll r1,r3,r1 extll r1,r3,r1
2144 extlh r2,r3,r2 extlh r2,r3,r2
2145 or r1.r2.r1 addl r1,r2,r1
2147 quad: ldq_u r1,X(r11)
2156 alpha_expand_unaligned_load (tgt
, mem
, size
, ofs
, sign
)
2158 HOST_WIDE_INT size
, ofs
;
2161 rtx meml
, memh
, addr
, extl
, exth
;
2162 enum machine_mode mode
;
2164 meml
= gen_reg_rtx (DImode
);
2165 memh
= gen_reg_rtx (DImode
);
2166 addr
= gen_reg_rtx (DImode
);
2167 extl
= gen_reg_rtx (DImode
);
2168 exth
= gen_reg_rtx (DImode
);
2170 emit_move_insn (meml
,
2171 change_address (mem
, DImode
,
2172 gen_rtx_AND (DImode
,
2173 plus_constant (XEXP (mem
, 0),
2177 emit_move_insn (memh
,
2178 change_address (mem
, DImode
,
2179 gen_rtx_AND (DImode
,
2180 plus_constant (XEXP (mem
, 0),
2184 if (sign
&& size
== 2)
2186 emit_move_insn (addr
, plus_constant (XEXP (mem
, 0), ofs
+2));
2188 emit_insn (gen_extxl (extl
, meml
, GEN_INT (64), addr
));
2189 emit_insn (gen_extqh (exth
, memh
, addr
));
2191 /* We must use tgt here for the target. Alpha-vms port fails if we use
2192 addr for the target, because addr is marked as a pointer and combine
2193 knows that pointers are always sign-extended 32 bit values. */
2194 addr
= expand_binop (DImode
, ior_optab
, extl
, exth
, tgt
, 1, OPTAB_WIDEN
);
2195 addr
= expand_binop (DImode
, ashr_optab
, addr
, GEN_INT (48),
2196 addr
, 1, OPTAB_WIDEN
);
2200 emit_move_insn (addr
, plus_constant (XEXP (mem
, 0), ofs
));
2201 emit_insn (gen_extxl (extl
, meml
, GEN_INT (size
*8), addr
));
2205 emit_insn (gen_extwh (exth
, memh
, addr
));
2210 emit_insn (gen_extlh (exth
, memh
, addr
));
2215 emit_insn (gen_extqh (exth
, memh
, addr
));
2223 addr
= expand_binop (mode
, ior_optab
, gen_lowpart (mode
, extl
),
2224 gen_lowpart (mode
, exth
), gen_lowpart (mode
, tgt
),
2229 emit_move_insn (tgt
, gen_lowpart(GET_MODE (tgt
), addr
));
2232 /* Similarly, use ins and msk instructions to perform unaligned stores. */
2235 alpha_expand_unaligned_store (dst
, src
, size
, ofs
)
2237 HOST_WIDE_INT size
, ofs
;
2239 rtx dstl
, dsth
, addr
, insl
, insh
, meml
, memh
;
2241 dstl
= gen_reg_rtx (DImode
);
2242 dsth
= gen_reg_rtx (DImode
);
2243 insl
= gen_reg_rtx (DImode
);
2244 insh
= gen_reg_rtx (DImode
);
2246 meml
= change_address (dst
, DImode
,
2247 gen_rtx_AND (DImode
,
2248 plus_constant (XEXP (dst
, 0), ofs
),
2250 memh
= change_address (dst
, DImode
,
2251 gen_rtx_AND (DImode
,
2252 plus_constant (XEXP (dst
, 0),
2256 emit_move_insn (dsth
, memh
);
2257 emit_move_insn (dstl
, meml
);
2258 addr
= copy_addr_to_reg (plus_constant (XEXP (dst
, 0), ofs
));
2260 if (src
!= const0_rtx
)
2262 emit_insn (gen_insxh (insh
, gen_lowpart (DImode
, src
),
2263 GEN_INT (size
*8), addr
));
2268 emit_insn (gen_inswl (insl
, gen_lowpart (HImode
, src
), addr
));
2271 emit_insn (gen_insll (insl
, gen_lowpart (SImode
, src
), addr
));
2274 emit_insn (gen_insql (insl
, src
, addr
));
2279 emit_insn (gen_mskxh (dsth
, dsth
, GEN_INT (size
*8), addr
));
2284 emit_insn (gen_mskxl (dstl
, dstl
, GEN_INT (0xffff), addr
));
2287 emit_insn (gen_mskxl (dstl
, dstl
, GEN_INT (0xffffffff), addr
));
2291 #if HOST_BITS_PER_WIDE_INT == 32
2292 rtx msk
= immed_double_const (0xffffffff, 0xffffffff, DImode
);
2294 rtx msk
= immed_double_const (0xffffffffffffffff, 0, DImode
);
2296 emit_insn (gen_mskxl (dstl
, dstl
, msk
, addr
));
2301 if (src
!= const0_rtx
)
2303 dsth
= expand_binop (DImode
, ior_optab
, insh
, dsth
, dsth
, 0, OPTAB_WIDEN
);
2304 dstl
= expand_binop (DImode
, ior_optab
, insl
, dstl
, dstl
, 0, OPTAB_WIDEN
);
2307 /* Must store high before low for degenerate case of aligned. */
2308 emit_move_insn (memh
, dsth
);
2309 emit_move_insn (meml
, dstl
);
2312 /* The block move code tries to maximize speed by separating loads and
2313 stores at the expense of register pressure: we load all of the data
2314 before we store it back out. There are two secondary effects worth
2315 mentioning, that this speeds copying to/from aligned and unaligned
2316 buffers, and that it makes the code significantly easier to write. */
2318 #define MAX_MOVE_WORDS 8
2320 /* Load an integral number of consecutive unaligned quadwords. */
2323 alpha_expand_unaligned_load_words (out_regs
, smem
, words
, ofs
)
2326 HOST_WIDE_INT words
, ofs
;
2328 rtx
const im8
= GEN_INT (-8);
2329 rtx
const i64
= GEN_INT (64);
2330 rtx ext_tmps
[MAX_MOVE_WORDS
], data_regs
[MAX_MOVE_WORDS
+1];
2334 /* Generate all the tmp registers we need. */
2335 for (i
= 0; i
< words
; ++i
)
2337 data_regs
[i
] = out_regs
[i
];
2338 ext_tmps
[i
] = gen_reg_rtx (DImode
);
2340 data_regs
[words
] = gen_reg_rtx (DImode
);
2343 smem
= change_address (smem
, GET_MODE (smem
),
2344 plus_constant (XEXP (smem
, 0), ofs
));
2346 /* Load up all of the source data. */
2347 for (i
= 0; i
< words
; ++i
)
2349 emit_move_insn (data_regs
[i
],
2350 change_address (smem
, DImode
,
2351 gen_rtx_AND (DImode
,
2352 plus_constant (XEXP(smem
,0),
2356 emit_move_insn (data_regs
[words
],
2357 change_address (smem
, DImode
,
2358 gen_rtx_AND (DImode
,
2359 plus_constant (XEXP(smem
,0),
2363 /* Extract the half-word fragments. Unfortunately DEC decided to make
2364 extxh with offset zero a noop instead of zeroing the register, so
2365 we must take care of that edge condition ourselves with cmov. */
2367 sreg
= copy_addr_to_reg (XEXP (smem
, 0));
2368 areg
= expand_binop (DImode
, and_optab
, sreg
, GEN_INT (7), NULL
,
2370 for (i
= 0; i
< words
; ++i
)
2372 emit_insn (gen_extxl (data_regs
[i
], data_regs
[i
], i64
, sreg
));
2374 emit_insn (gen_extqh (ext_tmps
[i
], data_regs
[i
+1], sreg
));
2375 emit_insn (gen_rtx_SET (VOIDmode
, ext_tmps
[i
],
2376 gen_rtx_IF_THEN_ELSE (DImode
,
2377 gen_rtx_EQ (DImode
, areg
,
2379 const0_rtx
, ext_tmps
[i
])));
2382 /* Merge the half-words into whole words. */
2383 for (i
= 0; i
< words
; ++i
)
2385 out_regs
[i
] = expand_binop (DImode
, ior_optab
, data_regs
[i
],
2386 ext_tmps
[i
], data_regs
[i
], 1, OPTAB_WIDEN
);
2390 /* Store an integral number of consecutive unaligned quadwords. DATA_REGS
2391 may be NULL to store zeros. */
2394 alpha_expand_unaligned_store_words (data_regs
, dmem
, words
, ofs
)
2397 HOST_WIDE_INT words
, ofs
;
2399 rtx
const im8
= GEN_INT (-8);
2400 rtx
const i64
= GEN_INT (64);
2401 #if HOST_BITS_PER_WIDE_INT == 32
2402 rtx
const im1
= immed_double_const (0xffffffff, 0xffffffff, DImode
);
2404 rtx
const im1
= immed_double_const (0xffffffffffffffff, 0, DImode
);
2406 rtx ins_tmps
[MAX_MOVE_WORDS
];
2407 rtx st_tmp_1
, st_tmp_2
, dreg
;
2408 rtx st_addr_1
, st_addr_2
;
2411 /* Generate all the tmp registers we need. */
2412 if (data_regs
!= NULL
)
2413 for (i
= 0; i
< words
; ++i
)
2414 ins_tmps
[i
] = gen_reg_rtx(DImode
);
2415 st_tmp_1
= gen_reg_rtx(DImode
);
2416 st_tmp_2
= gen_reg_rtx(DImode
);
2419 dmem
= change_address (dmem
, GET_MODE (dmem
),
2420 plus_constant (XEXP (dmem
, 0), ofs
));
2423 st_addr_2
= change_address (dmem
, DImode
,
2424 gen_rtx_AND (DImode
,
2425 plus_constant (XEXP(dmem
,0),
2428 st_addr_1
= change_address (dmem
, DImode
,
2429 gen_rtx_AND (DImode
,
2433 /* Load up the destination end bits. */
2434 emit_move_insn (st_tmp_2
, st_addr_2
);
2435 emit_move_insn (st_tmp_1
, st_addr_1
);
2437 /* Shift the input data into place. */
2438 dreg
= copy_addr_to_reg (XEXP (dmem
, 0));
2439 if (data_regs
!= NULL
)
2441 for (i
= words
-1; i
>= 0; --i
)
2443 emit_insn (gen_insxh (ins_tmps
[i
], data_regs
[i
], i64
, dreg
));
2444 emit_insn (gen_insql (data_regs
[i
], data_regs
[i
], dreg
));
2446 for (i
= words
-1; i
> 0; --i
)
2448 ins_tmps
[i
-1] = expand_binop (DImode
, ior_optab
, data_regs
[i
],
2449 ins_tmps
[i
-1], ins_tmps
[i
-1], 1,
2454 /* Split and merge the ends with the destination data. */
2455 emit_insn (gen_mskxh (st_tmp_2
, st_tmp_2
, i64
, dreg
));
2456 emit_insn (gen_mskxl (st_tmp_1
, st_tmp_1
, im1
, dreg
));
2458 if (data_regs
!= NULL
)
2460 st_tmp_2
= expand_binop (DImode
, ior_optab
, st_tmp_2
, ins_tmps
[words
-1],
2461 st_tmp_2
, 1, OPTAB_WIDEN
);
2462 st_tmp_1
= expand_binop (DImode
, ior_optab
, st_tmp_1
, data_regs
[0],
2463 st_tmp_1
, 1, OPTAB_WIDEN
);
2467 emit_move_insn (st_addr_2
, st_tmp_2
);
2468 for (i
= words
-1; i
> 0; --i
)
2470 emit_move_insn (change_address (dmem
, DImode
,
2471 gen_rtx_AND (DImode
,
2472 plus_constant(XEXP (dmem
,0),
2475 data_regs
? ins_tmps
[i
-1] : const0_rtx
);
2477 emit_move_insn (st_addr_1
, st_tmp_1
);
2481 /* Expand string/block move operations.
2483 operands[0] is the pointer to the destination.
2484 operands[1] is the pointer to the source.
2485 operands[2] is the number of bytes to move.
2486 operands[3] is the alignment. */
2489 alpha_expand_block_move (operands
)
2492 rtx bytes_rtx
= operands
[2];
2493 rtx align_rtx
= operands
[3];
2494 HOST_WIDE_INT orig_bytes
= INTVAL (bytes_rtx
);
2495 HOST_WIDE_INT bytes
= orig_bytes
;
2496 HOST_WIDE_INT src_align
= INTVAL (align_rtx
);
2497 HOST_WIDE_INT dst_align
= src_align
;
2498 rtx orig_src
= operands
[1];
2499 rtx orig_dst
= operands
[0];
2500 rtx data_regs
[2*MAX_MOVE_WORDS
+16];
2502 int i
, words
, ofs
, nregs
= 0;
2506 if (bytes
> MAX_MOVE_WORDS
*8)
2509 /* Look for additional alignment information from recorded register info. */
2511 tmp
= XEXP (orig_src
, 0);
2512 if (GET_CODE (tmp
) == REG
)
2514 if (REGNO_POINTER_ALIGN (REGNO (tmp
)) > src_align
)
2515 src_align
= REGNO_POINTER_ALIGN (REGNO (tmp
));
2517 else if (GET_CODE (tmp
) == PLUS
2518 && GET_CODE (XEXP (tmp
, 0)) == REG
2519 && GET_CODE (XEXP (tmp
, 1)) == CONST_INT
)
2521 HOST_WIDE_INT c
= INTVAL (XEXP (tmp
, 1));
2522 int a
= REGNO_POINTER_ALIGN (REGNO (XEXP (tmp
, 0)));
2526 if (a
>= 8 && c
% 8 == 0)
2528 else if (a
>= 4 && c
% 4 == 0)
2530 else if (a
>= 2 && c
% 2 == 0)
2535 tmp
= XEXP (orig_dst
, 0);
2536 if (GET_CODE (tmp
) == REG
)
2538 if (REGNO_POINTER_ALIGN (REGNO (tmp
)) > dst_align
)
2539 dst_align
= REGNO_POINTER_ALIGN (REGNO (tmp
));
2541 else if (GET_CODE (tmp
) == PLUS
2542 && GET_CODE (XEXP (tmp
, 0)) == REG
2543 && GET_CODE (XEXP (tmp
, 1)) == CONST_INT
)
2545 HOST_WIDE_INT c
= INTVAL (XEXP (tmp
, 1));
2546 int a
= REGNO_POINTER_ALIGN (REGNO (XEXP (tmp
, 0)));
2550 if (a
>= 8 && c
% 8 == 0)
2552 else if (a
>= 4 && c
% 4 == 0)
2554 else if (a
>= 2 && c
% 2 == 0)
2560 * Load the entire block into registers.
2563 if (GET_CODE (XEXP (orig_src
, 0)) == ADDRESSOF
)
2565 enum machine_mode mode
;
2566 tmp
= XEXP (XEXP (orig_src
, 0), 0);
2568 /* Don't use the existing register if we're reading more than
2569 is held in the register. Nor if there is not a mode that
2570 handles the exact size. */
2571 mode
= mode_for_size (bytes
* BITS_PER_UNIT
, MODE_INT
, 1);
2573 && GET_MODE_SIZE (GET_MODE (tmp
)) >= bytes
)
2577 data_regs
[nregs
] = gen_lowpart (DImode
, tmp
);
2578 data_regs
[nregs
+1] = gen_highpart (DImode
, tmp
);
2582 data_regs
[nregs
++] = gen_lowpart (mode
, tmp
);
2586 /* No appropriate mode; fall back on memory. */
2587 orig_src
= change_address (orig_src
, GET_MODE (orig_src
),
2588 copy_addr_to_reg (XEXP (orig_src
, 0)));
2592 if (src_align
>= 8 && bytes
>= 8)
2596 for (i
= 0; i
< words
; ++i
)
2597 data_regs
[nregs
+i
] = gen_reg_rtx(DImode
);
2599 for (i
= 0; i
< words
; ++i
)
2601 emit_move_insn (data_regs
[nregs
+i
],
2602 change_address (orig_src
, DImode
,
2603 plus_constant (XEXP (orig_src
, 0),
2611 if (src_align
>= 4 && bytes
>= 4)
2615 for (i
= 0; i
< words
; ++i
)
2616 data_regs
[nregs
+i
] = gen_reg_rtx(SImode
);
2618 for (i
= 0; i
< words
; ++i
)
2620 emit_move_insn (data_regs
[nregs
+i
],
2621 change_address (orig_src
, SImode
,
2622 plus_constant (XEXP (orig_src
, 0),
2634 for (i
= 0; i
< words
+1; ++i
)
2635 data_regs
[nregs
+i
] = gen_reg_rtx(DImode
);
2637 alpha_expand_unaligned_load_words (data_regs
+ nregs
, orig_src
,
2644 if (!TARGET_BWX
&& bytes
>= 8)
2646 data_regs
[nregs
++] = tmp
= gen_reg_rtx (DImode
);
2647 alpha_expand_unaligned_load (tmp
, orig_src
, 8, ofs
, 0);
2651 if (!TARGET_BWX
&& bytes
>= 4)
2653 data_regs
[nregs
++] = tmp
= gen_reg_rtx (SImode
);
2654 alpha_expand_unaligned_load (tmp
, orig_src
, 4, ofs
, 0);
2663 data_regs
[nregs
++] = tmp
= gen_reg_rtx (HImode
);
2664 emit_move_insn (tmp
,
2665 change_address (orig_src
, HImode
,
2666 plus_constant (XEXP (orig_src
, 0),
2670 } while (bytes
>= 2);
2672 else if (!TARGET_BWX
)
2674 data_regs
[nregs
++] = tmp
= gen_reg_rtx (HImode
);
2675 alpha_expand_unaligned_load (tmp
, orig_src
, 2, ofs
, 0);
2682 data_regs
[nregs
++] = tmp
= gen_reg_rtx (QImode
);
2683 emit_move_insn (tmp
,
2684 change_address (orig_src
, QImode
,
2685 plus_constant (XEXP (orig_src
, 0),
2692 if (nregs
> (int)(sizeof(data_regs
)/sizeof(*data_regs
)))
2696 * Now save it back out again.
2701 if (GET_CODE (XEXP (orig_dst
, 0)) == ADDRESSOF
)
2703 enum machine_mode mode
;
2704 tmp
= XEXP (XEXP (orig_dst
, 0), 0);
2706 mode
= mode_for_size (orig_bytes
* BITS_PER_UNIT
, MODE_INT
, 1);
2707 if (GET_MODE (tmp
) == mode
)
2711 emit_move_insn (tmp
, data_regs
[0]);
2715 else if (nregs
== 2 && mode
== TImode
)
2717 /* Undo the subregging done above when copying between
2718 two TImode registers. */
2719 if (GET_CODE (data_regs
[0]) == SUBREG
2720 && GET_MODE (SUBREG_REG (data_regs
[0])) == TImode
)
2722 emit_move_insn (tmp
, SUBREG_REG (data_regs
[0]));
2729 emit_move_insn (gen_lowpart (DImode
, tmp
), data_regs
[0]);
2730 emit_move_insn (gen_highpart (DImode
, tmp
), data_regs
[1]);
2734 emit_no_conflict_block (seq
, tmp
, data_regs
[0],
2735 data_regs
[1], NULL_RTX
);
2743 /* ??? If nregs > 1, consider reconstructing the word in regs. */
2744 /* ??? Optimize mode < dst_mode with strict_low_part. */
2746 /* No appropriate mode; fall back on memory. We can speed things
2747 up by recognizing extra alignment information. */
2748 orig_dst
= change_address (orig_dst
, GET_MODE (orig_dst
),
2749 copy_addr_to_reg (XEXP (orig_dst
, 0)));
2750 dst_align
= GET_MODE_SIZE (GET_MODE (tmp
));
2753 /* Write out the data in whatever chunks reading the source allowed. */
2756 while (i
< nregs
&& GET_MODE (data_regs
[i
]) == DImode
)
2758 emit_move_insn (change_address (orig_dst
, DImode
,
2759 plus_constant (XEXP (orig_dst
, 0),
2768 /* If the source has remaining DImode regs, write them out in
2770 while (i
< nregs
&& GET_MODE (data_regs
[i
]) == DImode
)
2772 tmp
= expand_binop (DImode
, lshr_optab
, data_regs
[i
], GEN_INT (32),
2773 NULL_RTX
, 1, OPTAB_WIDEN
);
2775 emit_move_insn (change_address (orig_dst
, SImode
,
2776 plus_constant (XEXP (orig_dst
, 0),
2778 gen_lowpart (SImode
, data_regs
[i
]));
2779 emit_move_insn (change_address (orig_dst
, SImode
,
2780 plus_constant (XEXP (orig_dst
, 0),
2782 gen_lowpart (SImode
, tmp
));
2787 while (i
< nregs
&& GET_MODE (data_regs
[i
]) == SImode
)
2789 emit_move_insn (change_address(orig_dst
, SImode
,
2790 plus_constant (XEXP (orig_dst
, 0),
2797 if (i
< nregs
&& GET_MODE (data_regs
[i
]) == DImode
)
2799 /* Write out a remaining block of words using unaligned methods. */
2801 for (words
= 1; i
+words
< nregs
; ++words
)
2802 if (GET_MODE (data_regs
[i
+words
]) != DImode
)
2806 alpha_expand_unaligned_store (orig_dst
, data_regs
[i
], 8, ofs
);
2808 alpha_expand_unaligned_store_words (data_regs
+i
, orig_dst
, words
, ofs
);
2814 /* Due to the above, this won't be aligned. */
2815 /* ??? If we have more than one of these, consider constructing full
2816 words in registers and using alpha_expand_unaligned_store_words. */
2817 while (i
< nregs
&& GET_MODE (data_regs
[i
]) == SImode
)
2819 alpha_expand_unaligned_store (orig_dst
, data_regs
[i
], 4, ofs
);
2825 while (i
< nregs
&& GET_MODE (data_regs
[i
]) == HImode
)
2827 emit_move_insn (change_address (orig_dst
, HImode
,
2828 plus_constant (XEXP (orig_dst
, 0),
2835 while (i
< nregs
&& GET_MODE (data_regs
[i
]) == HImode
)
2837 alpha_expand_unaligned_store (orig_dst
, data_regs
[i
], 2, ofs
);
2841 while (i
< nregs
&& GET_MODE (data_regs
[i
]) == QImode
)
2843 emit_move_insn (change_address (orig_dst
, QImode
,
2844 plus_constant (XEXP (orig_dst
, 0),
2859 alpha_expand_block_clear (operands
)
2862 rtx bytes_rtx
= operands
[1];
2863 rtx align_rtx
= operands
[2];
2864 HOST_WIDE_INT bytes
= INTVAL (bytes_rtx
);
2865 HOST_WIDE_INT align
= INTVAL (align_rtx
);
2866 rtx orig_dst
= operands
[0];
2868 HOST_WIDE_INT i
, words
, ofs
= 0;
2872 if (bytes
> MAX_MOVE_WORDS
*8)
2875 /* Look for stricter alignment. */
2877 tmp
= XEXP (orig_dst
, 0);
2878 if (GET_CODE (tmp
) == REG
)
2880 if (REGNO_POINTER_ALIGN (REGNO (tmp
)) > align
)
2881 align
= REGNO_POINTER_ALIGN (REGNO (tmp
));
2883 else if (GET_CODE (tmp
) == PLUS
2884 && GET_CODE (XEXP (tmp
, 0)) == REG
2885 && GET_CODE (XEXP (tmp
, 1)) == CONST_INT
)
2887 HOST_WIDE_INT c
= INTVAL (XEXP (tmp
, 1));
2888 int a
= REGNO_POINTER_ALIGN (REGNO (XEXP (tmp
, 0)));
2892 if (a
>= 8 && c
% 8 == 0)
2894 else if (a
>= 4 && c
% 4 == 0)
2896 else if (a
>= 2 && c
% 2 == 0)
2900 else if (GET_CODE (tmp
) == ADDRESSOF
)
2902 enum machine_mode mode
;
2904 mode
= mode_for_size (bytes
* BITS_PER_UNIT
, MODE_INT
, 1);
2905 if (GET_MODE (XEXP (tmp
, 0)) == mode
)
2907 emit_move_insn (XEXP (tmp
, 0), const0_rtx
);
2911 /* No appropriate mode; fall back on memory. */
2912 orig_dst
= change_address (orig_dst
, GET_MODE (orig_dst
),
2913 copy_addr_to_reg (tmp
));
2914 align
= GET_MODE_SIZE (GET_MODE (XEXP (tmp
, 0)));
2917 /* Handle a block of contiguous words first. */
2919 if (align
>= 8 && bytes
>= 8)
2923 for (i
= 0; i
< words
; ++i
)
2925 emit_move_insn (change_address(orig_dst
, DImode
,
2926 plus_constant (XEXP (orig_dst
, 0),
2934 if (align
>= 4 && bytes
>= 4)
2938 for (i
= 0; i
< words
; ++i
)
2940 emit_move_insn (change_address (orig_dst
, SImode
,
2941 plus_constant (XEXP (orig_dst
, 0),
2953 alpha_expand_unaligned_store_words (NULL
, orig_dst
, words
, ofs
);
2959 /* Next clean up any trailing pieces. We know from the contiguous
2960 block move that there are no aligned SImode or DImode hunks left. */
2962 if (!TARGET_BWX
&& bytes
>= 8)
2964 alpha_expand_unaligned_store (orig_dst
, const0_rtx
, 8, ofs
);
2968 if (!TARGET_BWX
&& bytes
>= 4)
2970 alpha_expand_unaligned_store (orig_dst
, const0_rtx
, 4, ofs
);
2979 emit_move_insn (change_address (orig_dst
, HImode
,
2980 plus_constant (XEXP (orig_dst
, 0),
2985 } while (bytes
>= 2);
2987 else if (!TARGET_BWX
)
2989 alpha_expand_unaligned_store (orig_dst
, const0_rtx
, 2, ofs
);
2996 emit_move_insn (change_address (orig_dst
, QImode
,
2997 plus_constant (XEXP (orig_dst
, 0),
3008 /* Adjust the cost of a scheduling dependency. Return the new cost of
3009 a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
3012 alpha_adjust_cost (insn
, link
, dep_insn
, cost
)
3019 enum attr_type insn_type
, dep_insn_type
;
3021 /* If the dependence is an anti-dependence, there is no cost. For an
3022 output dependence, there is sometimes a cost, but it doesn't seem
3023 worth handling those few cases. */
3025 if (REG_NOTE_KIND (link
) != 0)
3028 /* If we can't recognize the insns, we can't really do anything. */
3029 if (recog_memoized (insn
) < 0 || recog_memoized (dep_insn
) < 0)
3032 insn_type
= get_attr_type (insn
);
3033 dep_insn_type
= get_attr_type (dep_insn
);
3035 /* Bring in the user-defined memory latency. */
3036 if (dep_insn_type
== TYPE_ILD
3037 || dep_insn_type
== TYPE_FLD
3038 || dep_insn_type
== TYPE_LDSYM
)
3039 cost
+= alpha_memory_latency
-1;
3044 /* On EV4, if INSN is a store insn and DEP_INSN is setting the data
3045 being stored, we can sometimes lower the cost. */
3047 if ((insn_type
== TYPE_IST
|| insn_type
== TYPE_FST
)
3048 && (set
= single_set (dep_insn
)) != 0
3049 && GET_CODE (PATTERN (insn
)) == SET
3050 && rtx_equal_p (SET_DEST (set
), SET_SRC (PATTERN (insn
))))
3052 switch (dep_insn_type
)
3056 /* No savings here. */
3060 /* In these cases, we save one cycle. */
3064 /* In all other cases, we save two cycles. */
3065 return MAX (0, cost
- 2);
3069 /* Another case that needs adjustment is an arithmetic or logical
3070 operation. It's cost is usually one cycle, but we default it to
3071 two in the MD file. The only case that it is actually two is
3072 for the address in loads, stores, and jumps. */
3074 if (dep_insn_type
== TYPE_IADD
|| dep_insn_type
== TYPE_ILOG
)
3089 /* The final case is when a compare feeds into an integer branch;
3090 the cost is only one cycle in that case. */
3092 if (dep_insn_type
== TYPE_ICMP
&& insn_type
== TYPE_IBR
)
3097 /* And the lord DEC saith: "A special bypass provides an effective
3098 latency of 0 cycles for an ICMP or ILOG insn producing the test
3099 operand of an IBR or ICMOV insn." */
3101 if ((dep_insn_type
== TYPE_ICMP
|| dep_insn_type
== TYPE_ILOG
)
3102 && (set
= single_set (dep_insn
)) != 0)
3104 /* A branch only has one input. This must be it. */
3105 if (insn_type
== TYPE_IBR
)
3107 /* A conditional move has three, make sure it is the test. */
3108 if (insn_type
== TYPE_ICMOV
3109 && GET_CODE (set_src
= PATTERN (insn
)) == SET
3110 && GET_CODE (set_src
= SET_SRC (set_src
)) == IF_THEN_ELSE
3111 && rtx_equal_p (SET_DEST (set
), XEXP (set_src
, 0)))
3115 /* "The multiplier is unable to receive data from IEU bypass paths.
3116 The instruction issues at the expected time, but its latency is
3117 increased by the time it takes for the input data to become
3118 available to the multiplier" -- which happens in pipeline stage
3119 six, when results are comitted to the register file. */
3121 if (insn_type
== TYPE_IMUL
)
3123 switch (dep_insn_type
)
3125 /* These insns produce their results in pipeline stage five. */
3132 /* Other integer insns produce results in pipeline stage four. */
3140 /* There is additional latency to move the result of (most) FP
3141 operations anywhere but the FP register file. */
3143 if ((insn_type
== TYPE_FST
|| insn_type
== TYPE_FTOI
)
3144 && (dep_insn_type
== TYPE_FADD
||
3145 dep_insn_type
== TYPE_FMUL
||
3146 dep_insn_type
== TYPE_FCMOV
))
3152 /* Otherwise, return the default cost. */
3156 /* Functions to save and restore alpha_return_addr_rtx. */
3159 alpha_init_machine_status (p
)
3163 (struct machine_function
*) xcalloc (1, sizeof (struct machine_function
));
3167 alpha_mark_machine_status (p
)
3170 struct machine_function
*machine
= p
->machine
;
3172 ggc_mark_rtx (machine
->eh_epilogue_sp_ofs
);
3173 ggc_mark_rtx (machine
->ra_rtx
);
3176 /* Start the ball rolling with RETURN_ADDR_RTX. */
3179 alpha_return_addr (count
, frame
)
3181 rtx frame ATTRIBUTE_UNUSED
;
3188 reg
= cfun
->machine
->ra_rtx
;
3191 /* No rtx yet. Invent one, and initialize it from $26 in
3193 reg
= gen_reg_rtx (Pmode
);
3194 cfun
->machine
->ra_rtx
= reg
;
3195 init
= gen_rtx_SET (VOIDmode
, reg
, gen_rtx_REG (Pmode
, REG_RA
));
3197 /* Emit the insn to the prologue with the other argument copies. */
3198 push_topmost_sequence ();
3199 emit_insn_after (init
, get_insns ());
3200 pop_topmost_sequence ();
3207 alpha_ra_ever_killed ()
3211 #ifdef ASM_OUTPUT_MI_THUNK
3212 if (current_function_is_thunk
)
3215 if (!cfun
->machine
->ra_rtx
)
3216 return regs_ever_live
[REG_RA
];
3218 push_topmost_sequence ();
3220 pop_topmost_sequence ();
3222 return reg_set_between_p (gen_rtx_REG (Pmode
, REG_RA
), top
, NULL_RTX
);
3226 /* Print an operand. Recognize special options, documented below. */
3229 print_operand (file
, x
, code
)
3239 /* Generates fp-rounding mode suffix: nothing for normal, 'c' for
3240 chopped, 'm' for minus-infinity, and 'd' for dynamic rounding
3241 mode. alpha_fprm controls which suffix is generated. */
3244 case ALPHA_FPRM_NORM
:
3246 case ALPHA_FPRM_MINF
:
3249 case ALPHA_FPRM_CHOP
:
3252 case ALPHA_FPRM_DYN
:
3261 /* Generates trap-mode suffix for instructions that accept the su
3262 suffix only (cmpt et al). */
3263 if (alpha_fptm
>= ALPHA_FPTM_SU
)
3268 /* Generates trap-mode suffix for instructions that accept the
3269 v and sv suffix. The only instruction that needs this is cvtql. */
3278 case ALPHA_FPTM_SUI
:
3285 /* Generates trap-mode suffix for instructions that accept the
3286 v, sv, and svi suffix. The only instruction that needs this
3298 case ALPHA_FPTM_SUI
:
3299 fputs ("svi", file
);
3305 /* Generates trap-mode suffix for instructions that accept the u, su,
3306 and sui suffix. This is the bulk of the IEEE floating point
3307 instructions (addt et al). */
3318 case ALPHA_FPTM_SUI
:
3319 fputs ("sui", file
);
3325 /* Generates trap-mode suffix for instructions that accept the sui
3326 suffix (cvtqt and cvtqs). */
3331 case ALPHA_FPTM_SU
: /* cvtqt/cvtqs can't cause underflow */
3333 case ALPHA_FPTM_SUI
:
3334 fputs ("sui", file
);
3340 /* Generates single precision instruction suffix. */
3341 fprintf (file
, "%c", (TARGET_FLOAT_VAX
? 'f' : 's'));
3345 /* Generates double precision instruction suffix. */
3346 fprintf (file
, "%c", (TARGET_FLOAT_VAX
? 'g' : 't'));
3350 /* If this operand is the constant zero, write it as "$31". */
3351 if (GET_CODE (x
) == REG
)
3352 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
3353 else if (x
== CONST0_RTX (GET_MODE (x
)))
3354 fprintf (file
, "$31");
3356 output_operand_lossage ("invalid %%r value");
3361 /* Similar, but for floating-point. */
3362 if (GET_CODE (x
) == REG
)
3363 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
3364 else if (x
== CONST0_RTX (GET_MODE (x
)))
3365 fprintf (file
, "$f31");
3367 output_operand_lossage ("invalid %%R value");
3372 /* Write the 1's complement of a constant. */
3373 if (GET_CODE (x
) != CONST_INT
)
3374 output_operand_lossage ("invalid %%N value");
3376 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, ~ INTVAL (x
));
3380 /* Write 1 << C, for a constant C. */
3381 if (GET_CODE (x
) != CONST_INT
)
3382 output_operand_lossage ("invalid %%P value");
3384 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, (HOST_WIDE_INT
) 1 << INTVAL (x
));
3388 /* Write the high-order 16 bits of a constant, sign-extended. */
3389 if (GET_CODE (x
) != CONST_INT
)
3390 output_operand_lossage ("invalid %%h value");
3392 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
) >> 16);
3396 /* Write the low-order 16 bits of a constant, sign-extended. */
3397 if (GET_CODE (x
) != CONST_INT
)
3398 output_operand_lossage ("invalid %%L value");
3400 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
,
3401 (INTVAL (x
) & 0xffff) - 2 * (INTVAL (x
) & 0x8000));
3405 /* Write mask for ZAP insn. */
3406 if (GET_CODE (x
) == CONST_DOUBLE
)
3408 HOST_WIDE_INT mask
= 0;
3409 HOST_WIDE_INT value
;
3411 value
= CONST_DOUBLE_LOW (x
);
3412 for (i
= 0; i
< HOST_BITS_PER_WIDE_INT
/ HOST_BITS_PER_CHAR
;
3417 value
= CONST_DOUBLE_HIGH (x
);
3418 for (i
= 0; i
< HOST_BITS_PER_WIDE_INT
/ HOST_BITS_PER_CHAR
;
3421 mask
|= (1 << (i
+ sizeof (int)));
3423 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, mask
& 0xff);
3426 else if (GET_CODE (x
) == CONST_INT
)
3428 HOST_WIDE_INT mask
= 0, value
= INTVAL (x
);
3430 for (i
= 0; i
< 8; i
++, value
>>= 8)
3434 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, mask
);
3437 output_operand_lossage ("invalid %%m value");
3441 /* 'b', 'w', 'l', or 'q' as the value of the constant. */
3442 if (GET_CODE (x
) != CONST_INT
3443 || (INTVAL (x
) != 8 && INTVAL (x
) != 16
3444 && INTVAL (x
) != 32 && INTVAL (x
) != 64))
3445 output_operand_lossage ("invalid %%M value");
3447 fprintf (file
, "%s",
3448 (INTVAL (x
) == 8 ? "b"
3449 : INTVAL (x
) == 16 ? "w"
3450 : INTVAL (x
) == 32 ? "l"
3455 /* Similar, except do it from the mask. */
3456 if (GET_CODE (x
) == CONST_INT
&& INTVAL (x
) == 0xff)
3457 fprintf (file
, "b");
3458 else if (GET_CODE (x
) == CONST_INT
&& INTVAL (x
) == 0xffff)
3459 fprintf (file
, "w");
3460 else if (GET_CODE (x
) == CONST_INT
&& INTVAL (x
) == 0xffffffff)
3461 fprintf (file
, "l");
3462 #if HOST_BITS_PER_WIDE_INT == 32
3463 else if (GET_CODE (x
) == CONST_DOUBLE
3464 && CONST_DOUBLE_HIGH (x
) == 0
3465 && CONST_DOUBLE_LOW (x
) == -1)
3466 fprintf (file
, "l");
3467 else if (GET_CODE (x
) == CONST_DOUBLE
3468 && CONST_DOUBLE_HIGH (x
) == -1
3469 && CONST_DOUBLE_LOW (x
) == -1)
3470 fprintf (file
, "q");
3472 else if (GET_CODE (x
) == CONST_INT
&& INTVAL (x
) == -1)
3473 fprintf (file
, "q");
3474 else if (GET_CODE (x
) == CONST_DOUBLE
3475 && CONST_DOUBLE_HIGH (x
) == 0
3476 && CONST_DOUBLE_LOW (x
) == -1)
3477 fprintf (file
, "q");
3480 output_operand_lossage ("invalid %%U value");
3484 /* Write the constant value divided by 8. */
3485 if (GET_CODE (x
) != CONST_INT
3486 && (unsigned HOST_WIDE_INT
) INTVAL (x
) >= 64
3487 && (INTVAL (x
) & 7) != 8)
3488 output_operand_lossage ("invalid %%s value");
3490 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
) / 8);
3494 /* Same, except compute (64 - c) / 8 */
3496 if (GET_CODE (x
) != CONST_INT
3497 && (unsigned HOST_WIDE_INT
) INTVAL (x
) >= 64
3498 && (INTVAL (x
) & 7) != 8)
3499 output_operand_lossage ("invalid %%s value");
3501 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, (64 - INTVAL (x
)) / 8);
3504 case 'C': case 'D': case 'c': case 'd':
3505 /* Write out comparison name. */
3507 enum rtx_code c
= GET_CODE (x
);
3509 if (GET_RTX_CLASS (c
) != '<')
3510 output_operand_lossage ("invalid %%C value");
3513 c
= reverse_condition (c
);
3514 else if (code
== 'c')
3515 c
= swap_condition (c
);
3516 else if (code
== 'd')
3517 c
= swap_condition (reverse_condition (c
));
3520 fprintf (file
, "ule");
3522 fprintf (file
, "ult");
3523 else if (c
== UNORDERED
)
3524 fprintf (file
, "un");
3526 fprintf (file
, "%s", GET_RTX_NAME (c
));
3531 /* Write the divide or modulus operator. */
3532 switch (GET_CODE (x
))
3535 fprintf (file
, "div%s", GET_MODE (x
) == SImode
? "l" : "q");
3538 fprintf (file
, "div%su", GET_MODE (x
) == SImode
? "l" : "q");
3541 fprintf (file
, "rem%s", GET_MODE (x
) == SImode
? "l" : "q");
3544 fprintf (file
, "rem%su", GET_MODE (x
) == SImode
? "l" : "q");
3547 output_operand_lossage ("invalid %%E value");
3553 /* Write "_u" for unaligned access. */
3554 if (GET_CODE (x
) == MEM
&& GET_CODE (XEXP (x
, 0)) == AND
)
3555 fprintf (file
, "_u");
3559 if (GET_CODE (x
) == REG
)
3560 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
3561 else if (GET_CODE (x
) == MEM
)
3562 output_address (XEXP (x
, 0));
3564 output_addr_const (file
, x
);
3568 output_operand_lossage ("invalid %%xn code");
3573 print_operand_address (file
, addr
)
3578 HOST_WIDE_INT offset
= 0;
3580 if (GET_CODE (addr
) == AND
)
3581 addr
= XEXP (addr
, 0);
3583 if (GET_CODE (addr
) == PLUS
3584 && GET_CODE (XEXP (addr
, 1)) == CONST_INT
)
3586 offset
= INTVAL (XEXP (addr
, 1));
3587 addr
= XEXP (addr
, 0);
3589 if (GET_CODE (addr
) == REG
)
3590 basereg
= REGNO (addr
);
3591 else if (GET_CODE (addr
) == SUBREG
3592 && GET_CODE (SUBREG_REG (addr
)) == REG
)
3593 basereg
= REGNO (SUBREG_REG (addr
)) + SUBREG_WORD (addr
);
3594 else if (GET_CODE (addr
) == CONST_INT
)
3595 offset
= INTVAL (addr
);
3599 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, offset
);
3600 fprintf (file
, "($%d)", basereg
);
3603 /* Emit RTL insns to initialize the variable parts of a trampoline at
3604 TRAMP. FNADDR is an RTX for the address of the function's pure
3605 code. CXT is an RTX for the static chain value for the function.
3607 The three offset parameters are for the individual template's
3608 layout. A JMPOFS < 0 indicates that the trampoline does not
3609 contain instructions at all.
3611 We assume here that a function will be called many more times than
3612 its address is taken (e.g., it might be passed to qsort), so we
3613 take the trouble to initialize the "hint" field in the JMP insn.
3614 Note that the hint field is PC (new) + 4 * bits 13:0. */
3617 alpha_initialize_trampoline (tramp
, fnaddr
, cxt
, fnofs
, cxtofs
, jmpofs
)
3618 rtx tramp
, fnaddr
, cxt
;
3619 int fnofs
, cxtofs
, jmpofs
;
3621 rtx temp
, temp1
, addr
;
3622 /* VMS really uses DImode pointers in memory at this point. */
3623 enum machine_mode mode
= TARGET_OPEN_VMS
? Pmode
: ptr_mode
;
3625 #ifdef POINTERS_EXTEND_UNSIGNED
3626 fnaddr
= convert_memory_address (mode
, fnaddr
);
3627 cxt
= convert_memory_address (mode
, cxt
);
3630 /* Store function address and CXT. */
3631 addr
= memory_address (mode
, plus_constant (tramp
, fnofs
));
3632 emit_move_insn (gen_rtx_MEM (mode
, addr
), fnaddr
);
3633 addr
= memory_address (mode
, plus_constant (tramp
, cxtofs
));
3634 emit_move_insn (gen_rtx_MEM (mode
, addr
), cxt
);
3636 /* This has been disabled since the hint only has a 32k range, and in
3637 no existing OS is the stack within 32k of the text segment. */
3638 if (0 && jmpofs
>= 0)
3640 /* Compute hint value. */
3641 temp
= force_operand (plus_constant (tramp
, jmpofs
+4), NULL_RTX
);
3642 temp
= expand_binop (DImode
, sub_optab
, fnaddr
, temp
, temp
, 1,
3644 temp
= expand_shift (RSHIFT_EXPR
, Pmode
, temp
,
3645 build_int_2 (2, 0), NULL_RTX
, 1);
3646 temp
= expand_and (gen_lowpart (SImode
, temp
), GEN_INT (0x3fff), 0);
3648 /* Merge in the hint. */
3649 addr
= memory_address (SImode
, plus_constant (tramp
, jmpofs
));
3650 temp1
= force_reg (SImode
, gen_rtx_MEM (SImode
, addr
));
3651 temp1
= expand_and (temp1
, GEN_INT (0xffffc000), NULL_RTX
);
3652 temp1
= expand_binop (SImode
, ior_optab
, temp1
, temp
, temp1
, 1,
3654 emit_move_insn (gen_rtx_MEM (SImode
, addr
), temp1
);
3657 #ifdef TRANSFER_FROM_TRAMPOLINE
3658 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "__enable_execute_stack"),
3659 0, VOIDmode
, 1, addr
, Pmode
);
3663 emit_insn (gen_imb ());
3666 /* Determine where to put an argument to a function.
3667 Value is zero to push the argument on the stack,
3668 or a hard register in which to store the argument.
3670 MODE is the argument's machine mode.
3671 TYPE is the data type of the argument (as a tree).
3672 This is null for libcalls where that information may
3674 CUM is a variable of type CUMULATIVE_ARGS which gives info about
3675 the preceding args and about the function being called.
3676 NAMED is nonzero if this argument is a named parameter
3677 (otherwise it is an extra parameter matching an ellipsis).
3679 On Alpha the first 6 words of args are normally in registers
3680 and the rest are pushed. */
3683 function_arg(cum
, mode
, type
, named
)
3684 CUMULATIVE_ARGS cum
;
3685 enum machine_mode mode
;
3687 int named ATTRIBUTE_UNUSED
;
3691 if (cum
>= 6 || MUST_PASS_IN_STACK (mode
, type
))
3694 if (FUNCTION_ARG_PASS_BY_REFERENCE (cum
, mode
, type
, named
))
3696 else if (TARGET_FPREGS
3697 && (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
3698 || GET_MODE_CLASS (mode
) == MODE_FLOAT
))
3703 return gen_rtx_REG (mode
, cum
+ basereg
);
3707 alpha_build_va_list ()
3709 tree base
, ofs
, record
, type_decl
;
3711 if (TARGET_OPEN_VMS
)
3712 return ptr_type_node
;
3714 record
= make_lang_type (RECORD_TYPE
);
3715 type_decl
= build_decl (TYPE_DECL
, get_identifier ("__va_list_tag"), record
);
3716 TREE_CHAIN (record
) = type_decl
;
3717 TYPE_NAME (record
) = type_decl
;
3719 /* C++? SET_IS_AGGR_TYPE (record, 1); */
3721 ofs
= build_decl (FIELD_DECL
, get_identifier ("__offset"),
3723 DECL_FIELD_CONTEXT (ofs
) = record
;
3725 base
= build_decl (FIELD_DECL
, get_identifier ("__base"),
3727 DECL_FIELD_CONTEXT (base
) = record
;
3728 TREE_CHAIN (base
) = ofs
;
3730 TYPE_FIELDS (record
) = base
;
3731 layout_type (record
);
3737 alpha_va_start (stdarg_p
, valist
, nextarg
)
3740 rtx nextarg ATTRIBUTE_UNUSED
;
3742 HOST_WIDE_INT offset
;
3743 tree t
, offset_field
, base_field
;
3745 if (TARGET_OPEN_VMS
)
3746 std_expand_builtin_va_start (stdarg_p
, valist
, nextarg
);
3748 /* For Unix, SETUP_INCOMING_VARARGS moves the starting address base
3749 up by 48, storing fp arg registers in the first 48 bytes, and the
3750 integer arg registers in the next 48 bytes. This is only done,
3751 however, if any integer registers need to be stored.
3753 If no integer registers need be stored, then we must subtract 48
3754 in order to account for the integer arg registers which are counted
3755 in argsize above, but which are not actually stored on the stack. */
3757 if (NUM_ARGS
<= 5 + stdarg_p
)
3758 offset
= 6 * UNITS_PER_WORD
;
3760 offset
= -6 * UNITS_PER_WORD
;
3762 base_field
= TYPE_FIELDS (TREE_TYPE (valist
));
3763 offset_field
= TREE_CHAIN (base_field
);
3765 base_field
= build (COMPONENT_REF
, TREE_TYPE (base_field
),
3766 valist
, base_field
);
3767 offset_field
= build (COMPONENT_REF
, TREE_TYPE (offset_field
),
3768 valist
, offset_field
);
3770 t
= make_tree (ptr_type_node
, virtual_incoming_args_rtx
);
3771 t
= build (PLUS_EXPR
, ptr_type_node
, t
, build_int_2 (offset
, 0));
3772 t
= build (MODIFY_EXPR
, TREE_TYPE (base_field
), base_field
, t
);
3773 TREE_SIDE_EFFECTS (t
) = 1;
3774 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
3776 t
= build_int_2 (NUM_ARGS
*UNITS_PER_WORD
, 0);
3777 t
= build (MODIFY_EXPR
, TREE_TYPE (offset_field
), offset_field
, t
);
3778 TREE_SIDE_EFFECTS (t
) = 1;
3779 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
3783 alpha_va_arg (valist
, type
)
3786 HOST_WIDE_INT tsize
;
3789 tree offset_field
, base_field
, addr_tree
, addend
;
3790 tree wide_type
, wide_ofs
;
3792 if (TARGET_OPEN_VMS
)
3793 return std_expand_builtin_va_arg (valist
, type
);
3795 tsize
= ((TREE_INT_CST_LOW (TYPE_SIZE (type
)) / BITS_PER_UNIT
+ 7) / 8) * 8;
3797 base_field
= TYPE_FIELDS (TREE_TYPE (valist
));
3798 offset_field
= TREE_CHAIN (base_field
);
3800 base_field
= build (COMPONENT_REF
, TREE_TYPE (base_field
),
3801 valist
, base_field
);
3802 offset_field
= build (COMPONENT_REF
, TREE_TYPE (offset_field
),
3803 valist
, offset_field
);
3805 wide_type
= make_signed_type (64);
3806 wide_ofs
= save_expr (build1 (CONVERT_EXPR
, wide_type
, offset_field
));
3809 if (FLOAT_TYPE_P (type
))
3811 tree fpaddend
, cond
;
3813 fpaddend
= fold (build (PLUS_EXPR
, TREE_TYPE (addend
),
3814 addend
, build_int_2 (-6*8, 0)));
3816 cond
= fold (build (LT_EXPR
, integer_type_node
,
3817 wide_ofs
, build_int_2 (6*8, 0)));
3819 addend
= fold (build (COND_EXPR
, TREE_TYPE (addend
), cond
,
3823 addr_tree
= build (PLUS_EXPR
, TREE_TYPE (base_field
),
3824 base_field
, addend
);
3826 addr
= expand_expr (addr_tree
, NULL_RTX
, Pmode
, EXPAND_NORMAL
);
3827 addr
= copy_to_reg (addr
);
3829 t
= build (MODIFY_EXPR
, TREE_TYPE (offset_field
), offset_field
,
3830 build (PLUS_EXPR
, TREE_TYPE (offset_field
),
3831 offset_field
, build_int_2 (tsize
, 0)));
3832 TREE_SIDE_EFFECTS (t
) = 1;
3833 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
3838 /* This page contains routines that are used to determine what the function
3839 prologue and epilogue code will do and write them out. */
3841 /* Compute the size of the save area in the stack. */
3843 /* These variables are used for communication between the following functions.
3844 They indicate various things about the current function being compiled
3845 that are used to tell what kind of prologue, epilogue and procedure
3846 descriptior to generate. */
3848 /* Nonzero if we need a stack procedure. */
3849 static int vms_is_stack_procedure
;
3851 /* Register number (either FP or SP) that is used to unwind the frame. */
3852 static int vms_unwind_regno
;
3854 /* Register number used to save FP. We need not have one for RA since
3855 we don't modify it for register procedures. This is only defined
3856 for register frame procedures. */
3857 static int vms_save_fp_regno
;
3859 /* Register number used to reference objects off our PV. */
3860 static int vms_base_regno
;
3862 /* Compute register masks for saved registers. */
3865 alpha_sa_mask (imaskP
, fmaskP
)
3866 unsigned long *imaskP
;
3867 unsigned long *fmaskP
;
3869 unsigned long imask
= 0;
3870 unsigned long fmask
= 0;
3873 #ifdef ASM_OUTPUT_MI_THUNK
3874 if (!current_function_is_thunk
)
3877 if (TARGET_OPEN_VMS
&& vms_is_stack_procedure
)
3878 imask
|= (1L << HARD_FRAME_POINTER_REGNUM
);
3880 /* One for every register we have to save. */
3881 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3882 if (! fixed_regs
[i
] && ! call_used_regs
[i
]
3883 && regs_ever_live
[i
] && i
!= REG_RA
)
3888 fmask
|= (1L << (i
- 32));
3891 if (imask
|| fmask
|| alpha_ra_ever_killed ())
3892 imask
|= (1L << REG_RA
);
3905 #ifdef ASM_OUTPUT_MI_THUNK
3906 if (current_function_is_thunk
)
3911 /* One for every register we have to save. */
3912 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3913 if (! fixed_regs
[i
] && ! call_used_regs
[i
]
3914 && regs_ever_live
[i
] && i
!= REG_RA
)
3918 if (TARGET_OPEN_VMS
)
3920 /* Start by assuming we can use a register procedure if we don't
3921 make any calls (REG_RA not used) or need to save any
3922 registers and a stack procedure if we do. */
3923 vms_is_stack_procedure
= sa_size
!= 0 || alpha_ra_ever_killed ();
3925 /* Decide whether to refer to objects off our PV via FP or PV.
3926 If we need FP for something else or if we receive a nonlocal
3927 goto (which expects PV to contain the value), we must use PV.
3928 Otherwise, start by assuming we can use FP. */
3929 vms_base_regno
= (frame_pointer_needed
3930 || current_function_has_nonlocal_label
3931 || vms_is_stack_procedure
3932 || current_function_outgoing_args_size
3933 ? REG_PV
: HARD_FRAME_POINTER_REGNUM
);
3935 /* If we want to copy PV into FP, we need to find some register
3936 in which to save FP. */
3938 vms_save_fp_regno
= -1;
3939 if (vms_base_regno
== HARD_FRAME_POINTER_REGNUM
)
3940 for (i
= 0; i
< 32; i
++)
3941 if (! fixed_regs
[i
] && call_used_regs
[i
] && ! regs_ever_live
[i
])
3942 vms_save_fp_regno
= i
;
3944 if (vms_save_fp_regno
== -1)
3945 vms_base_regno
= REG_PV
, vms_is_stack_procedure
= 1;
3947 /* Stack unwinding should be done via FP unless we use it for PV. */
3948 vms_unwind_regno
= (vms_base_regno
== REG_PV
3949 ? HARD_FRAME_POINTER_REGNUM
: STACK_POINTER_REGNUM
);
3951 /* If this is a stack procedure, allow space for saving FP and RA. */
3952 if (vms_is_stack_procedure
)
3957 /* If some registers were saved but not RA, RA must also be saved,
3958 so leave space for it. */
3959 if (sa_size
!= 0 || alpha_ra_ever_killed ())
3962 /* Our size must be even (multiple of 16 bytes). */
3971 alpha_pv_save_size ()
3974 return vms_is_stack_procedure
? 8 : 0;
3981 return vms_unwind_regno
== HARD_FRAME_POINTER_REGNUM
;
3985 vms_valid_decl_attribute_p (decl
, attributes
, identifier
, args
)
3986 tree decl ATTRIBUTE_UNUSED
;
3987 tree attributes ATTRIBUTE_UNUSED
;
3991 if (is_attribute_p ("overlaid", identifier
))
3992 return (args
== NULL_TREE
);
3997 alpha_does_function_need_gp ()
4001 /* We never need a GP for Windows/NT or VMS. */
4002 if (TARGET_WINDOWS_NT
|| TARGET_OPEN_VMS
)
4005 #ifdef TARGET_PROFILING_NEEDS_GP
4010 #ifdef ASM_OUTPUT_MI_THUNK
4011 if (current_function_is_thunk
)
4015 /* If we need a GP (we have a LDSYM insn or a CALL_INSN), load it first.
4016 Even if we are a static function, we still need to do this in case
4017 our address is taken and passed to something like qsort. */
4019 push_topmost_sequence ();
4020 insn
= get_insns ();
4021 pop_topmost_sequence ();
4023 for (; insn
; insn
= NEXT_INSN (insn
))
4024 if (GET_RTX_CLASS (GET_CODE (insn
)) == 'i'
4025 && GET_CODE (PATTERN (insn
)) != USE
4026 && GET_CODE (PATTERN (insn
)) != CLOBBER
)
4028 enum attr_type type
= get_attr_type (insn
);
4029 if (type
== TYPE_LDSYM
|| type
== TYPE_JSR
)
4036 /* Write a version stamp. Don't write anything if we are running as a
4037 cross-compiler. Otherwise, use the versions in /usr/include/stamp.h. */
4044 alpha_write_verstamp (file
)
4045 FILE *file ATTRIBUTE_UNUSED
;
4048 fprintf (file
, "\t.verstamp %d %d\n", MS_STAMP
, LS_STAMP
);
4052 /* Helper function to set RTX_FRAME_RELATED_P on instructions, including
4056 set_frame_related_p ()
4058 rtx seq
= gen_sequence ();
4061 if (GET_CODE (seq
) == SEQUENCE
)
4063 int i
= XVECLEN (seq
, 0);
4065 RTX_FRAME_RELATED_P (XVECEXP (seq
, 0, i
)) = 1;
4066 return emit_insn (seq
);
4070 seq
= emit_insn (seq
);
4071 RTX_FRAME_RELATED_P (seq
) = 1;
4076 #define FRP(exp) (start_sequence (), exp, set_frame_related_p ())
4078 /* Write function prologue. */
4080 /* On vms we have two kinds of functions:
4082 - stack frame (PROC_STACK)
4083 these are 'normal' functions with local vars and which are
4084 calling other functions
4085 - register frame (PROC_REGISTER)
4086 keeps all data in registers, needs no stack
4088 We must pass this to the assembler so it can generate the
4089 proper pdsc (procedure descriptor)
4090 This is done with the '.pdesc' command.
4092 On not-vms, we don't really differentiate between the two, as we can
4093 simply allocate stack without saving registers. */
4096 alpha_expand_prologue ()
4098 /* Registers to save. */
4099 unsigned long imask
= 0;
4100 unsigned long fmask
= 0;
4101 /* Stack space needed for pushing registers clobbered by us. */
4102 HOST_WIDE_INT sa_size
;
4103 /* Complete stack size needed. */
4104 HOST_WIDE_INT frame_size
;
4105 /* Offset from base reg to register save area. */
4106 HOST_WIDE_INT reg_offset
;
4110 sa_size
= alpha_sa_size ();
4112 frame_size
= get_frame_size ();
4113 if (TARGET_OPEN_VMS
)
4114 frame_size
= ALPHA_ROUND (sa_size
4115 + (vms_is_stack_procedure
? 8 : 0)
4117 + current_function_pretend_args_size
);
4119 frame_size
= (ALPHA_ROUND (current_function_outgoing_args_size
)
4121 + ALPHA_ROUND (frame_size
4122 + current_function_pretend_args_size
));
4124 if (TARGET_OPEN_VMS
)
4127 reg_offset
= ALPHA_ROUND (current_function_outgoing_args_size
);
4129 alpha_sa_mask (&imask
, &fmask
);
4131 /* Adjust the stack by the frame size. If the frame size is > 4096
4132 bytes, we need to be sure we probe somewhere in the first and last
4133 4096 bytes (we can probably get away without the latter test) and
4134 every 8192 bytes in between. If the frame size is > 32768, we
4135 do this in a loop. Otherwise, we generate the explicit probe
4138 Note that we are only allowed to adjust sp once in the prologue. */
4140 if (frame_size
<= 32768)
4142 if (frame_size
> 4096)
4147 emit_insn (gen_probe_stack (GEN_INT (-probed
)));
4148 while ((probed
+= 8192) < frame_size
);
4150 /* We only have to do this probe if we aren't saving registers. */
4151 if (sa_size
== 0 && probed
+ 4096 < frame_size
)
4152 emit_insn (gen_probe_stack (GEN_INT (-frame_size
)));
4155 if (frame_size
!= 0)
4157 FRP (emit_insn (gen_adddi3 (stack_pointer_rtx
, stack_pointer_rtx
,
4158 GEN_INT (-frame_size
))));
4163 /* Here we generate code to set R22 to SP + 4096 and set R23 to the
4164 number of 8192 byte blocks to probe. We then probe each block
4165 in the loop and then set SP to the proper location. If the
4166 amount remaining is > 4096, we have to do one more probe if we
4167 are not saving any registers. */
4169 HOST_WIDE_INT blocks
= (frame_size
+ 4096) / 8192;
4170 HOST_WIDE_INT leftover
= frame_size
+ 4096 - blocks
* 8192;
4171 rtx ptr
= gen_rtx_REG (DImode
, 22);
4172 rtx count
= gen_rtx_REG (DImode
, 23);
4175 emit_move_insn (count
, GEN_INT (blocks
));
4176 emit_insn (gen_adddi3 (ptr
, stack_pointer_rtx
, GEN_INT (4096)));
4178 /* Because of the difficulty in emitting a new basic block this
4179 late in the compilation, generate the loop as a single insn. */
4180 emit_insn (gen_prologue_stack_probe_loop (count
, ptr
));
4182 if (leftover
> 4096 && sa_size
== 0)
4184 rtx last
= gen_rtx_MEM (DImode
, plus_constant (ptr
, -leftover
));
4185 MEM_VOLATILE_P (last
) = 1;
4186 emit_move_insn (last
, const0_rtx
);
4189 if (TARGET_WINDOWS_NT
)
4191 /* For NT stack unwind (done by 'reverse execution'), it's
4192 not OK to take the result of a loop, even though the value
4193 is already in ptr, so we reload it via a single operation
4194 and subtract it to sp.
4196 Yes, that's correct -- we have to reload the whole constant
4197 into a temporary via ldah+lda then subtract from sp. To
4198 ensure we get ldah+lda, we use a special pattern. */
4200 HOST_WIDE_INT lo
, hi
;
4201 lo
= ((frame_size
& 0xffff) ^ 0x8000) - 0x8000;
4202 hi
= frame_size
- lo
;
4204 emit_move_insn (ptr
, GEN_INT (hi
));
4205 emit_insn (gen_nt_lda (ptr
, GEN_INT (lo
)));
4206 seq
= emit_insn (gen_subdi3 (stack_pointer_rtx
, stack_pointer_rtx
,
4211 seq
= emit_insn (gen_adddi3 (stack_pointer_rtx
, ptr
,
4212 GEN_INT (-leftover
)));
4215 /* This alternative is special, because the DWARF code cannot
4216 possibly intuit through the loop above. So we invent this
4217 note it looks at instead. */
4218 RTX_FRAME_RELATED_P (seq
) = 1;
4220 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR
,
4221 gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
4222 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
4223 GEN_INT (-frame_size
))),
4227 /* Cope with very large offsets to the register save area. */
4228 sa_reg
= stack_pointer_rtx
;
4229 if (reg_offset
+ sa_size
> 0x8000)
4231 int low
= ((reg_offset
& 0xffff) ^ 0x8000) - 0x8000;
4234 if (low
+ sa_size
<= 0x8000)
4235 bias
= reg_offset
- low
, reg_offset
= low
;
4237 bias
= reg_offset
, reg_offset
= 0;
4239 sa_reg
= gen_rtx_REG (DImode
, 24);
4240 FRP (emit_insn (gen_adddi3 (sa_reg
, stack_pointer_rtx
, GEN_INT (bias
))));
4243 /* Save regs in stack order. Beginning with VMS PV. */
4244 if (TARGET_OPEN_VMS
&& vms_is_stack_procedure
)
4246 mem
= gen_rtx_MEM (DImode
, stack_pointer_rtx
);
4247 MEM_ALIAS_SET (mem
) = alpha_sr_alias_set
;
4248 FRP (emit_move_insn (mem
, gen_rtx_REG (DImode
, REG_PV
)));
4251 /* Save register RA next. */
4252 if (imask
& (1L << REG_RA
))
4254 mem
= gen_rtx_MEM (DImode
, plus_constant (sa_reg
, reg_offset
));
4255 MEM_ALIAS_SET (mem
) = alpha_sr_alias_set
;
4256 FRP (emit_move_insn (mem
, gen_rtx_REG (DImode
, REG_RA
)));
4257 imask
&= ~(1L << REG_RA
);
4261 /* Now save any other registers required to be saved. */
4262 for (i
= 0; i
< 32; i
++)
4263 if (imask
& (1L << i
))
4265 mem
= gen_rtx_MEM (DImode
, plus_constant (sa_reg
, reg_offset
));
4266 MEM_ALIAS_SET (mem
) = alpha_sr_alias_set
;
4267 FRP (emit_move_insn (mem
, gen_rtx_REG (DImode
, i
)));
4271 for (i
= 0; i
< 32; i
++)
4272 if (fmask
& (1L << i
))
4274 mem
= gen_rtx_MEM (DFmode
, plus_constant (sa_reg
, reg_offset
));
4275 MEM_ALIAS_SET (mem
) = alpha_sr_alias_set
;
4276 FRP (emit_move_insn (mem
, gen_rtx_REG (DFmode
, i
+32)));
4280 if (TARGET_OPEN_VMS
)
4282 if (!vms_is_stack_procedure
)
4284 /* Register frame procedures fave the fp. */
4285 FRP (emit_move_insn (gen_rtx_REG (DImode
, vms_save_fp_regno
),
4286 hard_frame_pointer_rtx
));
4289 if (vms_base_regno
!= REG_PV
)
4290 FRP (emit_move_insn (gen_rtx_REG (DImode
, vms_base_regno
),
4291 gen_rtx_REG (DImode
, REG_PV
)));
4293 if (vms_unwind_regno
== HARD_FRAME_POINTER_REGNUM
)
4295 FRP (emit_move_insn (hard_frame_pointer_rtx
, stack_pointer_rtx
));
4298 /* If we have to allocate space for outgoing args, do it now. */
4299 if (current_function_outgoing_args_size
!= 0)
4301 FRP (emit_move_insn (stack_pointer_rtx
,
4302 plus_constant (hard_frame_pointer_rtx
,
4303 - ALPHA_ROUND (current_function_outgoing_args_size
))));
4308 /* If we need a frame pointer, set it from the stack pointer. */
4309 if (frame_pointer_needed
)
4311 if (TARGET_CAN_FAULT_IN_PROLOGUE
)
4312 FRP (emit_move_insn (hard_frame_pointer_rtx
, stack_pointer_rtx
));
4315 /* This must always be the last instruction in the
4316 prologue, thus we emit a special move + clobber. */
4317 FRP (emit_insn (gen_init_fp (hard_frame_pointer_rtx
,
4318 stack_pointer_rtx
, sa_reg
)));
4323 /* The ABIs for VMS and OSF/1 say that while we can schedule insns into
4324 the prologue, for exception handling reasons, we cannot do this for
4325 any insn that might fault. We could prevent this for mems with a
4326 (clobber:BLK (scratch)), but this doesn't work for fp insns. So we
4327 have to prevent all such scheduling with a blockage.
4329 Linux, on the other hand, never bothered to implement OSF/1's
4330 exception handling, and so doesn't care about such things. Anyone
4331 planning to use dwarf2 frame-unwind info can also omit the blockage. */
4333 if (! TARGET_CAN_FAULT_IN_PROLOGUE
)
4334 emit_insn (gen_blockage ());
4337 /* Output the textual info surrounding the prologue. */
4340 alpha_start_function (file
, fnname
, decl
)
4343 tree decl ATTRIBUTE_UNUSED
;
4345 unsigned long imask
= 0;
4346 unsigned long fmask
= 0;
4347 /* Stack space needed for pushing registers clobbered by us. */
4348 HOST_WIDE_INT sa_size
;
4349 /* Complete stack size needed. */
4350 HOST_WIDE_INT frame_size
;
4351 /* Offset from base reg to register save area. */
4352 HOST_WIDE_INT reg_offset
;
4353 char *entry_label
= (char *) alloca (strlen (fnname
) + 6);
4356 sa_size
= alpha_sa_size ();
4358 frame_size
= get_frame_size ();
4359 if (TARGET_OPEN_VMS
)
4360 frame_size
= ALPHA_ROUND (sa_size
4361 + (vms_is_stack_procedure
? 8 : 0)
4363 + current_function_pretend_args_size
);
4365 frame_size
= (ALPHA_ROUND (current_function_outgoing_args_size
)
4367 + ALPHA_ROUND (frame_size
4368 + current_function_pretend_args_size
));
4370 if (TARGET_OPEN_VMS
)
4373 reg_offset
= ALPHA_ROUND (current_function_outgoing_args_size
);
4375 alpha_sa_mask (&imask
, &fmask
);
4377 /* Ecoff can handle multiple .file directives, so put out file and lineno.
4378 We have to do that before the .ent directive as we cannot switch
4379 files within procedures with native ecoff because line numbers are
4380 linked to procedure descriptors.
4381 Outputting the lineno helps debugging of one line functions as they
4382 would otherwise get no line number at all. Please note that we would
4383 like to put out last_linenum from final.c, but it is not accessible. */
4385 if (write_symbols
== SDB_DEBUG
)
4387 ASM_OUTPUT_SOURCE_FILENAME (file
,
4388 DECL_SOURCE_FILE (current_function_decl
));
4389 if (debug_info_level
!= DINFO_LEVEL_TERSE
)
4390 ASM_OUTPUT_SOURCE_LINE (file
,
4391 DECL_SOURCE_LINE (current_function_decl
));
4394 /* Issue function start and label. */
4395 if (TARGET_OPEN_VMS
|| !flag_inhibit_size_directive
)
4397 fputs ("\t.ent ", file
);
4398 assemble_name (file
, fnname
);
4402 strcpy (entry_label
, fnname
);
4403 if (TARGET_OPEN_VMS
)
4404 strcat (entry_label
, "..en");
4405 ASM_OUTPUT_LABEL (file
, entry_label
);
4406 inside_function
= TRUE
;
4408 if (TARGET_OPEN_VMS
)
4409 fprintf (file
, "\t.base $%d\n", vms_base_regno
);
4411 if (!TARGET_OPEN_VMS
&& TARGET_IEEE_CONFORMANT
4412 && !flag_inhibit_size_directive
)
4414 /* Set flags in procedure descriptor to request IEEE-conformant
4415 math-library routines. The value we set it to is PDSC_EXC_IEEE
4416 (/usr/include/pdsc.h). */
4417 fputs ("\t.eflag 48\n", file
);
4420 /* Set up offsets to alpha virtual arg/local debugging pointer. */
4421 alpha_auto_offset
= -frame_size
+ current_function_pretend_args_size
;
4422 alpha_arg_offset
= -frame_size
+ 48;
4424 /* Describe our frame. If the frame size is larger than an integer,
4425 print it as zero to avoid an assembler error. We won't be
4426 properly describing such a frame, but that's the best we can do. */
4427 if (TARGET_OPEN_VMS
)
4429 fprintf (file
, "\t.frame $%d,", vms_unwind_regno
);
4430 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
,
4431 frame_size
>= (1l << 31) ? 0 : frame_size
);
4432 fputs (",$26,", file
);
4433 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, reg_offset
);
4436 else if (!flag_inhibit_size_directive
)
4438 fprintf (file
, "\t.frame $%d,",
4439 (frame_pointer_needed
4440 ? HARD_FRAME_POINTER_REGNUM
: STACK_POINTER_REGNUM
));
4441 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
,
4442 frame_size
>= (1l << 31) ? 0 : frame_size
);
4443 fprintf (file
, ",$26,%d\n", current_function_pretend_args_size
);
4446 /* Describe which registers were spilled. */
4447 if (TARGET_OPEN_VMS
)
4450 /* ??? Does VMS care if mask contains ra? The old code did'nt
4451 set it, so I don't here. */
4452 fprintf (file
, "\t.mask 0x%lx,0\n", imask
& ~(1L << REG_RA
));
4454 fprintf (file
, "\t.fmask 0x%lx,0\n", fmask
);
4455 if (!vms_is_stack_procedure
)
4456 fprintf (file
, "\t.fp_save $%d\n", vms_save_fp_regno
);
4458 else if (!flag_inhibit_size_directive
)
4462 fprintf (file
, "\t.mask 0x%lx,", imask
);
4463 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
,
4464 frame_size
>= (1l << 31) ? 0 : reg_offset
- frame_size
);
4467 for (i
= 0; i
< 32; ++i
)
4468 if (imask
& (1L << i
))
4474 fprintf (file
, "\t.fmask 0x%lx,", fmask
);
4475 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
,
4476 frame_size
>= (1l << 31) ? 0 : reg_offset
- frame_size
);
4481 /* Emit GP related things. It is rather unfortunate about the alignment
4482 issues surrounding a CODE_LABEL that forces us to do the label in
4484 if (!TARGET_OPEN_VMS
&& !TARGET_WINDOWS_NT
)
4486 alpha_function_needs_gp
= alpha_does_function_need_gp ();
4487 if (alpha_function_needs_gp
)
4488 fputs ("\tldgp $29,0($27)\n", file
);
4491 assemble_name (file
, fnname
);
4492 fputs ("..ng:\n", file
);
4496 /* Ifdef'ed cause readonly_section and link_section are only
4498 readonly_section ();
4499 fprintf (file
, "\t.align 3\n");
4500 assemble_name (file
, fnname
); fputs ("..na:\n", file
);
4501 fputs ("\t.ascii \"", file
);
4502 assemble_name (file
, fnname
);
4503 fputs ("\\0\"\n", file
);
4506 fprintf (file
, "\t.align 3\n");
4507 fputs ("\t.name ", file
);
4508 assemble_name (file
, fnname
);
4509 fputs ("..na\n", file
);
4510 ASM_OUTPUT_LABEL (file
, fnname
);
4511 fprintf (file
, "\t.pdesc ");
4512 assemble_name (file
, fnname
);
4513 fprintf (file
, "..en,%s\n", vms_is_stack_procedure
? "stack" : "reg");
4514 alpha_need_linkage (fnname
, 1);
4519 /* Emit the .prologue note at the scheduled end of the prologue. */
4522 output_end_prologue (file
)
4525 if (TARGET_OPEN_VMS
)
4526 fputs ("\t.prologue\n", file
);
4527 else if (TARGET_WINDOWS_NT
)
4528 fputs ("\t.prologue 0\n", file
);
4529 else if (!flag_inhibit_size_directive
)
4530 fprintf (file
, "\t.prologue %d\n", alpha_function_needs_gp
);
4533 /* Write function epilogue. */
4535 /* ??? At some point we will want to support full unwind, and so will
4536 need to mark the epilogue as well. At the moment, we just confuse
4539 #define FRP(exp) exp
4542 alpha_expand_epilogue ()
4544 /* Registers to save. */
4545 unsigned long imask
= 0;
4546 unsigned long fmask
= 0;
4547 /* Stack space needed for pushing registers clobbered by us. */
4548 HOST_WIDE_INT sa_size
;
4549 /* Complete stack size needed. */
4550 HOST_WIDE_INT frame_size
;
4551 /* Offset from base reg to register save area. */
4552 HOST_WIDE_INT reg_offset
;
4553 int fp_is_frame_pointer
, fp_offset
;
4554 rtx sa_reg
, sa_reg_exp
= NULL
;
4555 rtx sp_adj1
, sp_adj2
, mem
;
4559 sa_size
= alpha_sa_size ();
4561 frame_size
= get_frame_size ();
4562 if (TARGET_OPEN_VMS
)
4563 frame_size
= ALPHA_ROUND (sa_size
4564 + (vms_is_stack_procedure
? 8 : 0)
4566 + current_function_pretend_args_size
);
4568 frame_size
= (ALPHA_ROUND (current_function_outgoing_args_size
)
4570 + ALPHA_ROUND (frame_size
4571 + current_function_pretend_args_size
));
4573 if (TARGET_OPEN_VMS
)
4576 reg_offset
= ALPHA_ROUND (current_function_outgoing_args_size
);
4578 alpha_sa_mask (&imask
, &fmask
);
4580 fp_is_frame_pointer
= ((TARGET_OPEN_VMS
&& vms_is_stack_procedure
)
4581 || (!TARGET_OPEN_VMS
&& frame_pointer_needed
));
4583 sa_reg
= stack_pointer_rtx
;
4585 eh_ofs
= cfun
->machine
->eh_epilogue_sp_ofs
;
4588 /* If we have a frame pointer, restore SP from it. */
4589 if ((TARGET_OPEN_VMS
4590 && vms_unwind_regno
== HARD_FRAME_POINTER_REGNUM
)
4591 || (!TARGET_OPEN_VMS
&& frame_pointer_needed
))
4593 FRP (emit_move_insn (stack_pointer_rtx
, hard_frame_pointer_rtx
));
4596 /* Cope with very large offsets to the register save area. */
4597 if (reg_offset
+ sa_size
> 0x8000)
4599 int low
= ((reg_offset
& 0xffff) ^ 0x8000) - 0x8000;
4602 if (low
+ sa_size
<= 0x8000)
4603 bias
= reg_offset
- low
, reg_offset
= low
;
4605 bias
= reg_offset
, reg_offset
= 0;
4607 sa_reg
= gen_rtx_REG (DImode
, 22);
4608 sa_reg_exp
= plus_constant (stack_pointer_rtx
, bias
);
4610 FRP (emit_move_insn (sa_reg
, sa_reg_exp
));
4613 /* Restore registers in order, excepting a true frame pointer. */
4617 mem
= gen_rtx_MEM (DImode
, plus_constant(sa_reg
, reg_offset
));
4618 MEM_ALIAS_SET (mem
) = alpha_sr_alias_set
;
4619 FRP (emit_move_insn (gen_rtx_REG (DImode
, REG_RA
), mem
));
4622 imask
&= ~(1L << REG_RA
);
4624 for (i
= 0; i
< 32; ++i
)
4625 if (imask
& (1L << i
))
4627 if (i
== HARD_FRAME_POINTER_REGNUM
&& fp_is_frame_pointer
)
4628 fp_offset
= reg_offset
;
4631 mem
= gen_rtx_MEM (DImode
, plus_constant(sa_reg
, reg_offset
));
4632 MEM_ALIAS_SET (mem
) = alpha_sr_alias_set
;
4633 FRP (emit_move_insn (gen_rtx_REG (DImode
, i
), mem
));
4638 for (i
= 0; i
< 32; ++i
)
4639 if (fmask
& (1L << i
))
4641 mem
= gen_rtx_MEM (DFmode
, plus_constant(sa_reg
, reg_offset
));
4642 MEM_ALIAS_SET (mem
) = alpha_sr_alias_set
;
4643 FRP (emit_move_insn (gen_rtx_REG (DFmode
, i
+32), mem
));
4648 if (frame_size
|| eh_ofs
)
4650 sp_adj1
= stack_pointer_rtx
;
4654 sp_adj1
= gen_rtx_REG (DImode
, 23);
4655 emit_move_insn (sp_adj1
,
4656 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, eh_ofs
));
4659 /* If the stack size is large, begin computation into a temporary
4660 register so as not to interfere with a potential fp restore,
4661 which must be consecutive with an SP restore. */
4662 if (frame_size
< 32768)
4663 sp_adj2
= GEN_INT (frame_size
);
4664 else if (frame_size
< 0x40007fffL
)
4666 int low
= ((frame_size
& 0xffff) ^ 0x8000) - 0x8000;
4668 sp_adj2
= plus_constant (sp_adj1
, frame_size
- low
);
4669 if (sa_reg_exp
&& rtx_equal_p (sa_reg_exp
, sp_adj2
))
4673 sp_adj1
= gen_rtx_REG (DImode
, 23);
4674 FRP (emit_move_insn (sp_adj1
, sp_adj2
));
4676 sp_adj2
= GEN_INT (low
);
4680 rtx tmp
= gen_rtx_REG (DImode
, 23);
4681 FRP (sp_adj2
= alpha_emit_set_const (tmp
, DImode
, frame_size
, 3));
4684 /* We can't drop new things to memory this late, afaik,
4685 so build it up by pieces. */
4686 FRP (sp_adj2
= alpha_emit_set_long_const (tmp
, frame_size
,
4687 -(frame_size
< 0)));
4693 /* From now on, things must be in order. So emit blockages. */
4695 /* Restore the frame pointer. */
4696 if (fp_is_frame_pointer
)
4698 emit_insn (gen_blockage ());
4699 mem
= gen_rtx_MEM (DImode
, plus_constant(sa_reg
, fp_offset
));
4700 MEM_ALIAS_SET (mem
) = alpha_sr_alias_set
;
4701 FRP (emit_move_insn (hard_frame_pointer_rtx
, mem
));
4703 else if (TARGET_OPEN_VMS
)
4705 emit_insn (gen_blockage ());
4706 FRP (emit_move_insn (hard_frame_pointer_rtx
,
4707 gen_rtx_REG (DImode
, vms_save_fp_regno
)));
4710 /* Restore the stack pointer. */
4711 emit_insn (gen_blockage ());
4712 FRP (emit_move_insn (stack_pointer_rtx
,
4713 gen_rtx_PLUS (DImode
, sp_adj1
, sp_adj2
)));
4717 if (TARGET_OPEN_VMS
&& !vms_is_stack_procedure
)
4719 emit_insn (gen_blockage ());
4720 FRP (emit_move_insn (hard_frame_pointer_rtx
,
4721 gen_rtx_REG (DImode
, vms_save_fp_regno
)));
4726 /* Output the rest of the textual info surrounding the epilogue. */
4729 alpha_end_function (file
, fnname
, decl
)
4732 tree decl ATTRIBUTE_UNUSED
;
4734 /* End the function. */
4735 if (!flag_inhibit_size_directive
)
4737 fputs ("\t.end ", file
);
4738 assemble_name (file
, fnname
);
4741 inside_function
= FALSE
;
4743 /* Show that we know this function if it is called again.
4745 Don't do this for global functions in object files destined for a
4746 shared library because the function may be overridden by the application
4747 or other libraries. Similarly, don't do this for weak functions. */
4749 if (!DECL_WEAK (current_function_decl
)
4750 && (!flag_pic
|| !TREE_PUBLIC (current_function_decl
)))
4751 SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl
), 0)) = 1;
4754 /* Debugging support. */
4758 /* Count the number of sdb related labels are generated (to find block
4759 start and end boundaries). */
4761 int sdb_label_count
= 0;
4763 /* Next label # for each statement. */
4765 static int sym_lineno
= 0;
4767 /* Count the number of .file directives, so that .loc is up to date. */
4769 static int num_source_filenames
= 0;
4771 /* Name of the file containing the current function. */
4773 static const char *current_function_file
= "";
4775 /* Offsets to alpha virtual arg/local debugging pointers. */
4777 long alpha_arg_offset
;
4778 long alpha_auto_offset
;
4780 /* Emit a new filename to a stream. */
4783 alpha_output_filename (stream
, name
)
4787 static int first_time
= TRUE
;
4788 char ltext_label_name
[100];
4793 ++num_source_filenames
;
4794 current_function_file
= name
;
4795 fprintf (stream
, "\t.file\t%d ", num_source_filenames
);
4796 output_quoted_string (stream
, name
);
4797 fprintf (stream
, "\n");
4798 if (!TARGET_GAS
&& write_symbols
== DBX_DEBUG
)
4799 fprintf (stream
, "\t#@stabs\n");
4802 else if (write_symbols
== DBX_DEBUG
)
4804 ASM_GENERATE_INTERNAL_LABEL (ltext_label_name
, "Ltext", 0);
4805 fprintf (stream
, "%s ", ASM_STABS_OP
);
4806 output_quoted_string (stream
, name
);
4807 fprintf (stream
, ",%d,0,0,%s\n", N_SOL
, <ext_label_name
[1]);
4810 else if (name
!= current_function_file
4811 && strcmp (name
, current_function_file
) != 0)
4813 if (inside_function
&& ! TARGET_GAS
)
4814 fprintf (stream
, "\t#.file\t%d ", num_source_filenames
);
4817 ++num_source_filenames
;
4818 current_function_file
= name
;
4819 fprintf (stream
, "\t.file\t%d ", num_source_filenames
);
4822 output_quoted_string (stream
, name
);
4823 fprintf (stream
, "\n");
4827 /* Emit a linenumber to a stream. */
4830 alpha_output_lineno (stream
, line
)
4834 if (write_symbols
== DBX_DEBUG
)
4836 /* mips-tfile doesn't understand .stabd directives. */
4838 fprintf (stream
, "$LM%d:\n\t%s %d,0,%d,$LM%d\n",
4839 sym_lineno
, ASM_STABN_OP
, N_SLINE
, line
, sym_lineno
);
4842 fprintf (stream
, "\n\t.loc\t%d %d\n", num_source_filenames
, line
);
4845 /* Structure to show the current status of registers and memory. */
4847 struct shadow_summary
4850 unsigned long i
: 31; /* Mask of int regs */
4851 unsigned long fp
: 31; /* Mask of fp regs */
4852 unsigned long mem
: 1; /* mem == imem | fpmem */
4856 static void summarize_insn
PARAMS ((rtx
, struct shadow_summary
*, int));
4857 static void alpha_handle_trap_shadows
PARAMS ((rtx
));
4859 /* Summary the effects of expression X on the machine. Update SUM, a pointer
4860 to the summary structure. SET is nonzero if the insn is setting the
4861 object, otherwise zero. */
4864 summarize_insn (x
, sum
, set
)
4866 struct shadow_summary
*sum
;
4869 const char *format_ptr
;
4875 switch (GET_CODE (x
))
4877 /* ??? Note that this case would be incorrect if the Alpha had a
4878 ZERO_EXTRACT in SET_DEST. */
4880 summarize_insn (SET_SRC (x
), sum
, 0);
4881 summarize_insn (SET_DEST (x
), sum
, 1);
4885 summarize_insn (XEXP (x
, 0), sum
, 1);
4889 summarize_insn (XEXP (x
, 0), sum
, 0);
4893 for (i
= ASM_OPERANDS_INPUT_LENGTH (x
) - 1; i
>= 0; i
--)
4894 summarize_insn (ASM_OPERANDS_INPUT (x
, i
), sum
, 0);
4898 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
4899 summarize_insn (XVECEXP (x
, 0, i
), sum
, 0);
4903 summarize_insn (SUBREG_REG (x
), sum
, 0);
4908 int regno
= REGNO (x
);
4909 unsigned long mask
= 1UL << (regno
% 32);
4911 if (regno
== 31 || regno
== 63)
4917 sum
->defd
.i
|= mask
;
4919 sum
->defd
.fp
|= mask
;
4924 sum
->used
.i
|= mask
;
4926 sum
->used
.fp
|= mask
;
4937 /* Find the regs used in memory address computation: */
4938 summarize_insn (XEXP (x
, 0), sum
, 0);
4941 case CONST_INT
: case CONST_DOUBLE
:
4942 case SYMBOL_REF
: case LABEL_REF
: case CONST
:
4945 /* Handle common unary and binary ops for efficiency. */
4946 case COMPARE
: case PLUS
: case MINUS
: case MULT
: case DIV
:
4947 case MOD
: case UDIV
: case UMOD
: case AND
: case IOR
:
4948 case XOR
: case ASHIFT
: case ROTATE
: case ASHIFTRT
: case LSHIFTRT
:
4949 case ROTATERT
: case SMIN
: case SMAX
: case UMIN
: case UMAX
:
4950 case NE
: case EQ
: case GE
: case GT
: case LE
:
4951 case LT
: case GEU
: case GTU
: case LEU
: case LTU
:
4952 summarize_insn (XEXP (x
, 0), sum
, 0);
4953 summarize_insn (XEXP (x
, 1), sum
, 0);
4956 case NEG
: case NOT
: case SIGN_EXTEND
: case ZERO_EXTEND
:
4957 case TRUNCATE
: case FLOAT_EXTEND
: case FLOAT_TRUNCATE
: case FLOAT
:
4958 case FIX
: case UNSIGNED_FLOAT
: case UNSIGNED_FIX
: case ABS
:
4959 case SQRT
: case FFS
:
4960 summarize_insn (XEXP (x
, 0), sum
, 0);
4964 format_ptr
= GET_RTX_FORMAT (GET_CODE (x
));
4965 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
4966 switch (format_ptr
[i
])
4969 summarize_insn (XEXP (x
, i
), sum
, 0);
4973 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
4974 summarize_insn (XVECEXP (x
, i
, j
), sum
, 0);
4986 /* Ensure a sufficient number of `trapb' insns are in the code when
4987 the user requests code with a trap precision of functions or
4990 In naive mode, when the user requests a trap-precision of
4991 "instruction", a trapb is needed after every instruction that may
4992 generate a trap. This ensures that the code is resumption safe but
4995 When optimizations are turned on, we delay issuing a trapb as long
4996 as possible. In this context, a trap shadow is the sequence of
4997 instructions that starts with a (potentially) trap generating
4998 instruction and extends to the next trapb or call_pal instruction
4999 (but GCC never generates call_pal by itself). We can delay (and
5000 therefore sometimes omit) a trapb subject to the following
5003 (a) On entry to the trap shadow, if any Alpha register or memory
5004 location contains a value that is used as an operand value by some
5005 instruction in the trap shadow (live on entry), then no instruction
5006 in the trap shadow may modify the register or memory location.
5008 (b) Within the trap shadow, the computation of the base register
5009 for a memory load or store instruction may not involve using the
5010 result of an instruction that might generate an UNPREDICTABLE
5013 (c) Within the trap shadow, no register may be used more than once
5014 as a destination register. (This is to make life easier for the
5017 (d) The trap shadow may not include any branch instructions. */
5020 alpha_handle_trap_shadows (insns
)
5023 struct shadow_summary shadow
;
5024 int trap_pending
, exception_nesting
;
5028 exception_nesting
= 0;
5031 shadow
.used
.mem
= 0;
5032 shadow
.defd
= shadow
.used
;
5034 for (i
= insns
; i
; i
= NEXT_INSN (i
))
5036 if (GET_CODE (i
) == NOTE
)
5038 switch (NOTE_LINE_NUMBER (i
))
5040 case NOTE_INSN_EH_REGION_BEG
:
5041 exception_nesting
++;
5046 case NOTE_INSN_EH_REGION_END
:
5047 exception_nesting
--;
5052 case NOTE_INSN_EPILOGUE_BEG
:
5053 if (trap_pending
&& alpha_tp
>= ALPHA_TP_FUNC
)
5058 else if (trap_pending
)
5060 if (alpha_tp
== ALPHA_TP_FUNC
)
5062 if (GET_CODE (i
) == JUMP_INSN
5063 && GET_CODE (PATTERN (i
)) == RETURN
)
5066 else if (alpha_tp
== ALPHA_TP_INSN
)
5070 struct shadow_summary sum
;
5075 sum
.defd
= sum
.used
;
5077 switch (GET_CODE (i
))
5080 /* Annoyingly, get_attr_trap will abort on these. */
5081 if (GET_CODE (PATTERN (i
)) == USE
5082 || GET_CODE (PATTERN (i
)) == CLOBBER
)
5085 summarize_insn (PATTERN (i
), &sum
, 0);
5087 if ((sum
.defd
.i
& shadow
.defd
.i
)
5088 || (sum
.defd
.fp
& shadow
.defd
.fp
))
5090 /* (c) would be violated */
5094 /* Combine shadow with summary of current insn: */
5095 shadow
.used
.i
|= sum
.used
.i
;
5096 shadow
.used
.fp
|= sum
.used
.fp
;
5097 shadow
.used
.mem
|= sum
.used
.mem
;
5098 shadow
.defd
.i
|= sum
.defd
.i
;
5099 shadow
.defd
.fp
|= sum
.defd
.fp
;
5100 shadow
.defd
.mem
|= sum
.defd
.mem
;
5102 if ((sum
.defd
.i
& shadow
.used
.i
)
5103 || (sum
.defd
.fp
& shadow
.used
.fp
)
5104 || (sum
.defd
.mem
& shadow
.used
.mem
))
5106 /* (a) would be violated (also takes care of (b)) */
5107 if (get_attr_trap (i
) == TRAP_YES
5108 && ((sum
.defd
.i
& sum
.used
.i
)
5109 || (sum
.defd
.fp
& sum
.used
.fp
)))
5128 n
= emit_insn_before (gen_trapb (), i
);
5129 PUT_MODE (n
, TImode
);
5130 PUT_MODE (i
, TImode
);
5134 shadow
.used
.mem
= 0;
5135 shadow
.defd
= shadow
.used
;
5140 if ((exception_nesting
> 0 || alpha_tp
>= ALPHA_TP_FUNC
)
5141 && GET_CODE (i
) == INSN
5142 && GET_CODE (PATTERN (i
)) != USE
5143 && GET_CODE (PATTERN (i
)) != CLOBBER
5144 && get_attr_trap (i
) == TRAP_YES
)
5146 if (optimize
&& !trap_pending
)
5147 summarize_insn (PATTERN (i
), &shadow
, 0);
5154 /* Alpha can only issue instruction groups simultaneously if they are
5155 suitibly aligned. This is very processor-specific. */
5157 enum alphaev4_pipe
{
5164 enum alphaev5_pipe
{
5175 static enum alphaev4_pipe alphaev4_insn_pipe
PARAMS ((rtx
));
5176 static enum alphaev5_pipe alphaev5_insn_pipe
PARAMS ((rtx
));
5177 static rtx alphaev4_next_group
PARAMS ((rtx
, int*, int*));
5178 static rtx alphaev5_next_group
PARAMS ((rtx
, int*, int*));
5179 static rtx alphaev4_next_nop
PARAMS ((int*));
5180 static rtx alphaev5_next_nop
PARAMS ((int*));
5182 static void alpha_align_insns
5183 PARAMS ((rtx
, int, rtx (*)(rtx
, int*, int*), rtx (*)(int*), int));
5185 static enum alphaev4_pipe
5186 alphaev4_insn_pipe (insn
)
5189 if (recog_memoized (insn
) < 0)
5191 if (get_attr_length (insn
) != 4)
5194 switch (get_attr_type (insn
))
5227 static enum alphaev5_pipe
5228 alphaev5_insn_pipe (insn
)
5231 if (recog_memoized (insn
) < 0)
5233 if (get_attr_length (insn
) != 4)
5236 switch (get_attr_type (insn
))
5276 /* IN_USE is a mask of the slots currently filled within the insn group.
5277 The mask bits come from alphaev4_pipe above. If EV4_IBX is set, then
5278 the insn in EV4_IB0 can be swapped by the hardware into EV4_IB1.
5280 LEN is, of course, the length of the group in bytes. */
5283 alphaev4_next_group (insn
, pin_use
, plen
)
5285 int *pin_use
, *plen
;
5291 if (GET_RTX_CLASS (GET_CODE (insn
)) != 'i'
5292 || GET_CODE (PATTERN (insn
)) == CLOBBER
5293 || GET_CODE (PATTERN (insn
)) == USE
)
5298 enum alphaev4_pipe pipe
;
5300 pipe
= alphaev4_insn_pipe (insn
);
5304 /* Force complex instructions to start new groups. */
5308 /* If this is a completely unrecognized insn, its an asm.
5309 We don't know how long it is, so record length as -1 to
5310 signal a needed realignment. */
5311 if (recog_memoized (insn
) < 0)
5314 len
= get_attr_length (insn
);
5318 if (in_use
& EV4_IB0
)
5320 if (in_use
& EV4_IB1
)
5325 in_use
|= EV4_IB0
| EV4_IBX
;
5329 if (in_use
& EV4_IB0
)
5331 if (!(in_use
& EV4_IBX
) || (in_use
& EV4_IB1
))
5339 if (in_use
& EV4_IB1
)
5349 /* Haifa doesn't do well scheduling branches. */
5350 if (GET_CODE (insn
) == JUMP_INSN
)
5354 insn
= next_nonnote_insn (insn
);
5356 if (!insn
|| GET_RTX_CLASS (GET_CODE (insn
)) != 'i')
5359 /* Let Haifa tell us where it thinks insn group boundaries are. */
5360 if (GET_MODE (insn
) == TImode
)
5363 if (GET_CODE (insn
) == CLOBBER
|| GET_CODE (insn
) == USE
)
5368 insn
= next_nonnote_insn (insn
);
5376 /* IN_USE is a mask of the slots currently filled within the insn group.
5377 The mask bits come from alphaev5_pipe above. If EV5_E01 is set, then
5378 the insn in EV5_E0 can be swapped by the hardware into EV5_E1.
5380 LEN is, of course, the length of the group in bytes. */
5383 alphaev5_next_group (insn
, pin_use
, plen
)
5385 int *pin_use
, *plen
;
5391 if (GET_RTX_CLASS (GET_CODE (insn
)) != 'i'
5392 || GET_CODE (PATTERN (insn
)) == CLOBBER
5393 || GET_CODE (PATTERN (insn
)) == USE
)
5398 enum alphaev5_pipe pipe
;
5400 pipe
= alphaev5_insn_pipe (insn
);
5404 /* Force complex instructions to start new groups. */
5408 /* If this is a completely unrecognized insn, its an asm.
5409 We don't know how long it is, so record length as -1 to
5410 signal a needed realignment. */
5411 if (recog_memoized (insn
) < 0)
5414 len
= get_attr_length (insn
);
5417 /* ??? Most of the places below, we would like to abort, as
5418 it would indicate an error either in Haifa, or in the
5419 scheduling description. Unfortunately, Haifa never
5420 schedules the last instruction of the BB, so we don't
5421 have an accurate TI bit to go off. */
5423 if (in_use
& EV5_E0
)
5425 if (in_use
& EV5_E1
)
5430 in_use
|= EV5_E0
| EV5_E01
;
5434 if (in_use
& EV5_E0
)
5436 if (!(in_use
& EV5_E01
) || (in_use
& EV5_E1
))
5444 if (in_use
& EV5_E1
)
5450 if (in_use
& EV5_FA
)
5452 if (in_use
& EV5_FM
)
5457 in_use
|= EV5_FA
| EV5_FAM
;
5461 if (in_use
& EV5_FA
)
5467 if (in_use
& EV5_FM
)
5480 /* Haifa doesn't do well scheduling branches. */
5481 /* ??? If this is predicted not-taken, slotting continues, except
5482 that no more IBR, FBR, or JSR insns may be slotted. */
5483 if (GET_CODE (insn
) == JUMP_INSN
)
5487 insn
= next_nonnote_insn (insn
);
5489 if (!insn
|| GET_RTX_CLASS (GET_CODE (insn
)) != 'i')
5492 /* Let Haifa tell us where it thinks insn group boundaries are. */
5493 if (GET_MODE (insn
) == TImode
)
5496 if (GET_CODE (insn
) == CLOBBER
|| GET_CODE (insn
) == USE
)
5501 insn
= next_nonnote_insn (insn
);
5510 alphaev4_next_nop (pin_use
)
5513 int in_use
= *pin_use
;
5516 if (!(in_use
& EV4_IB0
))
5521 else if ((in_use
& (EV4_IBX
|EV4_IB1
)) == EV4_IBX
)
5526 else if (TARGET_FP
&& !(in_use
& EV4_IB1
))
5539 alphaev5_next_nop (pin_use
)
5542 int in_use
= *pin_use
;
5545 if (!(in_use
& EV5_E1
))
5550 else if (TARGET_FP
&& !(in_use
& EV5_FA
))
5555 else if (TARGET_FP
&& !(in_use
& EV5_FM
))
5567 /* The instruction group alignment main loop. */
5570 alpha_align_insns (insns
, max_align
, next_group
, next_nop
, gp_in_use
)
5573 rtx (*next_group
) PARAMS ((rtx
, int*, int*));
5574 rtx (*next_nop
) PARAMS ((int*));
5577 /* ALIGN is the known alignment for the insn group. */
5579 /* OFS is the offset of the current insn in the insn group. */
5581 int prev_in_use
, in_use
, len
;
5584 /* Let shorten branches care for assigning alignments to code labels. */
5585 shorten_branches (insns
);
5587 align
= (FUNCTION_BOUNDARY
/BITS_PER_UNIT
< max_align
5588 ? FUNCTION_BOUNDARY
/BITS_PER_UNIT
: max_align
);
5590 /* Account for the initial GP load, which happens before the scheduled
5591 prologue we emitted as RTL. */
5592 ofs
= prev_in_use
= 0;
5593 if (alpha_does_function_need_gp())
5595 ofs
= 8 & (align
- 1);
5596 prev_in_use
= gp_in_use
;
5600 if (GET_CODE (i
) == NOTE
)
5601 i
= next_nonnote_insn (i
);
5605 next
= (*next_group
)(i
, &in_use
, &len
);
5607 /* When we see a label, resync alignment etc. */
5608 if (GET_CODE (i
) == CODE_LABEL
)
5610 int new_align
= 1 << label_to_alignment (i
);
5611 if (new_align
>= align
)
5613 align
= new_align
< max_align
? new_align
: max_align
;
5616 else if (ofs
& (new_align
-1))
5617 ofs
= (ofs
| (new_align
-1)) + 1;
5622 /* Handle complex instructions special. */
5623 else if (in_use
== 0)
5625 /* Asms will have length < 0. This is a signal that we have
5626 lost alignment knowledge. Assume, however, that the asm
5627 will not mis-align instructions. */
5636 /* If the known alignment is smaller than the recognized insn group,
5637 realign the output. */
5638 else if (align
< len
)
5640 int new_log_align
= len
> 8 ? 4 : 3;
5643 where
= prev_nonnote_insn (i
);
5644 if (!where
|| GET_CODE (where
) != CODE_LABEL
)
5647 emit_insn_before (gen_realign (GEN_INT (new_log_align
)), where
);
5648 align
= 1 << new_log_align
;
5652 /* If the group won't fit in the same INT16 as the previous,
5653 we need to add padding to keep the group together. Rather
5654 than simply leaving the insn filling to the assembler, we
5655 can make use of the knowledge of what sorts of instructions
5656 were issued in the previous group to make sure that all of
5657 the added nops are really free. */
5658 else if (ofs
+ len
> align
)
5660 int nop_count
= (align
- ofs
) / 4;
5663 /* Insert nops before labels and branches to truely merge the
5664 execution of the nops with the previous instruction group. */
5665 where
= prev_nonnote_insn (i
);
5668 if (GET_CODE (where
) == CODE_LABEL
)
5670 rtx where2
= prev_nonnote_insn (where
);
5671 if (where2
&& GET_CODE (where2
) == JUMP_INSN
)
5674 else if (GET_CODE (where
) != JUMP_INSN
)
5681 emit_insn_before ((*next_nop
)(&prev_in_use
), where
);
5682 while (--nop_count
);
5686 ofs
= (ofs
+ len
) & (align
- 1);
5687 prev_in_use
= in_use
;
5693 /* Machine dependant reorg pass. */
5699 if (alpha_tp
!= ALPHA_TP_PROG
|| flag_exceptions
)
5700 alpha_handle_trap_shadows (insns
);
5703 /* Due to the number of extra trapb insns, don't bother fixing up
5704 alignment when trap precision is instruction. Moreover, we can
5705 only do our job when sched2 is run and Haifa is our scheduler. */
5706 if (optimize
&& !optimize_size
5707 && alpha_tp
!= ALPHA_TP_INSN
5708 && flag_schedule_insns_after_reload
)
5710 if (alpha_cpu
== PROCESSOR_EV4
)
5711 alpha_align_insns (insns
, 8, alphaev4_next_group
,
5712 alphaev4_next_nop
, EV4_IB0
);
5713 else if (alpha_cpu
== PROCESSOR_EV5
)
5714 alpha_align_insns (insns
, 16, alphaev5_next_group
,
5715 alphaev5_next_nop
, EV5_E01
| EV5_E0
);
5721 /* Check a floating-point value for validity for a particular machine mode. */
5723 static const char * const float_strings
[] =
5725 /* These are for FLOAT_VAX. */
5726 "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
5727 "-1.70141173319264430e+38",
5728 "2.93873587705571877e-39", /* 2^-128 */
5729 "-2.93873587705571877e-39",
5730 /* These are for the default broken IEEE mode, which traps
5731 on infinity or denormal numbers. */
5732 "3.402823466385288598117e+38", /* 2^128 (1 - 2^-24) */
5733 "-3.402823466385288598117e+38",
5734 "1.1754943508222875079687e-38", /* 2^-126 */
5735 "-1.1754943508222875079687e-38",
5738 static REAL_VALUE_TYPE float_values
[8];
5739 static int inited_float_values
= 0;
5742 check_float_value (mode
, d
, overflow
)
5743 enum machine_mode mode
;
5745 int overflow ATTRIBUTE_UNUSED
;
5748 if (TARGET_IEEE
|| TARGET_IEEE_CONFORMANT
|| TARGET_IEEE_WITH_INEXACT
)
5751 if (inited_float_values
== 0)
5754 for (i
= 0; i
< 8; i
++)
5755 float_values
[i
] = REAL_VALUE_ATOF (float_strings
[i
], DFmode
);
5757 inited_float_values
= 1;
5763 REAL_VALUE_TYPE
*fvptr
;
5765 if (TARGET_FLOAT_VAX
)
5766 fvptr
= &float_values
[0];
5768 fvptr
= &float_values
[4];
5770 bcopy ((char *) d
, (char *) &r
, sizeof (REAL_VALUE_TYPE
));
5771 if (REAL_VALUES_LESS (fvptr
[0], r
))
5773 bcopy ((char *) &fvptr
[0], (char *) d
,
5774 sizeof (REAL_VALUE_TYPE
));
5777 else if (REAL_VALUES_LESS (r
, fvptr
[1]))
5779 bcopy ((char *) &fvptr
[1], (char *) d
,
5780 sizeof (REAL_VALUE_TYPE
));
5783 else if (REAL_VALUES_LESS (dconst0
, r
)
5784 && REAL_VALUES_LESS (r
, fvptr
[2]))
5786 bcopy ((char *) &dconst0
, (char *) d
, sizeof (REAL_VALUE_TYPE
));
5789 else if (REAL_VALUES_LESS (r
, dconst0
)
5790 && REAL_VALUES_LESS (fvptr
[3], r
))
5792 bcopy ((char *) &dconst0
, (char *) d
, sizeof (REAL_VALUE_TYPE
));
5802 /* Return the VMS argument type corresponding to MODE. */
5805 alpha_arg_type (mode
)
5806 enum machine_mode mode
;
5811 return TARGET_FLOAT_VAX
? FF
: FS
;
5813 return TARGET_FLOAT_VAX
? FD
: FT
;
5819 /* Return an rtx for an integer representing the VMS Argument Information
5823 alpha_arg_info_reg_val (cum
)
5824 CUMULATIVE_ARGS cum
;
5826 unsigned HOST_WIDE_INT regval
= cum
.num_args
;
5829 for (i
= 0; i
< 6; i
++)
5830 regval
|= ((int) cum
.atypes
[i
]) << (i
* 3 + 8);
5832 return GEN_INT (regval
);
5835 /* Structure to collect function names for final output
5838 enum links_kind
{KIND_UNUSED
, KIND_LOCAL
, KIND_EXTERN
};
5841 struct alpha_links
{
5842 struct alpha_links
*next
;
5844 enum links_kind kind
;
5847 static struct alpha_links
*alpha_links_base
= 0;
5849 /* Make (or fake) .linkage entry for function call.
5851 IS_LOCAL is 0 if name is used in call, 1 if name is used in definition. */
5854 alpha_need_linkage (name
, is_local
)
5859 struct alpha_links
*lptr
, *nptr
;
5864 /* Is this name already defined ? */
5866 for (lptr
= alpha_links_base
; lptr
; lptr
= lptr
->next
)
5867 if (strcmp (lptr
->name
, name
) == 0)
5871 /* Defined here but external assumed. */
5872 if (lptr
->kind
== KIND_EXTERN
)
5873 lptr
->kind
= KIND_LOCAL
;
5877 /* Used here but unused assumed. */
5878 if (lptr
->kind
== KIND_UNUSED
)
5879 lptr
->kind
= KIND_LOCAL
;
5884 nptr
= (struct alpha_links
*) xmalloc (sizeof (struct alpha_links
));
5885 nptr
->next
= alpha_links_base
;
5886 nptr
->name
= xstrdup (name
);
5888 /* Assume external if no definition. */
5889 nptr
->kind
= (is_local
? KIND_UNUSED
: KIND_EXTERN
);
5891 /* Ensure we have an IDENTIFIER so assemble_name can mark is used. */
5892 get_identifier (name
);
5894 alpha_links_base
= nptr
;
5901 alpha_write_linkage (stream
)
5904 struct alpha_links
*lptr
, *nptr
;
5906 readonly_section ();
5908 fprintf (stream
, "\t.align 3\n");
5910 for (lptr
= alpha_links_base
; lptr
; lptr
= nptr
)
5914 if (lptr
->kind
== KIND_UNUSED
5915 || ! TREE_SYMBOL_REFERENCED (get_identifier (lptr
->name
)))
5918 fprintf (stream
, "$%s..lk:\n", lptr
->name
);
5919 if (lptr
->kind
== KIND_LOCAL
)
5921 /* Local and used, build linkage pair. */
5922 fprintf (stream
, "\t.quad %s..en\n", lptr
->name
);
5923 fprintf (stream
, "\t.quad %s\n", lptr
->name
);
5926 /* External and used, request linkage pair. */
5927 fprintf (stream
, "\t.linkage %s\n", lptr
->name
);
5934 alpha_need_linkage (name
, is_local
)
5935 const char *name ATTRIBUTE_UNUSED
;
5936 int is_local ATTRIBUTE_UNUSED
;
5940 #endif /* OPEN_VMS */