1 /* Machine description for AArch64 architecture.
2 Copyright (C) 2009-2013 Free Software Foundation, Inc.
3 Contributed by ARM Ltd.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
25 #include "insn-codes.h"
27 #include "insn-attr.h"
31 #include "hard-reg-set.h"
37 #include "target-def.h"
38 #include "targhooks.h"
43 #include "langhooks.h"
44 #include "diagnostic-core.h"
49 #include "tree-vectorizer.h"
51 /* Defined for convenience. */
52 #define POINTER_BYTES (POINTER_SIZE / BITS_PER_UNIT)
54 /* Classifies an address.
57 A simple base register plus immediate offset.
60 A base register indexed by immediate offset with writeback.
63 A base register indexed by (optionally scaled) register.
66 A base register indexed by (optionally scaled) zero-extended register.
69 A base register indexed by (optionally scaled) sign-extended register.
72 A LO_SUM rtx with a base register and "LO12" symbol relocation.
75 A constant symbolic address, in pc-relative literal pool. */
77 enum aarch64_address_type
{
87 struct aarch64_address_info
{
88 enum aarch64_address_type type
;
92 enum aarch64_symbol_type symbol_type
;
95 struct simd_immediate_info
104 /* The current code model. */
105 enum aarch64_code_model aarch64_cmodel
;
108 #undef TARGET_HAVE_TLS
109 #define TARGET_HAVE_TLS 1
112 static bool aarch64_composite_type_p (const_tree
, enum machine_mode
);
113 static bool aarch64_vfp_is_call_or_return_candidate (enum machine_mode
,
115 enum machine_mode
*, int *,
117 static void aarch64_elf_asm_constructor (rtx
, int) ATTRIBUTE_UNUSED
;
118 static void aarch64_elf_asm_destructor (rtx
, int) ATTRIBUTE_UNUSED
;
119 static void aarch64_override_options_after_change (void);
120 static bool aarch64_vector_mode_supported_p (enum machine_mode
);
121 static unsigned bit_count (unsigned HOST_WIDE_INT
);
122 static bool aarch64_const_vec_all_same_int_p (rtx
,
123 HOST_WIDE_INT
, HOST_WIDE_INT
);
125 static bool aarch64_vectorize_vec_perm_const_ok (enum machine_mode vmode
,
126 const unsigned char *sel
);
128 /* The processor for which instructions should be scheduled. */
129 enum aarch64_processor aarch64_tune
= generic
;
131 /* The current tuning set. */
132 const struct tune_params
*aarch64_tune_params
;
134 /* Mask to specify which instructions we are allowed to generate. */
135 unsigned long aarch64_isa_flags
= 0;
137 /* Mask to specify which instruction scheduling options should be used. */
138 unsigned long aarch64_tune_flags
= 0;
140 /* Tuning parameters. */
142 #if HAVE_DESIGNATED_INITIALIZERS
143 #define NAMED_PARAM(NAME, VAL) .NAME = (VAL)
145 #define NAMED_PARAM(NAME, VAL) (VAL)
148 #if HAVE_DESIGNATED_INITIALIZERS && GCC_VERSION >= 2007
151 static const struct cpu_rtx_cost_table generic_rtx_cost_table
=
153 NAMED_PARAM (memory_load
, COSTS_N_INSNS (1)),
154 NAMED_PARAM (memory_store
, COSTS_N_INSNS (0)),
155 NAMED_PARAM (register_shift
, COSTS_N_INSNS (1)),
156 NAMED_PARAM (int_divide
, COSTS_N_INSNS (6)),
157 NAMED_PARAM (float_divide
, COSTS_N_INSNS (2)),
158 NAMED_PARAM (double_divide
, COSTS_N_INSNS (6)),
159 NAMED_PARAM (int_multiply
, COSTS_N_INSNS (1)),
160 NAMED_PARAM (int_multiply_extend
, COSTS_N_INSNS (1)),
161 NAMED_PARAM (int_multiply_add
, COSTS_N_INSNS (1)),
162 NAMED_PARAM (int_multiply_extend_add
, COSTS_N_INSNS (1)),
163 NAMED_PARAM (float_multiply
, COSTS_N_INSNS (0)),
164 NAMED_PARAM (double_multiply
, COSTS_N_INSNS (1))
167 #if HAVE_DESIGNATED_INITIALIZERS && GCC_VERSION >= 2007
170 static const struct cpu_addrcost_table generic_addrcost_table
=
172 NAMED_PARAM (pre_modify
, 0),
173 NAMED_PARAM (post_modify
, 0),
174 NAMED_PARAM (register_offset
, 0),
175 NAMED_PARAM (register_extend
, 0),
176 NAMED_PARAM (imm_offset
, 0)
179 #if HAVE_DESIGNATED_INITIALIZERS && GCC_VERSION >= 2007
182 static const struct cpu_regmove_cost generic_regmove_cost
=
184 NAMED_PARAM (GP2GP
, 1),
185 NAMED_PARAM (GP2FP
, 2),
186 NAMED_PARAM (FP2GP
, 2),
187 /* We currently do not provide direct support for TFmode Q->Q move.
188 Therefore we need to raise the cost above 2 in order to have
189 reload handle the situation. */
190 NAMED_PARAM (FP2FP
, 4)
193 /* Generic costs for vector insn classes. */
194 #if HAVE_DESIGNATED_INITIALIZERS && GCC_VERSION >= 2007
197 static const struct cpu_vector_cost generic_vector_cost
=
199 NAMED_PARAM (scalar_stmt_cost
, 1),
200 NAMED_PARAM (scalar_load_cost
, 1),
201 NAMED_PARAM (scalar_store_cost
, 1),
202 NAMED_PARAM (vec_stmt_cost
, 1),
203 NAMED_PARAM (vec_to_scalar_cost
, 1),
204 NAMED_PARAM (scalar_to_vec_cost
, 1),
205 NAMED_PARAM (vec_align_load_cost
, 1),
206 NAMED_PARAM (vec_unalign_load_cost
, 1),
207 NAMED_PARAM (vec_unalign_store_cost
, 1),
208 NAMED_PARAM (vec_store_cost
, 1),
209 NAMED_PARAM (cond_taken_branch_cost
, 3),
210 NAMED_PARAM (cond_not_taken_branch_cost
, 1)
213 #if HAVE_DESIGNATED_INITIALIZERS && GCC_VERSION >= 2007
216 static const struct tune_params generic_tunings
=
218 &generic_rtx_cost_table
,
219 &generic_addrcost_table
,
220 &generic_regmove_cost
,
221 &generic_vector_cost
,
222 NAMED_PARAM (memmov_cost
, 4)
225 /* A processor implementing AArch64. */
228 const char *const name
;
229 enum aarch64_processor core
;
231 const unsigned long flags
;
232 const struct tune_params
*const tune
;
235 /* Processor cores implementing AArch64. */
236 static const struct processor all_cores
[] =
238 #define AARCH64_CORE(NAME, IDENT, ARCH, FLAGS, COSTS) \
239 {NAME, IDENT, #ARCH, FLAGS | AARCH64_FL_FOR_ARCH##ARCH, &COSTS##_tunings},
240 #include "aarch64-cores.def"
242 {"generic", generic
, "8", AARCH64_FL_FPSIMD
| AARCH64_FL_FOR_ARCH8
, &generic_tunings
},
243 {NULL
, aarch64_none
, NULL
, 0, NULL
}
246 /* Architectures implementing AArch64. */
247 static const struct processor all_architectures
[] =
249 #define AARCH64_ARCH(NAME, CORE, ARCH, FLAGS) \
250 {NAME, CORE, #ARCH, FLAGS, NULL},
251 #include "aarch64-arches.def"
253 {"generic", generic
, "8", AARCH64_FL_FOR_ARCH8
, NULL
},
254 {NULL
, aarch64_none
, NULL
, 0, NULL
}
257 /* Target specification. These are populated as commandline arguments
258 are processed, or NULL if not specified. */
259 static const struct processor
*selected_arch
;
260 static const struct processor
*selected_cpu
;
261 static const struct processor
*selected_tune
;
263 #define AARCH64_CPU_DEFAULT_FLAGS ((selected_cpu) ? selected_cpu->flags : 0)
265 /* An ISA extension in the co-processor and main instruction set space. */
266 struct aarch64_option_extension
268 const char *const name
;
269 const unsigned long flags_on
;
270 const unsigned long flags_off
;
273 /* ISA extensions in AArch64. */
274 static const struct aarch64_option_extension all_extensions
[] =
276 #define AARCH64_OPT_EXTENSION(NAME, FLAGS_ON, FLAGS_OFF) \
277 {NAME, FLAGS_ON, FLAGS_OFF},
278 #include "aarch64-option-extensions.def"
279 #undef AARCH64_OPT_EXTENSION
283 /* Used to track the size of an address when generating a pre/post
284 increment address. */
285 static enum machine_mode aarch64_memory_reference_mode
;
287 /* Used to force GTY into this file. */
288 static GTY(()) int gty_dummy
;
290 /* A table of valid AArch64 "bitmask immediate" values for
291 logical instructions. */
293 #define AARCH64_NUM_BITMASKS 5334
294 static unsigned HOST_WIDE_INT aarch64_bitmasks
[AARCH64_NUM_BITMASKS
];
296 /* Did we set flag_omit_frame_pointer just so
297 aarch64_frame_pointer_required would be called? */
298 static bool faked_omit_frame_pointer
;
300 typedef enum aarch64_cond_code
302 AARCH64_EQ
= 0, AARCH64_NE
, AARCH64_CS
, AARCH64_CC
, AARCH64_MI
, AARCH64_PL
,
303 AARCH64_VS
, AARCH64_VC
, AARCH64_HI
, AARCH64_LS
, AARCH64_GE
, AARCH64_LT
,
304 AARCH64_GT
, AARCH64_LE
, AARCH64_AL
, AARCH64_NV
308 #define AARCH64_INVERSE_CONDITION_CODE(X) ((aarch64_cc) (((int) X) ^ 1))
310 /* The condition codes of the processor, and the inverse function. */
311 static const char * const aarch64_condition_codes
[] =
313 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
314 "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
317 /* Provide a mapping from gcc register numbers to dwarf register numbers. */
319 aarch64_dbx_register_number (unsigned regno
)
321 if (GP_REGNUM_P (regno
))
322 return AARCH64_DWARF_R0
+ regno
- R0_REGNUM
;
323 else if (regno
== SP_REGNUM
)
324 return AARCH64_DWARF_SP
;
325 else if (FP_REGNUM_P (regno
))
326 return AARCH64_DWARF_V0
+ regno
- V0_REGNUM
;
328 /* Return values >= DWARF_FRAME_REGISTERS indicate that there is no
329 equivalent DWARF register. */
330 return DWARF_FRAME_REGISTERS
;
333 /* Return TRUE if MODE is any of the large INT modes. */
335 aarch64_vect_struct_mode_p (enum machine_mode mode
)
337 return mode
== OImode
|| mode
== CImode
|| mode
== XImode
;
340 /* Return TRUE if MODE is any of the vector modes. */
342 aarch64_vector_mode_p (enum machine_mode mode
)
344 return aarch64_vector_mode_supported_p (mode
)
345 || aarch64_vect_struct_mode_p (mode
);
348 /* Implement target hook TARGET_ARRAY_MODE_SUPPORTED_P. */
350 aarch64_array_mode_supported_p (enum machine_mode mode
,
351 unsigned HOST_WIDE_INT nelems
)
354 && AARCH64_VALID_SIMD_QREG_MODE (mode
)
355 && (nelems
>= 2 && nelems
<= 4))
361 /* Implement HARD_REGNO_NREGS. */
364 aarch64_hard_regno_nregs (unsigned regno
, enum machine_mode mode
)
366 switch (aarch64_regno_regclass (regno
))
370 return (GET_MODE_SIZE (mode
) + UNITS_PER_VREG
- 1) / UNITS_PER_VREG
;
372 return (GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
377 /* Implement HARD_REGNO_MODE_OK. */
380 aarch64_hard_regno_mode_ok (unsigned regno
, enum machine_mode mode
)
382 if (GET_MODE_CLASS (mode
) == MODE_CC
)
383 return regno
== CC_REGNUM
;
385 if (regno
== SP_REGNUM
|| regno
== FRAME_POINTER_REGNUM
386 || regno
== ARG_POINTER_REGNUM
)
387 return mode
== Pmode
;
389 if (GP_REGNUM_P (regno
) && ! aarch64_vect_struct_mode_p (mode
))
392 if (FP_REGNUM_P (regno
))
394 if (aarch64_vect_struct_mode_p (mode
))
396 (regno
+ aarch64_hard_regno_nregs (regno
, mode
) - 1) <= V31_REGNUM
;
404 /* Return true if calls to DECL should be treated as
405 long-calls (ie called via a register). */
407 aarch64_decl_is_long_call_p (const_tree decl ATTRIBUTE_UNUSED
)
412 /* Return true if calls to symbol-ref SYM should be treated as
413 long-calls (ie called via a register). */
415 aarch64_is_long_call_p (rtx sym
)
417 return aarch64_decl_is_long_call_p (SYMBOL_REF_DECL (sym
));
420 /* Return true if the offsets to a zero/sign-extract operation
421 represent an expression that matches an extend operation. The
422 operands represent the paramters from
424 (extract (mult (reg) (mult_imm)) (extract_imm) (const_int 0)). */
426 aarch64_is_extend_from_extract (enum machine_mode mode
, rtx mult_imm
,
429 HOST_WIDE_INT mult_val
, extract_val
;
431 if (! CONST_INT_P (mult_imm
) || ! CONST_INT_P (extract_imm
))
434 mult_val
= INTVAL (mult_imm
);
435 extract_val
= INTVAL (extract_imm
);
438 && extract_val
< GET_MODE_BITSIZE (mode
)
439 && exact_log2 (extract_val
& ~7) > 0
440 && (extract_val
& 7) <= 4
441 && mult_val
== (1 << (extract_val
& 7)))
447 /* Emit an insn that's a simple single-set. Both the operands must be
448 known to be valid. */
450 emit_set_insn (rtx x
, rtx y
)
452 return emit_insn (gen_rtx_SET (VOIDmode
, x
, y
));
455 /* X and Y are two things to compare using CODE. Emit the compare insn and
456 return the rtx for register 0 in the proper mode. */
458 aarch64_gen_compare_reg (RTX_CODE code
, rtx x
, rtx y
)
460 enum machine_mode mode
= SELECT_CC_MODE (code
, x
, y
);
461 rtx cc_reg
= gen_rtx_REG (mode
, CC_REGNUM
);
463 emit_set_insn (cc_reg
, gen_rtx_COMPARE (mode
, x
, y
));
467 /* Build the SYMBOL_REF for __tls_get_addr. */
469 static GTY(()) rtx tls_get_addr_libfunc
;
472 aarch64_tls_get_addr (void)
474 if (!tls_get_addr_libfunc
)
475 tls_get_addr_libfunc
= init_one_libfunc ("__tls_get_addr");
476 return tls_get_addr_libfunc
;
479 /* Return the TLS model to use for ADDR. */
481 static enum tls_model
482 tls_symbolic_operand_type (rtx addr
)
484 enum tls_model tls_kind
= TLS_MODEL_NONE
;
487 if (GET_CODE (addr
) == CONST
)
489 split_const (addr
, &sym
, &addend
);
490 if (GET_CODE (sym
) == SYMBOL_REF
)
491 tls_kind
= SYMBOL_REF_TLS_MODEL (sym
);
493 else if (GET_CODE (addr
) == SYMBOL_REF
)
494 tls_kind
= SYMBOL_REF_TLS_MODEL (addr
);
499 /* We'll allow lo_sum's in addresses in our legitimate addresses
500 so that combine would take care of combining addresses where
501 necessary, but for generation purposes, we'll generate the address
504 tmp = hi (symbol_ref); adrp x1, foo
505 dest = lo_sum (tmp, symbol_ref); add dest, x1, :lo_12:foo
509 adrp x1, :got:foo adrp tmp, :tlsgd:foo
510 ldr x1, [:got_lo12:foo] add dest, tmp, :tlsgd_lo12:foo
514 Load TLS symbol, depending on TLS mechanism and TLS access model.
516 Global Dynamic - Traditional TLS:
518 add dest, tmp, #:tlsgd_lo12:imm
521 Global Dynamic - TLS Descriptors:
522 adrp dest, :tlsdesc:imm
523 ldr tmp, [dest, #:tlsdesc_lo12:imm]
524 add dest, dest, #:tlsdesc_lo12:imm
531 adrp tmp, :gottprel:imm
532 ldr dest, [tmp, #:gottprel_lo12:imm]
537 add t0, tp, #:tprel_hi12:imm
538 add t0, #:tprel_lo12_nc:imm
542 aarch64_load_symref_appropriately (rtx dest
, rtx imm
,
543 enum aarch64_symbol_type type
)
547 case SYMBOL_SMALL_ABSOLUTE
:
549 /* In ILP32, the mode of dest can be either SImode or DImode. */
551 enum machine_mode mode
= GET_MODE (dest
);
553 gcc_assert (mode
== Pmode
|| mode
== ptr_mode
);
555 if (can_create_pseudo_p ())
556 tmp_reg
= gen_reg_rtx (mode
);
558 emit_move_insn (tmp_reg
, gen_rtx_HIGH (mode
, imm
));
559 emit_insn (gen_add_losym (dest
, tmp_reg
, imm
));
563 case SYMBOL_TINY_ABSOLUTE
:
564 emit_insn (gen_rtx_SET (Pmode
, dest
, imm
));
567 case SYMBOL_SMALL_GOT
:
569 /* In ILP32, the mode of dest can be either SImode or DImode,
570 while the got entry is always of SImode size. The mode of
571 dest depends on how dest is used: if dest is assigned to a
572 pointer (e.g. in the memory), it has SImode; it may have
573 DImode if dest is dereferenced to access the memeory.
574 This is why we have to handle three different ldr_got_small
575 patterns here (two patterns for ILP32). */
577 enum machine_mode mode
= GET_MODE (dest
);
579 if (can_create_pseudo_p ())
580 tmp_reg
= gen_reg_rtx (mode
);
582 emit_move_insn (tmp_reg
, gen_rtx_HIGH (mode
, imm
));
583 if (mode
== ptr_mode
)
586 emit_insn (gen_ldr_got_small_di (dest
, tmp_reg
, imm
));
588 emit_insn (gen_ldr_got_small_si (dest
, tmp_reg
, imm
));
592 gcc_assert (mode
== Pmode
);
593 emit_insn (gen_ldr_got_small_sidi (dest
, tmp_reg
, imm
));
599 case SYMBOL_SMALL_TLSGD
:
602 rtx result
= gen_rtx_REG (Pmode
, R0_REGNUM
);
605 emit_call_insn (gen_tlsgd_small (result
, imm
));
606 insns
= get_insns ();
609 RTL_CONST_CALL_P (insns
) = 1;
610 emit_libcall_block (insns
, dest
, result
, imm
);
614 case SYMBOL_SMALL_TLSDESC
:
616 rtx x0
= gen_rtx_REG (Pmode
, R0_REGNUM
);
619 emit_insn (gen_tlsdesc_small (imm
));
620 tp
= aarch64_load_tp (NULL
);
621 emit_insn (gen_rtx_SET (Pmode
, dest
, gen_rtx_PLUS (Pmode
, tp
, x0
)));
622 set_unique_reg_note (get_last_insn (), REG_EQUIV
, imm
);
626 case SYMBOL_SMALL_GOTTPREL
:
628 rtx tmp_reg
= gen_reg_rtx (Pmode
);
629 rtx tp
= aarch64_load_tp (NULL
);
630 emit_insn (gen_tlsie_small (tmp_reg
, imm
));
631 emit_insn (gen_rtx_SET (Pmode
, dest
, gen_rtx_PLUS (Pmode
, tp
, tmp_reg
)));
632 set_unique_reg_note (get_last_insn (), REG_EQUIV
, imm
);
636 case SYMBOL_SMALL_TPREL
:
638 rtx tp
= aarch64_load_tp (NULL
);
639 emit_insn (gen_tlsle_small (dest
, tp
, imm
));
640 set_unique_reg_note (get_last_insn (), REG_EQUIV
, imm
);
644 case SYMBOL_TINY_GOT
:
645 emit_insn (gen_ldr_got_tiny (dest
, imm
));
653 /* Emit a move from SRC to DEST. Assume that the move expanders can
654 handle all moves if !can_create_pseudo_p (). The distinction is
655 important because, unlike emit_move_insn, the move expanders know
656 how to force Pmode objects into the constant pool even when the
657 constant pool address is not itself legitimate. */
659 aarch64_emit_move (rtx dest
, rtx src
)
661 return (can_create_pseudo_p ()
662 ? emit_move_insn (dest
, src
)
663 : emit_move_insn_1 (dest
, src
));
667 aarch64_split_128bit_move (rtx dst
, rtx src
)
671 enum machine_mode src_mode
= GET_MODE (src
);
672 enum machine_mode dst_mode
= GET_MODE (dst
);
673 int src_regno
= REGNO (src
);
674 int dst_regno
= REGNO (dst
);
676 gcc_assert (dst_mode
== TImode
|| dst_mode
== TFmode
);
678 if (REG_P (dst
) && REG_P (src
))
680 gcc_assert (src_mode
== TImode
|| src_mode
== TFmode
);
682 /* Handle r -> w, w -> r. */
683 if (FP_REGNUM_P (dst_regno
) && GP_REGNUM_P (src_regno
))
688 (gen_aarch64_movtilow_di (dst
, gen_lowpart (word_mode
, src
)));
690 (gen_aarch64_movtihigh_di (dst
, gen_highpart (word_mode
, src
)));
694 (gen_aarch64_movtflow_di (dst
, gen_lowpart (word_mode
, src
)));
696 (gen_aarch64_movtfhigh_di (dst
, gen_highpart (word_mode
, src
)));
702 else if (GP_REGNUM_P (dst_regno
) && FP_REGNUM_P (src_regno
))
707 (gen_aarch64_movdi_tilow (gen_lowpart (word_mode
, dst
), src
));
709 (gen_aarch64_movdi_tihigh (gen_highpart (word_mode
, dst
), src
));
713 (gen_aarch64_movdi_tflow (gen_lowpart (word_mode
, dst
), src
));
715 (gen_aarch64_movdi_tfhigh (gen_highpart (word_mode
, dst
), src
));
721 /* Fall through to r -> r cases. */
726 low_dst
= gen_lowpart (word_mode
, dst
);
728 && reg_overlap_mentioned_p (low_dst
, src
))
730 aarch64_emit_move (gen_highpart (word_mode
, dst
),
731 gen_highpart_mode (word_mode
, TImode
, src
));
732 aarch64_emit_move (low_dst
, gen_lowpart (word_mode
, src
));
736 aarch64_emit_move (low_dst
, gen_lowpart (word_mode
, src
));
737 aarch64_emit_move (gen_highpart (word_mode
, dst
),
738 gen_highpart_mode (word_mode
, TImode
, src
));
742 emit_move_insn (gen_rtx_REG (DFmode
, dst_regno
),
743 gen_rtx_REG (DFmode
, src_regno
));
744 emit_move_insn (gen_rtx_REG (DFmode
, dst_regno
+ 1),
745 gen_rtx_REG (DFmode
, src_regno
+ 1));
753 aarch64_split_128bit_move_p (rtx dst
, rtx src
)
755 return (! REG_P (src
)
756 || ! (FP_REGNUM_P (REGNO (dst
)) && FP_REGNUM_P (REGNO (src
))));
759 /* Split a complex SIMD combine. */
762 aarch64_split_simd_combine (rtx dst
, rtx src1
, rtx src2
)
764 enum machine_mode src_mode
= GET_MODE (src1
);
765 enum machine_mode dst_mode
= GET_MODE (dst
);
767 gcc_assert (VECTOR_MODE_P (dst_mode
));
769 if (REG_P (dst
) && REG_P (src1
) && REG_P (src2
))
771 rtx (*gen
) (rtx
, rtx
, rtx
);
776 gen
= gen_aarch64_simd_combinev8qi
;
779 gen
= gen_aarch64_simd_combinev4hi
;
782 gen
= gen_aarch64_simd_combinev2si
;
785 gen
= gen_aarch64_simd_combinev2sf
;
788 gen
= gen_aarch64_simd_combinedi
;
791 gen
= gen_aarch64_simd_combinedf
;
797 emit_insn (gen (dst
, src1
, src2
));
802 /* Split a complex SIMD move. */
805 aarch64_split_simd_move (rtx dst
, rtx src
)
807 enum machine_mode src_mode
= GET_MODE (src
);
808 enum machine_mode dst_mode
= GET_MODE (dst
);
810 gcc_assert (VECTOR_MODE_P (dst_mode
));
812 if (REG_P (dst
) && REG_P (src
))
814 rtx (*gen
) (rtx
, rtx
);
816 gcc_assert (VECTOR_MODE_P (src_mode
));
821 gen
= gen_aarch64_split_simd_movv16qi
;
824 gen
= gen_aarch64_split_simd_movv8hi
;
827 gen
= gen_aarch64_split_simd_movv4si
;
830 gen
= gen_aarch64_split_simd_movv2di
;
833 gen
= gen_aarch64_split_simd_movv4sf
;
836 gen
= gen_aarch64_split_simd_movv2df
;
842 emit_insn (gen (dst
, src
));
848 aarch64_force_temporary (enum machine_mode mode
, rtx x
, rtx value
)
850 if (can_create_pseudo_p ())
851 return force_reg (mode
, value
);
854 x
= aarch64_emit_move (x
, value
);
861 aarch64_add_offset (enum machine_mode mode
, rtx temp
, rtx reg
, HOST_WIDE_INT offset
)
863 if (!aarch64_plus_immediate (GEN_INT (offset
), mode
))
866 /* Load the full offset into a register. This
867 might be improvable in the future. */
868 high
= GEN_INT (offset
);
870 high
= aarch64_force_temporary (mode
, temp
, high
);
871 reg
= aarch64_force_temporary (mode
, temp
,
872 gen_rtx_PLUS (mode
, high
, reg
));
874 return plus_constant (mode
, reg
, offset
);
878 aarch64_expand_mov_immediate (rtx dest
, rtx imm
)
880 enum machine_mode mode
= GET_MODE (dest
);
881 unsigned HOST_WIDE_INT mask
;
884 unsigned HOST_WIDE_INT val
;
887 int one_match
, zero_match
;
889 gcc_assert (mode
== SImode
|| mode
== DImode
);
891 /* Check on what type of symbol it is. */
892 if (GET_CODE (imm
) == SYMBOL_REF
893 || GET_CODE (imm
) == LABEL_REF
894 || GET_CODE (imm
) == CONST
)
896 rtx mem
, base
, offset
;
897 enum aarch64_symbol_type sty
;
899 /* If we have (const (plus symbol offset)), separate out the offset
900 before we start classifying the symbol. */
901 split_const (imm
, &base
, &offset
);
903 sty
= aarch64_classify_symbol (base
, SYMBOL_CONTEXT_ADR
);
906 case SYMBOL_FORCE_TO_MEM
:
907 if (offset
!= const0_rtx
908 && targetm
.cannot_force_const_mem (mode
, imm
))
910 gcc_assert(can_create_pseudo_p ());
911 base
= aarch64_force_temporary (mode
, dest
, base
);
912 base
= aarch64_add_offset (mode
, NULL
, base
, INTVAL (offset
));
913 aarch64_emit_move (dest
, base
);
916 mem
= force_const_mem (ptr_mode
, imm
);
918 if (mode
!= ptr_mode
)
919 mem
= gen_rtx_ZERO_EXTEND (mode
, mem
);
920 emit_insn (gen_rtx_SET (VOIDmode
, dest
, mem
));
923 case SYMBOL_SMALL_TLSGD
:
924 case SYMBOL_SMALL_TLSDESC
:
925 case SYMBOL_SMALL_GOTTPREL
:
926 case SYMBOL_SMALL_GOT
:
927 case SYMBOL_TINY_GOT
:
928 if (offset
!= const0_rtx
)
930 gcc_assert(can_create_pseudo_p ());
931 base
= aarch64_force_temporary (mode
, dest
, base
);
932 base
= aarch64_add_offset (mode
, NULL
, base
, INTVAL (offset
));
933 aarch64_emit_move (dest
, base
);
938 case SYMBOL_SMALL_TPREL
:
939 case SYMBOL_SMALL_ABSOLUTE
:
940 case SYMBOL_TINY_ABSOLUTE
:
941 aarch64_load_symref_appropriately (dest
, imm
, sty
);
949 if (CONST_INT_P (imm
) && aarch64_move_imm (INTVAL (imm
), mode
))
951 emit_insn (gen_rtx_SET (VOIDmode
, dest
, imm
));
955 if (!CONST_INT_P (imm
))
957 if (GET_CODE (imm
) == HIGH
)
958 emit_insn (gen_rtx_SET (VOIDmode
, dest
, imm
));
961 rtx mem
= force_const_mem (mode
, imm
);
963 emit_insn (gen_rtx_SET (VOIDmode
, dest
, mem
));
971 /* We know we can't do this in 1 insn, and we must be able to do it
972 in two; so don't mess around looking for sequences that don't buy
974 emit_insn (gen_rtx_SET (VOIDmode
, dest
, GEN_INT (INTVAL (imm
) & 0xffff)));
975 emit_insn (gen_insv_immsi (dest
, GEN_INT (16),
976 GEN_INT ((INTVAL (imm
) >> 16) & 0xffff)));
980 /* Remaining cases are all for DImode. */
983 subtargets
= optimize
&& can_create_pseudo_p ();
989 for (i
= 0; i
< 64; i
+= 16, mask
<<= 16)
991 if ((val
& mask
) == 0)
993 else if ((val
& mask
) == mask
)
1000 for (i
= 0; i
< 64; i
+= 16, mask
<<= 16)
1002 if ((val
& mask
) != mask
)
1004 emit_insn (gen_rtx_SET (VOIDmode
, dest
, GEN_INT (val
| mask
)));
1005 emit_insn (gen_insv_immdi (dest
, GEN_INT (i
),
1006 GEN_INT ((val
>> i
) & 0xffff)));
1013 if (zero_match
== 2)
1014 goto simple_sequence
;
1016 mask
= 0x0ffff0000UL
;
1017 for (i
= 16; i
< 64; i
+= 16, mask
<<= 16)
1019 HOST_WIDE_INT comp
= mask
& ~(mask
- 1);
1021 if (aarch64_uimm12_shift (val
- (val
& mask
)))
1023 subtarget
= subtargets
? gen_reg_rtx (DImode
) : dest
;
1025 emit_insn (gen_rtx_SET (VOIDmode
, subtarget
, GEN_INT (val
& mask
)));
1026 emit_insn (gen_adddi3 (dest
, subtarget
,
1027 GEN_INT (val
- (val
& mask
))));
1030 else if (aarch64_uimm12_shift (-(val
- ((val
+ comp
) & mask
))))
1032 subtarget
= subtargets
? gen_reg_rtx (DImode
) : dest
;
1034 emit_insn (gen_rtx_SET (VOIDmode
, subtarget
,
1035 GEN_INT ((val
+ comp
) & mask
)));
1036 emit_insn (gen_adddi3 (dest
, subtarget
,
1037 GEN_INT (val
- ((val
+ comp
) & mask
))));
1040 else if (aarch64_uimm12_shift (val
- ((val
- comp
) | ~mask
)))
1042 subtarget
= subtargets
? gen_reg_rtx (DImode
) : dest
;
1044 emit_insn (gen_rtx_SET (VOIDmode
, subtarget
,
1045 GEN_INT ((val
- comp
) | ~mask
)));
1046 emit_insn (gen_adddi3 (dest
, subtarget
,
1047 GEN_INT (val
- ((val
- comp
) | ~mask
))));
1050 else if (aarch64_uimm12_shift (-(val
- (val
| ~mask
))))
1052 subtarget
= subtargets
? gen_reg_rtx (DImode
) : dest
;
1054 emit_insn (gen_rtx_SET (VOIDmode
, subtarget
,
1055 GEN_INT (val
| ~mask
)));
1056 emit_insn (gen_adddi3 (dest
, subtarget
,
1057 GEN_INT (val
- (val
| ~mask
))));
1062 /* See if we can do it by arithmetically combining two
1064 for (i
= 0; i
< AARCH64_NUM_BITMASKS
; i
++)
1069 if (aarch64_uimm12_shift (val
- aarch64_bitmasks
[i
])
1070 || aarch64_uimm12_shift (-val
+ aarch64_bitmasks
[i
]))
1072 subtarget
= subtargets
? gen_reg_rtx (DImode
) : dest
;
1073 emit_insn (gen_rtx_SET (VOIDmode
, subtarget
,
1074 GEN_INT (aarch64_bitmasks
[i
])));
1075 emit_insn (gen_adddi3 (dest
, subtarget
,
1076 GEN_INT (val
- aarch64_bitmasks
[i
])));
1080 for (j
= 0; j
< 64; j
+= 16, mask
<<= 16)
1082 if ((aarch64_bitmasks
[i
] & ~mask
) == (val
& ~mask
))
1084 emit_insn (gen_rtx_SET (VOIDmode
, dest
,
1085 GEN_INT (aarch64_bitmasks
[i
])));
1086 emit_insn (gen_insv_immdi (dest
, GEN_INT (j
),
1087 GEN_INT ((val
>> j
) & 0xffff)));
1093 /* See if we can do it by logically combining two immediates. */
1094 for (i
= 0; i
< AARCH64_NUM_BITMASKS
; i
++)
1096 if ((aarch64_bitmasks
[i
] & val
) == aarch64_bitmasks
[i
])
1100 for (j
= i
+ 1; j
< AARCH64_NUM_BITMASKS
; j
++)
1101 if (val
== (aarch64_bitmasks
[i
] | aarch64_bitmasks
[j
]))
1103 subtarget
= subtargets
? gen_reg_rtx (mode
) : dest
;
1104 emit_insn (gen_rtx_SET (VOIDmode
, subtarget
,
1105 GEN_INT (aarch64_bitmasks
[i
])));
1106 emit_insn (gen_iordi3 (dest
, subtarget
,
1107 GEN_INT (aarch64_bitmasks
[j
])));
1111 else if ((val
& aarch64_bitmasks
[i
]) == val
)
1115 for (j
= i
+ 1; j
< AARCH64_NUM_BITMASKS
; j
++)
1116 if (val
== (aarch64_bitmasks
[j
] & aarch64_bitmasks
[i
]))
1119 subtarget
= subtargets
? gen_reg_rtx (mode
) : dest
;
1120 emit_insn (gen_rtx_SET (VOIDmode
, subtarget
,
1121 GEN_INT (aarch64_bitmasks
[j
])));
1122 emit_insn (gen_anddi3 (dest
, subtarget
,
1123 GEN_INT (aarch64_bitmasks
[i
])));
1132 for (i
= 0; i
< 64; i
+= 16, mask
<<= 16)
1134 if ((val
& mask
) != 0)
1138 emit_insn (gen_rtx_SET (VOIDmode
, dest
,
1139 GEN_INT (val
& mask
)));
1143 emit_insn (gen_insv_immdi (dest
, GEN_INT (i
),
1144 GEN_INT ((val
>> i
) & 0xffff)));
1150 aarch64_function_ok_for_sibcall (tree decl
, tree exp ATTRIBUTE_UNUSED
)
1152 /* Indirect calls are not currently supported. */
1156 /* Cannot tail-call to long-calls, since these are outside of the
1157 range of a branch instruction (we could handle this if we added
1158 support for indirect tail-calls. */
1159 if (aarch64_decl_is_long_call_p (decl
))
1165 /* Implement TARGET_PASS_BY_REFERENCE. */
1168 aarch64_pass_by_reference (cumulative_args_t pcum ATTRIBUTE_UNUSED
,
1169 enum machine_mode mode
,
1171 bool named ATTRIBUTE_UNUSED
)
1174 enum machine_mode dummymode
;
1177 /* GET_MODE_SIZE (BLKmode) is useless since it is 0. */
1178 size
= (mode
== BLKmode
&& type
)
1179 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
);
1183 /* Arrays always passed by reference. */
1184 if (TREE_CODE (type
) == ARRAY_TYPE
)
1186 /* Other aggregates based on their size. */
1187 if (AGGREGATE_TYPE_P (type
))
1188 size
= int_size_in_bytes (type
);
1191 /* Variable sized arguments are always returned by reference. */
1195 /* Can this be a candidate to be passed in fp/simd register(s)? */
1196 if (aarch64_vfp_is_call_or_return_candidate (mode
, type
,
1201 /* Arguments which are variable sized or larger than 2 registers are
1202 passed by reference unless they are a homogenous floating point
1204 return size
> 2 * UNITS_PER_WORD
;
1207 /* Return TRUE if VALTYPE is padded to its least significant bits. */
1209 aarch64_return_in_msb (const_tree valtype
)
1211 enum machine_mode dummy_mode
;
1214 /* Never happens in little-endian mode. */
1215 if (!BYTES_BIG_ENDIAN
)
1218 /* Only composite types smaller than or equal to 16 bytes can
1219 be potentially returned in registers. */
1220 if (!aarch64_composite_type_p (valtype
, TYPE_MODE (valtype
))
1221 || int_size_in_bytes (valtype
) <= 0
1222 || int_size_in_bytes (valtype
) > 16)
1225 /* But not a composite that is an HFA (Homogeneous Floating-point Aggregate)
1226 or an HVA (Homogeneous Short-Vector Aggregate); such a special composite
1227 is always passed/returned in the least significant bits of fp/simd
1229 if (aarch64_vfp_is_call_or_return_candidate (TYPE_MODE (valtype
), valtype
,
1230 &dummy_mode
, &dummy_int
, NULL
))
1236 /* Implement TARGET_FUNCTION_VALUE.
1237 Define how to find the value returned by a function. */
1240 aarch64_function_value (const_tree type
, const_tree func
,
1241 bool outgoing ATTRIBUTE_UNUSED
)
1243 enum machine_mode mode
;
1246 enum machine_mode ag_mode
;
1248 mode
= TYPE_MODE (type
);
1249 if (INTEGRAL_TYPE_P (type
))
1250 mode
= promote_function_mode (type
, mode
, &unsignedp
, func
, 1);
1252 if (aarch64_return_in_msb (type
))
1254 HOST_WIDE_INT size
= int_size_in_bytes (type
);
1256 if (size
% UNITS_PER_WORD
!= 0)
1258 size
+= UNITS_PER_WORD
- size
% UNITS_PER_WORD
;
1259 mode
= mode_for_size (size
* BITS_PER_UNIT
, MODE_INT
, 0);
1263 if (aarch64_vfp_is_call_or_return_candidate (mode
, type
,
1264 &ag_mode
, &count
, NULL
))
1266 if (!aarch64_composite_type_p (type
, mode
))
1268 gcc_assert (count
== 1 && mode
== ag_mode
);
1269 return gen_rtx_REG (mode
, V0_REGNUM
);
1276 par
= gen_rtx_PARALLEL (mode
, rtvec_alloc (count
));
1277 for (i
= 0; i
< count
; i
++)
1279 rtx tmp
= gen_rtx_REG (ag_mode
, V0_REGNUM
+ i
);
1280 tmp
= gen_rtx_EXPR_LIST (VOIDmode
, tmp
,
1281 GEN_INT (i
* GET_MODE_SIZE (ag_mode
)));
1282 XVECEXP (par
, 0, i
) = tmp
;
1288 return gen_rtx_REG (mode
, R0_REGNUM
);
1291 /* Implements TARGET_FUNCTION_VALUE_REGNO_P.
1292 Return true if REGNO is the number of a hard register in which the values
1293 of called function may come back. */
1296 aarch64_function_value_regno_p (const unsigned int regno
)
1298 /* Maximum of 16 bytes can be returned in the general registers. Examples
1299 of 16-byte return values are: 128-bit integers and 16-byte small
1300 structures (excluding homogeneous floating-point aggregates). */
1301 if (regno
== R0_REGNUM
|| regno
== R1_REGNUM
)
1304 /* Up to four fp/simd registers can return a function value, e.g. a
1305 homogeneous floating-point aggregate having four members. */
1306 if (regno
>= V0_REGNUM
&& regno
< V0_REGNUM
+ HA_MAX_NUM_FLDS
)
1307 return !TARGET_GENERAL_REGS_ONLY
;
1312 /* Implement TARGET_RETURN_IN_MEMORY.
1314 If the type T of the result of a function is such that
1316 would require that arg be passed as a value in a register (or set of
1317 registers) according to the parameter passing rules, then the result
1318 is returned in the same registers as would be used for such an
1322 aarch64_return_in_memory (const_tree type
, const_tree fndecl ATTRIBUTE_UNUSED
)
1325 enum machine_mode ag_mode
;
1328 if (!AGGREGATE_TYPE_P (type
)
1329 && TREE_CODE (type
) != COMPLEX_TYPE
1330 && TREE_CODE (type
) != VECTOR_TYPE
)
1331 /* Simple scalar types always returned in registers. */
1334 if (aarch64_vfp_is_call_or_return_candidate (TYPE_MODE (type
),
1341 /* Types larger than 2 registers returned in memory. */
1342 size
= int_size_in_bytes (type
);
1343 return (size
< 0 || size
> 2 * UNITS_PER_WORD
);
1347 aarch64_vfp_is_call_candidate (cumulative_args_t pcum_v
, enum machine_mode mode
,
1348 const_tree type
, int *nregs
)
1350 CUMULATIVE_ARGS
*pcum
= get_cumulative_args (pcum_v
);
1351 return aarch64_vfp_is_call_or_return_candidate (mode
,
1353 &pcum
->aapcs_vfp_rmode
,
1358 /* Given MODE and TYPE of a function argument, return the alignment in
1359 bits. The idea is to suppress any stronger alignment requested by
1360 the user and opt for the natural alignment (specified in AAPCS64 \S 4.1).
1361 This is a helper function for local use only. */
1364 aarch64_function_arg_alignment (enum machine_mode mode
, const_tree type
)
1366 unsigned int alignment
;
1370 if (!integer_zerop (TYPE_SIZE (type
)))
1372 if (TYPE_MODE (type
) == mode
)
1373 alignment
= TYPE_ALIGN (type
);
1375 alignment
= GET_MODE_ALIGNMENT (mode
);
1381 alignment
= GET_MODE_ALIGNMENT (mode
);
1386 /* Layout a function argument according to the AAPCS64 rules. The rule
1387 numbers refer to the rule numbers in the AAPCS64. */
1390 aarch64_layout_arg (cumulative_args_t pcum_v
, enum machine_mode mode
,
1392 bool named ATTRIBUTE_UNUSED
)
1394 CUMULATIVE_ARGS
*pcum
= get_cumulative_args (pcum_v
);
1395 int ncrn
, nvrn
, nregs
;
1396 bool allocate_ncrn
, allocate_nvrn
;
1398 /* We need to do this once per argument. */
1399 if (pcum
->aapcs_arg_processed
)
1402 pcum
->aapcs_arg_processed
= true;
1404 allocate_ncrn
= (type
) ? !(FLOAT_TYPE_P (type
)) : !FLOAT_MODE_P (mode
);
1405 allocate_nvrn
= aarch64_vfp_is_call_candidate (pcum_v
,
1410 /* allocate_ncrn may be false-positive, but allocate_nvrn is quite reliable.
1411 The following code thus handles passing by SIMD/FP registers first. */
1413 nvrn
= pcum
->aapcs_nvrn
;
1415 /* C1 - C5 for floating point, homogenous floating point aggregates (HFA)
1416 and homogenous short-vector aggregates (HVA). */
1419 if (nvrn
+ nregs
<= NUM_FP_ARG_REGS
)
1421 pcum
->aapcs_nextnvrn
= nvrn
+ nregs
;
1422 if (!aarch64_composite_type_p (type
, mode
))
1424 gcc_assert (nregs
== 1);
1425 pcum
->aapcs_reg
= gen_rtx_REG (mode
, V0_REGNUM
+ nvrn
);
1431 par
= gen_rtx_PARALLEL (mode
, rtvec_alloc (nregs
));
1432 for (i
= 0; i
< nregs
; i
++)
1434 rtx tmp
= gen_rtx_REG (pcum
->aapcs_vfp_rmode
,
1435 V0_REGNUM
+ nvrn
+ i
);
1436 tmp
= gen_rtx_EXPR_LIST
1438 GEN_INT (i
* GET_MODE_SIZE (pcum
->aapcs_vfp_rmode
)));
1439 XVECEXP (par
, 0, i
) = tmp
;
1441 pcum
->aapcs_reg
= par
;
1447 /* C.3 NSRN is set to 8. */
1448 pcum
->aapcs_nextnvrn
= NUM_FP_ARG_REGS
;
1453 ncrn
= pcum
->aapcs_ncrn
;
1454 nregs
= ((type
? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
))
1455 + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
1458 /* C6 - C9. though the sign and zero extension semantics are
1459 handled elsewhere. This is the case where the argument fits
1460 entirely general registers. */
1461 if (allocate_ncrn
&& (ncrn
+ nregs
<= NUM_ARG_REGS
))
1463 unsigned int alignment
= aarch64_function_arg_alignment (mode
, type
);
1465 gcc_assert (nregs
== 0 || nregs
== 1 || nregs
== 2);
1467 /* C.8 if the argument has an alignment of 16 then the NGRN is
1468 rounded up to the next even number. */
1469 if (nregs
== 2 && alignment
== 16 * BITS_PER_UNIT
&& ncrn
% 2)
1472 gcc_assert (ncrn
+ nregs
<= NUM_ARG_REGS
);
1474 /* NREGS can be 0 when e.g. an empty structure is to be passed.
1475 A reg is still generated for it, but the caller should be smart
1476 enough not to use it. */
1477 if (nregs
== 0 || nregs
== 1 || GET_MODE_CLASS (mode
) == MODE_INT
)
1479 pcum
->aapcs_reg
= gen_rtx_REG (mode
, R0_REGNUM
+ ncrn
);
1486 par
= gen_rtx_PARALLEL (mode
, rtvec_alloc (nregs
));
1487 for (i
= 0; i
< nregs
; i
++)
1489 rtx tmp
= gen_rtx_REG (word_mode
, R0_REGNUM
+ ncrn
+ i
);
1490 tmp
= gen_rtx_EXPR_LIST (VOIDmode
, tmp
,
1491 GEN_INT (i
* UNITS_PER_WORD
));
1492 XVECEXP (par
, 0, i
) = tmp
;
1494 pcum
->aapcs_reg
= par
;
1497 pcum
->aapcs_nextncrn
= ncrn
+ nregs
;
1502 pcum
->aapcs_nextncrn
= NUM_ARG_REGS
;
1504 /* The argument is passed on stack; record the needed number of words for
1505 this argument (we can re-use NREGS) and align the total size if
1508 pcum
->aapcs_stack_words
= nregs
;
1509 if (aarch64_function_arg_alignment (mode
, type
) == 16 * BITS_PER_UNIT
)
1510 pcum
->aapcs_stack_size
= AARCH64_ROUND_UP (pcum
->aapcs_stack_size
,
1511 16 / UNITS_PER_WORD
) + 1;
1515 /* Implement TARGET_FUNCTION_ARG. */
1518 aarch64_function_arg (cumulative_args_t pcum_v
, enum machine_mode mode
,
1519 const_tree type
, bool named
)
1521 CUMULATIVE_ARGS
*pcum
= get_cumulative_args (pcum_v
);
1522 gcc_assert (pcum
->pcs_variant
== ARM_PCS_AAPCS64
);
1524 if (mode
== VOIDmode
)
1527 aarch64_layout_arg (pcum_v
, mode
, type
, named
);
1528 return pcum
->aapcs_reg
;
1532 aarch64_init_cumulative_args (CUMULATIVE_ARGS
*pcum
,
1533 const_tree fntype ATTRIBUTE_UNUSED
,
1534 rtx libname ATTRIBUTE_UNUSED
,
1535 const_tree fndecl ATTRIBUTE_UNUSED
,
1536 unsigned n_named ATTRIBUTE_UNUSED
)
1538 pcum
->aapcs_ncrn
= 0;
1539 pcum
->aapcs_nvrn
= 0;
1540 pcum
->aapcs_nextncrn
= 0;
1541 pcum
->aapcs_nextnvrn
= 0;
1542 pcum
->pcs_variant
= ARM_PCS_AAPCS64
;
1543 pcum
->aapcs_reg
= NULL_RTX
;
1544 pcum
->aapcs_arg_processed
= false;
1545 pcum
->aapcs_stack_words
= 0;
1546 pcum
->aapcs_stack_size
= 0;
1552 aarch64_function_arg_advance (cumulative_args_t pcum_v
,
1553 enum machine_mode mode
,
1557 CUMULATIVE_ARGS
*pcum
= get_cumulative_args (pcum_v
);
1558 if (pcum
->pcs_variant
== ARM_PCS_AAPCS64
)
1560 aarch64_layout_arg (pcum_v
, mode
, type
, named
);
1561 gcc_assert ((pcum
->aapcs_reg
!= NULL_RTX
)
1562 != (pcum
->aapcs_stack_words
!= 0));
1563 pcum
->aapcs_arg_processed
= false;
1564 pcum
->aapcs_ncrn
= pcum
->aapcs_nextncrn
;
1565 pcum
->aapcs_nvrn
= pcum
->aapcs_nextnvrn
;
1566 pcum
->aapcs_stack_size
+= pcum
->aapcs_stack_words
;
1567 pcum
->aapcs_stack_words
= 0;
1568 pcum
->aapcs_reg
= NULL_RTX
;
1573 aarch64_function_arg_regno_p (unsigned regno
)
1575 return ((GP_REGNUM_P (regno
) && regno
< R0_REGNUM
+ NUM_ARG_REGS
)
1576 || (FP_REGNUM_P (regno
) && regno
< V0_REGNUM
+ NUM_FP_ARG_REGS
));
1579 /* Implement FUNCTION_ARG_BOUNDARY. Every parameter gets at least
1580 PARM_BOUNDARY bits of alignment, but will be given anything up
1581 to STACK_BOUNDARY bits if the type requires it. This makes sure
1582 that both before and after the layout of each argument, the Next
1583 Stacked Argument Address (NSAA) will have a minimum alignment of
1587 aarch64_function_arg_boundary (enum machine_mode mode
, const_tree type
)
1589 unsigned int alignment
= aarch64_function_arg_alignment (mode
, type
);
1591 if (alignment
< PARM_BOUNDARY
)
1592 alignment
= PARM_BOUNDARY
;
1593 if (alignment
> STACK_BOUNDARY
)
1594 alignment
= STACK_BOUNDARY
;
1598 /* For use by FUNCTION_ARG_PADDING (MODE, TYPE).
1600 Return true if an argument passed on the stack should be padded upwards,
1601 i.e. if the least-significant byte of the stack slot has useful data.
1603 Small aggregate types are placed in the lowest memory address.
1605 The related parameter passing rules are B.4, C.3, C.5 and C.14. */
1608 aarch64_pad_arg_upward (enum machine_mode mode
, const_tree type
)
1610 /* On little-endian targets, the least significant byte of every stack
1611 argument is passed at the lowest byte address of the stack slot. */
1612 if (!BYTES_BIG_ENDIAN
)
1615 /* Otherwise, integral, floating-point and pointer types are padded downward:
1616 the least significant byte of a stack argument is passed at the highest
1617 byte address of the stack slot. */
1619 ? (INTEGRAL_TYPE_P (type
) || SCALAR_FLOAT_TYPE_P (type
)
1620 || POINTER_TYPE_P (type
))
1621 : (SCALAR_INT_MODE_P (mode
) || SCALAR_FLOAT_MODE_P (mode
)))
1624 /* Everything else padded upward, i.e. data in first byte of stack slot. */
1628 /* Similarly, for use by BLOCK_REG_PADDING (MODE, TYPE, FIRST).
1630 It specifies padding for the last (may also be the only)
1631 element of a block move between registers and memory. If
1632 assuming the block is in the memory, padding upward means that
1633 the last element is padded after its highest significant byte,
1634 while in downward padding, the last element is padded at the
1635 its least significant byte side.
1637 Small aggregates and small complex types are always padded
1640 We don't need to worry about homogeneous floating-point or
1641 short-vector aggregates; their move is not affected by the
1642 padding direction determined here. Regardless of endianness,
1643 each element of such an aggregate is put in the least
1644 significant bits of a fp/simd register.
1646 Return !BYTES_BIG_ENDIAN if the least significant byte of the
1647 register has useful data, and return the opposite if the most
1648 significant byte does. */
1651 aarch64_pad_reg_upward (enum machine_mode mode
, const_tree type
,
1652 bool first ATTRIBUTE_UNUSED
)
1655 /* Small composite types are always padded upward. */
1656 if (BYTES_BIG_ENDIAN
&& aarch64_composite_type_p (type
, mode
))
1658 HOST_WIDE_INT size
= (type
? int_size_in_bytes (type
)
1659 : GET_MODE_SIZE (mode
));
1660 if (size
< 2 * UNITS_PER_WORD
)
1664 /* Otherwise, use the default padding. */
1665 return !BYTES_BIG_ENDIAN
;
1668 static enum machine_mode
1669 aarch64_libgcc_cmp_return_mode (void)
1675 aarch64_frame_pointer_required (void)
1677 /* If the function contains dynamic stack allocations, we need to
1678 use the frame pointer to access the static parts of the frame. */
1679 if (cfun
->calls_alloca
)
1682 /* We may have turned flag_omit_frame_pointer on in order to have this
1683 function called; if we did, we also set the 'faked_omit_frame_pointer' flag
1684 and we'll check it here.
1685 If we really did set flag_omit_frame_pointer normally, then we return false
1686 (no frame pointer required) in all cases. */
1688 if (flag_omit_frame_pointer
&& !faked_omit_frame_pointer
)
1690 else if (flag_omit_leaf_frame_pointer
)
1691 return !crtl
->is_leaf
;
1695 /* Mark the registers that need to be saved by the callee and calculate
1696 the size of the callee-saved registers area and frame record (both FP
1697 and LR may be omitted). */
1699 aarch64_layout_frame (void)
1701 HOST_WIDE_INT offset
= 0;
1704 if (reload_completed
&& cfun
->machine
->frame
.laid_out
)
1707 cfun
->machine
->frame
.fp_lr_offset
= 0;
1709 /* First mark all the registers that really need to be saved... */
1710 for (regno
= R0_REGNUM
; regno
<= R30_REGNUM
; regno
++)
1711 cfun
->machine
->frame
.reg_offset
[regno
] = -1;
1713 for (regno
= V0_REGNUM
; regno
<= V31_REGNUM
; regno
++)
1714 cfun
->machine
->frame
.reg_offset
[regno
] = -1;
1716 /* ... that includes the eh data registers (if needed)... */
1717 if (crtl
->calls_eh_return
)
1718 for (regno
= 0; EH_RETURN_DATA_REGNO (regno
) != INVALID_REGNUM
; regno
++)
1719 cfun
->machine
->frame
.reg_offset
[EH_RETURN_DATA_REGNO (regno
)] = 0;
1721 /* ... and any callee saved register that dataflow says is live. */
1722 for (regno
= R0_REGNUM
; regno
<= R30_REGNUM
; regno
++)
1723 if (df_regs_ever_live_p (regno
)
1724 && !call_used_regs
[regno
])
1725 cfun
->machine
->frame
.reg_offset
[regno
] = 0;
1727 for (regno
= V0_REGNUM
; regno
<= V31_REGNUM
; regno
++)
1728 if (df_regs_ever_live_p (regno
)
1729 && !call_used_regs
[regno
])
1730 cfun
->machine
->frame
.reg_offset
[regno
] = 0;
1732 if (frame_pointer_needed
)
1734 cfun
->machine
->frame
.reg_offset
[R30_REGNUM
] = 0;
1735 cfun
->machine
->frame
.reg_offset
[R29_REGNUM
] = 0;
1736 cfun
->machine
->frame
.hardfp_offset
= 2 * UNITS_PER_WORD
;
1739 /* Now assign stack slots for them. */
1740 for (regno
= R0_REGNUM
; regno
<= R28_REGNUM
; regno
++)
1741 if (cfun
->machine
->frame
.reg_offset
[regno
] != -1)
1743 cfun
->machine
->frame
.reg_offset
[regno
] = offset
;
1744 offset
+= UNITS_PER_WORD
;
1747 for (regno
= V0_REGNUM
; regno
<= V31_REGNUM
; regno
++)
1748 if (cfun
->machine
->frame
.reg_offset
[regno
] != -1)
1750 cfun
->machine
->frame
.reg_offset
[regno
] = offset
;
1751 offset
+= UNITS_PER_WORD
;
1754 if (frame_pointer_needed
)
1756 cfun
->machine
->frame
.reg_offset
[R29_REGNUM
] = offset
;
1757 offset
+= UNITS_PER_WORD
;
1758 cfun
->machine
->frame
.fp_lr_offset
= UNITS_PER_WORD
;
1761 if (cfun
->machine
->frame
.reg_offset
[R30_REGNUM
] != -1)
1763 cfun
->machine
->frame
.reg_offset
[R30_REGNUM
] = offset
;
1764 offset
+= UNITS_PER_WORD
;
1765 cfun
->machine
->frame
.fp_lr_offset
+= UNITS_PER_WORD
;
1768 cfun
->machine
->frame
.padding0
=
1769 (AARCH64_ROUND_UP (offset
, STACK_BOUNDARY
/ BITS_PER_UNIT
) - offset
);
1770 offset
= AARCH64_ROUND_UP (offset
, STACK_BOUNDARY
/ BITS_PER_UNIT
);
1772 cfun
->machine
->frame
.saved_regs_size
= offset
;
1773 cfun
->machine
->frame
.laid_out
= true;
1776 /* Make the last instruction frame-related and note that it performs
1777 the operation described by FRAME_PATTERN. */
1780 aarch64_set_frame_expr (rtx frame_pattern
)
1784 insn
= get_last_insn ();
1785 RTX_FRAME_RELATED_P (insn
) = 1;
1786 RTX_FRAME_RELATED_P (frame_pattern
) = 1;
1787 REG_NOTES (insn
) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR
,
1793 aarch64_register_saved_on_entry (int regno
)
1795 return cfun
->machine
->frame
.reg_offset
[regno
] != -1;
1800 aarch64_save_or_restore_fprs (int start_offset
, int increment
,
1801 bool restore
, rtx base_rtx
)
1807 rtx (*gen_mem_ref
)(enum machine_mode
, rtx
) = (frame_pointer_needed
)? gen_frame_mem
: gen_rtx_MEM
;
1810 for (regno
= V0_REGNUM
; regno
<= V31_REGNUM
; regno
++)
1812 if (aarch64_register_saved_on_entry (regno
))
1815 mem
= gen_mem_ref (DFmode
,
1816 plus_constant (Pmode
,
1820 for (regno2
= regno
+ 1;
1821 regno2
<= V31_REGNUM
1822 && !aarch64_register_saved_on_entry (regno2
);
1827 if (regno2
<= V31_REGNUM
&&
1828 aarch64_register_saved_on_entry (regno2
))
1831 /* Next highest register to be saved. */
1832 mem2
= gen_mem_ref (DFmode
,
1836 start_offset
+ increment
));
1837 if (restore
== false)
1840 ( gen_store_pairdf (mem
, gen_rtx_REG (DFmode
, regno
),
1841 mem2
, gen_rtx_REG (DFmode
, regno2
)));
1847 ( gen_load_pairdf (gen_rtx_REG (DFmode
, regno
), mem
,
1848 gen_rtx_REG (DFmode
, regno2
), mem2
));
1850 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (DFmode
, regno
));
1851 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (DFmode
, regno2
));
1854 /* The first part of a frame-related parallel insn
1855 is always assumed to be relevant to the frame
1856 calculations; subsequent parts, are only
1857 frame-related if explicitly marked. */
1858 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn
), 0,
1861 start_offset
+= increment
* 2;
1865 if (restore
== false)
1866 insn
= emit_move_insn (mem
, gen_rtx_REG (DFmode
, regno
));
1869 insn
= emit_move_insn (gen_rtx_REG (DFmode
, regno
), mem
);
1870 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (DImode
, regno
));
1872 start_offset
+= increment
;
1874 RTX_FRAME_RELATED_P (insn
) = 1;
1881 /* offset from the stack pointer of where the saves and
1882 restore's have to happen. */
1884 aarch64_save_or_restore_callee_save_registers (HOST_WIDE_INT offset
,
1888 rtx base_rtx
= stack_pointer_rtx
;
1889 HOST_WIDE_INT start_offset
= offset
;
1890 HOST_WIDE_INT increment
= UNITS_PER_WORD
;
1891 rtx (*gen_mem_ref
)(enum machine_mode
, rtx
) = (frame_pointer_needed
)? gen_frame_mem
: gen_rtx_MEM
;
1892 unsigned limit
= (frame_pointer_needed
)? R28_REGNUM
: R30_REGNUM
;
1896 for (regno
= R0_REGNUM
; regno
<= limit
; regno
++)
1898 if (aarch64_register_saved_on_entry (regno
))
1901 mem
= gen_mem_ref (Pmode
,
1902 plus_constant (Pmode
,
1906 for (regno2
= regno
+ 1;
1908 && !aarch64_register_saved_on_entry (regno2
);
1913 if (regno2
<= limit
&&
1914 aarch64_register_saved_on_entry (regno2
))
1917 /* Next highest register to be saved. */
1918 mem2
= gen_mem_ref (Pmode
,
1922 start_offset
+ increment
));
1923 if (restore
== false)
1926 ( gen_store_pairdi (mem
, gen_rtx_REG (DImode
, regno
),
1927 mem2
, gen_rtx_REG (DImode
, regno2
)));
1933 ( gen_load_pairdi (gen_rtx_REG (DImode
, regno
), mem
,
1934 gen_rtx_REG (DImode
, regno2
), mem2
));
1936 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (DImode
, regno
));
1937 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (DImode
, regno2
));
1940 /* The first part of a frame-related parallel insn
1941 is always assumed to be relevant to the frame
1942 calculations; subsequent parts, are only
1943 frame-related if explicitly marked. */
1944 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn
), 0,
1947 start_offset
+= increment
* 2;
1951 if (restore
== false)
1952 insn
= emit_move_insn (mem
, gen_rtx_REG (DImode
, regno
));
1955 insn
= emit_move_insn (gen_rtx_REG (DImode
, regno
), mem
);
1956 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (DImode
, regno
));
1958 start_offset
+= increment
;
1960 RTX_FRAME_RELATED_P (insn
) = 1;
1964 aarch64_save_or_restore_fprs (start_offset
, increment
, restore
, base_rtx
);
1968 /* AArch64 stack frames generated by this compiler look like:
1970 +-------------------------------+
1972 | incoming stack arguments |
1974 +-------------------------------+ <-- arg_pointer_rtx
1976 | callee-allocated save area |
1977 | for register varargs |
1979 +-------------------------------+
1983 +-------------------------------+ <-- frame_pointer_rtx
1985 | callee-saved registers |
1987 +-------------------------------+
1989 +-------------------------------+
1991 P +-------------------------------+ <-- hard_frame_pointer_rtx
1992 | dynamic allocation |
1993 +-------------------------------+
1995 | outgoing stack arguments |
1997 +-------------------------------+ <-- stack_pointer_rtx
1999 Dynamic stack allocations such as alloca insert data at point P.
2000 They decrease stack_pointer_rtx but leave frame_pointer_rtx and
2001 hard_frame_pointer_rtx unchanged. */
2003 /* Generate the prologue instructions for entry into a function.
2004 Establish the stack frame by decreasing the stack pointer with a
2005 properly calculated size and, if necessary, create a frame record
2006 filled with the values of LR and previous frame pointer. The
2007 current FP is also set up is it is in use. */
2010 aarch64_expand_prologue (void)
2012 /* sub sp, sp, #<frame_size>
2013 stp {fp, lr}, [sp, #<frame_size> - 16]
2014 add fp, sp, #<frame_size> - hardfp_offset
2015 stp {cs_reg}, [fp, #-16] etc.
2017 sub sp, sp, <final_adjustment_if_any>
2019 HOST_WIDE_INT original_frame_size
; /* local variables + vararg save */
2020 HOST_WIDE_INT frame_size
, offset
;
2021 HOST_WIDE_INT fp_offset
; /* FP offset from SP */
2024 aarch64_layout_frame ();
2025 original_frame_size
= get_frame_size () + cfun
->machine
->saved_varargs_size
;
2026 gcc_assert ((!cfun
->machine
->saved_varargs_size
|| cfun
->stdarg
)
2027 && (cfun
->stdarg
|| !cfun
->machine
->saved_varargs_size
));
2028 frame_size
= (original_frame_size
+ cfun
->machine
->frame
.saved_regs_size
2029 + crtl
->outgoing_args_size
);
2030 offset
= frame_size
= AARCH64_ROUND_UP (frame_size
,
2031 STACK_BOUNDARY
/ BITS_PER_UNIT
);
2033 if (flag_stack_usage_info
)
2034 current_function_static_stack_size
= frame_size
;
2037 - original_frame_size
2038 - cfun
->machine
->frame
.saved_regs_size
);
2040 /* Store pairs and load pairs have a range only -512 to 504. */
2043 /* When the frame has a large size, an initial decrease is done on
2044 the stack pointer to jump over the callee-allocated save area for
2045 register varargs, the local variable area and/or the callee-saved
2046 register area. This will allow the pre-index write-back
2047 store pair instructions to be used for setting up the stack frame
2049 offset
= original_frame_size
+ cfun
->machine
->frame
.saved_regs_size
;
2051 offset
= cfun
->machine
->frame
.saved_regs_size
;
2053 frame_size
-= (offset
+ crtl
->outgoing_args_size
);
2056 if (frame_size
>= 0x1000000)
2058 rtx op0
= gen_rtx_REG (Pmode
, IP0_REGNUM
);
2059 emit_move_insn (op0
, GEN_INT (-frame_size
));
2060 emit_insn (gen_add2_insn (stack_pointer_rtx
, op0
));
2061 aarch64_set_frame_expr (gen_rtx_SET
2062 (Pmode
, stack_pointer_rtx
,
2063 gen_rtx_PLUS (Pmode
,
2065 GEN_INT (-frame_size
))));
2067 else if (frame_size
> 0)
2069 if ((frame_size
& 0xfff) != frame_size
)
2071 insn
= emit_insn (gen_add2_insn
2073 GEN_INT (-(frame_size
2074 & ~(HOST_WIDE_INT
)0xfff))));
2075 RTX_FRAME_RELATED_P (insn
) = 1;
2077 if ((frame_size
& 0xfff) != 0)
2079 insn
= emit_insn (gen_add2_insn
2081 GEN_INT (-(frame_size
2082 & (HOST_WIDE_INT
)0xfff))));
2083 RTX_FRAME_RELATED_P (insn
) = 1;
2092 /* Save the frame pointer and lr if the frame pointer is needed
2093 first. Make the frame pointer point to the location of the
2094 old frame pointer on the stack. */
2095 if (frame_pointer_needed
)
2101 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
,
2102 GEN_INT (-offset
)));
2103 RTX_FRAME_RELATED_P (insn
) = 1;
2104 aarch64_set_frame_expr (gen_rtx_SET
2105 (Pmode
, stack_pointer_rtx
,
2106 gen_rtx_MINUS (Pmode
,
2108 GEN_INT (offset
))));
2109 mem_fp
= gen_frame_mem (DImode
,
2110 plus_constant (Pmode
,
2113 mem_lr
= gen_frame_mem (DImode
,
2114 plus_constant (Pmode
,
2118 insn
= emit_insn (gen_store_pairdi (mem_fp
,
2119 hard_frame_pointer_rtx
,
2121 gen_rtx_REG (DImode
,
2126 insn
= emit_insn (gen_storewb_pairdi_di
2127 (stack_pointer_rtx
, stack_pointer_rtx
,
2128 hard_frame_pointer_rtx
,
2129 gen_rtx_REG (DImode
, LR_REGNUM
),
2131 GEN_INT (GET_MODE_SIZE (DImode
) - offset
)));
2132 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn
), 0, 2)) = 1;
2135 /* The first part of a frame-related parallel insn is always
2136 assumed to be relevant to the frame calculations;
2137 subsequent parts, are only frame-related if explicitly
2139 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn
), 0, 1)) = 1;
2140 RTX_FRAME_RELATED_P (insn
) = 1;
2142 /* Set up frame pointer to point to the location of the
2143 previous frame pointer on the stack. */
2144 insn
= emit_insn (gen_add3_insn (hard_frame_pointer_rtx
,
2146 GEN_INT (fp_offset
)));
2147 aarch64_set_frame_expr (gen_rtx_SET
2148 (Pmode
, hard_frame_pointer_rtx
,
2149 gen_rtx_PLUS (Pmode
,
2151 GEN_INT (fp_offset
))));
2152 RTX_FRAME_RELATED_P (insn
) = 1;
2153 insn
= emit_insn (gen_stack_tie (stack_pointer_rtx
,
2154 hard_frame_pointer_rtx
));
2158 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
,
2159 GEN_INT (-offset
)));
2160 RTX_FRAME_RELATED_P (insn
) = 1;
2163 aarch64_save_or_restore_callee_save_registers
2164 (fp_offset
+ cfun
->machine
->frame
.hardfp_offset
, 0);
2167 /* when offset >= 512,
2168 sub sp, sp, #<outgoing_args_size> */
2169 if (frame_size
> -1)
2171 if (crtl
->outgoing_args_size
> 0)
2173 insn
= emit_insn (gen_add2_insn
2175 GEN_INT (- crtl
->outgoing_args_size
)));
2176 RTX_FRAME_RELATED_P (insn
) = 1;
2181 /* Generate the epilogue instructions for returning from a function. */
2183 aarch64_expand_epilogue (bool for_sibcall
)
2185 HOST_WIDE_INT original_frame_size
, frame_size
, offset
;
2186 HOST_WIDE_INT fp_offset
;
2190 aarch64_layout_frame ();
2191 original_frame_size
= get_frame_size () + cfun
->machine
->saved_varargs_size
;
2192 frame_size
= (original_frame_size
+ cfun
->machine
->frame
.saved_regs_size
2193 + crtl
->outgoing_args_size
);
2194 offset
= frame_size
= AARCH64_ROUND_UP (frame_size
,
2195 STACK_BOUNDARY
/ BITS_PER_UNIT
);
2198 - original_frame_size
2199 - cfun
->machine
->frame
.saved_regs_size
);
2201 cfa_reg
= frame_pointer_needed
? hard_frame_pointer_rtx
: stack_pointer_rtx
;
2203 /* Store pairs and load pairs have a range only -512 to 504. */
2206 offset
= original_frame_size
+ cfun
->machine
->frame
.saved_regs_size
;
2208 offset
= cfun
->machine
->frame
.saved_regs_size
;
2210 frame_size
-= (offset
+ crtl
->outgoing_args_size
);
2212 if (!frame_pointer_needed
&& crtl
->outgoing_args_size
> 0)
2214 insn
= emit_insn (gen_add2_insn
2216 GEN_INT (crtl
->outgoing_args_size
)));
2217 RTX_FRAME_RELATED_P (insn
) = 1;
2223 /* If there were outgoing arguments or we've done dynamic stack
2224 allocation, then restore the stack pointer from the frame
2225 pointer. This is at most one insn and more efficient than using
2226 GCC's internal mechanism. */
2227 if (frame_pointer_needed
2228 && (crtl
->outgoing_args_size
|| cfun
->calls_alloca
))
2230 insn
= emit_insn (gen_add3_insn (stack_pointer_rtx
,
2231 hard_frame_pointer_rtx
,
2232 GEN_INT (- fp_offset
)));
2233 RTX_FRAME_RELATED_P (insn
) = 1;
2234 /* As SP is set to (FP - fp_offset), according to the rules in
2235 dwarf2cfi.c:dwarf2out_frame_debug_expr, CFA should be calculated
2236 from the value of SP from now on. */
2237 cfa_reg
= stack_pointer_rtx
;
2240 aarch64_save_or_restore_callee_save_registers
2241 (fp_offset
+ cfun
->machine
->frame
.hardfp_offset
, 1);
2243 /* Restore the frame pointer and lr if the frame pointer is needed. */
2246 if (frame_pointer_needed
)
2252 mem_fp
= gen_frame_mem (DImode
,
2253 plus_constant (Pmode
,
2256 mem_lr
= gen_frame_mem (DImode
,
2257 plus_constant (Pmode
,
2261 insn
= emit_insn (gen_load_pairdi (hard_frame_pointer_rtx
,
2263 gen_rtx_REG (DImode
,
2269 insn
= emit_insn (gen_loadwb_pairdi_di
2272 hard_frame_pointer_rtx
,
2273 gen_rtx_REG (DImode
, LR_REGNUM
),
2275 GEN_INT (GET_MODE_SIZE (DImode
) + offset
)));
2276 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn
), 0, 2)) = 1;
2277 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
2278 (gen_rtx_SET (Pmode
, stack_pointer_rtx
,
2279 plus_constant (Pmode
, cfa_reg
,
2283 /* The first part of a frame-related parallel insn
2284 is always assumed to be relevant to the frame
2285 calculations; subsequent parts, are only
2286 frame-related if explicitly marked. */
2287 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn
), 0, 1)) = 1;
2288 RTX_FRAME_RELATED_P (insn
) = 1;
2289 add_reg_note (insn
, REG_CFA_RESTORE
, hard_frame_pointer_rtx
);
2290 add_reg_note (insn
, REG_CFA_RESTORE
,
2291 gen_rtx_REG (DImode
, LR_REGNUM
));
2295 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
,
2297 RTX_FRAME_RELATED_P (insn
) = 1;
2302 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
,
2304 RTX_FRAME_RELATED_P (insn
) = 1;
2308 /* Stack adjustment for exception handler. */
2309 if (crtl
->calls_eh_return
)
2311 /* We need to unwind the stack by the offset computed by
2312 EH_RETURN_STACKADJ_RTX. However, at this point the CFA is
2313 based on SP. Ideally we would update the SP and define the
2314 CFA along the lines of:
2316 SP = SP + EH_RETURN_STACKADJ_RTX
2317 (regnote CFA = SP - EH_RETURN_STACKADJ_RTX)
2319 However the dwarf emitter only understands a constant
2322 The solution chosen here is to use the otherwise unused IP0
2323 as a temporary register to hold the current SP value. The
2324 CFA is described using IP0 then SP is modified. */
2326 rtx ip0
= gen_rtx_REG (DImode
, IP0_REGNUM
);
2328 insn
= emit_move_insn (ip0
, stack_pointer_rtx
);
2329 add_reg_note (insn
, REG_CFA_DEF_CFA
, ip0
);
2330 RTX_FRAME_RELATED_P (insn
) = 1;
2332 emit_insn (gen_add2_insn (stack_pointer_rtx
, EH_RETURN_STACKADJ_RTX
));
2334 /* Ensure the assignment to IP0 does not get optimized away. */
2338 if (frame_size
> -1)
2340 if (frame_size
>= 0x1000000)
2342 rtx op0
= gen_rtx_REG (Pmode
, IP0_REGNUM
);
2343 emit_move_insn (op0
, GEN_INT (frame_size
));
2344 emit_insn (gen_add2_insn (stack_pointer_rtx
, op0
));
2345 aarch64_set_frame_expr (gen_rtx_SET
2346 (Pmode
, stack_pointer_rtx
,
2347 gen_rtx_PLUS (Pmode
,
2349 GEN_INT (frame_size
))));
2351 else if (frame_size
> 0)
2353 if ((frame_size
& 0xfff) != 0)
2355 insn
= emit_insn (gen_add2_insn
2357 GEN_INT ((frame_size
2358 & (HOST_WIDE_INT
) 0xfff))));
2359 RTX_FRAME_RELATED_P (insn
) = 1;
2361 if ((frame_size
& 0xfff) != frame_size
)
2363 insn
= emit_insn (gen_add2_insn
2365 GEN_INT ((frame_size
2366 & ~ (HOST_WIDE_INT
) 0xfff))));
2367 RTX_FRAME_RELATED_P (insn
) = 1;
2371 aarch64_set_frame_expr (gen_rtx_SET (Pmode
, stack_pointer_rtx
,
2372 gen_rtx_PLUS (Pmode
,
2374 GEN_INT (offset
))));
2377 emit_use (gen_rtx_REG (DImode
, LR_REGNUM
));
2379 emit_jump_insn (ret_rtx
);
2382 /* Return the place to copy the exception unwinding return address to.
2383 This will probably be a stack slot, but could (in theory be the
2384 return register). */
2386 aarch64_final_eh_return_addr (void)
2388 HOST_WIDE_INT original_frame_size
, frame_size
, offset
, fp_offset
;
2389 aarch64_layout_frame ();
2390 original_frame_size
= get_frame_size () + cfun
->machine
->saved_varargs_size
;
2391 frame_size
= (original_frame_size
+ cfun
->machine
->frame
.saved_regs_size
2392 + crtl
->outgoing_args_size
);
2393 offset
= frame_size
= AARCH64_ROUND_UP (frame_size
,
2394 STACK_BOUNDARY
/ BITS_PER_UNIT
);
2396 - original_frame_size
2397 - cfun
->machine
->frame
.saved_regs_size
;
2399 if (cfun
->machine
->frame
.reg_offset
[LR_REGNUM
] < 0)
2400 return gen_rtx_REG (DImode
, LR_REGNUM
);
2402 /* DSE and CSELIB do not detect an alias between sp+k1 and fp+k2. This can
2403 result in a store to save LR introduced by builtin_eh_return () being
2404 incorrectly deleted because the alias is not detected.
2405 So in the calculation of the address to copy the exception unwinding
2406 return address to, we note 2 cases.
2407 If FP is needed and the fp_offset is 0, it means that SP = FP and hence
2408 we return a SP-relative location since all the addresses are SP-relative
2409 in this case. This prevents the store from being optimized away.
2410 If the fp_offset is not 0, then the addresses will be FP-relative and
2411 therefore we return a FP-relative location. */
2413 if (frame_pointer_needed
)
2416 return gen_frame_mem (DImode
,
2417 plus_constant (Pmode
, hard_frame_pointer_rtx
, UNITS_PER_WORD
));
2419 return gen_frame_mem (DImode
,
2420 plus_constant (Pmode
, stack_pointer_rtx
, UNITS_PER_WORD
));
2423 /* If FP is not needed, we calculate the location of LR, which would be
2424 at the top of the saved registers block. */
2426 return gen_frame_mem (DImode
,
2427 plus_constant (Pmode
,
2430 + cfun
->machine
->frame
.saved_regs_size
2431 - 2 * UNITS_PER_WORD
));
2434 /* Output code to build up a constant in a register. */
2436 aarch64_build_constant (int regnum
, HOST_WIDE_INT val
)
2438 if (aarch64_bitmask_imm (val
, DImode
))
2439 emit_move_insn (gen_rtx_REG (Pmode
, regnum
), GEN_INT (val
));
2445 HOST_WIDE_INT valp
= val
>> 16;
2449 for (i
= 16; i
< 64; i
+= 16)
2451 valm
= (valp
& 0xffff);
2462 /* zcount contains the number of additional MOVK instructions
2463 required if the constant is built up with an initial MOVZ instruction,
2464 while ncount is the number of MOVK instructions required if starting
2465 with a MOVN instruction. Choose the sequence that yields the fewest
2466 number of instructions, preferring MOVZ instructions when they are both
2468 if (ncount
< zcount
)
2470 emit_move_insn (gen_rtx_REG (Pmode
, regnum
),
2471 GEN_INT ((~val
) & 0xffff));
2476 emit_move_insn (gen_rtx_REG (Pmode
, regnum
),
2477 GEN_INT (val
& 0xffff));
2483 for (i
= 16; i
< 64; i
+= 16)
2485 if ((val
& 0xffff) != tval
)
2486 emit_insn (gen_insv_immdi (gen_rtx_REG (Pmode
, regnum
),
2487 GEN_INT (i
), GEN_INT (val
& 0xffff)));
2494 aarch64_add_constant (int regnum
, int scratchreg
, HOST_WIDE_INT delta
)
2496 HOST_WIDE_INT mdelta
= delta
;
2497 rtx this_rtx
= gen_rtx_REG (Pmode
, regnum
);
2498 rtx scratch_rtx
= gen_rtx_REG (Pmode
, scratchreg
);
2503 if (mdelta
>= 4096 * 4096)
2505 aarch64_build_constant (scratchreg
, delta
);
2506 emit_insn (gen_add3_insn (this_rtx
, this_rtx
, scratch_rtx
));
2508 else if (mdelta
> 0)
2512 emit_insn (gen_rtx_SET (Pmode
, scratch_rtx
, GEN_INT (mdelta
/ 4096)));
2513 rtx shift
= gen_rtx_ASHIFT (Pmode
, scratch_rtx
, GEN_INT (12));
2515 emit_insn (gen_rtx_SET (Pmode
, this_rtx
,
2516 gen_rtx_MINUS (Pmode
, this_rtx
, shift
)));
2518 emit_insn (gen_rtx_SET (Pmode
, this_rtx
,
2519 gen_rtx_PLUS (Pmode
, this_rtx
, shift
)));
2521 if (mdelta
% 4096 != 0)
2523 scratch_rtx
= GEN_INT ((delta
< 0 ? -1 : 1) * (mdelta
% 4096));
2524 emit_insn (gen_rtx_SET (Pmode
, this_rtx
,
2525 gen_rtx_PLUS (Pmode
, this_rtx
, scratch_rtx
)));
2530 /* Output code to add DELTA to the first argument, and then jump
2531 to FUNCTION. Used for C++ multiple inheritance. */
2533 aarch64_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
2534 HOST_WIDE_INT delta
,
2535 HOST_WIDE_INT vcall_offset
,
2538 /* The this pointer is always in x0. Note that this differs from
2539 Arm where the this pointer maybe bumped to r1 if r0 is required
2540 to return a pointer to an aggregate. On AArch64 a result value
2541 pointer will be in x8. */
2542 int this_regno
= R0_REGNUM
;
2543 rtx this_rtx
, temp0
, temp1
, addr
, insn
, funexp
;
2545 reload_completed
= 1;
2546 emit_note (NOTE_INSN_PROLOGUE_END
);
2548 if (vcall_offset
== 0)
2549 aarch64_add_constant (this_regno
, IP1_REGNUM
, delta
);
2552 gcc_assert ((vcall_offset
& (POINTER_BYTES
- 1)) == 0);
2554 this_rtx
= gen_rtx_REG (Pmode
, this_regno
);
2555 temp0
= gen_rtx_REG (Pmode
, IP0_REGNUM
);
2556 temp1
= gen_rtx_REG (Pmode
, IP1_REGNUM
);
2561 if (delta
>= -256 && delta
< 256)
2562 addr
= gen_rtx_PRE_MODIFY (Pmode
, this_rtx
,
2563 plus_constant (Pmode
, this_rtx
, delta
));
2565 aarch64_add_constant (this_regno
, IP1_REGNUM
, delta
);
2568 if (Pmode
== ptr_mode
)
2569 aarch64_emit_move (temp0
, gen_rtx_MEM (ptr_mode
, addr
));
2571 aarch64_emit_move (temp0
,
2572 gen_rtx_ZERO_EXTEND (Pmode
,
2573 gen_rtx_MEM (ptr_mode
, addr
)));
2575 if (vcall_offset
>= -256 && vcall_offset
< 4096 * POINTER_BYTES
)
2576 addr
= plus_constant (Pmode
, temp0
, vcall_offset
);
2579 aarch64_build_constant (IP1_REGNUM
, vcall_offset
);
2580 addr
= gen_rtx_PLUS (Pmode
, temp0
, temp1
);
2583 if (Pmode
== ptr_mode
)
2584 aarch64_emit_move (temp1
, gen_rtx_MEM (ptr_mode
,addr
));
2586 aarch64_emit_move (temp1
,
2587 gen_rtx_SIGN_EXTEND (Pmode
,
2588 gen_rtx_MEM (ptr_mode
, addr
)));
2590 emit_insn (gen_add2_insn (this_rtx
, temp1
));
2593 /* Generate a tail call to the target function. */
2594 if (!TREE_USED (function
))
2596 assemble_external (function
);
2597 TREE_USED (function
) = 1;
2599 funexp
= XEXP (DECL_RTL (function
), 0);
2600 funexp
= gen_rtx_MEM (FUNCTION_MODE
, funexp
);
2601 insn
= emit_call_insn (gen_sibcall (funexp
, const0_rtx
, NULL_RTX
));
2602 SIBLING_CALL_P (insn
) = 1;
2604 insn
= get_insns ();
2605 shorten_branches (insn
);
2606 final_start_function (insn
, file
, 1);
2607 final (insn
, file
, 1);
2608 final_end_function ();
2610 /* Stop pretending to be a post-reload pass. */
2611 reload_completed
= 0;
2615 aarch64_tls_operand_p_1 (rtx
*x
, void *data ATTRIBUTE_UNUSED
)
2617 if (GET_CODE (*x
) == SYMBOL_REF
)
2618 return SYMBOL_REF_TLS_MODEL (*x
) != 0;
2620 /* Don't recurse into UNSPEC_TLS looking for TLS symbols; these are
2621 TLS offsets, not real symbol references. */
2622 if (GET_CODE (*x
) == UNSPEC
2623 && XINT (*x
, 1) == UNSPEC_TLS
)
2630 aarch64_tls_referenced_p (rtx x
)
2632 if (!TARGET_HAVE_TLS
)
2635 return for_each_rtx (&x
, aarch64_tls_operand_p_1
, NULL
);
2640 aarch64_bitmasks_cmp (const void *i1
, const void *i2
)
2642 const unsigned HOST_WIDE_INT
*imm1
= (const unsigned HOST_WIDE_INT
*) i1
;
2643 const unsigned HOST_WIDE_INT
*imm2
= (const unsigned HOST_WIDE_INT
*) i2
;
2654 aarch64_build_bitmask_table (void)
2656 unsigned HOST_WIDE_INT mask
, imm
;
2657 unsigned int log_e
, e
, s
, r
;
2658 unsigned int nimms
= 0;
2660 for (log_e
= 1; log_e
<= 6; log_e
++)
2664 mask
= ~(HOST_WIDE_INT
) 0;
2666 mask
= ((HOST_WIDE_INT
) 1 << e
) - 1;
2667 for (s
= 1; s
< e
; s
++)
2669 for (r
= 0; r
< e
; r
++)
2671 /* set s consecutive bits to 1 (s < 64) */
2672 imm
= ((unsigned HOST_WIDE_INT
)1 << s
) - 1;
2673 /* rotate right by r */
2675 imm
= ((imm
>> r
) | (imm
<< (e
- r
))) & mask
;
2676 /* replicate the constant depending on SIMD size */
2678 case 1: imm
|= (imm
<< 2);
2679 case 2: imm
|= (imm
<< 4);
2680 case 3: imm
|= (imm
<< 8);
2681 case 4: imm
|= (imm
<< 16);
2682 case 5: imm
|= (imm
<< 32);
2688 gcc_assert (nimms
< AARCH64_NUM_BITMASKS
);
2689 aarch64_bitmasks
[nimms
++] = imm
;
2694 gcc_assert (nimms
== AARCH64_NUM_BITMASKS
);
2695 qsort (aarch64_bitmasks
, nimms
, sizeof (aarch64_bitmasks
[0]),
2696 aarch64_bitmasks_cmp
);
2700 /* Return true if val can be encoded as a 12-bit unsigned immediate with
2701 a left shift of 0 or 12 bits. */
2703 aarch64_uimm12_shift (HOST_WIDE_INT val
)
2705 return ((val
& (((HOST_WIDE_INT
) 0xfff) << 0)) == val
2706 || (val
& (((HOST_WIDE_INT
) 0xfff) << 12)) == val
2711 /* Return true if val is an immediate that can be loaded into a
2712 register by a MOVZ instruction. */
2714 aarch64_movw_imm (HOST_WIDE_INT val
, enum machine_mode mode
)
2716 if (GET_MODE_SIZE (mode
) > 4)
2718 if ((val
& (((HOST_WIDE_INT
) 0xffff) << 32)) == val
2719 || (val
& (((HOST_WIDE_INT
) 0xffff) << 48)) == val
)
2724 /* Ignore sign extension. */
2725 val
&= (HOST_WIDE_INT
) 0xffffffff;
2727 return ((val
& (((HOST_WIDE_INT
) 0xffff) << 0)) == val
2728 || (val
& (((HOST_WIDE_INT
) 0xffff) << 16)) == val
);
2732 /* Return true if val is a valid bitmask immediate. */
2734 aarch64_bitmask_imm (HOST_WIDE_INT val
, enum machine_mode mode
)
2736 if (GET_MODE_SIZE (mode
) < 8)
2738 /* Replicate bit pattern. */
2739 val
&= (HOST_WIDE_INT
) 0xffffffff;
2742 return bsearch (&val
, aarch64_bitmasks
, AARCH64_NUM_BITMASKS
,
2743 sizeof (aarch64_bitmasks
[0]), aarch64_bitmasks_cmp
) != NULL
;
2747 /* Return true if val is an immediate that can be loaded into a
2748 register in a single instruction. */
2750 aarch64_move_imm (HOST_WIDE_INT val
, enum machine_mode mode
)
2752 if (aarch64_movw_imm (val
, mode
) || aarch64_movw_imm (~val
, mode
))
2754 return aarch64_bitmask_imm (val
, mode
);
2758 aarch64_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED
, rtx x
)
2762 if (GET_CODE (x
) == HIGH
)
2765 split_const (x
, &base
, &offset
);
2766 if (GET_CODE (base
) == SYMBOL_REF
|| GET_CODE (base
) == LABEL_REF
)
2768 if (aarch64_classify_symbol (base
, SYMBOL_CONTEXT_ADR
)
2769 != SYMBOL_FORCE_TO_MEM
)
2772 /* Avoid generating a 64-bit relocation in ILP32; leave
2773 to aarch64_expand_mov_immediate to handle it properly. */
2774 return mode
!= ptr_mode
;
2777 return aarch64_tls_referenced_p (x
);
2780 /* Return true if register REGNO is a valid index register.
2781 STRICT_P is true if REG_OK_STRICT is in effect. */
2784 aarch64_regno_ok_for_index_p (int regno
, bool strict_p
)
2786 if (!HARD_REGISTER_NUM_P (regno
))
2794 regno
= reg_renumber
[regno
];
2796 return GP_REGNUM_P (regno
);
2799 /* Return true if register REGNO is a valid base register for mode MODE.
2800 STRICT_P is true if REG_OK_STRICT is in effect. */
2803 aarch64_regno_ok_for_base_p (int regno
, bool strict_p
)
2805 if (!HARD_REGISTER_NUM_P (regno
))
2813 regno
= reg_renumber
[regno
];
2816 /* The fake registers will be eliminated to either the stack or
2817 hard frame pointer, both of which are usually valid base registers.
2818 Reload deals with the cases where the eliminated form isn't valid. */
2819 return (GP_REGNUM_P (regno
)
2820 || regno
== SP_REGNUM
2821 || regno
== FRAME_POINTER_REGNUM
2822 || regno
== ARG_POINTER_REGNUM
);
2825 /* Return true if X is a valid base register for mode MODE.
2826 STRICT_P is true if REG_OK_STRICT is in effect. */
2829 aarch64_base_register_rtx_p (rtx x
, bool strict_p
)
2831 if (!strict_p
&& GET_CODE (x
) == SUBREG
)
2834 return (REG_P (x
) && aarch64_regno_ok_for_base_p (REGNO (x
), strict_p
));
2837 /* Return true if address offset is a valid index. If it is, fill in INFO
2838 appropriately. STRICT_P is true if REG_OK_STRICT is in effect. */
2841 aarch64_classify_index (struct aarch64_address_info
*info
, rtx x
,
2842 enum machine_mode mode
, bool strict_p
)
2844 enum aarch64_address_type type
;
2849 if ((REG_P (x
) || GET_CODE (x
) == SUBREG
)
2850 && GET_MODE (x
) == Pmode
)
2852 type
= ADDRESS_REG_REG
;
2856 /* (sign_extend:DI (reg:SI)) */
2857 else if ((GET_CODE (x
) == SIGN_EXTEND
2858 || GET_CODE (x
) == ZERO_EXTEND
)
2859 && GET_MODE (x
) == DImode
2860 && GET_MODE (XEXP (x
, 0)) == SImode
)
2862 type
= (GET_CODE (x
) == SIGN_EXTEND
)
2863 ? ADDRESS_REG_SXTW
: ADDRESS_REG_UXTW
;
2864 index
= XEXP (x
, 0);
2867 /* (mult:DI (sign_extend:DI (reg:SI)) (const_int scale)) */
2868 else if (GET_CODE (x
) == MULT
2869 && (GET_CODE (XEXP (x
, 0)) == SIGN_EXTEND
2870 || GET_CODE (XEXP (x
, 0)) == ZERO_EXTEND
)
2871 && GET_MODE (XEXP (x
, 0)) == DImode
2872 && GET_MODE (XEXP (XEXP (x
, 0), 0)) == SImode
2873 && CONST_INT_P (XEXP (x
, 1)))
2875 type
= (GET_CODE (XEXP (x
, 0)) == SIGN_EXTEND
)
2876 ? ADDRESS_REG_SXTW
: ADDRESS_REG_UXTW
;
2877 index
= XEXP (XEXP (x
, 0), 0);
2878 shift
= exact_log2 (INTVAL (XEXP (x
, 1)));
2880 /* (ashift:DI (sign_extend:DI (reg:SI)) (const_int shift)) */
2881 else if (GET_CODE (x
) == ASHIFT
2882 && (GET_CODE (XEXP (x
, 0)) == SIGN_EXTEND
2883 || GET_CODE (XEXP (x
, 0)) == ZERO_EXTEND
)
2884 && GET_MODE (XEXP (x
, 0)) == DImode
2885 && GET_MODE (XEXP (XEXP (x
, 0), 0)) == SImode
2886 && CONST_INT_P (XEXP (x
, 1)))
2888 type
= (GET_CODE (XEXP (x
, 0)) == SIGN_EXTEND
)
2889 ? ADDRESS_REG_SXTW
: ADDRESS_REG_UXTW
;
2890 index
= XEXP (XEXP (x
, 0), 0);
2891 shift
= INTVAL (XEXP (x
, 1));
2893 /* (sign_extract:DI (mult:DI (reg:DI) (const_int scale)) 32+shift 0) */
2894 else if ((GET_CODE (x
) == SIGN_EXTRACT
2895 || GET_CODE (x
) == ZERO_EXTRACT
)
2896 && GET_MODE (x
) == DImode
2897 && GET_CODE (XEXP (x
, 0)) == MULT
2898 && GET_MODE (XEXP (XEXP (x
, 0), 0)) == DImode
2899 && CONST_INT_P (XEXP (XEXP (x
, 0), 1)))
2901 type
= (GET_CODE (x
) == SIGN_EXTRACT
)
2902 ? ADDRESS_REG_SXTW
: ADDRESS_REG_UXTW
;
2903 index
= XEXP (XEXP (x
, 0), 0);
2904 shift
= exact_log2 (INTVAL (XEXP (XEXP (x
, 0), 1)));
2905 if (INTVAL (XEXP (x
, 1)) != 32 + shift
2906 || INTVAL (XEXP (x
, 2)) != 0)
2909 /* (and:DI (mult:DI (reg:DI) (const_int scale))
2910 (const_int 0xffffffff<<shift)) */
2911 else if (GET_CODE (x
) == AND
2912 && GET_MODE (x
) == DImode
2913 && GET_CODE (XEXP (x
, 0)) == MULT
2914 && GET_MODE (XEXP (XEXP (x
, 0), 0)) == DImode
2915 && CONST_INT_P (XEXP (XEXP (x
, 0), 1))
2916 && CONST_INT_P (XEXP (x
, 1)))
2918 type
= ADDRESS_REG_UXTW
;
2919 index
= XEXP (XEXP (x
, 0), 0);
2920 shift
= exact_log2 (INTVAL (XEXP (XEXP (x
, 0), 1)));
2921 if (INTVAL (XEXP (x
, 1)) != (HOST_WIDE_INT
)0xffffffff << shift
)
2924 /* (sign_extract:DI (ashift:DI (reg:DI) (const_int shift)) 32+shift 0) */
2925 else if ((GET_CODE (x
) == SIGN_EXTRACT
2926 || GET_CODE (x
) == ZERO_EXTRACT
)
2927 && GET_MODE (x
) == DImode
2928 && GET_CODE (XEXP (x
, 0)) == ASHIFT
2929 && GET_MODE (XEXP (XEXP (x
, 0), 0)) == DImode
2930 && CONST_INT_P (XEXP (XEXP (x
, 0), 1)))
2932 type
= (GET_CODE (x
) == SIGN_EXTRACT
)
2933 ? ADDRESS_REG_SXTW
: ADDRESS_REG_UXTW
;
2934 index
= XEXP (XEXP (x
, 0), 0);
2935 shift
= INTVAL (XEXP (XEXP (x
, 0), 1));
2936 if (INTVAL (XEXP (x
, 1)) != 32 + shift
2937 || INTVAL (XEXP (x
, 2)) != 0)
2940 /* (and:DI (ashift:DI (reg:DI) (const_int shift))
2941 (const_int 0xffffffff<<shift)) */
2942 else if (GET_CODE (x
) == AND
2943 && GET_MODE (x
) == DImode
2944 && GET_CODE (XEXP (x
, 0)) == ASHIFT
2945 && GET_MODE (XEXP (XEXP (x
, 0), 0)) == DImode
2946 && CONST_INT_P (XEXP (XEXP (x
, 0), 1))
2947 && CONST_INT_P (XEXP (x
, 1)))
2949 type
= ADDRESS_REG_UXTW
;
2950 index
= XEXP (XEXP (x
, 0), 0);
2951 shift
= INTVAL (XEXP (XEXP (x
, 0), 1));
2952 if (INTVAL (XEXP (x
, 1)) != (HOST_WIDE_INT
)0xffffffff << shift
)
2955 /* (mult:P (reg:P) (const_int scale)) */
2956 else if (GET_CODE (x
) == MULT
2957 && GET_MODE (x
) == Pmode
2958 && GET_MODE (XEXP (x
, 0)) == Pmode
2959 && CONST_INT_P (XEXP (x
, 1)))
2961 type
= ADDRESS_REG_REG
;
2962 index
= XEXP (x
, 0);
2963 shift
= exact_log2 (INTVAL (XEXP (x
, 1)));
2965 /* (ashift:P (reg:P) (const_int shift)) */
2966 else if (GET_CODE (x
) == ASHIFT
2967 && GET_MODE (x
) == Pmode
2968 && GET_MODE (XEXP (x
, 0)) == Pmode
2969 && CONST_INT_P (XEXP (x
, 1)))
2971 type
= ADDRESS_REG_REG
;
2972 index
= XEXP (x
, 0);
2973 shift
= INTVAL (XEXP (x
, 1));
2978 if (GET_CODE (index
) == SUBREG
)
2979 index
= SUBREG_REG (index
);
2982 (shift
> 0 && shift
<= 3
2983 && (1 << shift
) == GET_MODE_SIZE (mode
)))
2985 && aarch64_regno_ok_for_index_p (REGNO (index
), strict_p
))
2988 info
->offset
= index
;
2989 info
->shift
= shift
;
2997 offset_7bit_signed_scaled_p (enum machine_mode mode
, HOST_WIDE_INT offset
)
2999 return (offset
>= -64 * GET_MODE_SIZE (mode
)
3000 && offset
< 64 * GET_MODE_SIZE (mode
)
3001 && offset
% GET_MODE_SIZE (mode
) == 0);
3005 offset_9bit_signed_unscaled_p (enum machine_mode mode ATTRIBUTE_UNUSED
,
3006 HOST_WIDE_INT offset
)
3008 return offset
>= -256 && offset
< 256;
3012 offset_12bit_unsigned_scaled_p (enum machine_mode mode
, HOST_WIDE_INT offset
)
3015 && offset
< 4096 * GET_MODE_SIZE (mode
)
3016 && offset
% GET_MODE_SIZE (mode
) == 0);
3019 /* Return true if X is a valid address for machine mode MODE. If it is,
3020 fill in INFO appropriately. STRICT_P is true if REG_OK_STRICT is in
3021 effect. OUTER_CODE is PARALLEL for a load/store pair. */
3024 aarch64_classify_address (struct aarch64_address_info
*info
,
3025 rtx x
, enum machine_mode mode
,
3026 RTX_CODE outer_code
, bool strict_p
)
3028 enum rtx_code code
= GET_CODE (x
);
3030 bool allow_reg_index_p
=
3031 outer_code
!= PARALLEL
&& GET_MODE_SIZE(mode
) != 16;
3033 /* Don't support anything other than POST_INC or REG addressing for
3035 if (aarch64_vector_mode_p (mode
)
3036 && (code
!= POST_INC
&& code
!= REG
))
3043 info
->type
= ADDRESS_REG_IMM
;
3045 info
->offset
= const0_rtx
;
3046 return aarch64_base_register_rtx_p (x
, strict_p
);
3051 if (GET_MODE_SIZE (mode
) != 0
3052 && CONST_INT_P (op1
)
3053 && aarch64_base_register_rtx_p (op0
, strict_p
))
3055 HOST_WIDE_INT offset
= INTVAL (op1
);
3057 info
->type
= ADDRESS_REG_IMM
;
3061 /* TImode and TFmode values are allowed in both pairs of X
3062 registers and individual Q registers. The available
3064 X,X: 7-bit signed scaled offset
3065 Q: 9-bit signed offset
3066 We conservatively require an offset representable in either mode.
3068 if (mode
== TImode
|| mode
== TFmode
)
3069 return (offset_7bit_signed_scaled_p (mode
, offset
)
3070 && offset_9bit_signed_unscaled_p (mode
, offset
));
3072 if (outer_code
== PARALLEL
)
3073 return ((GET_MODE_SIZE (mode
) == 4 || GET_MODE_SIZE (mode
) == 8)
3074 && offset_7bit_signed_scaled_p (mode
, offset
));
3076 return (offset_9bit_signed_unscaled_p (mode
, offset
)
3077 || offset_12bit_unsigned_scaled_p (mode
, offset
));
3080 if (allow_reg_index_p
)
3082 /* Look for base + (scaled/extended) index register. */
3083 if (aarch64_base_register_rtx_p (op0
, strict_p
)
3084 && aarch64_classify_index (info
, op1
, mode
, strict_p
))
3089 if (aarch64_base_register_rtx_p (op1
, strict_p
)
3090 && aarch64_classify_index (info
, op0
, mode
, strict_p
))
3103 info
->type
= ADDRESS_REG_WB
;
3104 info
->base
= XEXP (x
, 0);
3105 info
->offset
= NULL_RTX
;
3106 return aarch64_base_register_rtx_p (info
->base
, strict_p
);
3110 info
->type
= ADDRESS_REG_WB
;
3111 info
->base
= XEXP (x
, 0);
3112 if (GET_CODE (XEXP (x
, 1)) == PLUS
3113 && CONST_INT_P (XEXP (XEXP (x
, 1), 1))
3114 && rtx_equal_p (XEXP (XEXP (x
, 1), 0), info
->base
)
3115 && aarch64_base_register_rtx_p (info
->base
, strict_p
))
3117 HOST_WIDE_INT offset
;
3118 info
->offset
= XEXP (XEXP (x
, 1), 1);
3119 offset
= INTVAL (info
->offset
);
3121 /* TImode and TFmode values are allowed in both pairs of X
3122 registers and individual Q registers. The available
3124 X,X: 7-bit signed scaled offset
3125 Q: 9-bit signed offset
3126 We conservatively require an offset representable in either mode.
3128 if (mode
== TImode
|| mode
== TFmode
)
3129 return (offset_7bit_signed_scaled_p (mode
, offset
)
3130 && offset_9bit_signed_unscaled_p (mode
, offset
));
3132 if (outer_code
== PARALLEL
)
3133 return ((GET_MODE_SIZE (mode
) == 4 || GET_MODE_SIZE (mode
) == 8)
3134 && offset_7bit_signed_scaled_p (mode
, offset
));
3136 return offset_9bit_signed_unscaled_p (mode
, offset
);
3143 /* load literal: pc-relative constant pool entry. Only supported
3144 for SI mode or larger. */
3145 info
->type
= ADDRESS_SYMBOLIC
;
3146 if (outer_code
!= PARALLEL
&& GET_MODE_SIZE (mode
) >= 4)
3150 split_const (x
, &sym
, &addend
);
3151 return (GET_CODE (sym
) == LABEL_REF
3152 || (GET_CODE (sym
) == SYMBOL_REF
3153 && CONSTANT_POOL_ADDRESS_P (sym
)));
3158 info
->type
= ADDRESS_LO_SUM
;
3159 info
->base
= XEXP (x
, 0);
3160 info
->offset
= XEXP (x
, 1);
3161 if (allow_reg_index_p
3162 && aarch64_base_register_rtx_p (info
->base
, strict_p
))
3165 split_const (info
->offset
, &sym
, &offs
);
3166 if (GET_CODE (sym
) == SYMBOL_REF
3167 && (aarch64_classify_symbol (sym
, SYMBOL_CONTEXT_MEM
)
3168 == SYMBOL_SMALL_ABSOLUTE
))
3170 /* The symbol and offset must be aligned to the access size. */
3172 unsigned int ref_size
;
3174 if (CONSTANT_POOL_ADDRESS_P (sym
))
3175 align
= GET_MODE_ALIGNMENT (get_pool_mode (sym
));
3176 else if (TREE_CONSTANT_POOL_ADDRESS_P (sym
))
3178 tree exp
= SYMBOL_REF_DECL (sym
);
3179 align
= TYPE_ALIGN (TREE_TYPE (exp
));
3180 align
= CONSTANT_ALIGNMENT (exp
, align
);
3182 else if (SYMBOL_REF_DECL (sym
))
3183 align
= DECL_ALIGN (SYMBOL_REF_DECL (sym
));
3185 align
= BITS_PER_UNIT
;
3187 ref_size
= GET_MODE_SIZE (mode
);
3189 ref_size
= GET_MODE_SIZE (DImode
);
3191 return ((INTVAL (offs
) & (ref_size
- 1)) == 0
3192 && ((align
/ BITS_PER_UNIT
) & (ref_size
- 1)) == 0);
3203 aarch64_symbolic_address_p (rtx x
)
3207 split_const (x
, &x
, &offset
);
3208 return GET_CODE (x
) == SYMBOL_REF
|| GET_CODE (x
) == LABEL_REF
;
3211 /* Classify the base of symbolic expression X, given that X appears in
3214 enum aarch64_symbol_type
3215 aarch64_classify_symbolic_expression (rtx x
,
3216 enum aarch64_symbol_context context
)
3220 split_const (x
, &x
, &offset
);
3221 return aarch64_classify_symbol (x
, context
);
3225 /* Return TRUE if X is a legitimate address for accessing memory in
3228 aarch64_legitimate_address_hook_p (enum machine_mode mode
, rtx x
, bool strict_p
)
3230 struct aarch64_address_info addr
;
3232 return aarch64_classify_address (&addr
, x
, mode
, MEM
, strict_p
);
3235 /* Return TRUE if X is a legitimate address for accessing memory in
3236 mode MODE. OUTER_CODE will be PARALLEL if this is a load/store
3239 aarch64_legitimate_address_p (enum machine_mode mode
, rtx x
,
3240 RTX_CODE outer_code
, bool strict_p
)
3242 struct aarch64_address_info addr
;
3244 return aarch64_classify_address (&addr
, x
, mode
, outer_code
, strict_p
);
3247 /* Return TRUE if rtx X is immediate constant 0.0 */
3249 aarch64_float_const_zero_rtx_p (rtx x
)
3253 if (GET_MODE (x
) == VOIDmode
)
3256 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
3257 if (REAL_VALUE_MINUS_ZERO (r
))
3258 return !HONOR_SIGNED_ZEROS (GET_MODE (x
));
3259 return REAL_VALUES_EQUAL (r
, dconst0
);
3262 /* Return the fixed registers used for condition codes. */
3265 aarch64_fixed_condition_code_regs (unsigned int *p1
, unsigned int *p2
)
3268 *p2
= INVALID_REGNUM
;
3273 aarch64_select_cc_mode (RTX_CODE code
, rtx x
, rtx y
)
3275 /* All floating point compares return CCFP if it is an equality
3276 comparison, and CCFPE otherwise. */
3277 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
)
3304 if ((GET_MODE (x
) == SImode
|| GET_MODE (x
) == DImode
)
3306 && (code
== EQ
|| code
== NE
|| code
== LT
|| code
== GE
)
3307 && (GET_CODE (x
) == PLUS
|| GET_CODE (x
) == MINUS
|| GET_CODE (x
) == AND
3308 || GET_CODE (x
) == NEG
))
3311 /* A compare with a shifted operand. Because of canonicalization,
3312 the comparison will have to be swapped when we emit the assembly
3314 if ((GET_MODE (x
) == SImode
|| GET_MODE (x
) == DImode
)
3315 && (GET_CODE (y
) == REG
|| GET_CODE (y
) == SUBREG
)
3316 && (GET_CODE (x
) == ASHIFT
|| GET_CODE (x
) == ASHIFTRT
3317 || GET_CODE (x
) == LSHIFTRT
3318 || GET_CODE (x
) == ZERO_EXTEND
|| GET_CODE (x
) == SIGN_EXTEND
))
3321 /* A compare of a mode narrower than SI mode against zero can be done
3322 by extending the value in the comparison. */
3323 if ((GET_MODE (x
) == QImode
|| GET_MODE (x
) == HImode
)
3325 /* Only use sign-extension if we really need it. */
3326 return ((code
== GT
|| code
== GE
|| code
== LE
|| code
== LT
)
3327 ? CC_SESWPmode
: CC_ZESWPmode
);
3329 /* For everything else, return CCmode. */
3334 aarch64_get_condition_code (rtx x
)
3336 enum machine_mode mode
= GET_MODE (XEXP (x
, 0));
3337 enum rtx_code comp_code
= GET_CODE (x
);
3339 if (GET_MODE_CLASS (mode
) != MODE_CC
)
3340 mode
= SELECT_CC_MODE (comp_code
, XEXP (x
, 0), XEXP (x
, 1));
3348 case GE
: return AARCH64_GE
;
3349 case GT
: return AARCH64_GT
;
3350 case LE
: return AARCH64_LS
;
3351 case LT
: return AARCH64_MI
;
3352 case NE
: return AARCH64_NE
;
3353 case EQ
: return AARCH64_EQ
;
3354 case ORDERED
: return AARCH64_VC
;
3355 case UNORDERED
: return AARCH64_VS
;
3356 case UNLT
: return AARCH64_LT
;
3357 case UNLE
: return AARCH64_LE
;
3358 case UNGT
: return AARCH64_HI
;
3359 case UNGE
: return AARCH64_PL
;
3360 default: gcc_unreachable ();
3367 case NE
: return AARCH64_NE
;
3368 case EQ
: return AARCH64_EQ
;
3369 case GE
: return AARCH64_GE
;
3370 case GT
: return AARCH64_GT
;
3371 case LE
: return AARCH64_LE
;
3372 case LT
: return AARCH64_LT
;
3373 case GEU
: return AARCH64_CS
;
3374 case GTU
: return AARCH64_HI
;
3375 case LEU
: return AARCH64_LS
;
3376 case LTU
: return AARCH64_CC
;
3377 default: gcc_unreachable ();
3386 case NE
: return AARCH64_NE
;
3387 case EQ
: return AARCH64_EQ
;
3388 case GE
: return AARCH64_LE
;
3389 case GT
: return AARCH64_LT
;
3390 case LE
: return AARCH64_GE
;
3391 case LT
: return AARCH64_GT
;
3392 case GEU
: return AARCH64_LS
;
3393 case GTU
: return AARCH64_CC
;
3394 case LEU
: return AARCH64_CS
;
3395 case LTU
: return AARCH64_HI
;
3396 default: gcc_unreachable ();
3403 case NE
: return AARCH64_NE
;
3404 case EQ
: return AARCH64_EQ
;
3405 case GE
: return AARCH64_PL
;
3406 case LT
: return AARCH64_MI
;
3407 default: gcc_unreachable ();
3418 bit_count (unsigned HOST_WIDE_INT value
)
3432 aarch64_print_operand (FILE *f
, rtx x
, char code
)
3437 /* Print the sign/zero-extend size as a character 8->b, 16->h, 32->w. */
3441 if (GET_CODE (x
) != CONST_INT
3442 || (n
= exact_log2 (INTVAL (x
) & ~7)) <= 0)
3444 output_operand_lossage ("invalid operand for '%%%c'", code
);
3460 output_operand_lossage ("invalid operand for '%%%c'", code
);
3470 /* Print N such that 2^N == X. */
3471 if (GET_CODE (x
) != CONST_INT
|| (n
= exact_log2 (INTVAL (x
))) < 0)
3473 output_operand_lossage ("invalid operand for '%%%c'", code
);
3477 asm_fprintf (f
, "%d", n
);
3482 /* Print the number of non-zero bits in X (a const_int). */
3483 if (GET_CODE (x
) != CONST_INT
)
3485 output_operand_lossage ("invalid operand for '%%%c'", code
);
3489 asm_fprintf (f
, "%u", bit_count (INTVAL (x
)));
3493 /* Print the higher numbered register of a pair (TImode) of regs. */
3494 if (GET_CODE (x
) != REG
|| !GP_REGNUM_P (REGNO (x
) + 1))
3496 output_operand_lossage ("invalid operand for '%%%c'", code
);
3500 asm_fprintf (f
, "%s", reg_names
[REGNO (x
) + 1]);
3504 /* Print a condition (eq, ne, etc). */
3506 /* CONST_TRUE_RTX means always -- that's the default. */
3507 if (x
== const_true_rtx
)
3510 if (!COMPARISON_P (x
))
3512 output_operand_lossage ("invalid operand for '%%%c'", code
);
3516 fputs (aarch64_condition_codes
[aarch64_get_condition_code (x
)], f
);
3520 /* Print the inverse of a condition (eq <-> ne, etc). */
3522 /* CONST_TRUE_RTX means never -- that's the default. */
3523 if (x
== const_true_rtx
)
3529 if (!COMPARISON_P (x
))
3531 output_operand_lossage ("invalid operand for '%%%c'", code
);
3535 fputs (aarch64_condition_codes
[AARCH64_INVERSE_CONDITION_CODE
3536 (aarch64_get_condition_code (x
))], f
);
3544 /* Print a scalar FP/SIMD register name. */
3545 if (!REG_P (x
) || !FP_REGNUM_P (REGNO (x
)))
3547 output_operand_lossage ("incompatible floating point / vector register operand for '%%%c'", code
);
3550 asm_fprintf (f
, "%c%d", code
, REGNO (x
) - V0_REGNUM
);
3557 /* Print the first FP/SIMD register name in a list. */
3558 if (!REG_P (x
) || !FP_REGNUM_P (REGNO (x
)))
3560 output_operand_lossage ("incompatible floating point / vector register operand for '%%%c'", code
);
3563 asm_fprintf (f
, "v%d", REGNO (x
) - V0_REGNUM
+ (code
- 'S'));
3567 /* Print bottom 16 bits of integer constant in hex. */
3568 if (GET_CODE (x
) != CONST_INT
)
3570 output_operand_lossage ("invalid operand for '%%%c'", code
);
3573 asm_fprintf (f
, "0x%wx", UINTVAL (x
) & 0xffff);
3578 /* Print a general register name or the zero register (32-bit or
3581 || (CONST_DOUBLE_P (x
) && aarch64_float_const_zero_rtx_p (x
)))
3583 asm_fprintf (f
, "%czr", code
);
3587 if (REG_P (x
) && GP_REGNUM_P (REGNO (x
)))
3589 asm_fprintf (f
, "%c%d", code
, REGNO (x
) - R0_REGNUM
);
3593 if (REG_P (x
) && REGNO (x
) == SP_REGNUM
)
3595 asm_fprintf (f
, "%ssp", code
== 'w' ? "w" : "");
3602 /* Print a normal operand, if it's a general register, then we
3606 output_operand_lossage ("missing operand");
3610 switch (GET_CODE (x
))
3613 asm_fprintf (f
, "%s", reg_names
[REGNO (x
)]);
3617 aarch64_memory_reference_mode
= GET_MODE (x
);
3618 output_address (XEXP (x
, 0));
3623 output_addr_const (asm_out_file
, x
);
3627 asm_fprintf (f
, "%wd", INTVAL (x
));
3631 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_VECTOR_INT
)
3633 gcc_assert (aarch64_const_vec_all_same_int_p (x
,
3635 HOST_WIDE_INT_MAX
));
3636 asm_fprintf (f
, "%wd", INTVAL (CONST_VECTOR_ELT (x
, 0)));
3638 else if (aarch64_simd_imm_zero_p (x
, GET_MODE (x
)))
3647 /* CONST_DOUBLE can represent a double-width integer.
3648 In this case, the mode of x is VOIDmode. */
3649 if (GET_MODE (x
) == VOIDmode
)
3651 else if (aarch64_float_const_zero_rtx_p (x
))
3656 else if (aarch64_float_const_representable_p (x
))
3659 char float_buf
[buf_size
] = {'\0'};
3661 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
3662 real_to_decimal_for_mode (float_buf
, &r
,
3665 asm_fprintf (asm_out_file
, "%s", float_buf
);
3669 output_operand_lossage ("invalid constant");
3672 output_operand_lossage ("invalid operand");
3678 if (GET_CODE (x
) == HIGH
)
3681 switch (aarch64_classify_symbolic_expression (x
, SYMBOL_CONTEXT_ADR
))
3683 case SYMBOL_SMALL_GOT
:
3684 asm_fprintf (asm_out_file
, ":got:");
3687 case SYMBOL_SMALL_TLSGD
:
3688 asm_fprintf (asm_out_file
, ":tlsgd:");
3691 case SYMBOL_SMALL_TLSDESC
:
3692 asm_fprintf (asm_out_file
, ":tlsdesc:");
3695 case SYMBOL_SMALL_GOTTPREL
:
3696 asm_fprintf (asm_out_file
, ":gottprel:");
3699 case SYMBOL_SMALL_TPREL
:
3700 asm_fprintf (asm_out_file
, ":tprel:");
3703 case SYMBOL_TINY_GOT
:
3710 output_addr_const (asm_out_file
, x
);
3714 switch (aarch64_classify_symbolic_expression (x
, SYMBOL_CONTEXT_ADR
))
3716 case SYMBOL_SMALL_GOT
:
3717 asm_fprintf (asm_out_file
, ":lo12:");
3720 case SYMBOL_SMALL_TLSGD
:
3721 asm_fprintf (asm_out_file
, ":tlsgd_lo12:");
3724 case SYMBOL_SMALL_TLSDESC
:
3725 asm_fprintf (asm_out_file
, ":tlsdesc_lo12:");
3728 case SYMBOL_SMALL_GOTTPREL
:
3729 asm_fprintf (asm_out_file
, ":gottprel_lo12:");
3732 case SYMBOL_SMALL_TPREL
:
3733 asm_fprintf (asm_out_file
, ":tprel_lo12_nc:");
3736 case SYMBOL_TINY_GOT
:
3737 asm_fprintf (asm_out_file
, ":got:");
3743 output_addr_const (asm_out_file
, x
);
3748 switch (aarch64_classify_symbolic_expression (x
, SYMBOL_CONTEXT_ADR
))
3750 case SYMBOL_SMALL_TPREL
:
3751 asm_fprintf (asm_out_file
, ":tprel_hi12:");
3756 output_addr_const (asm_out_file
, x
);
3760 output_operand_lossage ("invalid operand prefix '%%%c'", code
);
3766 aarch64_print_operand_address (FILE *f
, rtx x
)
3768 struct aarch64_address_info addr
;
3770 if (aarch64_classify_address (&addr
, x
, aarch64_memory_reference_mode
,
3774 case ADDRESS_REG_IMM
:
3775 if (addr
.offset
== const0_rtx
)
3776 asm_fprintf (f
, "[%s]", reg_names
[REGNO (addr
.base
)]);
3778 asm_fprintf (f
, "[%s,%wd]", reg_names
[REGNO (addr
.base
)],
3779 INTVAL (addr
.offset
));
3782 case ADDRESS_REG_REG
:
3783 if (addr
.shift
== 0)
3784 asm_fprintf (f
, "[%s,%s]", reg_names
[REGNO (addr
.base
)],
3785 reg_names
[REGNO (addr
.offset
)]);
3787 asm_fprintf (f
, "[%s,%s,lsl %u]", reg_names
[REGNO (addr
.base
)],
3788 reg_names
[REGNO (addr
.offset
)], addr
.shift
);
3791 case ADDRESS_REG_UXTW
:
3792 if (addr
.shift
== 0)
3793 asm_fprintf (f
, "[%s,w%d,uxtw]", reg_names
[REGNO (addr
.base
)],
3794 REGNO (addr
.offset
) - R0_REGNUM
);
3796 asm_fprintf (f
, "[%s,w%d,uxtw %u]", reg_names
[REGNO (addr
.base
)],
3797 REGNO (addr
.offset
) - R0_REGNUM
, addr
.shift
);
3800 case ADDRESS_REG_SXTW
:
3801 if (addr
.shift
== 0)
3802 asm_fprintf (f
, "[%s,w%d,sxtw]", reg_names
[REGNO (addr
.base
)],
3803 REGNO (addr
.offset
) - R0_REGNUM
);
3805 asm_fprintf (f
, "[%s,w%d,sxtw %u]", reg_names
[REGNO (addr
.base
)],
3806 REGNO (addr
.offset
) - R0_REGNUM
, addr
.shift
);
3809 case ADDRESS_REG_WB
:
3810 switch (GET_CODE (x
))
3813 asm_fprintf (f
, "[%s,%d]!", reg_names
[REGNO (addr
.base
)],
3814 GET_MODE_SIZE (aarch64_memory_reference_mode
));
3817 asm_fprintf (f
, "[%s],%d", reg_names
[REGNO (addr
.base
)],
3818 GET_MODE_SIZE (aarch64_memory_reference_mode
));
3821 asm_fprintf (f
, "[%s,-%d]!", reg_names
[REGNO (addr
.base
)],
3822 GET_MODE_SIZE (aarch64_memory_reference_mode
));
3825 asm_fprintf (f
, "[%s],-%d", reg_names
[REGNO (addr
.base
)],
3826 GET_MODE_SIZE (aarch64_memory_reference_mode
));
3829 asm_fprintf (f
, "[%s,%wd]!", reg_names
[REGNO (addr
.base
)],
3830 INTVAL (addr
.offset
));
3833 asm_fprintf (f
, "[%s],%wd", reg_names
[REGNO (addr
.base
)],
3834 INTVAL (addr
.offset
));
3841 case ADDRESS_LO_SUM
:
3842 asm_fprintf (f
, "[%s,#:lo12:", reg_names
[REGNO (addr
.base
)]);
3843 output_addr_const (f
, addr
.offset
);
3844 asm_fprintf (f
, "]");
3847 case ADDRESS_SYMBOLIC
:
3851 output_addr_const (f
, x
);
3855 aarch64_function_profiler (FILE *f ATTRIBUTE_UNUSED
,
3856 int labelno ATTRIBUTE_UNUSED
)
3858 sorry ("function profiling");
3862 aarch64_label_mentioned_p (rtx x
)
3867 if (GET_CODE (x
) == LABEL_REF
)
3870 /* UNSPEC_TLS entries for a symbol include a LABEL_REF for the
3871 referencing instruction, but they are constant offsets, not
3873 if (GET_CODE (x
) == UNSPEC
&& XINT (x
, 1) == UNSPEC_TLS
)
3876 fmt
= GET_RTX_FORMAT (GET_CODE (x
));
3877 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
3883 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
3884 if (aarch64_label_mentioned_p (XVECEXP (x
, i
, j
)))
3887 else if (fmt
[i
] == 'e' && aarch64_label_mentioned_p (XEXP (x
, i
)))
3894 /* Implement REGNO_REG_CLASS. */
3897 aarch64_regno_regclass (unsigned regno
)
3899 if (GP_REGNUM_P (regno
))
3902 if (regno
== SP_REGNUM
)
3905 if (regno
== FRAME_POINTER_REGNUM
3906 || regno
== ARG_POINTER_REGNUM
)
3909 if (FP_REGNUM_P (regno
))
3910 return FP_LO_REGNUM_P (regno
) ? FP_LO_REGS
: FP_REGS
;
3915 /* Try a machine-dependent way of reloading an illegitimate address
3916 operand. If we find one, push the reload and return the new rtx. */
3919 aarch64_legitimize_reload_address (rtx
*x_p
,
3920 enum machine_mode mode
,
3921 int opnum
, int type
,
3922 int ind_levels ATTRIBUTE_UNUSED
)
3926 /* Do not allow mem (plus (reg, const)) if vector mode. */
3927 if (aarch64_vector_mode_p (mode
)
3928 && GET_CODE (x
) == PLUS
3929 && REG_P (XEXP (x
, 0))
3930 && CONST_INT_P (XEXP (x
, 1)))
3934 push_reload (orig_rtx
, NULL_RTX
, x_p
, NULL
,
3935 BASE_REG_CLASS
, GET_MODE (x
), VOIDmode
, 0, 0,
3936 opnum
, (enum reload_type
) type
);
3940 /* We must recognize output that we have already generated ourselves. */
3941 if (GET_CODE (x
) == PLUS
3942 && GET_CODE (XEXP (x
, 0)) == PLUS
3943 && REG_P (XEXP (XEXP (x
, 0), 0))
3944 && CONST_INT_P (XEXP (XEXP (x
, 0), 1))
3945 && CONST_INT_P (XEXP (x
, 1)))
3947 push_reload (XEXP (x
, 0), NULL_RTX
, &XEXP (x
, 0), NULL
,
3948 BASE_REG_CLASS
, GET_MODE (x
), VOIDmode
, 0, 0,
3949 opnum
, (enum reload_type
) type
);
3953 /* We wish to handle large displacements off a base register by splitting
3954 the addend across an add and the mem insn. This can cut the number of
3955 extra insns needed from 3 to 1. It is only useful for load/store of a
3956 single register with 12 bit offset field. */
3957 if (GET_CODE (x
) == PLUS
3958 && REG_P (XEXP (x
, 0))
3959 && CONST_INT_P (XEXP (x
, 1))
3960 && HARD_REGISTER_P (XEXP (x
, 0))
3963 && aarch64_regno_ok_for_base_p (REGNO (XEXP (x
, 0)), true))
3965 HOST_WIDE_INT val
= INTVAL (XEXP (x
, 1));
3966 HOST_WIDE_INT low
= val
& 0xfff;
3967 HOST_WIDE_INT high
= val
- low
;
3970 enum machine_mode xmode
= GET_MODE (x
);
3972 /* In ILP32, xmode can be either DImode or SImode. */
3973 gcc_assert (xmode
== DImode
|| xmode
== SImode
);
3975 /* Reload non-zero BLKmode offsets. This is because we cannot ascertain
3976 BLKmode alignment. */
3977 if (GET_MODE_SIZE (mode
) == 0)
3980 offs
= low
% GET_MODE_SIZE (mode
);
3982 /* Align misaligned offset by adjusting high part to compensate. */
3985 if (aarch64_uimm12_shift (high
+ offs
))
3994 offs
= GET_MODE_SIZE (mode
) - offs
;
3996 high
= high
+ (low
& 0x1000) - offs
;
4001 /* Check for overflow. */
4002 if (high
+ low
!= val
)
4005 cst
= GEN_INT (high
);
4006 if (!aarch64_uimm12_shift (high
))
4007 cst
= force_const_mem (xmode
, cst
);
4009 /* Reload high part into base reg, leaving the low part
4010 in the mem instruction. */
4011 x
= gen_rtx_PLUS (xmode
,
4012 gen_rtx_PLUS (xmode
, XEXP (x
, 0), cst
),
4015 push_reload (XEXP (x
, 0), NULL_RTX
, &XEXP (x
, 0), NULL
,
4016 BASE_REG_CLASS
, xmode
, VOIDmode
, 0, 0,
4017 opnum
, (enum reload_type
) type
);
4026 aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED
, rtx x
,
4028 enum machine_mode mode
,
4029 secondary_reload_info
*sri
)
4031 /* Address expressions of the form PLUS (SP, large_offset) need two
4032 scratch registers, one for the constant, and one for holding a
4033 copy of SP, since SP cannot be used on the RHS of an add-reg
4036 && GET_CODE (x
) == PLUS
4037 && XEXP (x
, 0) == stack_pointer_rtx
4038 && CONST_INT_P (XEXP (x
, 1))
4039 && !aarch64_uimm12_shift (INTVAL (XEXP (x
, 1))))
4041 sri
->icode
= CODE_FOR_reload_sp_immediate
;
4045 /* Without the TARGET_SIMD instructions we cannot move a Q register
4046 to a Q register directly. We need a scratch. */
4047 if (REG_P (x
) && (mode
== TFmode
|| mode
== TImode
) && mode
== GET_MODE (x
)
4048 && FP_REGNUM_P (REGNO (x
)) && !TARGET_SIMD
4049 && reg_class_subset_p (rclass
, FP_REGS
))
4052 sri
->icode
= CODE_FOR_aarch64_reload_movtf
;
4053 else if (mode
== TImode
)
4054 sri
->icode
= CODE_FOR_aarch64_reload_movti
;
4058 /* A TFmode or TImode memory access should be handled via an FP_REGS
4059 because AArch64 has richer addressing modes for LDR/STR instructions
4060 than LDP/STP instructions. */
4061 if (!TARGET_GENERAL_REGS_ONLY
&& rclass
== CORE_REGS
4062 && GET_MODE_SIZE (mode
) == 16 && MEM_P (x
))
4065 if (rclass
== FP_REGS
&& (mode
== TImode
|| mode
== TFmode
) && CONSTANT_P(x
))
4072 aarch64_can_eliminate (const int from
, const int to
)
4074 /* If we need a frame pointer, we must eliminate FRAME_POINTER_REGNUM into
4075 HARD_FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */
4077 if (frame_pointer_needed
)
4079 if (from
== ARG_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
4081 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
4083 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
4084 && !cfun
->calls_alloca
)
4086 if (from
== FRAME_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
4092 /* If we decided that we didn't need a leaf frame pointer but then used
4093 LR in the function, then we'll want a frame pointer after all, so
4094 prevent this elimination to ensure a frame pointer is used.
4096 NOTE: the original value of flag_omit_frame_pointer gets trashed
4097 IFF flag_omit_leaf_frame_pointer is true, so we check the value
4098 of faked_omit_frame_pointer here (which is true when we always
4099 wish to keep non-leaf frame pointers but only wish to keep leaf frame
4100 pointers when LR is clobbered). */
4101 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
4102 && df_regs_ever_live_p (LR_REGNUM
)
4103 && faked_omit_frame_pointer
)
4111 aarch64_initial_elimination_offset (unsigned from
, unsigned to
)
4113 HOST_WIDE_INT frame_size
;
4114 HOST_WIDE_INT offset
;
4116 aarch64_layout_frame ();
4117 frame_size
= (get_frame_size () + cfun
->machine
->frame
.saved_regs_size
4118 + crtl
->outgoing_args_size
4119 + cfun
->machine
->saved_varargs_size
);
4121 frame_size
= AARCH64_ROUND_UP (frame_size
, STACK_BOUNDARY
/ BITS_PER_UNIT
);
4122 offset
= frame_size
;
4124 if (to
== HARD_FRAME_POINTER_REGNUM
)
4126 if (from
== ARG_POINTER_REGNUM
)
4127 return offset
- crtl
->outgoing_args_size
;
4129 if (from
== FRAME_POINTER_REGNUM
)
4130 return cfun
->machine
->frame
.saved_regs_size
;
4133 if (to
== STACK_POINTER_REGNUM
)
4135 if (from
== FRAME_POINTER_REGNUM
)
4137 HOST_WIDE_INT elim
= crtl
->outgoing_args_size
4138 + cfun
->machine
->frame
.saved_regs_size
4139 - cfun
->machine
->frame
.fp_lr_offset
;
4140 elim
= AARCH64_ROUND_UP (elim
, STACK_BOUNDARY
/ BITS_PER_UNIT
);
4149 /* Implement RETURN_ADDR_RTX. We do not support moving back to a
4153 aarch64_return_addr (int count
, rtx frame ATTRIBUTE_UNUSED
)
4157 return get_hard_reg_initial_val (Pmode
, LR_REGNUM
);
4162 aarch64_asm_trampoline_template (FILE *f
)
4166 asm_fprintf (f
, "\tldr\tw%d, .+16\n", IP1_REGNUM
- R0_REGNUM
);
4167 asm_fprintf (f
, "\tldr\tw%d, .+16\n", STATIC_CHAIN_REGNUM
- R0_REGNUM
);
4171 asm_fprintf (f
, "\tldr\t%s, .+16\n", reg_names
[IP1_REGNUM
]);
4172 asm_fprintf (f
, "\tldr\t%s, .+20\n", reg_names
[STATIC_CHAIN_REGNUM
]);
4174 asm_fprintf (f
, "\tbr\t%s\n", reg_names
[IP1_REGNUM
]);
4175 assemble_aligned_integer (4, const0_rtx
);
4176 assemble_aligned_integer (POINTER_BYTES
, const0_rtx
);
4177 assemble_aligned_integer (POINTER_BYTES
, const0_rtx
);
4181 aarch64_trampoline_init (rtx m_tramp
, tree fndecl
, rtx chain_value
)
4183 rtx fnaddr
, mem
, a_tramp
;
4184 const int tramp_code_sz
= 16;
4186 /* Don't need to copy the trailing D-words, we fill those in below. */
4187 emit_block_move (m_tramp
, assemble_trampoline_template (),
4188 GEN_INT (tramp_code_sz
), BLOCK_OP_NORMAL
);
4189 mem
= adjust_address (m_tramp
, ptr_mode
, tramp_code_sz
);
4190 fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
4191 if (GET_MODE (fnaddr
) != ptr_mode
)
4192 fnaddr
= convert_memory_address (ptr_mode
, fnaddr
);
4193 emit_move_insn (mem
, fnaddr
);
4195 mem
= adjust_address (m_tramp
, ptr_mode
, tramp_code_sz
+ POINTER_BYTES
);
4196 emit_move_insn (mem
, chain_value
);
4198 /* XXX We should really define a "clear_cache" pattern and use
4199 gen_clear_cache(). */
4200 a_tramp
= XEXP (m_tramp
, 0);
4201 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "__clear_cache"),
4202 LCT_NORMAL
, VOIDmode
, 2, a_tramp
, ptr_mode
,
4203 plus_constant (ptr_mode
, a_tramp
, TRAMPOLINE_SIZE
),
4207 static unsigned char
4208 aarch64_class_max_nregs (reg_class_t regclass
, enum machine_mode mode
)
4219 aarch64_vector_mode_p (mode
) ? (GET_MODE_SIZE (mode
) + 15) / 16 :
4220 (GET_MODE_SIZE (mode
) + 7) / 8;
4234 aarch64_preferred_reload_class (rtx x ATTRIBUTE_UNUSED
, reg_class_t regclass
)
4236 return ((regclass
== POINTER_REGS
|| regclass
== STACK_REG
)
4237 ? GENERAL_REGS
: regclass
);
4241 aarch64_asm_output_labelref (FILE* f
, const char *name
)
4243 asm_fprintf (f
, "%U%s", name
);
4247 aarch64_elf_asm_constructor (rtx symbol
, int priority
)
4249 if (priority
== DEFAULT_INIT_PRIORITY
)
4250 default_ctor_section_asm_out_constructor (symbol
, priority
);
4255 snprintf (buf
, sizeof (buf
), ".init_array.%.5u", priority
);
4256 s
= get_section (buf
, SECTION_WRITE
, NULL
);
4257 switch_to_section (s
);
4258 assemble_align (POINTER_SIZE
);
4259 assemble_aligned_integer (POINTER_BYTES
, symbol
);
4264 aarch64_elf_asm_destructor (rtx symbol
, int priority
)
4266 if (priority
== DEFAULT_INIT_PRIORITY
)
4267 default_dtor_section_asm_out_destructor (symbol
, priority
);
4272 snprintf (buf
, sizeof (buf
), ".fini_array.%.5u", priority
);
4273 s
= get_section (buf
, SECTION_WRITE
, NULL
);
4274 switch_to_section (s
);
4275 assemble_align (POINTER_SIZE
);
4276 assemble_aligned_integer (POINTER_BYTES
, symbol
);
4281 aarch64_output_casesi (rtx
*operands
)
4285 rtx diff_vec
= PATTERN (next_active_insn (operands
[2]));
4287 static const char *const patterns
[4][2] =
4290 "ldrb\t%w3, [%0,%w1,uxtw]",
4291 "add\t%3, %4, %w3, sxtb #2"
4294 "ldrh\t%w3, [%0,%w1,uxtw #1]",
4295 "add\t%3, %4, %w3, sxth #2"
4298 "ldr\t%w3, [%0,%w1,uxtw #2]",
4299 "add\t%3, %4, %w3, sxtw #2"
4301 /* We assume that DImode is only generated when not optimizing and
4302 that we don't really need 64-bit address offsets. That would
4303 imply an object file with 8GB of code in a single function! */
4305 "ldr\t%w3, [%0,%w1,uxtw #2]",
4306 "add\t%3, %4, %w3, sxtw #2"
4310 gcc_assert (GET_CODE (diff_vec
) == ADDR_DIFF_VEC
);
4312 index
= exact_log2 (GET_MODE_SIZE (GET_MODE (diff_vec
)));
4314 gcc_assert (index
>= 0 && index
<= 3);
4316 /* Need to implement table size reduction, by chaning the code below. */
4317 output_asm_insn (patterns
[index
][0], operands
);
4318 ASM_GENERATE_INTERNAL_LABEL (label
, "Lrtx", CODE_LABEL_NUMBER (operands
[2]));
4319 snprintf (buf
, sizeof (buf
),
4320 "adr\t%%4, %s", targetm
.strip_name_encoding (label
));
4321 output_asm_insn (buf
, operands
);
4322 output_asm_insn (patterns
[index
][1], operands
);
4323 output_asm_insn ("br\t%3", operands
);
4324 assemble_label (asm_out_file
, label
);
4329 /* Return size in bits of an arithmetic operand which is shifted/scaled and
4330 masked such that it is suitable for a UXTB, UXTH, or UXTW extend
4334 aarch64_uxt_size (int shift
, HOST_WIDE_INT mask
)
4336 if (shift
>= 0 && shift
<= 3)
4339 for (size
= 8; size
<= 32; size
*= 2)
4341 HOST_WIDE_INT bits
= ((HOST_WIDE_INT
)1U << size
) - 1;
4342 if (mask
== bits
<< shift
)
4350 aarch64_use_blocks_for_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED
,
4351 const_rtx x ATTRIBUTE_UNUSED
)
4353 /* We can't use blocks for constants when we're using a per-function
4359 aarch64_select_rtx_section (enum machine_mode mode ATTRIBUTE_UNUSED
,
4360 rtx x ATTRIBUTE_UNUSED
,
4361 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED
)
4363 /* Force all constant pool entries into the current function section. */
4364 return function_section (current_function_decl
);
4370 /* Helper function for rtx cost calculation. Strip a shift expression
4371 from X. Returns the inner operand if successful, or the original
4372 expression on failure. */
4374 aarch64_strip_shift (rtx x
)
4378 if ((GET_CODE (op
) == ASHIFT
4379 || GET_CODE (op
) == ASHIFTRT
4380 || GET_CODE (op
) == LSHIFTRT
)
4381 && CONST_INT_P (XEXP (op
, 1)))
4382 return XEXP (op
, 0);
4384 if (GET_CODE (op
) == MULT
4385 && CONST_INT_P (XEXP (op
, 1))
4386 && ((unsigned) exact_log2 (INTVAL (XEXP (op
, 1)))) < 64)
4387 return XEXP (op
, 0);
4392 /* Helper function for rtx cost calculation. Strip a shift or extend
4393 expression from X. Returns the inner operand if successful, or the
4394 original expression on failure. We deal with a number of possible
4395 canonicalization variations here. */
4397 aarch64_strip_shift_or_extend (rtx x
)
4401 /* Zero and sign extraction of a widened value. */
4402 if ((GET_CODE (op
) == ZERO_EXTRACT
|| GET_CODE (op
) == SIGN_EXTRACT
)
4403 && XEXP (op
, 2) == const0_rtx
4404 && aarch64_is_extend_from_extract (GET_MODE (op
), XEXP (XEXP (op
, 0), 1),
4406 return XEXP (XEXP (op
, 0), 0);
4408 /* It can also be represented (for zero-extend) as an AND with an
4410 if (GET_CODE (op
) == AND
4411 && GET_CODE (XEXP (op
, 0)) == MULT
4412 && CONST_INT_P (XEXP (XEXP (op
, 0), 1))
4413 && CONST_INT_P (XEXP (op
, 1))
4414 && aarch64_uxt_size (exact_log2 (INTVAL (XEXP (XEXP (op
, 0), 1))),
4415 INTVAL (XEXP (op
, 1))) != 0)
4416 return XEXP (XEXP (op
, 0), 0);
4418 /* Now handle extended register, as this may also have an optional
4419 left shift by 1..4. */
4420 if (GET_CODE (op
) == ASHIFT
4421 && CONST_INT_P (XEXP (op
, 1))
4422 && ((unsigned HOST_WIDE_INT
) INTVAL (XEXP (op
, 1))) <= 4)
4425 if (GET_CODE (op
) == ZERO_EXTEND
4426 || GET_CODE (op
) == SIGN_EXTEND
)
4432 return aarch64_strip_shift (x
);
4435 /* Calculate the cost of calculating X, storing it in *COST. Result
4436 is true if the total cost of the operation has now been calculated. */
4438 aarch64_rtx_costs (rtx x
, int code
, int outer ATTRIBUTE_UNUSED
,
4439 int param ATTRIBUTE_UNUSED
, int *cost
, bool speed
)
4442 const struct cpu_rtx_cost_table
*extra_cost
4443 = aarch64_tune_params
->insn_extra_cost
;
4451 switch (GET_CODE (op0
))
4455 *cost
+= extra_cost
->memory_store
;
4457 if (op1
!= const0_rtx
)
4458 *cost
+= rtx_cost (op1
, SET
, 1, speed
);
4462 if (! REG_P (SUBREG_REG (op0
)))
4463 *cost
+= rtx_cost (SUBREG_REG (op0
), SET
, 0, speed
);
4466 /* Cost is just the cost of the RHS of the set. */
4467 *cost
+= rtx_cost (op1
, SET
, 1, true);
4470 case ZERO_EXTRACT
: /* Bit-field insertion. */
4472 /* Strip any redundant widening of the RHS to meet the width of
4474 if (GET_CODE (op1
) == SUBREG
)
4475 op1
= SUBREG_REG (op1
);
4476 if ((GET_CODE (op1
) == ZERO_EXTEND
4477 || GET_CODE (op1
) == SIGN_EXTEND
)
4478 && GET_CODE (XEXP (op0
, 1)) == CONST_INT
4479 && (GET_MODE_BITSIZE (GET_MODE (XEXP (op1
, 0)))
4480 >= INTVAL (XEXP (op0
, 1))))
4481 op1
= XEXP (op1
, 0);
4482 *cost
+= rtx_cost (op1
, SET
, 1, speed
);
4492 *cost
+= extra_cost
->memory_load
;
4497 op0
= CONST0_RTX (GET_MODE (x
));
4505 if (op1
== const0_rtx
4506 && GET_CODE (op0
) == AND
)
4512 /* Comparisons can work if the order is swapped.
4513 Canonicalization puts the more complex operation first, but
4514 we want it in op1. */
4516 || (GET_CODE (op0
) == SUBREG
&& REG_P (SUBREG_REG (op0
)))))
4528 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_INT
4529 || (GET_MODE_CLASS (GET_MODE (x
)) == MODE_CC
4530 && GET_MODE_CLASS (GET_MODE (op0
)) == MODE_INT
))
4532 if (op0
!= const0_rtx
)
4533 *cost
+= rtx_cost (op0
, MINUS
, 0, speed
);
4535 if (CONST_INT_P (op1
))
4537 if (!aarch64_uimm12_shift (INTVAL (op1
)))
4538 *cost
+= rtx_cost (op1
, MINUS
, 1, speed
);
4542 op1
= aarch64_strip_shift_or_extend (op1
);
4543 *cost
+= rtx_cost (op1
, MINUS
, 1, speed
);
4554 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_INT
)
4556 if (CONST_INT_P (op1
) && aarch64_uimm12_shift (INTVAL (op1
)))
4558 *cost
+= rtx_cost (op0
, PLUS
, 0, speed
);
4562 rtx new_op0
= aarch64_strip_shift_or_extend (op0
);
4565 && GET_CODE (op0
) == MULT
)
4567 if ((GET_CODE (XEXP (op0
, 0)) == ZERO_EXTEND
4568 && GET_CODE (XEXP (op0
, 1)) == ZERO_EXTEND
)
4569 || (GET_CODE (XEXP (op0
, 0)) == SIGN_EXTEND
4570 && GET_CODE (XEXP (op0
, 1)) == SIGN_EXTEND
))
4572 *cost
+= (rtx_cost (XEXP (XEXP (op0
, 0), 0), MULT
, 0,
4574 + rtx_cost (XEXP (XEXP (op0
, 1), 0), MULT
, 1,
4576 + rtx_cost (op1
, PLUS
, 1, speed
));
4578 *cost
+= extra_cost
->int_multiply_extend_add
;
4581 *cost
+= (rtx_cost (XEXP (op0
, 0), MULT
, 0, speed
)
4582 + rtx_cost (XEXP (op0
, 1), MULT
, 1, speed
)
4583 + rtx_cost (op1
, PLUS
, 1, speed
));
4586 *cost
+= extra_cost
->int_multiply_add
;
4589 *cost
+= (rtx_cost (new_op0
, PLUS
, 0, speed
)
4590 + rtx_cost (op1
, PLUS
, 1, speed
));
4604 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_INT
)
4606 if (CONST_INT_P (op1
)
4607 && aarch64_bitmask_imm (INTVAL (op1
), GET_MODE (x
)))
4609 *cost
+= rtx_cost (op0
, AND
, 0, speed
);
4613 if (GET_CODE (op0
) == NOT
)
4614 op0
= XEXP (op0
, 0);
4615 op0
= aarch64_strip_shift (op0
);
4616 *cost
+= (rtx_cost (op0
, AND
, 0, speed
)
4617 + rtx_cost (op1
, AND
, 1, speed
));
4624 if ((GET_MODE (x
) == DImode
4625 && GET_MODE (XEXP (x
, 0)) == SImode
)
4626 || GET_CODE (XEXP (x
, 0)) == MEM
)
4628 *cost
+= rtx_cost (XEXP (x
, 0), ZERO_EXTEND
, 0, speed
);
4634 if (GET_CODE (XEXP (x
, 0)) == MEM
)
4636 *cost
+= rtx_cost (XEXP (x
, 0), SIGN_EXTEND
, 0, speed
);
4642 if (!CONST_INT_P (XEXP (x
, 1)))
4643 *cost
+= COSTS_N_INSNS (2);
4650 /* Shifting by a register often takes an extra cycle. */
4651 if (speed
&& !CONST_INT_P (XEXP (x
, 1)))
4652 *cost
+= extra_cost
->register_shift
;
4654 *cost
+= rtx_cost (XEXP (x
, 0), ASHIFT
, 0, speed
);
4658 if (!CONSTANT_P (XEXP (x
, 0)))
4659 *cost
+= rtx_cost (XEXP (x
, 0), HIGH
, 0, speed
);
4663 if (!CONSTANT_P (XEXP (x
, 1)))
4664 *cost
+= rtx_cost (XEXP (x
, 1), LO_SUM
, 1, speed
);
4665 *cost
+= rtx_cost (XEXP (x
, 0), LO_SUM
, 0, speed
);
4670 *cost
+= rtx_cost (XEXP (x
, 0), ZERO_EXTRACT
, 0, speed
);
4677 *cost
= COSTS_N_INSNS (1);
4678 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_INT
)
4680 if (CONST_INT_P (op1
)
4681 && exact_log2 (INTVAL (op1
)) > 0)
4683 *cost
+= rtx_cost (op0
, ASHIFT
, 0, speed
);
4687 if ((GET_CODE (op0
) == ZERO_EXTEND
4688 && GET_CODE (op1
) == ZERO_EXTEND
)
4689 || (GET_CODE (op0
) == SIGN_EXTEND
4690 && GET_CODE (op1
) == SIGN_EXTEND
))
4692 *cost
+= (rtx_cost (XEXP (op0
, 0), MULT
, 0, speed
)
4693 + rtx_cost (XEXP (op1
, 0), MULT
, 1, speed
));
4695 *cost
+= extra_cost
->int_multiply_extend
;
4700 *cost
+= extra_cost
->int_multiply
;
4704 if (GET_MODE (x
) == DFmode
)
4705 *cost
+= extra_cost
->double_multiply
;
4706 else if (GET_MODE (x
) == SFmode
)
4707 *cost
+= extra_cost
->float_multiply
;
4710 return false; /* All arguments need to be in registers. */
4714 *cost
= COSTS_N_INSNS (2);
4717 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_INT
)
4718 *cost
+= (extra_cost
->int_multiply_add
4719 + extra_cost
->int_divide
);
4720 else if (GET_MODE (x
) == DFmode
)
4721 *cost
+= (extra_cost
->double_multiply
4722 + extra_cost
->double_divide
);
4723 else if (GET_MODE (x
) == SFmode
)
4724 *cost
+= (extra_cost
->float_multiply
4725 + extra_cost
->float_divide
);
4727 return false; /* All arguments need to be in registers. */
4731 *cost
= COSTS_N_INSNS (1);
4734 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_INT
)
4735 *cost
+= extra_cost
->int_divide
;
4736 else if (GET_MODE (x
) == DFmode
)
4737 *cost
+= extra_cost
->double_divide
;
4738 else if (GET_MODE (x
) == SFmode
)
4739 *cost
+= extra_cost
->float_divide
;
4741 return false; /* All arguments need to be in registers. */
4750 aarch64_address_cost (rtx x ATTRIBUTE_UNUSED
,
4751 enum machine_mode mode ATTRIBUTE_UNUSED
,
4752 addr_space_t as ATTRIBUTE_UNUSED
, bool speed ATTRIBUTE_UNUSED
)
4754 enum rtx_code c
= GET_CODE (x
);
4755 const struct cpu_addrcost_table
*addr_cost
= aarch64_tune_params
->addr_cost
;
4757 if (c
== PRE_INC
|| c
== PRE_DEC
|| c
== PRE_MODIFY
)
4758 return addr_cost
->pre_modify
;
4760 if (c
== POST_INC
|| c
== POST_DEC
|| c
== POST_MODIFY
)
4761 return addr_cost
->post_modify
;
4765 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
4766 return addr_cost
->imm_offset
;
4767 else if (GET_CODE (XEXP (x
, 0)) == MULT
4768 || GET_CODE (XEXP (x
, 0)) == ZERO_EXTEND
4769 || GET_CODE (XEXP (x
, 0)) == SIGN_EXTEND
)
4770 return addr_cost
->register_extend
;
4772 return addr_cost
->register_offset
;
4774 else if (c
== MEM
|| c
== LABEL_REF
|| c
== SYMBOL_REF
)
4775 return addr_cost
->imm_offset
;
4781 aarch64_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED
,
4782 reg_class_t from
, reg_class_t to
)
4784 const struct cpu_regmove_cost
*regmove_cost
4785 = aarch64_tune_params
->regmove_cost
;
4787 if (from
== GENERAL_REGS
&& to
== GENERAL_REGS
)
4788 return regmove_cost
->GP2GP
;
4789 else if (from
== GENERAL_REGS
)
4790 return regmove_cost
->GP2FP
;
4791 else if (to
== GENERAL_REGS
)
4792 return regmove_cost
->FP2GP
;
4794 /* When AdvSIMD instructions are disabled it is not possible to move
4795 a 128-bit value directly between Q registers. This is handled in
4796 secondary reload. A general register is used as a scratch to move
4797 the upper DI value and the lower DI value is moved directly,
4798 hence the cost is the sum of three moves. */
4800 if (! TARGET_SIMD
&& GET_MODE_SIZE (from
) == 128 && GET_MODE_SIZE (to
) == 128)
4801 return regmove_cost
->GP2FP
+ regmove_cost
->FP2GP
+ regmove_cost
->FP2FP
;
4803 return regmove_cost
->FP2FP
;
4807 aarch64_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED
,
4808 reg_class_t rclass ATTRIBUTE_UNUSED
,
4809 bool in ATTRIBUTE_UNUSED
)
4811 return aarch64_tune_params
->memmov_cost
;
4814 /* Vectorizer cost model target hooks. */
4816 /* Implement targetm.vectorize.builtin_vectorization_cost. */
4818 aarch64_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost
,
4820 int misalign ATTRIBUTE_UNUSED
)
4824 switch (type_of_cost
)
4827 return aarch64_tune_params
->vec_costs
->scalar_stmt_cost
;
4830 return aarch64_tune_params
->vec_costs
->scalar_load_cost
;
4833 return aarch64_tune_params
->vec_costs
->scalar_store_cost
;
4836 return aarch64_tune_params
->vec_costs
->vec_stmt_cost
;
4839 return aarch64_tune_params
->vec_costs
->vec_align_load_cost
;
4842 return aarch64_tune_params
->vec_costs
->vec_store_cost
;
4845 return aarch64_tune_params
->vec_costs
->vec_to_scalar_cost
;
4848 return aarch64_tune_params
->vec_costs
->scalar_to_vec_cost
;
4850 case unaligned_load
:
4851 return aarch64_tune_params
->vec_costs
->vec_unalign_load_cost
;
4853 case unaligned_store
:
4854 return aarch64_tune_params
->vec_costs
->vec_unalign_store_cost
;
4856 case cond_branch_taken
:
4857 return aarch64_tune_params
->vec_costs
->cond_taken_branch_cost
;
4859 case cond_branch_not_taken
:
4860 return aarch64_tune_params
->vec_costs
->cond_not_taken_branch_cost
;
4863 case vec_promote_demote
:
4864 return aarch64_tune_params
->vec_costs
->vec_stmt_cost
;
4867 elements
= TYPE_VECTOR_SUBPARTS (vectype
);
4868 return elements
/ 2 + 1;
4875 /* Implement targetm.vectorize.add_stmt_cost. */
4877 aarch64_add_stmt_cost (void *data
, int count
, enum vect_cost_for_stmt kind
,
4878 struct _stmt_vec_info
*stmt_info
, int misalign
,
4879 enum vect_cost_model_location where
)
4881 unsigned *cost
= (unsigned *) data
;
4882 unsigned retval
= 0;
4884 if (flag_vect_cost_model
)
4886 tree vectype
= stmt_info
? stmt_vectype (stmt_info
) : NULL_TREE
;
4888 aarch64_builtin_vectorization_cost (kind
, vectype
, misalign
);
4890 /* Statements in an inner loop relative to the loop being
4891 vectorized are weighted more heavily. The value here is
4892 a function (linear for now) of the loop nest level. */
4893 if (where
== vect_body
&& stmt_info
&& stmt_in_inner_loop_p (stmt_info
))
4895 loop_vec_info loop_info
= STMT_VINFO_LOOP_VINFO (stmt_info
);
4896 struct loop
*loop
= LOOP_VINFO_LOOP (loop_info
);
4897 unsigned nest_level
= loop_depth (loop
);
4899 count
*= nest_level
;
4902 retval
= (unsigned) (count
* stmt_cost
);
4903 cost
[where
] += retval
;
4909 static void initialize_aarch64_code_model (void);
4911 /* Parse the architecture extension string. */
4914 aarch64_parse_extension (char *str
)
4916 /* The extension string is parsed left to right. */
4917 const struct aarch64_option_extension
*opt
= NULL
;
4919 /* Flag to say whether we are adding or removing an extension. */
4920 int adding_ext
= -1;
4922 while (str
!= NULL
&& *str
!= 0)
4928 ext
= strchr (str
, '+');
4935 if (len
>= 2 && strncmp (str
, "no", 2) == 0)
4946 error ("missing feature modifier after %qs", "+no");
4950 /* Scan over the extensions table trying to find an exact match. */
4951 for (opt
= all_extensions
; opt
->name
!= NULL
; opt
++)
4953 if (strlen (opt
->name
) == len
&& strncmp (opt
->name
, str
, len
) == 0)
4955 /* Add or remove the extension. */
4957 aarch64_isa_flags
|= opt
->flags_on
;
4959 aarch64_isa_flags
&= ~(opt
->flags_off
);
4964 if (opt
->name
== NULL
)
4966 /* Extension not found in list. */
4967 error ("unknown feature modifier %qs", str
);
4977 /* Parse the ARCH string. */
4980 aarch64_parse_arch (void)
4983 const struct processor
*arch
;
4984 char *str
= (char *) alloca (strlen (aarch64_arch_string
) + 1);
4987 strcpy (str
, aarch64_arch_string
);
4989 ext
= strchr (str
, '+');
4998 error ("missing arch name in -march=%qs", str
);
5002 /* Loop through the list of supported ARCHs to find a match. */
5003 for (arch
= all_architectures
; arch
->name
!= NULL
; arch
++)
5005 if (strlen (arch
->name
) == len
&& strncmp (arch
->name
, str
, len
) == 0)
5007 selected_arch
= arch
;
5008 aarch64_isa_flags
= selected_arch
->flags
;
5009 selected_cpu
= &all_cores
[selected_arch
->core
];
5013 /* ARCH string contains at least one extension. */
5014 aarch64_parse_extension (ext
);
5021 /* ARCH name not found in list. */
5022 error ("unknown value %qs for -march", str
);
5026 /* Parse the CPU string. */
5029 aarch64_parse_cpu (void)
5032 const struct processor
*cpu
;
5033 char *str
= (char *) alloca (strlen (aarch64_cpu_string
) + 1);
5036 strcpy (str
, aarch64_cpu_string
);
5038 ext
= strchr (str
, '+');
5047 error ("missing cpu name in -mcpu=%qs", str
);
5051 /* Loop through the list of supported CPUs to find a match. */
5052 for (cpu
= all_cores
; cpu
->name
!= NULL
; cpu
++)
5054 if (strlen (cpu
->name
) == len
&& strncmp (cpu
->name
, str
, len
) == 0)
5057 aarch64_isa_flags
= selected_cpu
->flags
;
5061 /* CPU string contains at least one extension. */
5062 aarch64_parse_extension (ext
);
5069 /* CPU name not found in list. */
5070 error ("unknown value %qs for -mcpu", str
);
5074 /* Parse the TUNE string. */
5077 aarch64_parse_tune (void)
5079 const struct processor
*cpu
;
5080 char *str
= (char *) alloca (strlen (aarch64_tune_string
) + 1);
5081 strcpy (str
, aarch64_tune_string
);
5083 /* Loop through the list of supported CPUs to find a match. */
5084 for (cpu
= all_cores
; cpu
->name
!= NULL
; cpu
++)
5086 if (strcmp (cpu
->name
, str
) == 0)
5088 selected_tune
= cpu
;
5093 /* CPU name not found in list. */
5094 error ("unknown value %qs for -mtune", str
);
5099 /* Implement TARGET_OPTION_OVERRIDE. */
5102 aarch64_override_options (void)
5104 /* march wins over mcpu, so when march is defined, mcpu takes the same value,
5105 otherwise march remains undefined. mtune can be used with either march or
5108 if (aarch64_arch_string
)
5110 aarch64_parse_arch ();
5111 aarch64_cpu_string
= NULL
;
5114 if (aarch64_cpu_string
)
5116 aarch64_parse_cpu ();
5117 selected_arch
= NULL
;
5120 if (aarch64_tune_string
)
5122 aarch64_parse_tune ();
5125 initialize_aarch64_code_model ();
5127 aarch64_build_bitmask_table ();
5129 /* This target defaults to strict volatile bitfields. */
5130 if (flag_strict_volatile_bitfields
< 0 && abi_version_at_least (2))
5131 flag_strict_volatile_bitfields
= 1;
5133 /* If the user did not specify a processor, choose the default
5134 one for them. This will be the CPU set during configuration using
5135 --with-cpu, otherwise it is "generic". */
5138 selected_cpu
= &all_cores
[TARGET_CPU_DEFAULT
& 0x3f];
5139 aarch64_isa_flags
= TARGET_CPU_DEFAULT
>> 6;
5142 gcc_assert (selected_cpu
);
5144 /* The selected cpu may be an architecture, so lookup tuning by core ID. */
5146 selected_tune
= &all_cores
[selected_cpu
->core
];
5148 aarch64_tune_flags
= selected_tune
->flags
;
5149 aarch64_tune
= selected_tune
->core
;
5150 aarch64_tune_params
= selected_tune
->tune
;
5152 aarch64_override_options_after_change ();
5155 /* Implement targetm.override_options_after_change. */
5158 aarch64_override_options_after_change (void)
5160 faked_omit_frame_pointer
= false;
5162 /* To omit leaf frame pointers, we need to turn flag_omit_frame_pointer on so
5163 that aarch64_frame_pointer_required will be called. We need to remember
5164 whether flag_omit_frame_pointer was turned on normally or just faked. */
5166 if (flag_omit_leaf_frame_pointer
&& !flag_omit_frame_pointer
)
5168 flag_omit_frame_pointer
= true;
5169 faked_omit_frame_pointer
= true;
5173 static struct machine_function
*
5174 aarch64_init_machine_status (void)
5176 struct machine_function
*machine
;
5177 machine
= ggc_alloc_cleared_machine_function ();
5182 aarch64_init_expanders (void)
5184 init_machine_status
= aarch64_init_machine_status
;
5187 /* A checking mechanism for the implementation of the various code models. */
5189 initialize_aarch64_code_model (void)
5193 switch (aarch64_cmodel_var
)
5195 case AARCH64_CMODEL_TINY
:
5196 aarch64_cmodel
= AARCH64_CMODEL_TINY_PIC
;
5198 case AARCH64_CMODEL_SMALL
:
5199 aarch64_cmodel
= AARCH64_CMODEL_SMALL_PIC
;
5201 case AARCH64_CMODEL_LARGE
:
5202 sorry ("code model %qs with -f%s", "large",
5203 flag_pic
> 1 ? "PIC" : "pic");
5209 aarch64_cmodel
= aarch64_cmodel_var
;
5212 /* Return true if SYMBOL_REF X binds locally. */
5215 aarch64_symbol_binds_local_p (const_rtx x
)
5217 return (SYMBOL_REF_DECL (x
)
5218 ? targetm
.binds_local_p (SYMBOL_REF_DECL (x
))
5219 : SYMBOL_REF_LOCAL_P (x
));
5222 /* Return true if SYMBOL_REF X is thread local */
5224 aarch64_tls_symbol_p (rtx x
)
5226 if (! TARGET_HAVE_TLS
)
5229 if (GET_CODE (x
) != SYMBOL_REF
)
5232 return SYMBOL_REF_TLS_MODEL (x
) != 0;
5235 /* Classify a TLS symbol into one of the TLS kinds. */
5236 enum aarch64_symbol_type
5237 aarch64_classify_tls_symbol (rtx x
)
5239 enum tls_model tls_kind
= tls_symbolic_operand_type (x
);
5243 case TLS_MODEL_GLOBAL_DYNAMIC
:
5244 case TLS_MODEL_LOCAL_DYNAMIC
:
5245 return TARGET_TLS_DESC
? SYMBOL_SMALL_TLSDESC
: SYMBOL_SMALL_TLSGD
;
5247 case TLS_MODEL_INITIAL_EXEC
:
5248 return SYMBOL_SMALL_GOTTPREL
;
5250 case TLS_MODEL_LOCAL_EXEC
:
5251 return SYMBOL_SMALL_TPREL
;
5253 case TLS_MODEL_EMULATED
:
5254 case TLS_MODEL_NONE
:
5255 return SYMBOL_FORCE_TO_MEM
;
5262 /* Return the method that should be used to access SYMBOL_REF or
5263 LABEL_REF X in context CONTEXT. */
5265 enum aarch64_symbol_type
5266 aarch64_classify_symbol (rtx x
,
5267 enum aarch64_symbol_context context ATTRIBUTE_UNUSED
)
5269 if (GET_CODE (x
) == LABEL_REF
)
5271 switch (aarch64_cmodel
)
5273 case AARCH64_CMODEL_LARGE
:
5274 return SYMBOL_FORCE_TO_MEM
;
5276 case AARCH64_CMODEL_TINY_PIC
:
5277 case AARCH64_CMODEL_TINY
:
5278 return SYMBOL_TINY_ABSOLUTE
;
5280 case AARCH64_CMODEL_SMALL_PIC
:
5281 case AARCH64_CMODEL_SMALL
:
5282 return SYMBOL_SMALL_ABSOLUTE
;
5289 if (GET_CODE (x
) == SYMBOL_REF
)
5291 if (aarch64_cmodel
== AARCH64_CMODEL_LARGE
5292 || CONSTANT_POOL_ADDRESS_P (x
))
5293 return SYMBOL_FORCE_TO_MEM
;
5295 if (aarch64_tls_symbol_p (x
))
5296 return aarch64_classify_tls_symbol (x
);
5298 switch (aarch64_cmodel
)
5300 case AARCH64_CMODEL_TINY
:
5301 if (SYMBOL_REF_WEAK (x
))
5302 return SYMBOL_FORCE_TO_MEM
;
5303 return SYMBOL_TINY_ABSOLUTE
;
5305 case AARCH64_CMODEL_SMALL
:
5306 if (SYMBOL_REF_WEAK (x
))
5307 return SYMBOL_FORCE_TO_MEM
;
5308 return SYMBOL_SMALL_ABSOLUTE
;
5310 case AARCH64_CMODEL_TINY_PIC
:
5311 if (!aarch64_symbol_binds_local_p (x
))
5312 return SYMBOL_TINY_GOT
;
5313 return SYMBOL_TINY_ABSOLUTE
;
5315 case AARCH64_CMODEL_SMALL_PIC
:
5316 if (!aarch64_symbol_binds_local_p (x
))
5317 return SYMBOL_SMALL_GOT
;
5318 return SYMBOL_SMALL_ABSOLUTE
;
5325 /* By default push everything into the constant pool. */
5326 return SYMBOL_FORCE_TO_MEM
;
5330 aarch64_constant_address_p (rtx x
)
5332 return (CONSTANT_P (x
) && memory_address_p (DImode
, x
));
5336 aarch64_legitimate_pic_operand_p (rtx x
)
5338 if (GET_CODE (x
) == SYMBOL_REF
5339 || (GET_CODE (x
) == CONST
5340 && GET_CODE (XEXP (x
, 0)) == PLUS
5341 && GET_CODE (XEXP (XEXP (x
, 0), 0)) == SYMBOL_REF
))
5347 /* Return true if X holds either a quarter-precision or
5348 floating-point +0.0 constant. */
5350 aarch64_valid_floating_const (enum machine_mode mode
, rtx x
)
5352 if (!CONST_DOUBLE_P (x
))
5355 /* TODO: We could handle moving 0.0 to a TFmode register,
5356 but first we would like to refactor the movtf_aarch64
5357 to be more amicable to split moves properly and
5358 correctly gate on TARGET_SIMD. For now - reject all
5359 constants which are not to SFmode or DFmode registers. */
5360 if (!(mode
== SFmode
|| mode
== DFmode
))
5363 if (aarch64_float_const_zero_rtx_p (x
))
5365 return aarch64_float_const_representable_p (x
);
5369 aarch64_legitimate_constant_p (enum machine_mode mode
, rtx x
)
5371 /* Do not allow vector struct mode constants. We could support
5372 0 and -1 easily, but they need support in aarch64-simd.md. */
5373 if (TARGET_SIMD
&& aarch64_vect_struct_mode_p (mode
))
5376 /* This could probably go away because
5377 we now decompose CONST_INTs according to expand_mov_immediate. */
5378 if ((GET_CODE (x
) == CONST_VECTOR
5379 && aarch64_simd_valid_immediate (x
, mode
, false, NULL
))
5380 || CONST_INT_P (x
) || aarch64_valid_floating_const (mode
, x
))
5381 return !targetm
.cannot_force_const_mem (mode
, x
);
5383 if (GET_CODE (x
) == HIGH
5384 && aarch64_valid_symref (XEXP (x
, 0), GET_MODE (XEXP (x
, 0))))
5387 return aarch64_constant_address_p (x
);
5391 aarch64_load_tp (rtx target
)
5394 || GET_MODE (target
) != Pmode
5395 || !register_operand (target
, Pmode
))
5396 target
= gen_reg_rtx (Pmode
);
5398 /* Can return in any reg. */
5399 emit_insn (gen_aarch64_load_tp_hard (target
));
5403 /* On AAPCS systems, this is the "struct __va_list". */
5404 static GTY(()) tree va_list_type
;
5406 /* Implement TARGET_BUILD_BUILTIN_VA_LIST.
5407 Return the type to use as __builtin_va_list.
5409 AAPCS64 \S 7.1.4 requires that va_list be a typedef for a type defined as:
5421 aarch64_build_builtin_va_list (void)
5424 tree f_stack
, f_grtop
, f_vrtop
, f_groff
, f_vroff
;
5426 /* Create the type. */
5427 va_list_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
5428 /* Give it the required name. */
5429 va_list_name
= build_decl (BUILTINS_LOCATION
,
5431 get_identifier ("__va_list"),
5433 DECL_ARTIFICIAL (va_list_name
) = 1;
5434 TYPE_NAME (va_list_type
) = va_list_name
;
5435 TYPE_STUB_DECL (va_list_type
) = va_list_name
;
5437 /* Create the fields. */
5438 f_stack
= build_decl (BUILTINS_LOCATION
,
5439 FIELD_DECL
, get_identifier ("__stack"),
5441 f_grtop
= build_decl (BUILTINS_LOCATION
,
5442 FIELD_DECL
, get_identifier ("__gr_top"),
5444 f_vrtop
= build_decl (BUILTINS_LOCATION
,
5445 FIELD_DECL
, get_identifier ("__vr_top"),
5447 f_groff
= build_decl (BUILTINS_LOCATION
,
5448 FIELD_DECL
, get_identifier ("__gr_offs"),
5450 f_vroff
= build_decl (BUILTINS_LOCATION
,
5451 FIELD_DECL
, get_identifier ("__vr_offs"),
5454 DECL_ARTIFICIAL (f_stack
) = 1;
5455 DECL_ARTIFICIAL (f_grtop
) = 1;
5456 DECL_ARTIFICIAL (f_vrtop
) = 1;
5457 DECL_ARTIFICIAL (f_groff
) = 1;
5458 DECL_ARTIFICIAL (f_vroff
) = 1;
5460 DECL_FIELD_CONTEXT (f_stack
) = va_list_type
;
5461 DECL_FIELD_CONTEXT (f_grtop
) = va_list_type
;
5462 DECL_FIELD_CONTEXT (f_vrtop
) = va_list_type
;
5463 DECL_FIELD_CONTEXT (f_groff
) = va_list_type
;
5464 DECL_FIELD_CONTEXT (f_vroff
) = va_list_type
;
5466 TYPE_FIELDS (va_list_type
) = f_stack
;
5467 DECL_CHAIN (f_stack
) = f_grtop
;
5468 DECL_CHAIN (f_grtop
) = f_vrtop
;
5469 DECL_CHAIN (f_vrtop
) = f_groff
;
5470 DECL_CHAIN (f_groff
) = f_vroff
;
5472 /* Compute its layout. */
5473 layout_type (va_list_type
);
5475 return va_list_type
;
5478 /* Implement TARGET_EXPAND_BUILTIN_VA_START. */
5480 aarch64_expand_builtin_va_start (tree valist
, rtx nextarg ATTRIBUTE_UNUSED
)
5482 const CUMULATIVE_ARGS
*cum
;
5483 tree f_stack
, f_grtop
, f_vrtop
, f_groff
, f_vroff
;
5484 tree stack
, grtop
, vrtop
, groff
, vroff
;
5486 int gr_save_area_size
;
5487 int vr_save_area_size
;
5490 cum
= &crtl
->args
.info
;
5492 = (NUM_ARG_REGS
- cum
->aapcs_ncrn
) * UNITS_PER_WORD
;
5494 = (NUM_FP_ARG_REGS
- cum
->aapcs_nvrn
) * UNITS_PER_VREG
;
5496 if (TARGET_GENERAL_REGS_ONLY
)
5498 if (cum
->aapcs_nvrn
> 0)
5499 sorry ("%qs and floating point or vector arguments",
5500 "-mgeneral-regs-only");
5501 vr_save_area_size
= 0;
5504 f_stack
= TYPE_FIELDS (va_list_type_node
);
5505 f_grtop
= DECL_CHAIN (f_stack
);
5506 f_vrtop
= DECL_CHAIN (f_grtop
);
5507 f_groff
= DECL_CHAIN (f_vrtop
);
5508 f_vroff
= DECL_CHAIN (f_groff
);
5510 stack
= build3 (COMPONENT_REF
, TREE_TYPE (f_stack
), valist
, f_stack
,
5512 grtop
= build3 (COMPONENT_REF
, TREE_TYPE (f_grtop
), valist
, f_grtop
,
5514 vrtop
= build3 (COMPONENT_REF
, TREE_TYPE (f_vrtop
), valist
, f_vrtop
,
5516 groff
= build3 (COMPONENT_REF
, TREE_TYPE (f_groff
), valist
, f_groff
,
5518 vroff
= build3 (COMPONENT_REF
, TREE_TYPE (f_vroff
), valist
, f_vroff
,
5521 /* Emit code to initialize STACK, which points to the next varargs stack
5522 argument. CUM->AAPCS_STACK_SIZE gives the number of stack words used
5523 by named arguments. STACK is 8-byte aligned. */
5524 t
= make_tree (TREE_TYPE (stack
), virtual_incoming_args_rtx
);
5525 if (cum
->aapcs_stack_size
> 0)
5526 t
= fold_build_pointer_plus_hwi (t
, cum
->aapcs_stack_size
* UNITS_PER_WORD
);
5527 t
= build2 (MODIFY_EXPR
, TREE_TYPE (stack
), stack
, t
);
5528 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
5530 /* Emit code to initialize GRTOP, the top of the GR save area.
5531 virtual_incoming_args_rtx should have been 16 byte aligned. */
5532 t
= make_tree (TREE_TYPE (grtop
), virtual_incoming_args_rtx
);
5533 t
= build2 (MODIFY_EXPR
, TREE_TYPE (grtop
), grtop
, t
);
5534 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
5536 /* Emit code to initialize VRTOP, the top of the VR save area.
5537 This address is gr_save_area_bytes below GRTOP, rounded
5538 down to the next 16-byte boundary. */
5539 t
= make_tree (TREE_TYPE (vrtop
), virtual_incoming_args_rtx
);
5540 vr_offset
= AARCH64_ROUND_UP (gr_save_area_size
,
5541 STACK_BOUNDARY
/ BITS_PER_UNIT
);
5544 t
= fold_build_pointer_plus_hwi (t
, -vr_offset
);
5545 t
= build2 (MODIFY_EXPR
, TREE_TYPE (vrtop
), vrtop
, t
);
5546 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
5548 /* Emit code to initialize GROFF, the offset from GRTOP of the
5549 next GPR argument. */
5550 t
= build2 (MODIFY_EXPR
, TREE_TYPE (groff
), groff
,
5551 build_int_cst (TREE_TYPE (groff
), -gr_save_area_size
));
5552 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
5554 /* Likewise emit code to initialize VROFF, the offset from FTOP
5555 of the next VR argument. */
5556 t
= build2 (MODIFY_EXPR
, TREE_TYPE (vroff
), vroff
,
5557 build_int_cst (TREE_TYPE (vroff
), -vr_save_area_size
));
5558 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
5561 /* Implement TARGET_GIMPLIFY_VA_ARG_EXPR. */
5564 aarch64_gimplify_va_arg_expr (tree valist
, tree type
, gimple_seq
*pre_p
,
5565 gimple_seq
*post_p ATTRIBUTE_UNUSED
)
5569 bool is_ha
; /* is HFA or HVA. */
5570 bool dw_align
; /* double-word align. */
5571 enum machine_mode ag_mode
= VOIDmode
;
5573 enum machine_mode mode
;
5575 tree f_stack
, f_grtop
, f_vrtop
, f_groff
, f_vroff
;
5576 tree stack
, f_top
, f_off
, off
, arg
, roundup
, on_stack
;
5577 HOST_WIDE_INT size
, rsize
, adjust
, align
;
5578 tree t
, u
, cond1
, cond2
;
5580 indirect_p
= pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
5582 type
= build_pointer_type (type
);
5584 mode
= TYPE_MODE (type
);
5586 f_stack
= TYPE_FIELDS (va_list_type_node
);
5587 f_grtop
= DECL_CHAIN (f_stack
);
5588 f_vrtop
= DECL_CHAIN (f_grtop
);
5589 f_groff
= DECL_CHAIN (f_vrtop
);
5590 f_vroff
= DECL_CHAIN (f_groff
);
5592 stack
= build3 (COMPONENT_REF
, TREE_TYPE (f_stack
), unshare_expr (valist
),
5593 f_stack
, NULL_TREE
);
5594 size
= int_size_in_bytes (type
);
5595 align
= aarch64_function_arg_alignment (mode
, type
) / BITS_PER_UNIT
;
5599 if (aarch64_vfp_is_call_or_return_candidate (mode
,
5605 /* TYPE passed in fp/simd registers. */
5606 if (TARGET_GENERAL_REGS_ONLY
)
5607 sorry ("%qs and floating point or vector arguments",
5608 "-mgeneral-regs-only");
5610 f_top
= build3 (COMPONENT_REF
, TREE_TYPE (f_vrtop
),
5611 unshare_expr (valist
), f_vrtop
, NULL_TREE
);
5612 f_off
= build3 (COMPONENT_REF
, TREE_TYPE (f_vroff
),
5613 unshare_expr (valist
), f_vroff
, NULL_TREE
);
5615 rsize
= nregs
* UNITS_PER_VREG
;
5619 if (BYTES_BIG_ENDIAN
&& GET_MODE_SIZE (ag_mode
) < UNITS_PER_VREG
)
5620 adjust
= UNITS_PER_VREG
- GET_MODE_SIZE (ag_mode
);
5622 else if (BLOCK_REG_PADDING (mode
, type
, 1) == downward
5623 && size
< UNITS_PER_VREG
)
5625 adjust
= UNITS_PER_VREG
- size
;
5630 /* TYPE passed in general registers. */
5631 f_top
= build3 (COMPONENT_REF
, TREE_TYPE (f_grtop
),
5632 unshare_expr (valist
), f_grtop
, NULL_TREE
);
5633 f_off
= build3 (COMPONENT_REF
, TREE_TYPE (f_groff
),
5634 unshare_expr (valist
), f_groff
, NULL_TREE
);
5635 rsize
= (size
+ UNITS_PER_WORD
- 1) & -UNITS_PER_WORD
;
5636 nregs
= rsize
/ UNITS_PER_WORD
;
5641 if (BLOCK_REG_PADDING (mode
, type
, 1) == downward
5642 && size
< UNITS_PER_WORD
)
5644 adjust
= UNITS_PER_WORD
- size
;
5648 /* Get a local temporary for the field value. */
5649 off
= get_initialized_tmp_var (f_off
, pre_p
, NULL
);
5651 /* Emit code to branch if off >= 0. */
5652 t
= build2 (GE_EXPR
, boolean_type_node
, off
,
5653 build_int_cst (TREE_TYPE (off
), 0));
5654 cond1
= build3 (COND_EXPR
, ptr_type_node
, t
, NULL_TREE
, NULL_TREE
);
5658 /* Emit: offs = (offs + 15) & -16. */
5659 t
= build2 (PLUS_EXPR
, TREE_TYPE (off
), off
,
5660 build_int_cst (TREE_TYPE (off
), 15));
5661 t
= build2 (BIT_AND_EXPR
, TREE_TYPE (off
), t
,
5662 build_int_cst (TREE_TYPE (off
), -16));
5663 roundup
= build2 (MODIFY_EXPR
, TREE_TYPE (off
), off
, t
);
5668 /* Update ap.__[g|v]r_offs */
5669 t
= build2 (PLUS_EXPR
, TREE_TYPE (off
), off
,
5670 build_int_cst (TREE_TYPE (off
), rsize
));
5671 t
= build2 (MODIFY_EXPR
, TREE_TYPE (f_off
), unshare_expr (f_off
), t
);
5675 t
= build2 (COMPOUND_EXPR
, TREE_TYPE (t
), roundup
, t
);
5677 /* [cond2] if (ap.__[g|v]r_offs > 0) */
5678 u
= build2 (GT_EXPR
, boolean_type_node
, unshare_expr (f_off
),
5679 build_int_cst (TREE_TYPE (f_off
), 0));
5680 cond2
= build3 (COND_EXPR
, ptr_type_node
, u
, NULL_TREE
, NULL_TREE
);
5682 /* String up: make sure the assignment happens before the use. */
5683 t
= build2 (COMPOUND_EXPR
, TREE_TYPE (cond2
), t
, cond2
);
5684 COND_EXPR_ELSE (cond1
) = t
;
5686 /* Prepare the trees handling the argument that is passed on the stack;
5687 the top level node will store in ON_STACK. */
5688 arg
= get_initialized_tmp_var (stack
, pre_p
, NULL
);
5691 /* if (alignof(type) > 8) (arg = arg + 15) & -16; */
5692 t
= fold_convert (intDI_type_node
, arg
);
5693 t
= build2 (PLUS_EXPR
, TREE_TYPE (t
), t
,
5694 build_int_cst (TREE_TYPE (t
), 15));
5695 t
= build2 (BIT_AND_EXPR
, TREE_TYPE (t
), t
,
5696 build_int_cst (TREE_TYPE (t
), -16));
5697 t
= fold_convert (TREE_TYPE (arg
), t
);
5698 roundup
= build2 (MODIFY_EXPR
, TREE_TYPE (arg
), arg
, t
);
5702 /* Advance ap.__stack */
5703 t
= fold_convert (intDI_type_node
, arg
);
5704 t
= build2 (PLUS_EXPR
, TREE_TYPE (t
), t
,
5705 build_int_cst (TREE_TYPE (t
), size
+ 7));
5706 t
= build2 (BIT_AND_EXPR
, TREE_TYPE (t
), t
,
5707 build_int_cst (TREE_TYPE (t
), -8));
5708 t
= fold_convert (TREE_TYPE (arg
), t
);
5709 t
= build2 (MODIFY_EXPR
, TREE_TYPE (stack
), unshare_expr (stack
), t
);
5710 /* String up roundup and advance. */
5712 t
= build2 (COMPOUND_EXPR
, TREE_TYPE (t
), roundup
, t
);
5713 /* String up with arg */
5714 on_stack
= build2 (COMPOUND_EXPR
, TREE_TYPE (arg
), t
, arg
);
5715 /* Big-endianness related address adjustment. */
5716 if (BLOCK_REG_PADDING (mode
, type
, 1) == downward
5717 && size
< UNITS_PER_WORD
)
5719 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (arg
), arg
,
5720 size_int (UNITS_PER_WORD
- size
));
5721 on_stack
= build2 (COMPOUND_EXPR
, TREE_TYPE (arg
), on_stack
, t
);
5724 COND_EXPR_THEN (cond1
) = unshare_expr (on_stack
);
5725 COND_EXPR_THEN (cond2
) = unshare_expr (on_stack
);
5727 /* Adjustment to OFFSET in the case of BIG_ENDIAN. */
5730 t
= build2 (PREINCREMENT_EXPR
, TREE_TYPE (off
), off
,
5731 build_int_cst (TREE_TYPE (off
), adjust
));
5733 t
= fold_convert (sizetype
, t
);
5734 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (f_top
), f_top
, t
);
5738 /* type ha; // treat as "struct {ftype field[n];}"
5739 ... [computing offs]
5740 for (i = 0; i <nregs; ++i, offs += 16)
5741 ha.field[i] = *((ftype *)(ap.__vr_top + offs));
5744 tree tmp_ha
, field_t
, field_ptr_t
;
5746 /* Declare a local variable. */
5747 tmp_ha
= create_tmp_var_raw (type
, "ha");
5748 gimple_add_tmp_var (tmp_ha
);
5750 /* Establish the base type. */
5754 field_t
= float_type_node
;
5755 field_ptr_t
= float_ptr_type_node
;
5758 field_t
= double_type_node
;
5759 field_ptr_t
= double_ptr_type_node
;
5762 field_t
= long_double_type_node
;
5763 field_ptr_t
= long_double_ptr_type_node
;
5765 /* The half precision and quad precision are not fully supported yet. Enable
5766 the following code after the support is complete. Need to find the correct
5767 type node for __fp16 *. */
5770 field_t
= float_type_node
;
5771 field_ptr_t
= float_ptr_type_node
;
5777 tree innertype
= make_signed_type (GET_MODE_PRECISION (SImode
));
5778 field_t
= build_vector_type_for_mode (innertype
, ag_mode
);
5779 field_ptr_t
= build_pointer_type (field_t
);
5786 /* *(field_ptr_t)&ha = *((field_ptr_t)vr_saved_area */
5787 tmp_ha
= build1 (ADDR_EXPR
, field_ptr_t
, tmp_ha
);
5789 t
= fold_convert (field_ptr_t
, addr
);
5790 t
= build2 (MODIFY_EXPR
, field_t
,
5791 build1 (INDIRECT_REF
, field_t
, tmp_ha
),
5792 build1 (INDIRECT_REF
, field_t
, t
));
5794 /* ha.field[i] = *((field_ptr_t)vr_saved_area + i) */
5795 for (i
= 1; i
< nregs
; ++i
)
5797 addr
= fold_build_pointer_plus_hwi (addr
, UNITS_PER_VREG
);
5798 u
= fold_convert (field_ptr_t
, addr
);
5799 u
= build2 (MODIFY_EXPR
, field_t
,
5800 build2 (MEM_REF
, field_t
, tmp_ha
,
5801 build_int_cst (field_ptr_t
,
5803 int_size_in_bytes (field_t
)))),
5804 build1 (INDIRECT_REF
, field_t
, u
));
5805 t
= build2 (COMPOUND_EXPR
, TREE_TYPE (t
), t
, u
);
5808 u
= fold_convert (TREE_TYPE (f_top
), tmp_ha
);
5809 t
= build2 (COMPOUND_EXPR
, TREE_TYPE (f_top
), t
, u
);
5812 COND_EXPR_ELSE (cond2
) = t
;
5813 addr
= fold_convert (build_pointer_type (type
), cond1
);
5814 addr
= build_va_arg_indirect_ref (addr
);
5817 addr
= build_va_arg_indirect_ref (addr
);
5822 /* Implement TARGET_SETUP_INCOMING_VARARGS. */
5825 aarch64_setup_incoming_varargs (cumulative_args_t cum_v
, enum machine_mode mode
,
5826 tree type
, int *pretend_size ATTRIBUTE_UNUSED
,
5829 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
5830 CUMULATIVE_ARGS local_cum
;
5831 int gr_saved
, vr_saved
;
5833 /* The caller has advanced CUM up to, but not beyond, the last named
5834 argument. Advance a local copy of CUM past the last "real" named
5835 argument, to find out how many registers are left over. */
5837 aarch64_function_arg_advance (pack_cumulative_args(&local_cum
), mode
, type
, true);
5839 /* Found out how many registers we need to save. */
5840 gr_saved
= NUM_ARG_REGS
- local_cum
.aapcs_ncrn
;
5841 vr_saved
= NUM_FP_ARG_REGS
- local_cum
.aapcs_nvrn
;
5843 if (TARGET_GENERAL_REGS_ONLY
)
5845 if (local_cum
.aapcs_nvrn
> 0)
5846 sorry ("%qs and floating point or vector arguments",
5847 "-mgeneral-regs-only");
5857 /* virtual_incoming_args_rtx should have been 16-byte aligned. */
5858 ptr
= plus_constant (Pmode
, virtual_incoming_args_rtx
,
5859 - gr_saved
* UNITS_PER_WORD
);
5860 mem
= gen_frame_mem (BLKmode
, ptr
);
5861 set_mem_alias_set (mem
, get_varargs_alias_set ());
5863 move_block_from_reg (local_cum
.aapcs_ncrn
+ R0_REGNUM
,
5868 /* We can't use move_block_from_reg, because it will use
5869 the wrong mode, storing D regs only. */
5870 enum machine_mode mode
= TImode
;
5873 /* Set OFF to the offset from virtual_incoming_args_rtx of
5874 the first vector register. The VR save area lies below
5875 the GR one, and is aligned to 16 bytes. */
5876 off
= -AARCH64_ROUND_UP (gr_saved
* UNITS_PER_WORD
,
5877 STACK_BOUNDARY
/ BITS_PER_UNIT
);
5878 off
-= vr_saved
* UNITS_PER_VREG
;
5880 for (i
= local_cum
.aapcs_nvrn
; i
< NUM_FP_ARG_REGS
; ++i
)
5884 ptr
= plus_constant (Pmode
, virtual_incoming_args_rtx
, off
);
5885 mem
= gen_frame_mem (mode
, ptr
);
5886 set_mem_alias_set (mem
, get_varargs_alias_set ());
5887 aarch64_emit_move (mem
, gen_rtx_REG (mode
, V0_REGNUM
+ i
));
5888 off
+= UNITS_PER_VREG
;
5893 /* We don't save the size into *PRETEND_SIZE because we want to avoid
5894 any complication of having crtl->args.pretend_args_size changed. */
5895 cfun
->machine
->saved_varargs_size
5896 = (AARCH64_ROUND_UP (gr_saved
* UNITS_PER_WORD
,
5897 STACK_BOUNDARY
/ BITS_PER_UNIT
)
5898 + vr_saved
* UNITS_PER_VREG
);
5902 aarch64_conditional_register_usage (void)
5907 for (i
= V0_REGNUM
; i
<= V31_REGNUM
; i
++)
5910 call_used_regs
[i
] = 1;
5915 /* Walk down the type tree of TYPE counting consecutive base elements.
5916 If *MODEP is VOIDmode, then set it to the first valid floating point
5917 type. If a non-floating point type is found, or if a floating point
5918 type that doesn't match a non-VOIDmode *MODEP is found, then return -1,
5919 otherwise return the count in the sub-tree. */
5921 aapcs_vfp_sub_candidate (const_tree type
, enum machine_mode
*modep
)
5923 enum machine_mode mode
;
5926 switch (TREE_CODE (type
))
5929 mode
= TYPE_MODE (type
);
5930 if (mode
!= DFmode
&& mode
!= SFmode
&& mode
!= TFmode
)
5933 if (*modep
== VOIDmode
)
5942 mode
= TYPE_MODE (TREE_TYPE (type
));
5943 if (mode
!= DFmode
&& mode
!= SFmode
&& mode
!= TFmode
)
5946 if (*modep
== VOIDmode
)
5955 /* Use V2SImode and V4SImode as representatives of all 64-bit
5956 and 128-bit vector types. */
5957 size
= int_size_in_bytes (type
);
5970 if (*modep
== VOIDmode
)
5973 /* Vector modes are considered to be opaque: two vectors are
5974 equivalent for the purposes of being homogeneous aggregates
5975 if they are the same size. */
5984 tree index
= TYPE_DOMAIN (type
);
5986 /* Can't handle incomplete types. */
5987 if (!COMPLETE_TYPE_P (type
))
5990 count
= aapcs_vfp_sub_candidate (TREE_TYPE (type
), modep
);
5993 || !TYPE_MAX_VALUE (index
)
5994 || !host_integerp (TYPE_MAX_VALUE (index
), 1)
5995 || !TYPE_MIN_VALUE (index
)
5996 || !host_integerp (TYPE_MIN_VALUE (index
), 1)
6000 count
*= (1 + tree_low_cst (TYPE_MAX_VALUE (index
), 1)
6001 - tree_low_cst (TYPE_MIN_VALUE (index
), 1));
6003 /* There must be no padding. */
6004 if (!host_integerp (TYPE_SIZE (type
), 1)
6005 || (tree_low_cst (TYPE_SIZE (type
), 1)
6006 != count
* GET_MODE_BITSIZE (*modep
)))
6018 /* Can't handle incomplete types. */
6019 if (!COMPLETE_TYPE_P (type
))
6022 for (field
= TYPE_FIELDS (type
); field
; field
= TREE_CHAIN (field
))
6024 if (TREE_CODE (field
) != FIELD_DECL
)
6027 sub_count
= aapcs_vfp_sub_candidate (TREE_TYPE (field
), modep
);
6033 /* There must be no padding. */
6034 if (!host_integerp (TYPE_SIZE (type
), 1)
6035 || (tree_low_cst (TYPE_SIZE (type
), 1)
6036 != count
* GET_MODE_BITSIZE (*modep
)))
6043 case QUAL_UNION_TYPE
:
6045 /* These aren't very interesting except in a degenerate case. */
6050 /* Can't handle incomplete types. */
6051 if (!COMPLETE_TYPE_P (type
))
6054 for (field
= TYPE_FIELDS (type
); field
; field
= TREE_CHAIN (field
))
6056 if (TREE_CODE (field
) != FIELD_DECL
)
6059 sub_count
= aapcs_vfp_sub_candidate (TREE_TYPE (field
), modep
);
6062 count
= count
> sub_count
? count
: sub_count
;
6065 /* There must be no padding. */
6066 if (!host_integerp (TYPE_SIZE (type
), 1)
6067 || (tree_low_cst (TYPE_SIZE (type
), 1)
6068 != count
* GET_MODE_BITSIZE (*modep
)))
6081 /* Return TRUE if the type, as described by TYPE and MODE, is a composite
6082 type as described in AAPCS64 \S 4.3. This includes aggregate, union and
6083 array types. The C99 floating-point complex types are also considered
6084 as composite types, according to AAPCS64 \S 7.1.1. The complex integer
6085 types, which are GCC extensions and out of the scope of AAPCS64, are
6086 treated as composite types here as well.
6088 Note that MODE itself is not sufficient in determining whether a type
6089 is such a composite type or not. This is because
6090 stor-layout.c:compute_record_mode may have already changed the MODE
6091 (BLKmode) of a RECORD_TYPE TYPE to some other mode. For example, a
6092 structure with only one field may have its MODE set to the mode of the
6093 field. Also an integer mode whose size matches the size of the
6094 RECORD_TYPE type may be used to substitute the original mode
6095 (i.e. BLKmode) in certain circumstances. In other words, MODE cannot be
6096 solely relied on. */
6099 aarch64_composite_type_p (const_tree type
,
6100 enum machine_mode mode
)
6102 if (type
&& (AGGREGATE_TYPE_P (type
) || TREE_CODE (type
) == COMPLEX_TYPE
))
6106 || GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
6107 || GET_MODE_CLASS (mode
) == MODE_COMPLEX_INT
)
6113 /* Return TRUE if the type, as described by TYPE and MODE, is a short vector
6114 type as described in AAPCS64 \S 4.1.2.
6116 See the comment above aarch64_composite_type_p for the notes on MODE. */
6119 aarch64_short_vector_p (const_tree type
,
6120 enum machine_mode mode
)
6122 HOST_WIDE_INT size
= -1;
6124 if (type
&& TREE_CODE (type
) == VECTOR_TYPE
)
6125 size
= int_size_in_bytes (type
);
6126 else if (!aarch64_composite_type_p (type
, mode
)
6127 && (GET_MODE_CLASS (mode
) == MODE_VECTOR_INT
6128 || GET_MODE_CLASS (mode
) == MODE_VECTOR_FLOAT
))
6129 size
= GET_MODE_SIZE (mode
);
6131 return (size
== 8 || size
== 16) ? true : false;
6134 /* Return TRUE if an argument, whose type is described by TYPE and MODE,
6135 shall be passed or returned in simd/fp register(s) (providing these
6136 parameter passing registers are available).
6138 Upon successful return, *COUNT returns the number of needed registers,
6139 *BASE_MODE returns the mode of the individual register and when IS_HAF
6140 is not NULL, *IS_HA indicates whether or not the argument is a homogeneous
6141 floating-point aggregate or a homogeneous short-vector aggregate. */
6144 aarch64_vfp_is_call_or_return_candidate (enum machine_mode mode
,
6146 enum machine_mode
*base_mode
,
6150 enum machine_mode new_mode
= VOIDmode
;
6151 bool composite_p
= aarch64_composite_type_p (type
, mode
);
6153 if (is_ha
!= NULL
) *is_ha
= false;
6155 if ((!composite_p
&& GET_MODE_CLASS (mode
) == MODE_FLOAT
)
6156 || aarch64_short_vector_p (type
, mode
))
6161 else if (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
)
6163 if (is_ha
!= NULL
) *is_ha
= true;
6165 new_mode
= GET_MODE_INNER (mode
);
6167 else if (type
&& composite_p
)
6169 int ag_count
= aapcs_vfp_sub_candidate (type
, &new_mode
);
6171 if (ag_count
> 0 && ag_count
<= HA_MAX_NUM_FLDS
)
6173 if (is_ha
!= NULL
) *is_ha
= true;
6182 *base_mode
= new_mode
;
6186 /* Implement TARGET_STRUCT_VALUE_RTX. */
6189 aarch64_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED
,
6190 int incoming ATTRIBUTE_UNUSED
)
6192 return gen_rtx_REG (Pmode
, AARCH64_STRUCT_VALUE_REGNUM
);
6195 /* Implements target hook vector_mode_supported_p. */
6197 aarch64_vector_mode_supported_p (enum machine_mode mode
)
6200 && (mode
== V4SImode
|| mode
== V8HImode
6201 || mode
== V16QImode
|| mode
== V2DImode
6202 || mode
== V2SImode
|| mode
== V4HImode
6203 || mode
== V8QImode
|| mode
== V2SFmode
6204 || mode
== V4SFmode
|| mode
== V2DFmode
))
6210 /* Return appropriate SIMD container
6211 for MODE within a vector of WIDTH bits. */
6212 static enum machine_mode
6213 aarch64_simd_container_mode (enum machine_mode mode
, unsigned width
)
6215 gcc_assert (width
== 64 || width
== 128);
6254 /* Return 128-bit container as the preferred SIMD mode for MODE. */
6255 static enum machine_mode
6256 aarch64_preferred_simd_mode (enum machine_mode mode
)
6258 return aarch64_simd_container_mode (mode
, 128);
6261 /* Return the bitmask of possible vector sizes for the vectorizer
6264 aarch64_autovectorize_vector_sizes (void)
6269 /* A table to help perform AArch64-specific name mangling for AdvSIMD
6270 vector types in order to conform to the AAPCS64 (see "Procedure
6271 Call Standard for the ARM 64-bit Architecture", Appendix A). To
6272 qualify for emission with the mangled names defined in that document,
6273 a vector type must not only be of the correct mode but also be
6274 composed of AdvSIMD vector element types (e.g.
6275 _builtin_aarch64_simd_qi); these types are registered by
6276 aarch64_init_simd_builtins (). In other words, vector types defined
6277 in other ways e.g. via vector_size attribute will get default
6281 enum machine_mode mode
;
6282 const char *element_type_name
;
6283 const char *mangled_name
;
6284 } aarch64_simd_mangle_map_entry
;
6286 static aarch64_simd_mangle_map_entry aarch64_simd_mangle_map
[] = {
6287 /* 64-bit containerized types. */
6288 { V8QImode
, "__builtin_aarch64_simd_qi", "10__Int8x8_t" },
6289 { V8QImode
, "__builtin_aarch64_simd_uqi", "11__Uint8x8_t" },
6290 { V4HImode
, "__builtin_aarch64_simd_hi", "11__Int16x4_t" },
6291 { V4HImode
, "__builtin_aarch64_simd_uhi", "12__Uint16x4_t" },
6292 { V2SImode
, "__builtin_aarch64_simd_si", "11__Int32x2_t" },
6293 { V2SImode
, "__builtin_aarch64_simd_usi", "12__Uint32x2_t" },
6294 { V2SFmode
, "__builtin_aarch64_simd_sf", "13__Float32x2_t" },
6295 { V8QImode
, "__builtin_aarch64_simd_poly8", "11__Poly8x8_t" },
6296 { V4HImode
, "__builtin_aarch64_simd_poly16", "12__Poly16x4_t" },
6297 /* 128-bit containerized types. */
6298 { V16QImode
, "__builtin_aarch64_simd_qi", "11__Int8x16_t" },
6299 { V16QImode
, "__builtin_aarch64_simd_uqi", "12__Uint8x16_t" },
6300 { V8HImode
, "__builtin_aarch64_simd_hi", "11__Int16x8_t" },
6301 { V8HImode
, "__builtin_aarch64_simd_uhi", "12__Uint16x8_t" },
6302 { V4SImode
, "__builtin_aarch64_simd_si", "11__Int32x4_t" },
6303 { V4SImode
, "__builtin_aarch64_simd_usi", "12__Uint32x4_t" },
6304 { V2DImode
, "__builtin_aarch64_simd_di", "11__Int64x2_t" },
6305 { V2DImode
, "__builtin_aarch64_simd_udi", "12__Uint64x2_t" },
6306 { V4SFmode
, "__builtin_aarch64_simd_sf", "13__Float32x4_t" },
6307 { V2DFmode
, "__builtin_aarch64_simd_df", "13__Float64x2_t" },
6308 { V16QImode
, "__builtin_aarch64_simd_poly8", "12__Poly8x16_t" },
6309 { V8HImode
, "__builtin_aarch64_simd_poly16", "12__Poly16x8_t" },
6310 { VOIDmode
, NULL
, NULL
}
6313 /* Implement TARGET_MANGLE_TYPE. */
6316 aarch64_mangle_type (const_tree type
)
6318 /* The AArch64 ABI documents say that "__va_list" has to be
6319 managled as if it is in the "std" namespace. */
6320 if (lang_hooks
.types_compatible_p (CONST_CAST_TREE (type
), va_list_type
))
6321 return "St9__va_list";
6323 /* Check the mode of the vector type, and the name of the vector
6324 element type, against the table. */
6325 if (TREE_CODE (type
) == VECTOR_TYPE
)
6327 aarch64_simd_mangle_map_entry
*pos
= aarch64_simd_mangle_map
;
6329 while (pos
->mode
!= VOIDmode
)
6331 tree elt_type
= TREE_TYPE (type
);
6333 if (pos
->mode
== TYPE_MODE (type
)
6334 && TREE_CODE (TYPE_NAME (elt_type
)) == TYPE_DECL
6335 && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (elt_type
))),
6336 pos
->element_type_name
))
6337 return pos
->mangled_name
;
6343 /* Use the default mangling. */
6347 /* Return the equivalent letter for size. */
6349 sizetochar (int size
)
6353 case 64: return 'd';
6354 case 32: return 's';
6355 case 16: return 'h';
6356 case 8 : return 'b';
6357 default: gcc_unreachable ();
6361 /* Return true iff x is a uniform vector of floating-point
6362 constants, and the constant can be represented in
6363 quarter-precision form. Note, as aarch64_float_const_representable
6364 rejects both +0.0 and -0.0, we will also reject +0.0 and -0.0. */
6366 aarch64_vect_float_const_representable_p (rtx x
)
6369 REAL_VALUE_TYPE r0
, ri
;
6372 if (GET_MODE_CLASS (GET_MODE (x
)) != MODE_VECTOR_FLOAT
)
6375 x0
= CONST_VECTOR_ELT (x
, 0);
6376 if (!CONST_DOUBLE_P (x0
))
6379 REAL_VALUE_FROM_CONST_DOUBLE (r0
, x0
);
6381 for (i
= 1; i
< CONST_VECTOR_NUNITS (x
); i
++)
6383 xi
= CONST_VECTOR_ELT (x
, i
);
6384 if (!CONST_DOUBLE_P (xi
))
6387 REAL_VALUE_FROM_CONST_DOUBLE (ri
, xi
);
6388 if (!REAL_VALUES_EQUAL (r0
, ri
))
6392 return aarch64_float_const_representable_p (x0
);
6395 /* Return true for valid and false for invalid. */
6397 aarch64_simd_valid_immediate (rtx op
, enum machine_mode mode
, bool inverse
,
6398 struct simd_immediate_info
*info
)
6400 #define CHECK(STRIDE, ELSIZE, CLASS, TEST, SHIFT, NEG) \
6402 for (i = 0; i < idx; i += (STRIDE)) \
6407 immtype = (CLASS); \
6408 elsize = (ELSIZE); \
6414 unsigned int i
, elsize
= 0, idx
= 0, n_elts
= CONST_VECTOR_NUNITS (op
);
6415 unsigned int innersize
= GET_MODE_SIZE (GET_MODE_INNER (mode
));
6416 unsigned char bytes
[16];
6417 int immtype
= -1, matches
;
6418 unsigned int invmask
= inverse
? 0xff : 0;
6421 if (GET_MODE_CLASS (mode
) == MODE_VECTOR_FLOAT
)
6423 if (! (aarch64_simd_imm_zero_p (op
, mode
)
6424 || aarch64_vect_float_const_representable_p (op
)))
6429 info
->value
= CONST_VECTOR_ELT (op
, 0);
6430 info
->element_width
= GET_MODE_BITSIZE (GET_MODE (info
->value
));
6438 /* Splat vector constant out into a byte vector. */
6439 for (i
= 0; i
< n_elts
; i
++)
6441 rtx el
= CONST_VECTOR_ELT (op
, i
);
6442 unsigned HOST_WIDE_INT elpart
;
6443 unsigned int part
, parts
;
6445 if (GET_CODE (el
) == CONST_INT
)
6447 elpart
= INTVAL (el
);
6450 else if (GET_CODE (el
) == CONST_DOUBLE
)
6452 elpart
= CONST_DOUBLE_LOW (el
);
6458 for (part
= 0; part
< parts
; part
++)
6461 for (byte
= 0; byte
< innersize
; byte
++)
6463 bytes
[idx
++] = (elpart
& 0xff) ^ invmask
;
6464 elpart
>>= BITS_PER_UNIT
;
6466 if (GET_CODE (el
) == CONST_DOUBLE
)
6467 elpart
= CONST_DOUBLE_HIGH (el
);
6472 gcc_assert (idx
== GET_MODE_SIZE (mode
));
6476 CHECK (4, 32, 0, bytes
[i
] == bytes
[0] && bytes
[i
+ 1] == 0
6477 && bytes
[i
+ 2] == 0 && bytes
[i
+ 3] == 0, 0, 0);
6479 CHECK (4, 32, 1, bytes
[i
] == 0 && bytes
[i
+ 1] == bytes
[1]
6480 && bytes
[i
+ 2] == 0 && bytes
[i
+ 3] == 0, 8, 0);
6482 CHECK (4, 32, 2, bytes
[i
] == 0 && bytes
[i
+ 1] == 0
6483 && bytes
[i
+ 2] == bytes
[2] && bytes
[i
+ 3] == 0, 16, 0);
6485 CHECK (4, 32, 3, bytes
[i
] == 0 && bytes
[i
+ 1] == 0
6486 && bytes
[i
+ 2] == 0 && bytes
[i
+ 3] == bytes
[3], 24, 0);
6488 CHECK (2, 16, 4, bytes
[i
] == bytes
[0] && bytes
[i
+ 1] == 0, 0, 0);
6490 CHECK (2, 16, 5, bytes
[i
] == 0 && bytes
[i
+ 1] == bytes
[1], 8, 0);
6492 CHECK (4, 32, 6, bytes
[i
] == bytes
[0] && bytes
[i
+ 1] == 0xff
6493 && bytes
[i
+ 2] == 0xff && bytes
[i
+ 3] == 0xff, 0, 1);
6495 CHECK (4, 32, 7, bytes
[i
] == 0xff && bytes
[i
+ 1] == bytes
[1]
6496 && bytes
[i
+ 2] == 0xff && bytes
[i
+ 3] == 0xff, 8, 1);
6498 CHECK (4, 32, 8, bytes
[i
] == 0xff && bytes
[i
+ 1] == 0xff
6499 && bytes
[i
+ 2] == bytes
[2] && bytes
[i
+ 3] == 0xff, 16, 1);
6501 CHECK (4, 32, 9, bytes
[i
] == 0xff && bytes
[i
+ 1] == 0xff
6502 && bytes
[i
+ 2] == 0xff && bytes
[i
+ 3] == bytes
[3], 24, 1);
6504 CHECK (2, 16, 10, bytes
[i
] == bytes
[0] && bytes
[i
+ 1] == 0xff, 0, 1);
6506 CHECK (2, 16, 11, bytes
[i
] == 0xff && bytes
[i
+ 1] == bytes
[1], 8, 1);
6508 CHECK (4, 32, 12, bytes
[i
] == 0xff && bytes
[i
+ 1] == bytes
[1]
6509 && bytes
[i
+ 2] == 0 && bytes
[i
+ 3] == 0, 8, 0);
6511 CHECK (4, 32, 13, bytes
[i
] == 0 && bytes
[i
+ 1] == bytes
[1]
6512 && bytes
[i
+ 2] == 0xff && bytes
[i
+ 3] == 0xff, 8, 1);
6514 CHECK (4, 32, 14, bytes
[i
] == 0xff && bytes
[i
+ 1] == 0xff
6515 && bytes
[i
+ 2] == bytes
[2] && bytes
[i
+ 3] == 0, 16, 0);
6517 CHECK (4, 32, 15, bytes
[i
] == 0 && bytes
[i
+ 1] == 0
6518 && bytes
[i
+ 2] == bytes
[2] && bytes
[i
+ 3] == 0xff, 16, 1);
6520 CHECK (1, 8, 16, bytes
[i
] == bytes
[0], 0, 0);
6522 CHECK (1, 64, 17, (bytes
[i
] == 0 || bytes
[i
] == 0xff)
6523 && bytes
[i
] == bytes
[(i
+ 8) % idx
], 0, 0);
6532 info
->element_width
= elsize
;
6533 info
->mvn
= emvn
!= 0;
6534 info
->shift
= eshift
;
6536 unsigned HOST_WIDE_INT imm
= 0;
6538 if (immtype
>= 12 && immtype
<= 15)
6541 /* Un-invert bytes of recognized vector, if necessary. */
6543 for (i
= 0; i
< idx
; i
++)
6544 bytes
[i
] ^= invmask
;
6548 /* FIXME: Broken on 32-bit H_W_I hosts. */
6549 gcc_assert (sizeof (HOST_WIDE_INT
) == 8);
6551 for (i
= 0; i
< 8; i
++)
6552 imm
|= (unsigned HOST_WIDE_INT
) (bytes
[i
] ? 0xff : 0)
6553 << (i
* BITS_PER_UNIT
);
6556 info
->value
= GEN_INT (imm
);
6560 for (i
= 0; i
< elsize
/ BITS_PER_UNIT
; i
++)
6561 imm
|= (unsigned HOST_WIDE_INT
) bytes
[i
] << (i
* BITS_PER_UNIT
);
6563 /* Construct 'abcdefgh' because the assembler cannot handle
6564 generic constants. */
6567 imm
= (imm
>> info
->shift
) & 0xff;
6568 info
->value
= GEN_INT (imm
);
6577 aarch64_const_vec_all_same_int_p (rtx x
,
6578 HOST_WIDE_INT minval
,
6579 HOST_WIDE_INT maxval
)
6581 HOST_WIDE_INT firstval
;
6584 if (GET_CODE (x
) != CONST_VECTOR
6585 || GET_MODE_CLASS (GET_MODE (x
)) != MODE_VECTOR_INT
)
6588 firstval
= INTVAL (CONST_VECTOR_ELT (x
, 0));
6589 if (firstval
< minval
|| firstval
> maxval
)
6592 count
= CONST_VECTOR_NUNITS (x
);
6593 for (i
= 1; i
< count
; i
++)
6594 if (INTVAL (CONST_VECTOR_ELT (x
, i
)) != firstval
)
6600 /* Check of immediate shift constants are within range. */
6602 aarch64_simd_shift_imm_p (rtx x
, enum machine_mode mode
, bool left
)
6604 int bit_width
= GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
;
6606 return aarch64_const_vec_all_same_int_p (x
, 0, bit_width
- 1);
6608 return aarch64_const_vec_all_same_int_p (x
, 1, bit_width
);
6611 /* Return true if X is a uniform vector where all elements
6612 are either the floating-point constant 0.0 or the
6613 integer constant 0. */
6615 aarch64_simd_imm_zero_p (rtx x
, enum machine_mode mode
)
6617 return x
== CONST0_RTX (mode
);
6621 aarch64_simd_imm_scalar_p (rtx x
, enum machine_mode mode ATTRIBUTE_UNUSED
)
6623 HOST_WIDE_INT imm
= INTVAL (x
);
6626 for (i
= 0; i
< 8; i
++)
6628 unsigned int byte
= imm
& 0xff;
6629 if (byte
!= 0xff && byte
!= 0)
6638 aarch64_mov_operand_p (rtx x
,
6639 enum aarch64_symbol_context context
,
6640 enum machine_mode mode
)
6642 if (GET_CODE (x
) == HIGH
6643 && aarch64_valid_symref (XEXP (x
, 0), GET_MODE (XEXP (x
, 0))))
6646 if (CONST_INT_P (x
) && aarch64_move_imm (INTVAL (x
), mode
))
6649 if (GET_CODE (x
) == SYMBOL_REF
&& mode
== DImode
&& CONSTANT_ADDRESS_P (x
))
6652 return aarch64_classify_symbolic_expression (x
, context
)
6653 == SYMBOL_TINY_ABSOLUTE
;
6656 /* Return a const_int vector of VAL. */
6658 aarch64_simd_gen_const_vector_dup (enum machine_mode mode
, int val
)
6660 int nunits
= GET_MODE_NUNITS (mode
);
6661 rtvec v
= rtvec_alloc (nunits
);
6664 for (i
=0; i
< nunits
; i
++)
6665 RTVEC_ELT (v
, i
) = GEN_INT (val
);
6667 return gen_rtx_CONST_VECTOR (mode
, v
);
6670 /* Check OP is a legal scalar immediate for the MOVI instruction. */
6673 aarch64_simd_scalar_immediate_valid_for_move (rtx op
, enum machine_mode mode
)
6675 enum machine_mode vmode
;
6677 gcc_assert (!VECTOR_MODE_P (mode
));
6678 vmode
= aarch64_preferred_simd_mode (mode
);
6679 rtx op_v
= aarch64_simd_gen_const_vector_dup (vmode
, INTVAL (op
));
6680 return aarch64_simd_valid_immediate (op_v
, vmode
, false, NULL
);
6683 /* Construct and return a PARALLEL RTX vector. */
6685 aarch64_simd_vect_par_cnst_half (enum machine_mode mode
, bool high
)
6687 int nunits
= GET_MODE_NUNITS (mode
);
6688 rtvec v
= rtvec_alloc (nunits
/ 2);
6689 int base
= high
? nunits
/ 2 : 0;
6693 for (i
=0; i
< nunits
/ 2; i
++)
6694 RTVEC_ELT (v
, i
) = GEN_INT (base
+ i
);
6696 t1
= gen_rtx_PARALLEL (mode
, v
);
6700 /* Bounds-check lanes. Ensure OPERAND lies between LOW (inclusive) and
6701 HIGH (exclusive). */
6703 aarch64_simd_lane_bounds (rtx operand
, HOST_WIDE_INT low
, HOST_WIDE_INT high
)
6706 gcc_assert (GET_CODE (operand
) == CONST_INT
);
6707 lane
= INTVAL (operand
);
6709 if (lane
< low
|| lane
>= high
)
6710 error ("lane out of range");
6714 aarch64_simd_const_bounds (rtx operand
, HOST_WIDE_INT low
, HOST_WIDE_INT high
)
6716 gcc_assert (GET_CODE (operand
) == CONST_INT
);
6717 HOST_WIDE_INT lane
= INTVAL (operand
);
6719 if (lane
< low
|| lane
>= high
)
6720 error ("constant out of range");
6723 /* Emit code to reinterpret one AdvSIMD type as another,
6724 without altering bits. */
6726 aarch64_simd_reinterpret (rtx dest
, rtx src
)
6728 emit_move_insn (dest
, gen_lowpart (GET_MODE (dest
), src
));
6731 /* Emit code to place a AdvSIMD pair result in memory locations (with equal
6734 aarch64_simd_emit_pair_result_insn (enum machine_mode mode
,
6735 rtx (*intfn
) (rtx
, rtx
, rtx
), rtx destaddr
,
6738 rtx mem
= gen_rtx_MEM (mode
, destaddr
);
6739 rtx tmp1
= gen_reg_rtx (mode
);
6740 rtx tmp2
= gen_reg_rtx (mode
);
6742 emit_insn (intfn (tmp1
, op1
, tmp2
));
6744 emit_move_insn (mem
, tmp1
);
6745 mem
= adjust_address (mem
, mode
, GET_MODE_SIZE (mode
));
6746 emit_move_insn (mem
, tmp2
);
6749 /* Return TRUE if OP is a valid vector addressing mode. */
6751 aarch64_simd_mem_operand_p (rtx op
)
6753 return MEM_P (op
) && (GET_CODE (XEXP (op
, 0)) == POST_INC
6754 || GET_CODE (XEXP (op
, 0)) == REG
);
6757 /* Set up OPERANDS for a register copy from SRC to DEST, taking care
6758 not to early-clobber SRC registers in the process.
6760 We assume that the operands described by SRC and DEST represent a
6761 decomposed copy of OPERANDS[1] into OPERANDS[0]. COUNT is the
6762 number of components into which the copy has been decomposed. */
6764 aarch64_simd_disambiguate_copy (rtx
*operands
, rtx
*dest
,
6765 rtx
*src
, unsigned int count
)
6769 if (!reg_overlap_mentioned_p (operands
[0], operands
[1])
6770 || REGNO (operands
[0]) < REGNO (operands
[1]))
6772 for (i
= 0; i
< count
; i
++)
6774 operands
[2 * i
] = dest
[i
];
6775 operands
[2 * i
+ 1] = src
[i
];
6780 for (i
= 0; i
< count
; i
++)
6782 operands
[2 * i
] = dest
[count
- i
- 1];
6783 operands
[2 * i
+ 1] = src
[count
- i
- 1];
6788 /* Compute and return the length of aarch64_simd_mov<mode>, where <mode> is
6789 one of VSTRUCT modes: OI, CI or XI. */
6791 aarch64_simd_attr_length_move (rtx insn
)
6793 enum machine_mode mode
;
6795 extract_insn_cached (insn
);
6797 if (REG_P (recog_data
.operand
[0]) && REG_P (recog_data
.operand
[1]))
6799 mode
= GET_MODE (recog_data
.operand
[0]);
6815 /* Implement target hook TARGET_VECTOR_ALIGNMENT. The AAPCS64 sets the maximum
6816 alignment of a vector to 128 bits. */
6817 static HOST_WIDE_INT
6818 aarch64_simd_vector_alignment (const_tree type
)
6820 HOST_WIDE_INT align
= tree_low_cst (TYPE_SIZE (type
), 0);
6821 return MIN (align
, 128);
6824 /* Implement target hook TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE. */
6826 aarch64_simd_vector_alignment_reachable (const_tree type
, bool is_packed
)
6831 /* We guarantee alignment for vectors up to 128-bits. */
6832 if (tree_int_cst_compare (TYPE_SIZE (type
),
6833 bitsize_int (BIGGEST_ALIGNMENT
)) > 0)
6836 /* Vectors whose size is <= BIGGEST_ALIGNMENT are naturally aligned. */
6840 /* If VALS is a vector constant that can be loaded into a register
6841 using DUP, generate instructions to do so and return an RTX to
6842 assign to the register. Otherwise return NULL_RTX. */
6844 aarch64_simd_dup_constant (rtx vals
)
6846 enum machine_mode mode
= GET_MODE (vals
);
6847 enum machine_mode inner_mode
= GET_MODE_INNER (mode
);
6848 int n_elts
= GET_MODE_NUNITS (mode
);
6849 bool all_same
= true;
6853 if (GET_CODE (vals
) != CONST_VECTOR
)
6856 for (i
= 1; i
< n_elts
; ++i
)
6858 x
= CONST_VECTOR_ELT (vals
, i
);
6859 if (!rtx_equal_p (x
, CONST_VECTOR_ELT (vals
, 0)))
6866 /* We can load this constant by using DUP and a constant in a
6867 single ARM register. This will be cheaper than a vector
6869 x
= copy_to_mode_reg (inner_mode
, CONST_VECTOR_ELT (vals
, 0));
6870 return gen_rtx_VEC_DUPLICATE (mode
, x
);
6874 /* Generate code to load VALS, which is a PARALLEL containing only
6875 constants (for vec_init) or CONST_VECTOR, efficiently into a
6876 register. Returns an RTX to copy into the register, or NULL_RTX
6877 for a PARALLEL that can not be converted into a CONST_VECTOR. */
6879 aarch64_simd_make_constant (rtx vals
)
6881 enum machine_mode mode
= GET_MODE (vals
);
6883 rtx const_vec
= NULL_RTX
;
6884 int n_elts
= GET_MODE_NUNITS (mode
);
6888 if (GET_CODE (vals
) == CONST_VECTOR
)
6890 else if (GET_CODE (vals
) == PARALLEL
)
6892 /* A CONST_VECTOR must contain only CONST_INTs and
6893 CONST_DOUBLEs, but CONSTANT_P allows more (e.g. SYMBOL_REF).
6894 Only store valid constants in a CONST_VECTOR. */
6895 for (i
= 0; i
< n_elts
; ++i
)
6897 rtx x
= XVECEXP (vals
, 0, i
);
6898 if (CONST_INT_P (x
) || CONST_DOUBLE_P (x
))
6901 if (n_const
== n_elts
)
6902 const_vec
= gen_rtx_CONST_VECTOR (mode
, XVEC (vals
, 0));
6907 if (const_vec
!= NULL_RTX
6908 && aarch64_simd_valid_immediate (const_vec
, mode
, false, NULL
))
6909 /* Load using MOVI/MVNI. */
6911 else if ((const_dup
= aarch64_simd_dup_constant (vals
)) != NULL_RTX
)
6912 /* Loaded using DUP. */
6914 else if (const_vec
!= NULL_RTX
)
6915 /* Load from constant pool. We can not take advantage of single-cycle
6916 LD1 because we need a PC-relative addressing mode. */
6919 /* A PARALLEL containing something not valid inside CONST_VECTOR.
6920 We can not construct an initializer. */
6925 aarch64_expand_vector_init (rtx target
, rtx vals
)
6927 enum machine_mode mode
= GET_MODE (target
);
6928 enum machine_mode inner_mode
= GET_MODE_INNER (mode
);
6929 int n_elts
= GET_MODE_NUNITS (mode
);
6930 int n_var
= 0, one_var
= -1;
6931 bool all_same
= true;
6935 x
= XVECEXP (vals
, 0, 0);
6936 if (!CONST_INT_P (x
) && !CONST_DOUBLE_P (x
))
6937 n_var
= 1, one_var
= 0;
6939 for (i
= 1; i
< n_elts
; ++i
)
6941 x
= XVECEXP (vals
, 0, i
);
6942 if (!CONST_INT_P (x
) && !CONST_DOUBLE_P (x
))
6943 ++n_var
, one_var
= i
;
6945 if (!rtx_equal_p (x
, XVECEXP (vals
, 0, 0)))
6951 rtx constant
= aarch64_simd_make_constant (vals
);
6952 if (constant
!= NULL_RTX
)
6954 emit_move_insn (target
, constant
);
6959 /* Splat a single non-constant element if we can. */
6962 x
= copy_to_mode_reg (inner_mode
, XVECEXP (vals
, 0, 0));
6963 aarch64_emit_move (target
, gen_rtx_VEC_DUPLICATE (mode
, x
));
6967 /* One field is non-constant. Load constant then overwrite varying
6968 field. This is more efficient than using the stack. */
6971 rtx copy
= copy_rtx (vals
);
6972 rtx index
= GEN_INT (one_var
);
6973 enum insn_code icode
;
6975 /* Load constant part of vector, substitute neighboring value for
6977 XVECEXP (copy
, 0, one_var
) = XVECEXP (vals
, 0, one_var
^ 1);
6978 aarch64_expand_vector_init (target
, copy
);
6980 /* Insert variable. */
6981 x
= copy_to_mode_reg (inner_mode
, XVECEXP (vals
, 0, one_var
));
6982 icode
= optab_handler (vec_set_optab
, mode
);
6983 gcc_assert (icode
!= CODE_FOR_nothing
);
6984 emit_insn (GEN_FCN (icode
) (target
, x
, index
));
6988 /* Construct the vector in memory one field at a time
6989 and load the whole vector. */
6990 mem
= assign_stack_temp (mode
, GET_MODE_SIZE (mode
));
6991 for (i
= 0; i
< n_elts
; i
++)
6992 emit_move_insn (adjust_address_nv (mem
, inner_mode
,
6993 i
* GET_MODE_SIZE (inner_mode
)),
6994 XVECEXP (vals
, 0, i
));
6995 emit_move_insn (target
, mem
);
6999 static unsigned HOST_WIDE_INT
7000 aarch64_shift_truncation_mask (enum machine_mode mode
)
7003 (aarch64_vector_mode_supported_p (mode
)
7004 || aarch64_vect_struct_mode_p (mode
)) ? 0 : (GET_MODE_BITSIZE (mode
) - 1);
7007 #ifndef TLS_SECTION_ASM_FLAG
7008 #define TLS_SECTION_ASM_FLAG 'T'
7012 aarch64_elf_asm_named_section (const char *name
, unsigned int flags
,
7013 tree decl ATTRIBUTE_UNUSED
)
7015 char flagchars
[10], *f
= flagchars
;
7017 /* If we have already declared this section, we can use an
7018 abbreviated form to switch back to it -- unless this section is
7019 part of a COMDAT groups, in which case GAS requires the full
7020 declaration every time. */
7021 if (!(HAVE_COMDAT_GROUP
&& (flags
& SECTION_LINKONCE
))
7022 && (flags
& SECTION_DECLARED
))
7024 fprintf (asm_out_file
, "\t.section\t%s\n", name
);
7028 if (!(flags
& SECTION_DEBUG
))
7030 if (flags
& SECTION_WRITE
)
7032 if (flags
& SECTION_CODE
)
7034 if (flags
& SECTION_SMALL
)
7036 if (flags
& SECTION_MERGE
)
7038 if (flags
& SECTION_STRINGS
)
7040 if (flags
& SECTION_TLS
)
7041 *f
++ = TLS_SECTION_ASM_FLAG
;
7042 if (HAVE_COMDAT_GROUP
&& (flags
& SECTION_LINKONCE
))
7046 fprintf (asm_out_file
, "\t.section\t%s,\"%s\"", name
, flagchars
);
7048 if (!(flags
& SECTION_NOTYPE
))
7053 if (flags
& SECTION_BSS
)
7058 #ifdef TYPE_OPERAND_FMT
7059 format
= "," TYPE_OPERAND_FMT
;
7064 fprintf (asm_out_file
, format
, type
);
7066 if (flags
& SECTION_ENTSIZE
)
7067 fprintf (asm_out_file
, ",%d", flags
& SECTION_ENTSIZE
);
7068 if (HAVE_COMDAT_GROUP
&& (flags
& SECTION_LINKONCE
))
7070 if (TREE_CODE (decl
) == IDENTIFIER_NODE
)
7071 fprintf (asm_out_file
, ",%s,comdat", IDENTIFIER_POINTER (decl
));
7073 fprintf (asm_out_file
, ",%s,comdat",
7074 IDENTIFIER_POINTER (DECL_COMDAT_GROUP (decl
)));
7078 putc ('\n', asm_out_file
);
7081 /* Select a format to encode pointers in exception handling data. */
7083 aarch64_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED
, int global
)
7086 switch (aarch64_cmodel
)
7088 case AARCH64_CMODEL_TINY
:
7089 case AARCH64_CMODEL_TINY_PIC
:
7090 case AARCH64_CMODEL_SMALL
:
7091 case AARCH64_CMODEL_SMALL_PIC
:
7092 /* text+got+data < 4Gb. 4-byte signed relocs are sufficient
7094 type
= DW_EH_PE_sdata4
;
7097 /* No assumptions here. 8-byte relocs required. */
7098 type
= DW_EH_PE_sdata8
;
7101 return (global
? DW_EH_PE_indirect
: 0) | DW_EH_PE_pcrel
| type
;
7104 /* Emit load exclusive. */
7107 aarch64_emit_load_exclusive (enum machine_mode mode
, rtx rval
,
7108 rtx mem
, rtx model_rtx
)
7110 rtx (*gen
) (rtx
, rtx
, rtx
);
7114 case QImode
: gen
= gen_aarch64_load_exclusiveqi
; break;
7115 case HImode
: gen
= gen_aarch64_load_exclusivehi
; break;
7116 case SImode
: gen
= gen_aarch64_load_exclusivesi
; break;
7117 case DImode
: gen
= gen_aarch64_load_exclusivedi
; break;
7122 emit_insn (gen (rval
, mem
, model_rtx
));
7125 /* Emit store exclusive. */
7128 aarch64_emit_store_exclusive (enum machine_mode mode
, rtx bval
,
7129 rtx rval
, rtx mem
, rtx model_rtx
)
7131 rtx (*gen
) (rtx
, rtx
, rtx
, rtx
);
7135 case QImode
: gen
= gen_aarch64_store_exclusiveqi
; break;
7136 case HImode
: gen
= gen_aarch64_store_exclusivehi
; break;
7137 case SImode
: gen
= gen_aarch64_store_exclusivesi
; break;
7138 case DImode
: gen
= gen_aarch64_store_exclusivedi
; break;
7143 emit_insn (gen (bval
, rval
, mem
, model_rtx
));
7146 /* Mark the previous jump instruction as unlikely. */
7149 aarch64_emit_unlikely_jump (rtx insn
)
7151 rtx very_unlikely
= GEN_INT (REG_BR_PROB_BASE
/ 100 - 1);
7153 insn
= emit_jump_insn (insn
);
7154 add_reg_note (insn
, REG_BR_PROB
, very_unlikely
);
7157 /* Expand a compare and swap pattern. */
7160 aarch64_expand_compare_and_swap (rtx operands
[])
7162 rtx bval
, rval
, mem
, oldval
, newval
, is_weak
, mod_s
, mod_f
, x
;
7163 enum machine_mode mode
, cmp_mode
;
7164 rtx (*gen
) (rtx
, rtx
, rtx
, rtx
, rtx
, rtx
, rtx
);
7169 oldval
= operands
[3];
7170 newval
= operands
[4];
7171 is_weak
= operands
[5];
7172 mod_s
= operands
[6];
7173 mod_f
= operands
[7];
7174 mode
= GET_MODE (mem
);
7177 /* Normally the succ memory model must be stronger than fail, but in the
7178 unlikely event of fail being ACQUIRE and succ being RELEASE we need to
7179 promote succ to ACQ_REL so that we don't lose the acquire semantics. */
7181 if (INTVAL (mod_f
) == MEMMODEL_ACQUIRE
7182 && INTVAL (mod_s
) == MEMMODEL_RELEASE
)
7183 mod_s
= GEN_INT (MEMMODEL_ACQ_REL
);
7189 /* For short modes, we're going to perform the comparison in SImode,
7190 so do the zero-extension now. */
7192 rval
= gen_reg_rtx (SImode
);
7193 oldval
= convert_modes (SImode
, mode
, oldval
, true);
7198 /* Force the value into a register if needed. */
7199 if (!aarch64_plus_operand (oldval
, mode
))
7200 oldval
= force_reg (cmp_mode
, oldval
);
7209 case QImode
: gen
= gen_atomic_compare_and_swapqi_1
; break;
7210 case HImode
: gen
= gen_atomic_compare_and_swaphi_1
; break;
7211 case SImode
: gen
= gen_atomic_compare_and_swapsi_1
; break;
7212 case DImode
: gen
= gen_atomic_compare_and_swapdi_1
; break;
7217 emit_insn (gen (rval
, mem
, oldval
, newval
, is_weak
, mod_s
, mod_f
));
7219 if (mode
== QImode
|| mode
== HImode
)
7220 emit_move_insn (operands
[1], gen_lowpart (mode
, rval
));
7222 x
= gen_rtx_REG (CCmode
, CC_REGNUM
);
7223 x
= gen_rtx_EQ (SImode
, x
, const0_rtx
);
7224 emit_insn (gen_rtx_SET (VOIDmode
, bval
, x
));
7227 /* Split a compare and swap pattern. */
7230 aarch64_split_compare_and_swap (rtx operands
[])
7232 rtx rval
, mem
, oldval
, newval
, scratch
;
7233 enum machine_mode mode
;
7235 rtx label1
, label2
, x
, cond
;
7239 oldval
= operands
[2];
7240 newval
= operands
[3];
7241 is_weak
= (operands
[4] != const0_rtx
);
7242 scratch
= operands
[7];
7243 mode
= GET_MODE (mem
);
7248 label1
= gen_label_rtx ();
7249 emit_label (label1
);
7251 label2
= gen_label_rtx ();
7253 aarch64_emit_load_exclusive (mode
, rval
, mem
, operands
[5]);
7255 cond
= aarch64_gen_compare_reg (NE
, rval
, oldval
);
7256 x
= gen_rtx_NE (VOIDmode
, cond
, const0_rtx
);
7257 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
7258 gen_rtx_LABEL_REF (Pmode
, label2
), pc_rtx
);
7259 aarch64_emit_unlikely_jump (gen_rtx_SET (VOIDmode
, pc_rtx
, x
));
7261 aarch64_emit_store_exclusive (mode
, scratch
, mem
, newval
, operands
[5]);
7265 x
= gen_rtx_NE (VOIDmode
, scratch
, const0_rtx
);
7266 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
7267 gen_rtx_LABEL_REF (Pmode
, label1
), pc_rtx
);
7268 aarch64_emit_unlikely_jump (gen_rtx_SET (VOIDmode
, pc_rtx
, x
));
7272 cond
= gen_rtx_REG (CCmode
, CC_REGNUM
);
7273 x
= gen_rtx_COMPARE (CCmode
, scratch
, const0_rtx
);
7274 emit_insn (gen_rtx_SET (VOIDmode
, cond
, x
));
7277 emit_label (label2
);
7280 /* Split an atomic operation. */
7283 aarch64_split_atomic_op (enum rtx_code code
, rtx old_out
, rtx new_out
, rtx mem
,
7284 rtx value
, rtx model_rtx
, rtx cond
)
7286 enum machine_mode mode
= GET_MODE (mem
);
7287 enum machine_mode wmode
= (mode
== DImode
? DImode
: SImode
);
7290 label
= gen_label_rtx ();
7294 new_out
= gen_lowpart (wmode
, new_out
);
7296 old_out
= gen_lowpart (wmode
, old_out
);
7299 value
= simplify_gen_subreg (wmode
, value
, mode
, 0);
7301 aarch64_emit_load_exclusive (mode
, old_out
, mem
, model_rtx
);
7310 x
= gen_rtx_AND (wmode
, old_out
, value
);
7311 emit_insn (gen_rtx_SET (VOIDmode
, new_out
, x
));
7312 x
= gen_rtx_NOT (wmode
, new_out
);
7313 emit_insn (gen_rtx_SET (VOIDmode
, new_out
, x
));
7317 if (CONST_INT_P (value
))
7319 value
= GEN_INT (-INTVAL (value
));
7325 x
= gen_rtx_fmt_ee (code
, wmode
, old_out
, value
);
7326 emit_insn (gen_rtx_SET (VOIDmode
, new_out
, x
));
7330 aarch64_emit_store_exclusive (mode
, cond
, mem
,
7331 gen_lowpart (mode
, new_out
), model_rtx
);
7333 x
= gen_rtx_NE (VOIDmode
, cond
, const0_rtx
);
7334 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
7335 gen_rtx_LABEL_REF (Pmode
, label
), pc_rtx
);
7336 aarch64_emit_unlikely_jump (gen_rtx_SET (VOIDmode
, pc_rtx
, x
));
7340 aarch64_print_extension (void)
7342 const struct aarch64_option_extension
*opt
= NULL
;
7344 for (opt
= all_extensions
; opt
->name
!= NULL
; opt
++)
7345 if ((aarch64_isa_flags
& opt
->flags_on
) == opt
->flags_on
)
7346 asm_fprintf (asm_out_file
, "+%s", opt
->name
);
7348 asm_fprintf (asm_out_file
, "\n");
7352 aarch64_start_file (void)
7356 asm_fprintf (asm_out_file
, "\t.arch %s", selected_arch
->name
);
7357 aarch64_print_extension ();
7359 else if (selected_cpu
)
7361 asm_fprintf (asm_out_file
, "\t.cpu %s", selected_cpu
->name
);
7362 aarch64_print_extension ();
7364 default_file_start();
7367 /* Target hook for c_mode_for_suffix. */
7368 static enum machine_mode
7369 aarch64_c_mode_for_suffix (char suffix
)
7377 /* We can only represent floating point constants which will fit in
7378 "quarter-precision" values. These values are characterised by
7379 a sign bit, a 4-bit mantissa and a 3-bit exponent. And are given
7382 (-1)^s * (n/16) * 2^r
7385 's' is the sign bit.
7386 'n' is an integer in the range 16 <= n <= 31.
7387 'r' is an integer in the range -3 <= r <= 4. */
7389 /* Return true iff X can be represented by a quarter-precision
7390 floating point immediate operand X. Note, we cannot represent 0.0. */
7392 aarch64_float_const_representable_p (rtx x
)
7394 /* This represents our current view of how many bits
7395 make up the mantissa. */
7396 int point_pos
= 2 * HOST_BITS_PER_WIDE_INT
- 1;
7398 unsigned HOST_WIDE_INT mantissa
, mask
;
7399 HOST_WIDE_INT m1
, m2
;
7400 REAL_VALUE_TYPE r
, m
;
7402 if (!CONST_DOUBLE_P (x
))
7405 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
7407 /* We cannot represent infinities, NaNs or +/-zero. We won't
7408 know if we have +zero until we analyse the mantissa, but we
7409 can reject the other invalid values. */
7410 if (REAL_VALUE_ISINF (r
) || REAL_VALUE_ISNAN (r
)
7411 || REAL_VALUE_MINUS_ZERO (r
))
7414 /* Extract exponent. */
7415 r
= real_value_abs (&r
);
7416 exponent
= REAL_EXP (&r
);
7418 /* For the mantissa, we expand into two HOST_WIDE_INTS, apart from the
7419 highest (sign) bit, with a fixed binary point at bit point_pos.
7420 m1 holds the low part of the mantissa, m2 the high part.
7421 WARNING: If we ever have a representation using more than 2 * H_W_I - 1
7422 bits for the mantissa, this can fail (low bits will be lost). */
7423 real_ldexp (&m
, &r
, point_pos
- exponent
);
7424 REAL_VALUE_TO_INT (&m1
, &m2
, m
);
7426 /* If the low part of the mantissa has bits set we cannot represent
7430 /* We have rejected the lower HOST_WIDE_INT, so update our
7431 understanding of how many bits lie in the mantissa and
7432 look only at the high HOST_WIDE_INT. */
7434 point_pos
-= HOST_BITS_PER_WIDE_INT
;
7436 /* We can only represent values with a mantissa of the form 1.xxxx. */
7437 mask
= ((unsigned HOST_WIDE_INT
)1 << (point_pos
- 5)) - 1;
7438 if ((mantissa
& mask
) != 0)
7441 /* Having filtered unrepresentable values, we may now remove all
7442 but the highest 5 bits. */
7443 mantissa
>>= point_pos
- 5;
7445 /* We cannot represent the value 0.0, so reject it. This is handled
7450 /* Then, as bit 4 is always set, we can mask it off, leaving
7451 the mantissa in the range [0, 15]. */
7452 mantissa
&= ~(1 << 4);
7453 gcc_assert (mantissa
<= 15);
7455 /* GCC internally does not use IEEE754-like encoding (where normalized
7456 significands are in the range [1, 2). GCC uses [0.5, 1) (see real.c).
7457 Our mantissa values are shifted 4 places to the left relative to
7458 normalized IEEE754 so we must modify the exponent returned by REAL_EXP
7459 by 5 places to correct for GCC's representation. */
7460 exponent
= 5 - exponent
;
7462 return (exponent
>= 0 && exponent
<= 7);
7466 aarch64_output_simd_mov_immediate (rtx const_vector
,
7467 enum machine_mode mode
,
7471 static char templ
[40];
7472 const char *mnemonic
;
7473 const char *shift_op
;
7474 unsigned int lane_count
= 0;
7477 struct simd_immediate_info info
= { NULL_RTX
, 0, 0, false, false };
7479 /* This will return true to show const_vector is legal for use as either
7480 a AdvSIMD MOVI instruction (or, implicitly, MVNI) immediate. It will
7481 also update INFO to show how the immediate should be generated. */
7482 is_valid
= aarch64_simd_valid_immediate (const_vector
, mode
, false, &info
);
7483 gcc_assert (is_valid
);
7485 element_char
= sizetochar (info
.element_width
);
7486 lane_count
= width
/ info
.element_width
;
7488 mode
= GET_MODE_INNER (mode
);
7489 if (mode
== SFmode
|| mode
== DFmode
)
7491 gcc_assert (info
.shift
== 0 && ! info
.mvn
);
7492 if (aarch64_float_const_zero_rtx_p (info
.value
))
7493 info
.value
= GEN_INT (0);
7498 REAL_VALUE_FROM_CONST_DOUBLE (r
, info
.value
);
7499 char float_buf
[buf_size
] = {'\0'};
7500 real_to_decimal_for_mode (float_buf
, &r
, buf_size
, buf_size
, 1, mode
);
7503 if (lane_count
== 1)
7504 snprintf (templ
, sizeof (templ
), "fmov\t%%d0, %s", float_buf
);
7506 snprintf (templ
, sizeof (templ
), "fmov\t%%0.%d%c, %s",
7507 lane_count
, element_char
, float_buf
);
7512 mnemonic
= info
.mvn
? "mvni" : "movi";
7513 shift_op
= info
.msl
? "msl" : "lsl";
7515 if (lane_count
== 1)
7516 snprintf (templ
, sizeof (templ
), "%s\t%%d0, " HOST_WIDE_INT_PRINT_HEX
,
7517 mnemonic
, UINTVAL (info
.value
));
7518 else if (info
.shift
)
7519 snprintf (templ
, sizeof (templ
), "%s\t%%0.%d%c, " HOST_WIDE_INT_PRINT_HEX
7520 ", %s %d", mnemonic
, lane_count
, element_char
,
7521 UINTVAL (info
.value
), shift_op
, info
.shift
);
7523 snprintf (templ
, sizeof (templ
), "%s\t%%0.%d%c, " HOST_WIDE_INT_PRINT_HEX
,
7524 mnemonic
, lane_count
, element_char
, UINTVAL (info
.value
));
7529 aarch64_output_scalar_simd_mov_immediate (rtx immediate
,
7530 enum machine_mode mode
)
7532 enum machine_mode vmode
;
7534 gcc_assert (!VECTOR_MODE_P (mode
));
7535 vmode
= aarch64_simd_container_mode (mode
, 64);
7536 rtx v_op
= aarch64_simd_gen_const_vector_dup (vmode
, INTVAL (immediate
));
7537 return aarch64_output_simd_mov_immediate (v_op
, vmode
, 64);
7540 /* Split operands into moves from op[1] + op[2] into op[0]. */
7543 aarch64_split_combinev16qi (rtx operands
[3])
7545 unsigned int dest
= REGNO (operands
[0]);
7546 unsigned int src1
= REGNO (operands
[1]);
7547 unsigned int src2
= REGNO (operands
[2]);
7548 enum machine_mode halfmode
= GET_MODE (operands
[1]);
7549 unsigned int halfregs
= HARD_REGNO_NREGS (src1
, halfmode
);
7552 gcc_assert (halfmode
== V16QImode
);
7554 if (src1
== dest
&& src2
== dest
+ halfregs
)
7556 /* No-op move. Can't split to nothing; emit something. */
7557 emit_note (NOTE_INSN_DELETED
);
7561 /* Preserve register attributes for variable tracking. */
7562 destlo
= gen_rtx_REG_offset (operands
[0], halfmode
, dest
, 0);
7563 desthi
= gen_rtx_REG_offset (operands
[0], halfmode
, dest
+ halfregs
,
7564 GET_MODE_SIZE (halfmode
));
7566 /* Special case of reversed high/low parts. */
7567 if (reg_overlap_mentioned_p (operands
[2], destlo
)
7568 && reg_overlap_mentioned_p (operands
[1], desthi
))
7570 emit_insn (gen_xorv16qi3 (operands
[1], operands
[1], operands
[2]));
7571 emit_insn (gen_xorv16qi3 (operands
[2], operands
[1], operands
[2]));
7572 emit_insn (gen_xorv16qi3 (operands
[1], operands
[1], operands
[2]));
7574 else if (!reg_overlap_mentioned_p (operands
[2], destlo
))
7576 /* Try to avoid unnecessary moves if part of the result
7577 is in the right place already. */
7579 emit_move_insn (destlo
, operands
[1]);
7580 if (src2
!= dest
+ halfregs
)
7581 emit_move_insn (desthi
, operands
[2]);
7585 if (src2
!= dest
+ halfregs
)
7586 emit_move_insn (desthi
, operands
[2]);
7588 emit_move_insn (destlo
, operands
[1]);
7592 /* vec_perm support. */
7594 #define MAX_VECT_LEN 16
7596 struct expand_vec_perm_d
7598 rtx target
, op0
, op1
;
7599 unsigned char perm
[MAX_VECT_LEN
];
7600 enum machine_mode vmode
;
7606 /* Generate a variable permutation. */
7609 aarch64_expand_vec_perm_1 (rtx target
, rtx op0
, rtx op1
, rtx sel
)
7611 enum machine_mode vmode
= GET_MODE (target
);
7612 bool one_vector_p
= rtx_equal_p (op0
, op1
);
7614 gcc_checking_assert (vmode
== V8QImode
|| vmode
== V16QImode
);
7615 gcc_checking_assert (GET_MODE (op0
) == vmode
);
7616 gcc_checking_assert (GET_MODE (op1
) == vmode
);
7617 gcc_checking_assert (GET_MODE (sel
) == vmode
);
7618 gcc_checking_assert (TARGET_SIMD
);
7622 if (vmode
== V8QImode
)
7624 /* Expand the argument to a V16QI mode by duplicating it. */
7625 rtx pair
= gen_reg_rtx (V16QImode
);
7626 emit_insn (gen_aarch64_combinev8qi (pair
, op0
, op0
));
7627 emit_insn (gen_aarch64_tbl1v8qi (target
, pair
, sel
));
7631 emit_insn (gen_aarch64_tbl1v16qi (target
, op0
, sel
));
7638 if (vmode
== V8QImode
)
7640 pair
= gen_reg_rtx (V16QImode
);
7641 emit_insn (gen_aarch64_combinev8qi (pair
, op0
, op1
));
7642 emit_insn (gen_aarch64_tbl1v8qi (target
, pair
, sel
));
7646 pair
= gen_reg_rtx (OImode
);
7647 emit_insn (gen_aarch64_combinev16qi (pair
, op0
, op1
));
7648 emit_insn (gen_aarch64_tbl2v16qi (target
, pair
, sel
));
7654 aarch64_expand_vec_perm (rtx target
, rtx op0
, rtx op1
, rtx sel
)
7656 enum machine_mode vmode
= GET_MODE (target
);
7657 unsigned int i
, nelt
= GET_MODE_NUNITS (vmode
);
7658 bool one_vector_p
= rtx_equal_p (op0
, op1
);
7659 rtx rmask
[MAX_VECT_LEN
], mask
;
7661 gcc_checking_assert (!BYTES_BIG_ENDIAN
);
7663 /* The TBL instruction does not use a modulo index, so we must take care
7664 of that ourselves. */
7665 mask
= GEN_INT (one_vector_p
? nelt
- 1 : 2 * nelt
- 1);
7666 for (i
= 0; i
< nelt
; ++i
)
7668 mask
= gen_rtx_CONST_VECTOR (vmode
, gen_rtvec_v (nelt
, rmask
));
7669 sel
= expand_simple_binop (vmode
, AND
, sel
, mask
, NULL
, 0, OPTAB_LIB_WIDEN
);
7671 aarch64_expand_vec_perm_1 (target
, op0
, op1
, sel
);
7674 /* Recognize patterns suitable for the TRN instructions. */
7676 aarch64_evpc_trn (struct expand_vec_perm_d
*d
)
7678 unsigned int i
, odd
, mask
, nelt
= d
->nelt
;
7679 rtx out
, in0
, in1
, x
;
7680 rtx (*gen
) (rtx
, rtx
, rtx
);
7681 enum machine_mode vmode
= d
->vmode
;
7683 if (GET_MODE_UNIT_SIZE (vmode
) > 8)
7686 /* Note that these are little-endian tests.
7687 We correct for big-endian later. */
7688 if (d
->perm
[0] == 0)
7690 else if (d
->perm
[0] == 1)
7694 mask
= (d
->one_vector_p
? nelt
- 1 : 2 * nelt
- 1);
7696 for (i
= 0; i
< nelt
; i
+= 2)
7698 if (d
->perm
[i
] != i
+ odd
)
7700 if (d
->perm
[i
+ 1] != ((i
+ nelt
+ odd
) & mask
))
7710 if (BYTES_BIG_ENDIAN
)
7712 x
= in0
, in0
= in1
, in1
= x
;
7721 case V16QImode
: gen
= gen_aarch64_trn2v16qi
; break;
7722 case V8QImode
: gen
= gen_aarch64_trn2v8qi
; break;
7723 case V8HImode
: gen
= gen_aarch64_trn2v8hi
; break;
7724 case V4HImode
: gen
= gen_aarch64_trn2v4hi
; break;
7725 case V4SImode
: gen
= gen_aarch64_trn2v4si
; break;
7726 case V2SImode
: gen
= gen_aarch64_trn2v2si
; break;
7727 case V2DImode
: gen
= gen_aarch64_trn2v2di
; break;
7728 case V4SFmode
: gen
= gen_aarch64_trn2v4sf
; break;
7729 case V2SFmode
: gen
= gen_aarch64_trn2v2sf
; break;
7730 case V2DFmode
: gen
= gen_aarch64_trn2v2df
; break;
7739 case V16QImode
: gen
= gen_aarch64_trn1v16qi
; break;
7740 case V8QImode
: gen
= gen_aarch64_trn1v8qi
; break;
7741 case V8HImode
: gen
= gen_aarch64_trn1v8hi
; break;
7742 case V4HImode
: gen
= gen_aarch64_trn1v4hi
; break;
7743 case V4SImode
: gen
= gen_aarch64_trn1v4si
; break;
7744 case V2SImode
: gen
= gen_aarch64_trn1v2si
; break;
7745 case V2DImode
: gen
= gen_aarch64_trn1v2di
; break;
7746 case V4SFmode
: gen
= gen_aarch64_trn1v4sf
; break;
7747 case V2SFmode
: gen
= gen_aarch64_trn1v2sf
; break;
7748 case V2DFmode
: gen
= gen_aarch64_trn1v2df
; break;
7754 emit_insn (gen (out
, in0
, in1
));
7758 /* Recognize patterns suitable for the UZP instructions. */
7760 aarch64_evpc_uzp (struct expand_vec_perm_d
*d
)
7762 unsigned int i
, odd
, mask
, nelt
= d
->nelt
;
7763 rtx out
, in0
, in1
, x
;
7764 rtx (*gen
) (rtx
, rtx
, rtx
);
7765 enum machine_mode vmode
= d
->vmode
;
7767 if (GET_MODE_UNIT_SIZE (vmode
) > 8)
7770 /* Note that these are little-endian tests.
7771 We correct for big-endian later. */
7772 if (d
->perm
[0] == 0)
7774 else if (d
->perm
[0] == 1)
7778 mask
= (d
->one_vector_p
? nelt
- 1 : 2 * nelt
- 1);
7780 for (i
= 0; i
< nelt
; i
++)
7782 unsigned elt
= (i
* 2 + odd
) & mask
;
7783 if (d
->perm
[i
] != elt
)
7793 if (BYTES_BIG_ENDIAN
)
7795 x
= in0
, in0
= in1
, in1
= x
;
7804 case V16QImode
: gen
= gen_aarch64_uzp2v16qi
; break;
7805 case V8QImode
: gen
= gen_aarch64_uzp2v8qi
; break;
7806 case V8HImode
: gen
= gen_aarch64_uzp2v8hi
; break;
7807 case V4HImode
: gen
= gen_aarch64_uzp2v4hi
; break;
7808 case V4SImode
: gen
= gen_aarch64_uzp2v4si
; break;
7809 case V2SImode
: gen
= gen_aarch64_uzp2v2si
; break;
7810 case V2DImode
: gen
= gen_aarch64_uzp2v2di
; break;
7811 case V4SFmode
: gen
= gen_aarch64_uzp2v4sf
; break;
7812 case V2SFmode
: gen
= gen_aarch64_uzp2v2sf
; break;
7813 case V2DFmode
: gen
= gen_aarch64_uzp2v2df
; break;
7822 case V16QImode
: gen
= gen_aarch64_uzp1v16qi
; break;
7823 case V8QImode
: gen
= gen_aarch64_uzp1v8qi
; break;
7824 case V8HImode
: gen
= gen_aarch64_uzp1v8hi
; break;
7825 case V4HImode
: gen
= gen_aarch64_uzp1v4hi
; break;
7826 case V4SImode
: gen
= gen_aarch64_uzp1v4si
; break;
7827 case V2SImode
: gen
= gen_aarch64_uzp1v2si
; break;
7828 case V2DImode
: gen
= gen_aarch64_uzp1v2di
; break;
7829 case V4SFmode
: gen
= gen_aarch64_uzp1v4sf
; break;
7830 case V2SFmode
: gen
= gen_aarch64_uzp1v2sf
; break;
7831 case V2DFmode
: gen
= gen_aarch64_uzp1v2df
; break;
7837 emit_insn (gen (out
, in0
, in1
));
7841 /* Recognize patterns suitable for the ZIP instructions. */
7843 aarch64_evpc_zip (struct expand_vec_perm_d
*d
)
7845 unsigned int i
, high
, mask
, nelt
= d
->nelt
;
7846 rtx out
, in0
, in1
, x
;
7847 rtx (*gen
) (rtx
, rtx
, rtx
);
7848 enum machine_mode vmode
= d
->vmode
;
7850 if (GET_MODE_UNIT_SIZE (vmode
) > 8)
7853 /* Note that these are little-endian tests.
7854 We correct for big-endian later. */
7856 if (d
->perm
[0] == high
)
7859 else if (d
->perm
[0] == 0)
7863 mask
= (d
->one_vector_p
? nelt
- 1 : 2 * nelt
- 1);
7865 for (i
= 0; i
< nelt
/ 2; i
++)
7867 unsigned elt
= (i
+ high
) & mask
;
7868 if (d
->perm
[i
* 2] != elt
)
7870 elt
= (elt
+ nelt
) & mask
;
7871 if (d
->perm
[i
* 2 + 1] != elt
)
7881 if (BYTES_BIG_ENDIAN
)
7883 x
= in0
, in0
= in1
, in1
= x
;
7892 case V16QImode
: gen
= gen_aarch64_zip2v16qi
; break;
7893 case V8QImode
: gen
= gen_aarch64_zip2v8qi
; break;
7894 case V8HImode
: gen
= gen_aarch64_zip2v8hi
; break;
7895 case V4HImode
: gen
= gen_aarch64_zip2v4hi
; break;
7896 case V4SImode
: gen
= gen_aarch64_zip2v4si
; break;
7897 case V2SImode
: gen
= gen_aarch64_zip2v2si
; break;
7898 case V2DImode
: gen
= gen_aarch64_zip2v2di
; break;
7899 case V4SFmode
: gen
= gen_aarch64_zip2v4sf
; break;
7900 case V2SFmode
: gen
= gen_aarch64_zip2v2sf
; break;
7901 case V2DFmode
: gen
= gen_aarch64_zip2v2df
; break;
7910 case V16QImode
: gen
= gen_aarch64_zip1v16qi
; break;
7911 case V8QImode
: gen
= gen_aarch64_zip1v8qi
; break;
7912 case V8HImode
: gen
= gen_aarch64_zip1v8hi
; break;
7913 case V4HImode
: gen
= gen_aarch64_zip1v4hi
; break;
7914 case V4SImode
: gen
= gen_aarch64_zip1v4si
; break;
7915 case V2SImode
: gen
= gen_aarch64_zip1v2si
; break;
7916 case V2DImode
: gen
= gen_aarch64_zip1v2di
; break;
7917 case V4SFmode
: gen
= gen_aarch64_zip1v4sf
; break;
7918 case V2SFmode
: gen
= gen_aarch64_zip1v2sf
; break;
7919 case V2DFmode
: gen
= gen_aarch64_zip1v2df
; break;
7925 emit_insn (gen (out
, in0
, in1
));
7930 aarch64_evpc_tbl (struct expand_vec_perm_d
*d
)
7932 rtx rperm
[MAX_VECT_LEN
], sel
;
7933 enum machine_mode vmode
= d
->vmode
;
7934 unsigned int i
, nelt
= d
->nelt
;
7936 /* TODO: ARM's TBL indexing is little-endian. In order to handle GCC's
7937 numbering of elements for big-endian, we must reverse the order. */
7938 if (BYTES_BIG_ENDIAN
)
7944 /* Generic code will try constant permutation twice. Once with the
7945 original mode and again with the elements lowered to QImode.
7946 So wait and don't do the selector expansion ourselves. */
7947 if (vmode
!= V8QImode
&& vmode
!= V16QImode
)
7950 for (i
= 0; i
< nelt
; ++i
)
7951 rperm
[i
] = GEN_INT (d
->perm
[i
]);
7952 sel
= gen_rtx_CONST_VECTOR (vmode
, gen_rtvec_v (nelt
, rperm
));
7953 sel
= force_reg (vmode
, sel
);
7955 aarch64_expand_vec_perm_1 (d
->target
, d
->op0
, d
->op1
, sel
);
7960 aarch64_expand_vec_perm_const_1 (struct expand_vec_perm_d
*d
)
7962 /* The pattern matching functions above are written to look for a small
7963 number to begin the sequence (0, 1, N/2). If we begin with an index
7964 from the second operand, we can swap the operands. */
7965 if (d
->perm
[0] >= d
->nelt
)
7967 unsigned i
, nelt
= d
->nelt
;
7970 for (i
= 0; i
< nelt
; ++i
)
7971 d
->perm
[i
] = (d
->perm
[i
] + nelt
) & (2 * nelt
- 1);
7980 if (aarch64_evpc_zip (d
))
7982 else if (aarch64_evpc_uzp (d
))
7984 else if (aarch64_evpc_trn (d
))
7986 return aarch64_evpc_tbl (d
);
7991 /* Expand a vec_perm_const pattern. */
7994 aarch64_expand_vec_perm_const (rtx target
, rtx op0
, rtx op1
, rtx sel
)
7996 struct expand_vec_perm_d d
;
8003 d
.vmode
= GET_MODE (target
);
8004 gcc_assert (VECTOR_MODE_P (d
.vmode
));
8005 d
.nelt
= nelt
= GET_MODE_NUNITS (d
.vmode
);
8006 d
.testing_p
= false;
8008 for (i
= which
= 0; i
< nelt
; ++i
)
8010 rtx e
= XVECEXP (sel
, 0, i
);
8011 int ei
= INTVAL (e
) & (2 * nelt
- 1);
8012 which
|= (ei
< nelt
? 1 : 2);
8022 d
.one_vector_p
= false;
8023 if (!rtx_equal_p (op0
, op1
))
8026 /* The elements of PERM do not suggest that only the first operand
8027 is used, but both operands are identical. Allow easier matching
8028 of the permutation by folding the permutation into the single
8032 for (i
= 0; i
< nelt
; ++i
)
8033 d
.perm
[i
] &= nelt
- 1;
8035 d
.one_vector_p
= true;
8040 d
.one_vector_p
= true;
8044 return aarch64_expand_vec_perm_const_1 (&d
);
8048 aarch64_vectorize_vec_perm_const_ok (enum machine_mode vmode
,
8049 const unsigned char *sel
)
8051 struct expand_vec_perm_d d
;
8052 unsigned int i
, nelt
, which
;
8056 d
.nelt
= nelt
= GET_MODE_NUNITS (d
.vmode
);
8058 memcpy (d
.perm
, sel
, nelt
);
8060 /* Calculate whether all elements are in one vector. */
8061 for (i
= which
= 0; i
< nelt
; ++i
)
8063 unsigned char e
= d
.perm
[i
];
8064 gcc_assert (e
< 2 * nelt
);
8065 which
|= (e
< nelt
? 1 : 2);
8068 /* If all elements are from the second vector, reindex as if from the
8071 for (i
= 0; i
< nelt
; ++i
)
8074 /* Check whether the mask can be applied to a single vector. */
8075 d
.one_vector_p
= (which
!= 3);
8077 d
.target
= gen_raw_REG (d
.vmode
, LAST_VIRTUAL_REGISTER
+ 1);
8078 d
.op1
= d
.op0
= gen_raw_REG (d
.vmode
, LAST_VIRTUAL_REGISTER
+ 2);
8079 if (!d
.one_vector_p
)
8080 d
.op1
= gen_raw_REG (d
.vmode
, LAST_VIRTUAL_REGISTER
+ 3);
8083 ret
= aarch64_expand_vec_perm_const_1 (&d
);
8089 #undef TARGET_ADDRESS_COST
8090 #define TARGET_ADDRESS_COST aarch64_address_cost
8092 /* This hook will determines whether unnamed bitfields affect the alignment
8093 of the containing structure. The hook returns true if the structure
8094 should inherit the alignment requirements of an unnamed bitfield's
8096 #undef TARGET_ALIGN_ANON_BITFIELD
8097 #define TARGET_ALIGN_ANON_BITFIELD hook_bool_void_true
8099 #undef TARGET_ASM_ALIGNED_DI_OP
8100 #define TARGET_ASM_ALIGNED_DI_OP "\t.xword\t"
8102 #undef TARGET_ASM_ALIGNED_HI_OP
8103 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
8105 #undef TARGET_ASM_ALIGNED_SI_OP
8106 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
8108 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
8109 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
8110 hook_bool_const_tree_hwi_hwi_const_tree_true
8112 #undef TARGET_ASM_FILE_START
8113 #define TARGET_ASM_FILE_START aarch64_start_file
8115 #undef TARGET_ASM_OUTPUT_MI_THUNK
8116 #define TARGET_ASM_OUTPUT_MI_THUNK aarch64_output_mi_thunk
8118 #undef TARGET_ASM_SELECT_RTX_SECTION
8119 #define TARGET_ASM_SELECT_RTX_SECTION aarch64_select_rtx_section
8121 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
8122 #define TARGET_ASM_TRAMPOLINE_TEMPLATE aarch64_asm_trampoline_template
8124 #undef TARGET_BUILD_BUILTIN_VA_LIST
8125 #define TARGET_BUILD_BUILTIN_VA_LIST aarch64_build_builtin_va_list
8127 #undef TARGET_CALLEE_COPIES
8128 #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false
8130 #undef TARGET_CAN_ELIMINATE
8131 #define TARGET_CAN_ELIMINATE aarch64_can_eliminate
8133 #undef TARGET_CANNOT_FORCE_CONST_MEM
8134 #define TARGET_CANNOT_FORCE_CONST_MEM aarch64_cannot_force_const_mem
8136 #undef TARGET_CONDITIONAL_REGISTER_USAGE
8137 #define TARGET_CONDITIONAL_REGISTER_USAGE aarch64_conditional_register_usage
8139 /* Only the least significant bit is used for initialization guard
8141 #undef TARGET_CXX_GUARD_MASK_BIT
8142 #define TARGET_CXX_GUARD_MASK_BIT hook_bool_void_true
8144 #undef TARGET_C_MODE_FOR_SUFFIX
8145 #define TARGET_C_MODE_FOR_SUFFIX aarch64_c_mode_for_suffix
8147 #ifdef TARGET_BIG_ENDIAN_DEFAULT
8148 #undef TARGET_DEFAULT_TARGET_FLAGS
8149 #define TARGET_DEFAULT_TARGET_FLAGS (MASK_BIG_END)
8152 #undef TARGET_CLASS_MAX_NREGS
8153 #define TARGET_CLASS_MAX_NREGS aarch64_class_max_nregs
8155 #undef TARGET_BUILTIN_DECL
8156 #define TARGET_BUILTIN_DECL aarch64_builtin_decl
8158 #undef TARGET_EXPAND_BUILTIN
8159 #define TARGET_EXPAND_BUILTIN aarch64_expand_builtin
8161 #undef TARGET_EXPAND_BUILTIN_VA_START
8162 #define TARGET_EXPAND_BUILTIN_VA_START aarch64_expand_builtin_va_start
8164 #undef TARGET_FOLD_BUILTIN
8165 #define TARGET_FOLD_BUILTIN aarch64_fold_builtin
8167 #undef TARGET_FUNCTION_ARG
8168 #define TARGET_FUNCTION_ARG aarch64_function_arg
8170 #undef TARGET_FUNCTION_ARG_ADVANCE
8171 #define TARGET_FUNCTION_ARG_ADVANCE aarch64_function_arg_advance
8173 #undef TARGET_FUNCTION_ARG_BOUNDARY
8174 #define TARGET_FUNCTION_ARG_BOUNDARY aarch64_function_arg_boundary
8176 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
8177 #define TARGET_FUNCTION_OK_FOR_SIBCALL aarch64_function_ok_for_sibcall
8179 #undef TARGET_FUNCTION_VALUE
8180 #define TARGET_FUNCTION_VALUE aarch64_function_value
8182 #undef TARGET_FUNCTION_VALUE_REGNO_P
8183 #define TARGET_FUNCTION_VALUE_REGNO_P aarch64_function_value_regno_p
8185 #undef TARGET_FRAME_POINTER_REQUIRED
8186 #define TARGET_FRAME_POINTER_REQUIRED aarch64_frame_pointer_required
8188 #undef TARGET_GIMPLE_FOLD_BUILTIN
8189 #define TARGET_GIMPLE_FOLD_BUILTIN aarch64_gimple_fold_builtin
8191 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
8192 #define TARGET_GIMPLIFY_VA_ARG_EXPR aarch64_gimplify_va_arg_expr
8194 #undef TARGET_INIT_BUILTINS
8195 #define TARGET_INIT_BUILTINS aarch64_init_builtins
8197 #undef TARGET_LEGITIMATE_ADDRESS_P
8198 #define TARGET_LEGITIMATE_ADDRESS_P aarch64_legitimate_address_hook_p
8200 #undef TARGET_LEGITIMATE_CONSTANT_P
8201 #define TARGET_LEGITIMATE_CONSTANT_P aarch64_legitimate_constant_p
8203 #undef TARGET_LIBGCC_CMP_RETURN_MODE
8204 #define TARGET_LIBGCC_CMP_RETURN_MODE aarch64_libgcc_cmp_return_mode
8206 #undef TARGET_MANGLE_TYPE
8207 #define TARGET_MANGLE_TYPE aarch64_mangle_type
8209 #undef TARGET_MEMORY_MOVE_COST
8210 #define TARGET_MEMORY_MOVE_COST aarch64_memory_move_cost
8212 #undef TARGET_MUST_PASS_IN_STACK
8213 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
8215 /* This target hook should return true if accesses to volatile bitfields
8216 should use the narrowest mode possible. It should return false if these
8217 accesses should use the bitfield container type. */
8218 #undef TARGET_NARROW_VOLATILE_BITFIELD
8219 #define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
8221 #undef TARGET_OPTION_OVERRIDE
8222 #define TARGET_OPTION_OVERRIDE aarch64_override_options
8224 #undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
8225 #define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE \
8226 aarch64_override_options_after_change
8228 #undef TARGET_PASS_BY_REFERENCE
8229 #define TARGET_PASS_BY_REFERENCE aarch64_pass_by_reference
8231 #undef TARGET_PREFERRED_RELOAD_CLASS
8232 #define TARGET_PREFERRED_RELOAD_CLASS aarch64_preferred_reload_class
8234 #undef TARGET_SECONDARY_RELOAD
8235 #define TARGET_SECONDARY_RELOAD aarch64_secondary_reload
8237 #undef TARGET_SHIFT_TRUNCATION_MASK
8238 #define TARGET_SHIFT_TRUNCATION_MASK aarch64_shift_truncation_mask
8240 #undef TARGET_SETUP_INCOMING_VARARGS
8241 #define TARGET_SETUP_INCOMING_VARARGS aarch64_setup_incoming_varargs
8243 #undef TARGET_STRUCT_VALUE_RTX
8244 #define TARGET_STRUCT_VALUE_RTX aarch64_struct_value_rtx
8246 #undef TARGET_REGISTER_MOVE_COST
8247 #define TARGET_REGISTER_MOVE_COST aarch64_register_move_cost
8249 #undef TARGET_RETURN_IN_MEMORY
8250 #define TARGET_RETURN_IN_MEMORY aarch64_return_in_memory
8252 #undef TARGET_RETURN_IN_MSB
8253 #define TARGET_RETURN_IN_MSB aarch64_return_in_msb
8255 #undef TARGET_RTX_COSTS
8256 #define TARGET_RTX_COSTS aarch64_rtx_costs
8258 #undef TARGET_TRAMPOLINE_INIT
8259 #define TARGET_TRAMPOLINE_INIT aarch64_trampoline_init
8261 #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
8262 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P aarch64_use_blocks_for_constant_p
8264 #undef TARGET_VECTOR_MODE_SUPPORTED_P
8265 #define TARGET_VECTOR_MODE_SUPPORTED_P aarch64_vector_mode_supported_p
8267 #undef TARGET_ARRAY_MODE_SUPPORTED_P
8268 #define TARGET_ARRAY_MODE_SUPPORTED_P aarch64_array_mode_supported_p
8270 #undef TARGET_VECTORIZE_ADD_STMT_COST
8271 #define TARGET_VECTORIZE_ADD_STMT_COST aarch64_add_stmt_cost
8273 #undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST
8274 #define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST \
8275 aarch64_builtin_vectorization_cost
8277 #undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE
8278 #define TARGET_VECTORIZE_PREFERRED_SIMD_MODE aarch64_preferred_simd_mode
8280 #undef TARGET_VECTORIZE_BUILTINS
8281 #define TARGET_VECTORIZE_BUILTINS
8283 #undef TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION
8284 #define TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION \
8285 aarch64_builtin_vectorized_function
8287 #undef TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES
8288 #define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES \
8289 aarch64_autovectorize_vector_sizes
8291 /* Section anchor support. */
8293 #undef TARGET_MIN_ANCHOR_OFFSET
8294 #define TARGET_MIN_ANCHOR_OFFSET -256
8296 /* Limit the maximum anchor offset to 4k-1, since that's the limit for a
8297 byte offset; we can do much more for larger data types, but have no way
8298 to determine the size of the access. We assume accesses are aligned. */
8299 #undef TARGET_MAX_ANCHOR_OFFSET
8300 #define TARGET_MAX_ANCHOR_OFFSET 4095
8302 #undef TARGET_VECTOR_ALIGNMENT
8303 #define TARGET_VECTOR_ALIGNMENT aarch64_simd_vector_alignment
8305 #undef TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE
8306 #define TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE \
8307 aarch64_simd_vector_alignment_reachable
8309 /* vec_perm support. */
8311 #undef TARGET_VECTORIZE_VEC_PERM_CONST_OK
8312 #define TARGET_VECTORIZE_VEC_PERM_CONST_OK \
8313 aarch64_vectorize_vec_perm_const_ok
8316 #undef TARGET_FIXED_CONDITION_CODE_REGS
8317 #define TARGET_FIXED_CONDITION_CODE_REGS aarch64_fixed_condition_code_regs
8319 struct gcc_target targetm
= TARGET_INITIALIZER
;
8321 #include "gt-aarch64.h"