1 /* Machine description for AArch64 architecture.
2 Copyright (C) 2009, 2010, 2011, 2012 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 /* Classifies an address.
52 A simple base register plus immediate offset.
55 A base register indexed by immediate offset with writeback.
58 A base register indexed by (optionally scaled) register.
61 A base register indexed by (optionally scaled) zero-extended register.
64 A base register indexed by (optionally scaled) sign-extended register.
67 A LO_SUM rtx with a base register and "LO12" symbol relocation.
70 A constant symbolic address, in pc-relative literal pool. */
72 enum aarch64_address_type
{
82 struct aarch64_address_info
{
83 enum aarch64_address_type type
;
87 enum aarch64_symbol_type symbol_type
;
90 /* The current code model. */
91 enum aarch64_code_model aarch64_cmodel
;
94 #undef TARGET_HAVE_TLS
95 #define TARGET_HAVE_TLS 1
98 static bool aarch64_composite_type_p (const_tree
, enum machine_mode
);
99 static bool aarch64_vfp_is_call_or_return_candidate (enum machine_mode
,
101 enum machine_mode
*, int *,
103 static void aarch64_elf_asm_constructor (rtx
, int) ATTRIBUTE_UNUSED
;
104 static void aarch64_elf_asm_destructor (rtx
, int) ATTRIBUTE_UNUSED
;
105 static void aarch64_override_options_after_change (void);
106 static int aarch64_simd_valid_immediate (rtx
, enum machine_mode
, int, rtx
*,
107 int *, unsigned char *, int *, int *);
108 static bool aarch64_vector_mode_supported_p (enum machine_mode
);
109 static unsigned bit_count (unsigned HOST_WIDE_INT
);
110 static bool aarch64_const_vec_all_same_int_p (rtx
,
111 HOST_WIDE_INT
, HOST_WIDE_INT
);
113 /* The processor for which instructions should be scheduled. */
114 enum aarch64_processor aarch64_tune
= generic
;
116 /* The current tuning set. */
117 const struct tune_params
*aarch64_tune_params
;
119 /* Mask to specify which instructions we are allowed to generate. */
120 unsigned long aarch64_isa_flags
= 0;
122 /* Mask to specify which instruction scheduling options should be used. */
123 unsigned long aarch64_tune_flags
= 0;
125 /* Tuning parameters. */
127 #if HAVE_DESIGNATED_INITIALIZERS
128 #define NAMED_PARAM(NAME, VAL) .NAME = (VAL)
130 #define NAMED_PARAM(NAME, VAL) (VAL)
133 #if HAVE_DESIGNATED_INITIALIZERS && GCC_VERSION >= 2007
136 static const struct cpu_rtx_cost_table generic_rtx_cost_table
=
138 NAMED_PARAM (memory_load
, COSTS_N_INSNS (1)),
139 NAMED_PARAM (memory_store
, COSTS_N_INSNS (0)),
140 NAMED_PARAM (register_shift
, COSTS_N_INSNS (1)),
141 NAMED_PARAM (int_divide
, COSTS_N_INSNS (6)),
142 NAMED_PARAM (float_divide
, COSTS_N_INSNS (2)),
143 NAMED_PARAM (double_divide
, COSTS_N_INSNS (6)),
144 NAMED_PARAM (int_multiply
, COSTS_N_INSNS (1)),
145 NAMED_PARAM (int_multiply_extend
, COSTS_N_INSNS (1)),
146 NAMED_PARAM (int_multiply_add
, COSTS_N_INSNS (1)),
147 NAMED_PARAM (int_multiply_extend_add
, COSTS_N_INSNS (1)),
148 NAMED_PARAM (float_multiply
, COSTS_N_INSNS (0)),
149 NAMED_PARAM (double_multiply
, COSTS_N_INSNS (1))
152 #if HAVE_DESIGNATED_INITIALIZERS && GCC_VERSION >= 2007
155 static const struct cpu_addrcost_table generic_addrcost_table
=
157 NAMED_PARAM (pre_modify
, 0),
158 NAMED_PARAM (post_modify
, 0),
159 NAMED_PARAM (register_offset
, 0),
160 NAMED_PARAM (register_extend
, 0),
161 NAMED_PARAM (imm_offset
, 0)
164 #if HAVE_DESIGNATED_INITIALIZERS && GCC_VERSION >= 2007
167 static const struct cpu_regmove_cost generic_regmove_cost
=
169 NAMED_PARAM (GP2GP
, 1),
170 NAMED_PARAM (GP2FP
, 2),
171 NAMED_PARAM (FP2GP
, 2),
172 /* We currently do not provide direct support for TFmode Q->Q move.
173 Therefore we need to raise the cost above 2 in order to have
174 reload handle the situation. */
175 NAMED_PARAM (FP2FP
, 4)
178 #if HAVE_DESIGNATED_INITIALIZERS && GCC_VERSION >= 2007
181 static const struct tune_params generic_tunings
=
183 &generic_rtx_cost_table
,
184 &generic_addrcost_table
,
185 &generic_regmove_cost
,
186 NAMED_PARAM (memmov_cost
, 4)
189 /* A processor implementing AArch64. */
192 const char *const name
;
193 enum aarch64_processor core
;
195 const unsigned long flags
;
196 const struct tune_params
*const tune
;
199 /* Processor cores implementing AArch64. */
200 static const struct processor all_cores
[] =
202 #define AARCH64_CORE(NAME, IDENT, ARCH, FLAGS, COSTS) \
203 {NAME, IDENT, #ARCH, FLAGS | AARCH64_FL_FOR_ARCH##ARCH, &COSTS##_tunings},
204 #include "aarch64-cores.def"
206 {"generic", generic
, "8", AARCH64_FL_FPSIMD
| AARCH64_FL_FOR_ARCH8
, &generic_tunings
},
207 {NULL
, aarch64_none
, NULL
, 0, NULL
}
210 /* Architectures implementing AArch64. */
211 static const struct processor all_architectures
[] =
213 #define AARCH64_ARCH(NAME, CORE, ARCH, FLAGS) \
214 {NAME, CORE, #ARCH, FLAGS, NULL},
215 #include "aarch64-arches.def"
217 {"generic", generic
, "8", AARCH64_FL_FOR_ARCH8
, NULL
},
218 {NULL
, aarch64_none
, NULL
, 0, NULL
}
221 /* Target specification. These are populated as commandline arguments
222 are processed, or NULL if not specified. */
223 static const struct processor
*selected_arch
;
224 static const struct processor
*selected_cpu
;
225 static const struct processor
*selected_tune
;
227 #define AARCH64_CPU_DEFAULT_FLAGS ((selected_cpu) ? selected_cpu->flags : 0)
229 /* An ISA extension in the co-processor and main instruction set space. */
230 struct aarch64_option_extension
232 const char *const name
;
233 const unsigned long flags_on
;
234 const unsigned long flags_off
;
237 /* ISA extensions in AArch64. */
238 static const struct aarch64_option_extension all_extensions
[] =
240 #define AARCH64_OPT_EXTENSION(NAME, FLAGS_ON, FLAGS_OFF) \
241 {NAME, FLAGS_ON, FLAGS_OFF},
242 #include "aarch64-option-extensions.def"
243 #undef AARCH64_OPT_EXTENSION
247 /* Used to track the size of an address when generating a pre/post
248 increment address. */
249 static enum machine_mode aarch64_memory_reference_mode
;
251 /* Used to force GTY into this file. */
252 static GTY(()) int gty_dummy
;
254 /* A table of valid AArch64 "bitmask immediate" values for
255 logical instructions. */
257 #define AARCH64_NUM_BITMASKS 5334
258 static unsigned HOST_WIDE_INT aarch64_bitmasks
[AARCH64_NUM_BITMASKS
];
260 /* Did we set flag_omit_frame_pointer just so
261 aarch64_frame_pointer_required would be called? */
262 static bool faked_omit_frame_pointer
;
264 typedef enum aarch64_cond_code
266 AARCH64_EQ
= 0, AARCH64_NE
, AARCH64_CS
, AARCH64_CC
, AARCH64_MI
, AARCH64_PL
,
267 AARCH64_VS
, AARCH64_VC
, AARCH64_HI
, AARCH64_LS
, AARCH64_GE
, AARCH64_LT
,
268 AARCH64_GT
, AARCH64_LE
, AARCH64_AL
, AARCH64_NV
272 #define AARCH64_INVERSE_CONDITION_CODE(X) ((aarch64_cc) (((int) X) ^ 1))
274 /* The condition codes of the processor, and the inverse function. */
275 static const char * const aarch64_condition_codes
[] =
277 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
278 "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
281 /* Provide a mapping from gcc register numbers to dwarf register numbers. */
283 aarch64_dbx_register_number (unsigned regno
)
285 if (GP_REGNUM_P (regno
))
286 return AARCH64_DWARF_R0
+ regno
- R0_REGNUM
;
287 else if (regno
== SP_REGNUM
)
288 return AARCH64_DWARF_SP
;
289 else if (FP_REGNUM_P (regno
))
290 return AARCH64_DWARF_V0
+ regno
- V0_REGNUM
;
292 /* Return values >= DWARF_FRAME_REGISTERS indicate that there is no
293 equivalent DWARF register. */
294 return DWARF_FRAME_REGISTERS
;
297 /* Return TRUE if MODE is any of the large INT modes. */
299 aarch64_vect_struct_mode_p (enum machine_mode mode
)
301 return mode
== OImode
|| mode
== CImode
|| mode
== XImode
;
304 /* Return TRUE if MODE is any of the vector modes. */
306 aarch64_vector_mode_p (enum machine_mode mode
)
308 return aarch64_vector_mode_supported_p (mode
)
309 || aarch64_vect_struct_mode_p (mode
);
312 /* Implement target hook TARGET_ARRAY_MODE_SUPPORTED_P. */
314 aarch64_array_mode_supported_p (enum machine_mode mode
,
315 unsigned HOST_WIDE_INT nelems
)
318 && AARCH64_VALID_SIMD_QREG_MODE (mode
)
319 && (nelems
>= 2 && nelems
<= 4))
325 /* Implement HARD_REGNO_NREGS. */
328 aarch64_hard_regno_nregs (unsigned regno
, enum machine_mode mode
)
330 switch (aarch64_regno_regclass (regno
))
334 return (GET_MODE_SIZE (mode
) + UNITS_PER_VREG
- 1) / UNITS_PER_VREG
;
336 return (GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
341 /* Implement HARD_REGNO_MODE_OK. */
344 aarch64_hard_regno_mode_ok (unsigned regno
, enum machine_mode mode
)
346 if (GET_MODE_CLASS (mode
) == MODE_CC
)
347 return regno
== CC_REGNUM
;
349 if (regno
== SP_REGNUM
|| regno
== FRAME_POINTER_REGNUM
350 || regno
== ARG_POINTER_REGNUM
)
351 return mode
== Pmode
;
353 if (GP_REGNUM_P (regno
) && ! aarch64_vect_struct_mode_p (mode
))
356 if (FP_REGNUM_P (regno
))
358 if (aarch64_vect_struct_mode_p (mode
))
360 (regno
+ aarch64_hard_regno_nregs (regno
, mode
) - 1) <= V31_REGNUM
;
368 /* Return true if calls to DECL should be treated as
369 long-calls (ie called via a register). */
371 aarch64_decl_is_long_call_p (const_tree decl ATTRIBUTE_UNUSED
)
376 /* Return true if calls to symbol-ref SYM should be treated as
377 long-calls (ie called via a register). */
379 aarch64_is_long_call_p (rtx sym
)
381 return aarch64_decl_is_long_call_p (SYMBOL_REF_DECL (sym
));
384 /* Return true if the offsets to a zero/sign-extract operation
385 represent an expression that matches an extend operation. The
386 operands represent the paramters from
388 (extract (mult (reg) (mult_imm)) (extract_imm) (const_int 0)). */
390 aarch64_is_extend_from_extract (enum machine_mode mode
, rtx mult_imm
,
393 HOST_WIDE_INT mult_val
, extract_val
;
395 if (! CONST_INT_P (mult_imm
) || ! CONST_INT_P (extract_imm
))
398 mult_val
= INTVAL (mult_imm
);
399 extract_val
= INTVAL (extract_imm
);
402 && extract_val
< GET_MODE_BITSIZE (mode
)
403 && exact_log2 (extract_val
& ~7) > 0
404 && (extract_val
& 7) <= 4
405 && mult_val
== (1 << (extract_val
& 7)))
411 /* Emit an insn that's a simple single-set. Both the operands must be
412 known to be valid. */
414 emit_set_insn (rtx x
, rtx y
)
416 return emit_insn (gen_rtx_SET (VOIDmode
, x
, y
));
419 /* X and Y are two things to compare using CODE. Emit the compare insn and
420 return the rtx for register 0 in the proper mode. */
422 aarch64_gen_compare_reg (RTX_CODE code
, rtx x
, rtx y
)
424 enum machine_mode mode
= SELECT_CC_MODE (code
, x
, y
);
425 rtx cc_reg
= gen_rtx_REG (mode
, CC_REGNUM
);
427 emit_set_insn (cc_reg
, gen_rtx_COMPARE (mode
, x
, y
));
431 /* Build the SYMBOL_REF for __tls_get_addr. */
433 static GTY(()) rtx tls_get_addr_libfunc
;
436 aarch64_tls_get_addr (void)
438 if (!tls_get_addr_libfunc
)
439 tls_get_addr_libfunc
= init_one_libfunc ("__tls_get_addr");
440 return tls_get_addr_libfunc
;
443 /* Return the TLS model to use for ADDR. */
445 static enum tls_model
446 tls_symbolic_operand_type (rtx addr
)
448 enum tls_model tls_kind
= TLS_MODEL_NONE
;
451 if (GET_CODE (addr
) == CONST
)
453 split_const (addr
, &sym
, &addend
);
454 if (GET_CODE (sym
) == SYMBOL_REF
)
455 tls_kind
= SYMBOL_REF_TLS_MODEL (sym
);
457 else if (GET_CODE (addr
) == SYMBOL_REF
)
458 tls_kind
= SYMBOL_REF_TLS_MODEL (addr
);
463 /* We'll allow lo_sum's in addresses in our legitimate addresses
464 so that combine would take care of combining addresses where
465 necessary, but for generation purposes, we'll generate the address
468 tmp = hi (symbol_ref); adrp x1, foo
469 dest = lo_sum (tmp, symbol_ref); add dest, x1, :lo_12:foo
473 adrp x1, :got:foo adrp tmp, :tlsgd:foo
474 ldr x1, [:got_lo12:foo] add dest, tmp, :tlsgd_lo12:foo
478 Load TLS symbol, depending on TLS mechanism and TLS access model.
480 Global Dynamic - Traditional TLS:
482 add dest, tmp, #:tlsgd_lo12:imm
485 Global Dynamic - TLS Descriptors:
486 adrp dest, :tlsdesc:imm
487 ldr tmp, [dest, #:tlsdesc_lo12:imm]
488 add dest, dest, #:tlsdesc_lo12:imm
495 adrp tmp, :gottprel:imm
496 ldr dest, [tmp, #:gottprel_lo12:imm]
501 add t0, tp, #:tprel_hi12:imm
502 add t0, #:tprel_lo12_nc:imm
506 aarch64_load_symref_appropriately (rtx dest
, rtx imm
,
507 enum aarch64_symbol_type type
)
511 case SYMBOL_SMALL_ABSOLUTE
:
514 if (can_create_pseudo_p ())
516 tmp_reg
= gen_reg_rtx (Pmode
);
519 emit_move_insn (tmp_reg
, gen_rtx_HIGH (Pmode
, imm
));
520 emit_insn (gen_add_losym (dest
, tmp_reg
, imm
));
524 case SYMBOL_SMALL_GOT
:
527 if (can_create_pseudo_p ())
529 tmp_reg
= gen_reg_rtx (Pmode
);
531 emit_move_insn (tmp_reg
, gen_rtx_HIGH (Pmode
, imm
));
532 emit_insn (gen_ldr_got_small (dest
, tmp_reg
, imm
));
536 case SYMBOL_SMALL_TLSGD
:
539 rtx result
= gen_rtx_REG (Pmode
, R0_REGNUM
);
542 emit_call_insn (gen_tlsgd_small (result
, imm
));
543 insns
= get_insns ();
546 RTL_CONST_CALL_P (insns
) = 1;
547 emit_libcall_block (insns
, dest
, result
, imm
);
551 case SYMBOL_SMALL_TLSDESC
:
553 rtx x0
= gen_rtx_REG (Pmode
, R0_REGNUM
);
556 emit_insn (gen_tlsdesc_small (imm
));
557 tp
= aarch64_load_tp (NULL
);
558 emit_insn (gen_rtx_SET (Pmode
, dest
, gen_rtx_PLUS (Pmode
, tp
, x0
)));
559 set_unique_reg_note (get_last_insn (), REG_EQUIV
, imm
);
563 case SYMBOL_SMALL_GOTTPREL
:
565 rtx tmp_reg
= gen_reg_rtx (Pmode
);
566 rtx tp
= aarch64_load_tp (NULL
);
567 emit_insn (gen_tlsie_small (tmp_reg
, imm
));
568 emit_insn (gen_rtx_SET (Pmode
, dest
, gen_rtx_PLUS (Pmode
, tp
, tmp_reg
)));
569 set_unique_reg_note (get_last_insn (), REG_EQUIV
, imm
);
573 case SYMBOL_SMALL_TPREL
:
575 rtx tp
= aarch64_load_tp (NULL
);
576 emit_insn (gen_tlsle_small (dest
, tp
, imm
));
577 set_unique_reg_note (get_last_insn (), REG_EQUIV
, imm
);
586 /* Emit a move from SRC to DEST. Assume that the move expanders can
587 handle all moves if !can_create_pseudo_p (). The distinction is
588 important because, unlike emit_move_insn, the move expanders know
589 how to force Pmode objects into the constant pool even when the
590 constant pool address is not itself legitimate. */
592 aarch64_emit_move (rtx dest
, rtx src
)
594 return (can_create_pseudo_p ()
595 ? emit_move_insn (dest
, src
)
596 : emit_move_insn_1 (dest
, src
));
600 aarch64_split_128bit_move (rtx dst
, rtx src
)
604 gcc_assert (GET_MODE (dst
) == TImode
);
606 if (REG_P (dst
) && REG_P (src
))
608 int src_regno
= REGNO (src
);
609 int dst_regno
= REGNO (dst
);
611 gcc_assert (GET_MODE (src
) == TImode
);
613 /* Handle r -> w, w -> r. */
614 if (FP_REGNUM_P (dst_regno
) && GP_REGNUM_P (src_regno
))
616 emit_insn (gen_aarch64_movtilow_di (dst
,
617 gen_lowpart (word_mode
, src
)));
618 emit_insn (gen_aarch64_movtihigh_di (dst
,
619 gen_highpart (word_mode
, src
)));
622 else if (GP_REGNUM_P (dst_regno
) && FP_REGNUM_P (src_regno
))
624 emit_insn (gen_aarch64_movdi_tilow (gen_lowpart (word_mode
, dst
),
626 emit_insn (gen_aarch64_movdi_tihigh (gen_highpart (word_mode
, dst
),
630 /* Fall through to r -> r cases. */
633 low_dst
= gen_lowpart (word_mode
, dst
);
635 && reg_overlap_mentioned_p (low_dst
, src
))
637 aarch64_emit_move (gen_highpart (word_mode
, dst
),
638 gen_highpart_mode (word_mode
, TImode
, src
));
639 aarch64_emit_move (low_dst
, gen_lowpart (word_mode
, src
));
643 aarch64_emit_move (low_dst
, gen_lowpart (word_mode
, src
));
644 aarch64_emit_move (gen_highpart (word_mode
, dst
),
645 gen_highpart_mode (word_mode
, TImode
, src
));
650 aarch64_split_128bit_move_p (rtx dst
, rtx src
)
652 return (! REG_P (src
)
653 || ! (FP_REGNUM_P (REGNO (dst
)) && FP_REGNUM_P (REGNO (src
))));
657 aarch64_force_temporary (rtx x
, rtx value
)
659 if (can_create_pseudo_p ())
660 return force_reg (Pmode
, value
);
663 x
= aarch64_emit_move (x
, value
);
670 aarch64_add_offset (enum machine_mode mode
, rtx temp
, rtx reg
, HOST_WIDE_INT offset
)
672 if (!aarch64_plus_immediate (GEN_INT (offset
), DImode
))
675 /* Load the full offset into a register. This
676 might be improvable in the future. */
677 high
= GEN_INT (offset
);
679 high
= aarch64_force_temporary (temp
, high
);
680 reg
= aarch64_force_temporary (temp
, gen_rtx_PLUS (Pmode
, high
, reg
));
682 return plus_constant (mode
, reg
, offset
);
686 aarch64_expand_mov_immediate (rtx dest
, rtx imm
)
688 enum machine_mode mode
= GET_MODE (dest
);
689 unsigned HOST_WIDE_INT mask
;
692 unsigned HOST_WIDE_INT val
;
695 int one_match
, zero_match
;
697 gcc_assert (mode
== SImode
|| mode
== DImode
);
699 /* Check on what type of symbol it is. */
700 if (GET_CODE (imm
) == SYMBOL_REF
701 || GET_CODE (imm
) == LABEL_REF
702 || GET_CODE (imm
) == CONST
)
704 rtx mem
, base
, offset
;
705 enum aarch64_symbol_type sty
;
707 /* If we have (const (plus symbol offset)), separate out the offset
708 before we start classifying the symbol. */
709 split_const (imm
, &base
, &offset
);
711 sty
= aarch64_classify_symbol (base
, SYMBOL_CONTEXT_ADR
);
714 case SYMBOL_FORCE_TO_MEM
:
715 if (offset
!= const0_rtx
716 && targetm
.cannot_force_const_mem (mode
, imm
))
718 gcc_assert(can_create_pseudo_p ());
719 base
= aarch64_force_temporary (dest
, base
);
720 base
= aarch64_add_offset (mode
, NULL
, base
, INTVAL (offset
));
721 aarch64_emit_move (dest
, base
);
724 mem
= force_const_mem (mode
, imm
);
726 emit_insn (gen_rtx_SET (VOIDmode
, dest
, mem
));
729 case SYMBOL_SMALL_TLSGD
:
730 case SYMBOL_SMALL_TLSDESC
:
731 case SYMBOL_SMALL_GOTTPREL
:
732 case SYMBOL_SMALL_GOT
:
733 if (offset
!= const0_rtx
)
735 gcc_assert(can_create_pseudo_p ());
736 base
= aarch64_force_temporary (dest
, base
);
737 base
= aarch64_add_offset (mode
, NULL
, base
, INTVAL (offset
));
738 aarch64_emit_move (dest
, base
);
743 case SYMBOL_SMALL_TPREL
:
744 case SYMBOL_SMALL_ABSOLUTE
:
745 aarch64_load_symref_appropriately (dest
, imm
, sty
);
753 if (CONST_INT_P (imm
) && aarch64_move_imm (INTVAL (imm
), mode
))
755 emit_insn (gen_rtx_SET (VOIDmode
, dest
, imm
));
759 if (!CONST_INT_P (imm
))
761 if (GET_CODE (imm
) == HIGH
)
762 emit_insn (gen_rtx_SET (VOIDmode
, dest
, imm
));
765 rtx mem
= force_const_mem (mode
, imm
);
767 emit_insn (gen_rtx_SET (VOIDmode
, dest
, mem
));
775 /* We know we can't do this in 1 insn, and we must be able to do it
776 in two; so don't mess around looking for sequences that don't buy
778 emit_insn (gen_rtx_SET (VOIDmode
, dest
, GEN_INT (INTVAL (imm
) & 0xffff)));
779 emit_insn (gen_insv_immsi (dest
, GEN_INT (16),
780 GEN_INT ((INTVAL (imm
) >> 16) & 0xffff)));
784 /* Remaining cases are all for DImode. */
787 subtargets
= optimize
&& can_create_pseudo_p ();
793 for (i
= 0; i
< 64; i
+= 16, mask
<<= 16)
795 if ((val
& mask
) == 0)
797 else if ((val
& mask
) == mask
)
804 for (i
= 0; i
< 64; i
+= 16, mask
<<= 16)
806 if ((val
& mask
) != mask
)
808 emit_insn (gen_rtx_SET (VOIDmode
, dest
, GEN_INT (val
| mask
)));
809 emit_insn (gen_insv_immdi (dest
, GEN_INT (i
),
810 GEN_INT ((val
>> i
) & 0xffff)));
818 goto simple_sequence
;
820 mask
= 0x0ffff0000UL
;
821 for (i
= 16; i
< 64; i
+= 16, mask
<<= 16)
823 HOST_WIDE_INT comp
= mask
& ~(mask
- 1);
825 if (aarch64_uimm12_shift (val
- (val
& mask
)))
827 subtarget
= subtargets
? gen_reg_rtx (DImode
) : dest
;
829 emit_insn (gen_rtx_SET (VOIDmode
, subtarget
, GEN_INT (val
& mask
)));
830 emit_insn (gen_adddi3 (dest
, subtarget
,
831 GEN_INT (val
- (val
& mask
))));
834 else if (aarch64_uimm12_shift (-(val
- ((val
+ comp
) & mask
))))
836 subtarget
= subtargets
? gen_reg_rtx (DImode
) : dest
;
838 emit_insn (gen_rtx_SET (VOIDmode
, subtarget
,
839 GEN_INT ((val
+ comp
) & mask
)));
840 emit_insn (gen_adddi3 (dest
, subtarget
,
841 GEN_INT (val
- ((val
+ comp
) & mask
))));
844 else if (aarch64_uimm12_shift (val
- ((val
- comp
) | ~mask
)))
846 subtarget
= subtargets
? gen_reg_rtx (DImode
) : dest
;
848 emit_insn (gen_rtx_SET (VOIDmode
, subtarget
,
849 GEN_INT ((val
- comp
) | ~mask
)));
850 emit_insn (gen_adddi3 (dest
, subtarget
,
851 GEN_INT (val
- ((val
- comp
) | ~mask
))));
854 else if (aarch64_uimm12_shift (-(val
- (val
| ~mask
))))
856 subtarget
= subtargets
? gen_reg_rtx (DImode
) : dest
;
858 emit_insn (gen_rtx_SET (VOIDmode
, subtarget
,
859 GEN_INT (val
| ~mask
)));
860 emit_insn (gen_adddi3 (dest
, subtarget
,
861 GEN_INT (val
- (val
| ~mask
))));
866 /* See if we can do it by arithmetically combining two
868 for (i
= 0; i
< AARCH64_NUM_BITMASKS
; i
++)
873 if (aarch64_uimm12_shift (val
- aarch64_bitmasks
[i
])
874 || aarch64_uimm12_shift (-val
+ aarch64_bitmasks
[i
]))
876 subtarget
= subtargets
? gen_reg_rtx (DImode
) : dest
;
877 emit_insn (gen_rtx_SET (VOIDmode
, subtarget
,
878 GEN_INT (aarch64_bitmasks
[i
])));
879 emit_insn (gen_adddi3 (dest
, subtarget
,
880 GEN_INT (val
- aarch64_bitmasks
[i
])));
884 for (j
= 0; j
< 64; j
+= 16, mask
<<= 16)
886 if ((aarch64_bitmasks
[i
] & ~mask
) == (val
& ~mask
))
888 emit_insn (gen_rtx_SET (VOIDmode
, dest
,
889 GEN_INT (aarch64_bitmasks
[i
])));
890 emit_insn (gen_insv_immdi (dest
, GEN_INT (j
),
891 GEN_INT ((val
>> j
) & 0xffff)));
897 /* See if we can do it by logically combining two immediates. */
898 for (i
= 0; i
< AARCH64_NUM_BITMASKS
; i
++)
900 if ((aarch64_bitmasks
[i
] & val
) == aarch64_bitmasks
[i
])
904 for (j
= i
+ 1; j
< AARCH64_NUM_BITMASKS
; j
++)
905 if (val
== (aarch64_bitmasks
[i
] | aarch64_bitmasks
[j
]))
907 subtarget
= subtargets
? gen_reg_rtx (mode
) : dest
;
908 emit_insn (gen_rtx_SET (VOIDmode
, subtarget
,
909 GEN_INT (aarch64_bitmasks
[i
])));
910 emit_insn (gen_iordi3 (dest
, subtarget
,
911 GEN_INT (aarch64_bitmasks
[j
])));
915 else if ((val
& aarch64_bitmasks
[i
]) == val
)
919 for (j
= i
+ 1; j
< AARCH64_NUM_BITMASKS
; j
++)
920 if (val
== (aarch64_bitmasks
[j
] & aarch64_bitmasks
[i
]))
923 subtarget
= subtargets
? gen_reg_rtx (mode
) : dest
;
924 emit_insn (gen_rtx_SET (VOIDmode
, subtarget
,
925 GEN_INT (aarch64_bitmasks
[j
])));
926 emit_insn (gen_anddi3 (dest
, subtarget
,
927 GEN_INT (aarch64_bitmasks
[i
])));
936 for (i
= 0; i
< 64; i
+= 16, mask
<<= 16)
938 if ((val
& mask
) != 0)
942 emit_insn (gen_rtx_SET (VOIDmode
, dest
,
943 GEN_INT (val
& mask
)));
947 emit_insn (gen_insv_immdi (dest
, GEN_INT (i
),
948 GEN_INT ((val
>> i
) & 0xffff)));
954 aarch64_function_ok_for_sibcall (tree decl
, tree exp ATTRIBUTE_UNUSED
)
956 /* Indirect calls are not currently supported. */
960 /* Cannot tail-call to long-calls, since these are outside of the
961 range of a branch instruction (we could handle this if we added
962 support for indirect tail-calls. */
963 if (aarch64_decl_is_long_call_p (decl
))
969 /* Implement TARGET_PASS_BY_REFERENCE. */
972 aarch64_pass_by_reference (cumulative_args_t pcum ATTRIBUTE_UNUSED
,
973 enum machine_mode mode
,
975 bool named ATTRIBUTE_UNUSED
)
978 enum machine_mode dummymode
;
981 /* GET_MODE_SIZE (BLKmode) is useless since it is 0. */
982 size
= (mode
== BLKmode
&& type
)
983 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
);
987 /* Arrays always passed by reference. */
988 if (TREE_CODE (type
) == ARRAY_TYPE
)
990 /* Other aggregates based on their size. */
991 if (AGGREGATE_TYPE_P (type
))
992 size
= int_size_in_bytes (type
);
995 /* Variable sized arguments are always returned by reference. */
999 /* Can this be a candidate to be passed in fp/simd register(s)? */
1000 if (aarch64_vfp_is_call_or_return_candidate (mode
, type
,
1005 /* Arguments which are variable sized or larger than 2 registers are
1006 passed by reference unless they are a homogenous floating point
1008 return size
> 2 * UNITS_PER_WORD
;
1011 /* Return TRUE if VALTYPE is padded to its least significant bits. */
1013 aarch64_return_in_msb (const_tree valtype
)
1015 enum machine_mode dummy_mode
;
1018 /* Never happens in little-endian mode. */
1019 if (!BYTES_BIG_ENDIAN
)
1022 /* Only composite types smaller than or equal to 16 bytes can
1023 be potentially returned in registers. */
1024 if (!aarch64_composite_type_p (valtype
, TYPE_MODE (valtype
))
1025 || int_size_in_bytes (valtype
) <= 0
1026 || int_size_in_bytes (valtype
) > 16)
1029 /* But not a composite that is an HFA (Homogeneous Floating-point Aggregate)
1030 or an HVA (Homogeneous Short-Vector Aggregate); such a special composite
1031 is always passed/returned in the least significant bits of fp/simd
1033 if (aarch64_vfp_is_call_or_return_candidate (TYPE_MODE (valtype
), valtype
,
1034 &dummy_mode
, &dummy_int
, NULL
))
1040 /* Implement TARGET_FUNCTION_VALUE.
1041 Define how to find the value returned by a function. */
1044 aarch64_function_value (const_tree type
, const_tree func
,
1045 bool outgoing ATTRIBUTE_UNUSED
)
1047 enum machine_mode mode
;
1050 enum machine_mode ag_mode
;
1052 mode
= TYPE_MODE (type
);
1053 if (INTEGRAL_TYPE_P (type
))
1054 mode
= promote_function_mode (type
, mode
, &unsignedp
, func
, 1);
1056 if (aarch64_return_in_msb (type
))
1058 HOST_WIDE_INT size
= int_size_in_bytes (type
);
1060 if (size
% UNITS_PER_WORD
!= 0)
1062 size
+= UNITS_PER_WORD
- size
% UNITS_PER_WORD
;
1063 mode
= mode_for_size (size
* BITS_PER_UNIT
, MODE_INT
, 0);
1067 if (aarch64_vfp_is_call_or_return_candidate (mode
, type
,
1068 &ag_mode
, &count
, NULL
))
1070 if (!aarch64_composite_type_p (type
, mode
))
1072 gcc_assert (count
== 1 && mode
== ag_mode
);
1073 return gen_rtx_REG (mode
, V0_REGNUM
);
1080 par
= gen_rtx_PARALLEL (mode
, rtvec_alloc (count
));
1081 for (i
= 0; i
< count
; i
++)
1083 rtx tmp
= gen_rtx_REG (ag_mode
, V0_REGNUM
+ i
);
1084 tmp
= gen_rtx_EXPR_LIST (VOIDmode
, tmp
,
1085 GEN_INT (i
* GET_MODE_SIZE (ag_mode
)));
1086 XVECEXP (par
, 0, i
) = tmp
;
1092 return gen_rtx_REG (mode
, R0_REGNUM
);
1095 /* Implements TARGET_FUNCTION_VALUE_REGNO_P.
1096 Return true if REGNO is the number of a hard register in which the values
1097 of called function may come back. */
1100 aarch64_function_value_regno_p (const unsigned int regno
)
1102 /* Maximum of 16 bytes can be returned in the general registers. Examples
1103 of 16-byte return values are: 128-bit integers and 16-byte small
1104 structures (excluding homogeneous floating-point aggregates). */
1105 if (regno
== R0_REGNUM
|| regno
== R1_REGNUM
)
1108 /* Up to four fp/simd registers can return a function value, e.g. a
1109 homogeneous floating-point aggregate having four members. */
1110 if (regno
>= V0_REGNUM
&& regno
< V0_REGNUM
+ HA_MAX_NUM_FLDS
)
1111 return !TARGET_GENERAL_REGS_ONLY
;
1116 /* Implement TARGET_RETURN_IN_MEMORY.
1118 If the type T of the result of a function is such that
1120 would require that arg be passed as a value in a register (or set of
1121 registers) according to the parameter passing rules, then the result
1122 is returned in the same registers as would be used for such an
1126 aarch64_return_in_memory (const_tree type
, const_tree fndecl ATTRIBUTE_UNUSED
)
1129 enum machine_mode ag_mode
;
1132 if (!AGGREGATE_TYPE_P (type
)
1133 && TREE_CODE (type
) != COMPLEX_TYPE
1134 && TREE_CODE (type
) != VECTOR_TYPE
)
1135 /* Simple scalar types always returned in registers. */
1138 if (aarch64_vfp_is_call_or_return_candidate (TYPE_MODE (type
),
1145 /* Types larger than 2 registers returned in memory. */
1146 size
= int_size_in_bytes (type
);
1147 return (size
< 0 || size
> 2 * UNITS_PER_WORD
);
1151 aarch64_vfp_is_call_candidate (cumulative_args_t pcum_v
, enum machine_mode mode
,
1152 const_tree type
, int *nregs
)
1154 CUMULATIVE_ARGS
*pcum
= get_cumulative_args (pcum_v
);
1155 return aarch64_vfp_is_call_or_return_candidate (mode
,
1157 &pcum
->aapcs_vfp_rmode
,
1162 /* Given MODE and TYPE of a function argument, return the alignment in
1163 bits. The idea is to suppress any stronger alignment requested by
1164 the user and opt for the natural alignment (specified in AAPCS64 \S 4.1).
1165 This is a helper function for local use only. */
1168 aarch64_function_arg_alignment (enum machine_mode mode
, const_tree type
)
1170 unsigned int alignment
;
1174 if (!integer_zerop (TYPE_SIZE (type
)))
1176 if (TYPE_MODE (type
) == mode
)
1177 alignment
= TYPE_ALIGN (type
);
1179 alignment
= GET_MODE_ALIGNMENT (mode
);
1185 alignment
= GET_MODE_ALIGNMENT (mode
);
1190 /* Layout a function argument according to the AAPCS64 rules. The rule
1191 numbers refer to the rule numbers in the AAPCS64. */
1194 aarch64_layout_arg (cumulative_args_t pcum_v
, enum machine_mode mode
,
1196 bool named ATTRIBUTE_UNUSED
)
1198 CUMULATIVE_ARGS
*pcum
= get_cumulative_args (pcum_v
);
1199 int ncrn
, nvrn
, nregs
;
1200 bool allocate_ncrn
, allocate_nvrn
;
1202 /* We need to do this once per argument. */
1203 if (pcum
->aapcs_arg_processed
)
1206 pcum
->aapcs_arg_processed
= true;
1208 allocate_ncrn
= (type
) ? !(FLOAT_TYPE_P (type
)) : !FLOAT_MODE_P (mode
);
1209 allocate_nvrn
= aarch64_vfp_is_call_candidate (pcum_v
,
1214 /* allocate_ncrn may be false-positive, but allocate_nvrn is quite reliable.
1215 The following code thus handles passing by SIMD/FP registers first. */
1217 nvrn
= pcum
->aapcs_nvrn
;
1219 /* C1 - C5 for floating point, homogenous floating point aggregates (HFA)
1220 and homogenous short-vector aggregates (HVA). */
1223 if (nvrn
+ nregs
<= NUM_FP_ARG_REGS
)
1225 pcum
->aapcs_nextnvrn
= nvrn
+ nregs
;
1226 if (!aarch64_composite_type_p (type
, mode
))
1228 gcc_assert (nregs
== 1);
1229 pcum
->aapcs_reg
= gen_rtx_REG (mode
, V0_REGNUM
+ nvrn
);
1235 par
= gen_rtx_PARALLEL (mode
, rtvec_alloc (nregs
));
1236 for (i
= 0; i
< nregs
; i
++)
1238 rtx tmp
= gen_rtx_REG (pcum
->aapcs_vfp_rmode
,
1239 V0_REGNUM
+ nvrn
+ i
);
1240 tmp
= gen_rtx_EXPR_LIST
1242 GEN_INT (i
* GET_MODE_SIZE (pcum
->aapcs_vfp_rmode
)));
1243 XVECEXP (par
, 0, i
) = tmp
;
1245 pcum
->aapcs_reg
= par
;
1251 /* C.3 NSRN is set to 8. */
1252 pcum
->aapcs_nextnvrn
= NUM_FP_ARG_REGS
;
1257 ncrn
= pcum
->aapcs_ncrn
;
1258 nregs
= ((type
? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
))
1259 + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
1262 /* C6 - C9. though the sign and zero extension semantics are
1263 handled elsewhere. This is the case where the argument fits
1264 entirely general registers. */
1265 if (allocate_ncrn
&& (ncrn
+ nregs
<= NUM_ARG_REGS
))
1267 unsigned int alignment
= aarch64_function_arg_alignment (mode
, type
);
1269 gcc_assert (nregs
== 0 || nregs
== 1 || nregs
== 2);
1271 /* C.8 if the argument has an alignment of 16 then the NGRN is
1272 rounded up to the next even number. */
1273 if (nregs
== 2 && alignment
== 16 * BITS_PER_UNIT
&& ncrn
% 2)
1276 gcc_assert (ncrn
+ nregs
<= NUM_ARG_REGS
);
1278 /* NREGS can be 0 when e.g. an empty structure is to be passed.
1279 A reg is still generated for it, but the caller should be smart
1280 enough not to use it. */
1281 if (nregs
== 0 || nregs
== 1 || GET_MODE_CLASS (mode
) == MODE_INT
)
1283 pcum
->aapcs_reg
= gen_rtx_REG (mode
, R0_REGNUM
+ ncrn
);
1290 par
= gen_rtx_PARALLEL (mode
, rtvec_alloc (nregs
));
1291 for (i
= 0; i
< nregs
; i
++)
1293 rtx tmp
= gen_rtx_REG (word_mode
, R0_REGNUM
+ ncrn
+ i
);
1294 tmp
= gen_rtx_EXPR_LIST (VOIDmode
, tmp
,
1295 GEN_INT (i
* UNITS_PER_WORD
));
1296 XVECEXP (par
, 0, i
) = tmp
;
1298 pcum
->aapcs_reg
= par
;
1301 pcum
->aapcs_nextncrn
= ncrn
+ nregs
;
1306 pcum
->aapcs_nextncrn
= NUM_ARG_REGS
;
1308 /* The argument is passed on stack; record the needed number of words for
1309 this argument (we can re-use NREGS) and align the total size if
1312 pcum
->aapcs_stack_words
= nregs
;
1313 if (aarch64_function_arg_alignment (mode
, type
) == 16 * BITS_PER_UNIT
)
1314 pcum
->aapcs_stack_size
= AARCH64_ROUND_UP (pcum
->aapcs_stack_size
,
1315 16 / UNITS_PER_WORD
) + 1;
1319 /* Implement TARGET_FUNCTION_ARG. */
1322 aarch64_function_arg (cumulative_args_t pcum_v
, enum machine_mode mode
,
1323 const_tree type
, bool named
)
1325 CUMULATIVE_ARGS
*pcum
= get_cumulative_args (pcum_v
);
1326 gcc_assert (pcum
->pcs_variant
== ARM_PCS_AAPCS64
);
1328 if (mode
== VOIDmode
)
1331 aarch64_layout_arg (pcum_v
, mode
, type
, named
);
1332 return pcum
->aapcs_reg
;
1336 aarch64_init_cumulative_args (CUMULATIVE_ARGS
*pcum
,
1337 const_tree fntype ATTRIBUTE_UNUSED
,
1338 rtx libname ATTRIBUTE_UNUSED
,
1339 const_tree fndecl ATTRIBUTE_UNUSED
,
1340 unsigned n_named ATTRIBUTE_UNUSED
)
1342 pcum
->aapcs_ncrn
= 0;
1343 pcum
->aapcs_nvrn
= 0;
1344 pcum
->aapcs_nextncrn
= 0;
1345 pcum
->aapcs_nextnvrn
= 0;
1346 pcum
->pcs_variant
= ARM_PCS_AAPCS64
;
1347 pcum
->aapcs_reg
= NULL_RTX
;
1348 pcum
->aapcs_arg_processed
= false;
1349 pcum
->aapcs_stack_words
= 0;
1350 pcum
->aapcs_stack_size
= 0;
1356 aarch64_function_arg_advance (cumulative_args_t pcum_v
,
1357 enum machine_mode mode
,
1361 CUMULATIVE_ARGS
*pcum
= get_cumulative_args (pcum_v
);
1362 if (pcum
->pcs_variant
== ARM_PCS_AAPCS64
)
1364 aarch64_layout_arg (pcum_v
, mode
, type
, named
);
1365 gcc_assert ((pcum
->aapcs_reg
!= NULL_RTX
)
1366 != (pcum
->aapcs_stack_words
!= 0));
1367 pcum
->aapcs_arg_processed
= false;
1368 pcum
->aapcs_ncrn
= pcum
->aapcs_nextncrn
;
1369 pcum
->aapcs_nvrn
= pcum
->aapcs_nextnvrn
;
1370 pcum
->aapcs_stack_size
+= pcum
->aapcs_stack_words
;
1371 pcum
->aapcs_stack_words
= 0;
1372 pcum
->aapcs_reg
= NULL_RTX
;
1377 aarch64_function_arg_regno_p (unsigned regno
)
1379 return ((GP_REGNUM_P (regno
) && regno
< R0_REGNUM
+ NUM_ARG_REGS
)
1380 || (FP_REGNUM_P (regno
) && regno
< V0_REGNUM
+ NUM_FP_ARG_REGS
));
1383 /* Implement FUNCTION_ARG_BOUNDARY. Every parameter gets at least
1384 PARM_BOUNDARY bits of alignment, but will be given anything up
1385 to STACK_BOUNDARY bits if the type requires it. This makes sure
1386 that both before and after the layout of each argument, the Next
1387 Stacked Argument Address (NSAA) will have a minimum alignment of
1391 aarch64_function_arg_boundary (enum machine_mode mode
, const_tree type
)
1393 unsigned int alignment
= aarch64_function_arg_alignment (mode
, type
);
1395 if (alignment
< PARM_BOUNDARY
)
1396 alignment
= PARM_BOUNDARY
;
1397 if (alignment
> STACK_BOUNDARY
)
1398 alignment
= STACK_BOUNDARY
;
1402 /* For use by FUNCTION_ARG_PADDING (MODE, TYPE).
1404 Return true if an argument passed on the stack should be padded upwards,
1405 i.e. if the least-significant byte of the stack slot has useful data.
1407 Small aggregate types are placed in the lowest memory address.
1409 The related parameter passing rules are B.4, C.3, C.5 and C.14. */
1412 aarch64_pad_arg_upward (enum machine_mode mode
, const_tree type
)
1414 /* On little-endian targets, the least significant byte of every stack
1415 argument is passed at the lowest byte address of the stack slot. */
1416 if (!BYTES_BIG_ENDIAN
)
1419 /* Otherwise, integral types and floating point types are padded downward:
1420 the least significant byte of a stack argument is passed at the highest
1421 byte address of the stack slot. */
1423 ? (INTEGRAL_TYPE_P (type
) || SCALAR_FLOAT_TYPE_P (type
))
1424 : (SCALAR_INT_MODE_P (mode
) || SCALAR_FLOAT_MODE_P (mode
)))
1427 /* Everything else padded upward, i.e. data in first byte of stack slot. */
1431 /* Similarly, for use by BLOCK_REG_PADDING (MODE, TYPE, FIRST).
1433 It specifies padding for the last (may also be the only)
1434 element of a block move between registers and memory. If
1435 assuming the block is in the memory, padding upward means that
1436 the last element is padded after its highest significant byte,
1437 while in downward padding, the last element is padded at the
1438 its least significant byte side.
1440 Small aggregates and small complex types are always padded
1443 We don't need to worry about homogeneous floating-point or
1444 short-vector aggregates; their move is not affected by the
1445 padding direction determined here. Regardless of endianness,
1446 each element of such an aggregate is put in the least
1447 significant bits of a fp/simd register.
1449 Return !BYTES_BIG_ENDIAN if the least significant byte of the
1450 register has useful data, and return the opposite if the most
1451 significant byte does. */
1454 aarch64_pad_reg_upward (enum machine_mode mode
, const_tree type
,
1455 bool first ATTRIBUTE_UNUSED
)
1458 /* Small composite types are always padded upward. */
1459 if (BYTES_BIG_ENDIAN
&& aarch64_composite_type_p (type
, mode
))
1461 HOST_WIDE_INT size
= (type
? int_size_in_bytes (type
)
1462 : GET_MODE_SIZE (mode
));
1463 if (size
< 2 * UNITS_PER_WORD
)
1467 /* Otherwise, use the default padding. */
1468 return !BYTES_BIG_ENDIAN
;
1471 static enum machine_mode
1472 aarch64_libgcc_cmp_return_mode (void)
1478 aarch64_frame_pointer_required (void)
1480 /* If the function contains dynamic stack allocations, we need to
1481 use the frame pointer to access the static parts of the frame. */
1482 if (cfun
->calls_alloca
)
1485 /* We may have turned flag_omit_frame_pointer on in order to have this
1486 function called; if we did, we also set the 'faked_omit_frame_pointer' flag
1487 and we'll check it here.
1488 If we really did set flag_omit_frame_pointer normally, then we return false
1489 (no frame pointer required) in all cases. */
1491 if (flag_omit_frame_pointer
&& !faked_omit_frame_pointer
)
1493 else if (flag_omit_leaf_frame_pointer
)
1494 return !crtl
->is_leaf
;
1498 /* Mark the registers that need to be saved by the callee and calculate
1499 the size of the callee-saved registers area and frame record (both FP
1500 and LR may be omitted). */
1502 aarch64_layout_frame (void)
1504 HOST_WIDE_INT offset
= 0;
1507 if (reload_completed
&& cfun
->machine
->frame
.laid_out
)
1510 cfun
->machine
->frame
.fp_lr_offset
= 0;
1512 /* First mark all the registers that really need to be saved... */
1513 for (regno
= R0_REGNUM
; regno
<= R30_REGNUM
; regno
++)
1514 cfun
->machine
->frame
.reg_offset
[regno
] = -1;
1516 for (regno
= V0_REGNUM
; regno
<= V31_REGNUM
; regno
++)
1517 cfun
->machine
->frame
.reg_offset
[regno
] = -1;
1519 /* ... that includes the eh data registers (if needed)... */
1520 if (crtl
->calls_eh_return
)
1521 for (regno
= 0; EH_RETURN_DATA_REGNO (regno
) != INVALID_REGNUM
; regno
++)
1522 cfun
->machine
->frame
.reg_offset
[EH_RETURN_DATA_REGNO (regno
)] = 0;
1524 /* ... and any callee saved register that dataflow says is live. */
1525 for (regno
= R0_REGNUM
; regno
<= R30_REGNUM
; regno
++)
1526 if (df_regs_ever_live_p (regno
)
1527 && !call_used_regs
[regno
])
1528 cfun
->machine
->frame
.reg_offset
[regno
] = 0;
1530 for (regno
= V0_REGNUM
; regno
<= V31_REGNUM
; regno
++)
1531 if (df_regs_ever_live_p (regno
)
1532 && !call_used_regs
[regno
])
1533 cfun
->machine
->frame
.reg_offset
[regno
] = 0;
1535 if (frame_pointer_needed
)
1537 cfun
->machine
->frame
.reg_offset
[R30_REGNUM
] = 0;
1538 cfun
->machine
->frame
.reg_offset
[R29_REGNUM
] = 0;
1539 cfun
->machine
->frame
.hardfp_offset
= 2 * UNITS_PER_WORD
;
1542 /* Now assign stack slots for them. */
1543 for (regno
= R0_REGNUM
; regno
<= R28_REGNUM
; regno
++)
1544 if (cfun
->machine
->frame
.reg_offset
[regno
] != -1)
1546 cfun
->machine
->frame
.reg_offset
[regno
] = offset
;
1547 offset
+= UNITS_PER_WORD
;
1550 for (regno
= V0_REGNUM
; regno
<= V31_REGNUM
; regno
++)
1551 if (cfun
->machine
->frame
.reg_offset
[regno
] != -1)
1553 cfun
->machine
->frame
.reg_offset
[regno
] = offset
;
1554 offset
+= UNITS_PER_WORD
;
1557 if (frame_pointer_needed
)
1559 cfun
->machine
->frame
.reg_offset
[R29_REGNUM
] = offset
;
1560 offset
+= UNITS_PER_WORD
;
1561 cfun
->machine
->frame
.fp_lr_offset
= UNITS_PER_WORD
;
1564 if (cfun
->machine
->frame
.reg_offset
[R30_REGNUM
] != -1)
1566 cfun
->machine
->frame
.reg_offset
[R30_REGNUM
] = offset
;
1567 offset
+= UNITS_PER_WORD
;
1568 cfun
->machine
->frame
.fp_lr_offset
+= UNITS_PER_WORD
;
1571 cfun
->machine
->frame
.padding0
=
1572 (AARCH64_ROUND_UP (offset
, STACK_BOUNDARY
/ BITS_PER_UNIT
) - offset
);
1573 offset
= AARCH64_ROUND_UP (offset
, STACK_BOUNDARY
/ BITS_PER_UNIT
);
1575 cfun
->machine
->frame
.saved_regs_size
= offset
;
1576 cfun
->machine
->frame
.laid_out
= true;
1579 /* Make the last instruction frame-related and note that it performs
1580 the operation described by FRAME_PATTERN. */
1583 aarch64_set_frame_expr (rtx frame_pattern
)
1587 insn
= get_last_insn ();
1588 RTX_FRAME_RELATED_P (insn
) = 1;
1589 RTX_FRAME_RELATED_P (frame_pattern
) = 1;
1590 REG_NOTES (insn
) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR
,
1596 aarch64_register_saved_on_entry (int regno
)
1598 return cfun
->machine
->frame
.reg_offset
[regno
] != -1;
1603 aarch64_save_or_restore_fprs (int start_offset
, int increment
,
1604 bool restore
, rtx base_rtx
)
1610 rtx (*gen_mem_ref
)(enum machine_mode
, rtx
) = (frame_pointer_needed
)? gen_frame_mem
: gen_rtx_MEM
;
1613 for (regno
= V0_REGNUM
; regno
<= V31_REGNUM
; regno
++)
1615 if (aarch64_register_saved_on_entry (regno
))
1618 mem
= gen_mem_ref (DFmode
,
1619 plus_constant (Pmode
,
1623 for (regno2
= regno
+ 1;
1624 regno2
<= V31_REGNUM
1625 && !aarch64_register_saved_on_entry (regno2
);
1630 if (regno2
<= V31_REGNUM
&&
1631 aarch64_register_saved_on_entry (regno2
))
1634 /* Next highest register to be saved. */
1635 mem2
= gen_mem_ref (DFmode
,
1639 start_offset
+ increment
));
1640 if (restore
== false)
1643 ( gen_store_pairdf (mem
, gen_rtx_REG (DFmode
, regno
),
1644 mem2
, gen_rtx_REG (DFmode
, regno2
)));
1650 ( gen_load_pairdf (gen_rtx_REG (DFmode
, regno
), mem
,
1651 gen_rtx_REG (DFmode
, regno2
), mem2
));
1653 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (DFmode
, regno
));
1654 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (DFmode
, regno2
));
1657 /* The first part of a frame-related parallel insn
1658 is always assumed to be relevant to the frame
1659 calculations; subsequent parts, are only
1660 frame-related if explicitly marked. */
1661 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn
), 0,
1664 start_offset
+= increment
* 2;
1668 if (restore
== false)
1669 insn
= emit_move_insn (mem
, gen_rtx_REG (DFmode
, regno
));
1672 insn
= emit_move_insn (gen_rtx_REG (DFmode
, regno
), mem
);
1673 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (DImode
, regno
));
1675 start_offset
+= increment
;
1677 RTX_FRAME_RELATED_P (insn
) = 1;
1684 /* offset from the stack pointer of where the saves and
1685 restore's have to happen. */
1687 aarch64_save_or_restore_callee_save_registers (HOST_WIDE_INT offset
,
1691 rtx base_rtx
= stack_pointer_rtx
;
1692 HOST_WIDE_INT start_offset
= offset
;
1693 HOST_WIDE_INT increment
= UNITS_PER_WORD
;
1694 rtx (*gen_mem_ref
)(enum machine_mode
, rtx
) = (frame_pointer_needed
)? gen_frame_mem
: gen_rtx_MEM
;
1695 unsigned limit
= (frame_pointer_needed
)? R28_REGNUM
: R30_REGNUM
;
1699 for (regno
= R0_REGNUM
; regno
<= limit
; regno
++)
1701 if (aarch64_register_saved_on_entry (regno
))
1704 mem
= gen_mem_ref (Pmode
,
1705 plus_constant (Pmode
,
1709 for (regno2
= regno
+ 1;
1711 && !aarch64_register_saved_on_entry (regno2
);
1716 if (regno2
<= limit
&&
1717 aarch64_register_saved_on_entry (regno2
))
1720 /* Next highest register to be saved. */
1721 mem2
= gen_mem_ref (Pmode
,
1725 start_offset
+ increment
));
1726 if (restore
== false)
1729 ( gen_store_pairdi (mem
, gen_rtx_REG (DImode
, regno
),
1730 mem2
, gen_rtx_REG (DImode
, regno2
)));
1736 ( gen_load_pairdi (gen_rtx_REG (DImode
, regno
), mem
,
1737 gen_rtx_REG (DImode
, regno2
), mem2
));
1739 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (DImode
, regno
));
1740 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (DImode
, regno2
));
1743 /* The first part of a frame-related parallel insn
1744 is always assumed to be relevant to the frame
1745 calculations; subsequent parts, are only
1746 frame-related if explicitly marked. */
1747 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn
), 0,
1750 start_offset
+= increment
* 2;
1754 if (restore
== false)
1755 insn
= emit_move_insn (mem
, gen_rtx_REG (DImode
, regno
));
1758 insn
= emit_move_insn (gen_rtx_REG (DImode
, regno
), mem
);
1759 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (DImode
, regno
));
1761 start_offset
+= increment
;
1763 RTX_FRAME_RELATED_P (insn
) = 1;
1767 aarch64_save_or_restore_fprs (start_offset
, increment
, restore
, base_rtx
);
1771 /* AArch64 stack frames generated by this compiler look like:
1773 +-------------------------------+
1775 | incoming stack arguments |
1777 +-------------------------------+ <-- arg_pointer_rtx
1779 | callee-allocated save area |
1780 | for register varargs |
1782 +-------------------------------+
1786 +-------------------------------+ <-- frame_pointer_rtx
1788 | callee-saved registers |
1790 +-------------------------------+
1792 +-------------------------------+
1794 P +-------------------------------+ <-- hard_frame_pointer_rtx
1795 | dynamic allocation |
1796 +-------------------------------+
1798 | outgoing stack arguments |
1800 +-------------------------------+ <-- stack_pointer_rtx
1802 Dynamic stack allocations such as alloca insert data at point P.
1803 They decrease stack_pointer_rtx but leave frame_pointer_rtx and
1804 hard_frame_pointer_rtx unchanged. */
1806 /* Generate the prologue instructions for entry into a function.
1807 Establish the stack frame by decreasing the stack pointer with a
1808 properly calculated size and, if necessary, create a frame record
1809 filled with the values of LR and previous frame pointer. The
1810 current FP is also set up is it is in use. */
1813 aarch64_expand_prologue (void)
1815 /* sub sp, sp, #<frame_size>
1816 stp {fp, lr}, [sp, #<frame_size> - 16]
1817 add fp, sp, #<frame_size> - hardfp_offset
1818 stp {cs_reg}, [fp, #-16] etc.
1820 sub sp, sp, <final_adjustment_if_any>
1822 HOST_WIDE_INT original_frame_size
; /* local variables + vararg save */
1823 HOST_WIDE_INT frame_size
, offset
;
1824 HOST_WIDE_INT fp_offset
; /* FP offset from SP */
1827 aarch64_layout_frame ();
1828 original_frame_size
= get_frame_size () + cfun
->machine
->saved_varargs_size
;
1829 gcc_assert ((!cfun
->machine
->saved_varargs_size
|| cfun
->stdarg
)
1830 && (cfun
->stdarg
|| !cfun
->machine
->saved_varargs_size
));
1831 frame_size
= (original_frame_size
+ cfun
->machine
->frame
.saved_regs_size
1832 + crtl
->outgoing_args_size
);
1833 offset
= frame_size
= AARCH64_ROUND_UP (frame_size
,
1834 STACK_BOUNDARY
/ BITS_PER_UNIT
);
1836 if (flag_stack_usage_info
)
1837 current_function_static_stack_size
= frame_size
;
1840 - original_frame_size
1841 - cfun
->machine
->frame
.saved_regs_size
);
1843 /* Store pairs and load pairs have a range only -512 to 504. */
1846 /* When the frame has a large size, an initial decrease is done on
1847 the stack pointer to jump over the callee-allocated save area for
1848 register varargs, the local variable area and/or the callee-saved
1849 register area. This will allow the pre-index write-back
1850 store pair instructions to be used for setting up the stack frame
1852 offset
= original_frame_size
+ cfun
->machine
->frame
.saved_regs_size
;
1854 offset
= cfun
->machine
->frame
.saved_regs_size
;
1856 frame_size
-= (offset
+ crtl
->outgoing_args_size
);
1859 if (frame_size
>= 0x1000000)
1861 rtx op0
= gen_rtx_REG (Pmode
, IP0_REGNUM
);
1862 emit_move_insn (op0
, GEN_INT (-frame_size
));
1863 emit_insn (gen_add2_insn (stack_pointer_rtx
, op0
));
1864 aarch64_set_frame_expr (gen_rtx_SET
1865 (Pmode
, stack_pointer_rtx
,
1866 gen_rtx_PLUS (Pmode
,
1868 GEN_INT (-frame_size
))));
1870 else if (frame_size
> 0)
1872 if ((frame_size
& 0xfff) != frame_size
)
1874 insn
= emit_insn (gen_add2_insn
1876 GEN_INT (-(frame_size
1877 & ~(HOST_WIDE_INT
)0xfff))));
1878 RTX_FRAME_RELATED_P (insn
) = 1;
1880 if ((frame_size
& 0xfff) != 0)
1882 insn
= emit_insn (gen_add2_insn
1884 GEN_INT (-(frame_size
1885 & (HOST_WIDE_INT
)0xfff))));
1886 RTX_FRAME_RELATED_P (insn
) = 1;
1895 /* Save the frame pointer and lr if the frame pointer is needed
1896 first. Make the frame pointer point to the location of the
1897 old frame pointer on the stack. */
1898 if (frame_pointer_needed
)
1904 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
,
1905 GEN_INT (-offset
)));
1906 RTX_FRAME_RELATED_P (insn
) = 1;
1907 aarch64_set_frame_expr (gen_rtx_SET
1908 (Pmode
, stack_pointer_rtx
,
1909 gen_rtx_MINUS (Pmode
,
1911 GEN_INT (offset
))));
1912 mem_fp
= gen_frame_mem (DImode
,
1913 plus_constant (Pmode
,
1916 mem_lr
= gen_frame_mem (DImode
,
1917 plus_constant (Pmode
,
1921 insn
= emit_insn (gen_store_pairdi (mem_fp
,
1922 hard_frame_pointer_rtx
,
1924 gen_rtx_REG (DImode
,
1929 insn
= emit_insn (gen_storewb_pairdi_di
1930 (stack_pointer_rtx
, stack_pointer_rtx
,
1931 hard_frame_pointer_rtx
,
1932 gen_rtx_REG (DImode
, LR_REGNUM
),
1934 GEN_INT (GET_MODE_SIZE (DImode
) - offset
)));
1935 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn
), 0, 2)) = 1;
1938 /* The first part of a frame-related parallel insn is always
1939 assumed to be relevant to the frame calculations;
1940 subsequent parts, are only frame-related if explicitly
1942 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn
), 0, 1)) = 1;
1943 RTX_FRAME_RELATED_P (insn
) = 1;
1945 /* Set up frame pointer to point to the location of the
1946 previous frame pointer on the stack. */
1947 insn
= emit_insn (gen_add3_insn (hard_frame_pointer_rtx
,
1949 GEN_INT (fp_offset
)));
1950 aarch64_set_frame_expr (gen_rtx_SET
1951 (Pmode
, hard_frame_pointer_rtx
,
1952 gen_rtx_PLUS (Pmode
,
1954 GEN_INT (fp_offset
))));
1955 RTX_FRAME_RELATED_P (insn
) = 1;
1956 insn
= emit_insn (gen_stack_tie (stack_pointer_rtx
,
1957 hard_frame_pointer_rtx
));
1961 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
,
1962 GEN_INT (-offset
)));
1963 RTX_FRAME_RELATED_P (insn
) = 1;
1966 aarch64_save_or_restore_callee_save_registers
1967 (fp_offset
+ cfun
->machine
->frame
.hardfp_offset
, 0);
1970 /* when offset >= 512,
1971 sub sp, sp, #<outgoing_args_size> */
1972 if (frame_size
> -1)
1974 if (crtl
->outgoing_args_size
> 0)
1976 insn
= emit_insn (gen_add2_insn
1978 GEN_INT (- crtl
->outgoing_args_size
)));
1979 RTX_FRAME_RELATED_P (insn
) = 1;
1984 /* Generate the epilogue instructions for returning from a function. */
1986 aarch64_expand_epilogue (bool for_sibcall
)
1988 HOST_WIDE_INT original_frame_size
, frame_size
, offset
;
1989 HOST_WIDE_INT fp_offset
;
1993 aarch64_layout_frame ();
1994 original_frame_size
= get_frame_size () + cfun
->machine
->saved_varargs_size
;
1995 frame_size
= (original_frame_size
+ cfun
->machine
->frame
.saved_regs_size
1996 + crtl
->outgoing_args_size
);
1997 offset
= frame_size
= AARCH64_ROUND_UP (frame_size
,
1998 STACK_BOUNDARY
/ BITS_PER_UNIT
);
2001 - original_frame_size
2002 - cfun
->machine
->frame
.saved_regs_size
);
2004 cfa_reg
= frame_pointer_needed
? hard_frame_pointer_rtx
: stack_pointer_rtx
;
2006 /* Store pairs and load pairs have a range only -512 to 504. */
2009 offset
= original_frame_size
+ cfun
->machine
->frame
.saved_regs_size
;
2011 offset
= cfun
->machine
->frame
.saved_regs_size
;
2013 frame_size
-= (offset
+ crtl
->outgoing_args_size
);
2015 if (!frame_pointer_needed
&& crtl
->outgoing_args_size
> 0)
2017 insn
= emit_insn (gen_add2_insn
2019 GEN_INT (crtl
->outgoing_args_size
)));
2020 RTX_FRAME_RELATED_P (insn
) = 1;
2026 /* If there were outgoing arguments or we've done dynamic stack
2027 allocation, then restore the stack pointer from the frame
2028 pointer. This is at most one insn and more efficient than using
2029 GCC's internal mechanism. */
2030 if (frame_pointer_needed
2031 && (crtl
->outgoing_args_size
|| cfun
->calls_alloca
))
2033 insn
= emit_insn (gen_add3_insn (stack_pointer_rtx
,
2034 hard_frame_pointer_rtx
,
2035 GEN_INT (- fp_offset
)));
2036 RTX_FRAME_RELATED_P (insn
) = 1;
2037 /* As SP is set to (FP - fp_offset), according to the rules in
2038 dwarf2cfi.c:dwarf2out_frame_debug_expr, CFA should be calculated
2039 from the value of SP from now on. */
2040 cfa_reg
= stack_pointer_rtx
;
2043 aarch64_save_or_restore_callee_save_registers
2044 (fp_offset
+ cfun
->machine
->frame
.hardfp_offset
, 1);
2046 /* Restore the frame pointer and lr if the frame pointer is needed. */
2049 if (frame_pointer_needed
)
2055 mem_fp
= gen_frame_mem (DImode
,
2056 plus_constant (Pmode
,
2059 mem_lr
= gen_frame_mem (DImode
,
2060 plus_constant (Pmode
,
2064 insn
= emit_insn (gen_load_pairdi (hard_frame_pointer_rtx
,
2066 gen_rtx_REG (DImode
,
2072 insn
= emit_insn (gen_loadwb_pairdi_di
2075 hard_frame_pointer_rtx
,
2076 gen_rtx_REG (DImode
, LR_REGNUM
),
2078 GEN_INT (GET_MODE_SIZE (DImode
) + offset
)));
2079 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn
), 0, 2)) = 1;
2080 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
2081 (gen_rtx_SET (Pmode
, stack_pointer_rtx
,
2082 plus_constant (Pmode
, cfa_reg
,
2086 /* The first part of a frame-related parallel insn
2087 is always assumed to be relevant to the frame
2088 calculations; subsequent parts, are only
2089 frame-related if explicitly marked. */
2090 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn
), 0, 1)) = 1;
2091 RTX_FRAME_RELATED_P (insn
) = 1;
2092 add_reg_note (insn
, REG_CFA_RESTORE
, hard_frame_pointer_rtx
);
2093 add_reg_note (insn
, REG_CFA_RESTORE
,
2094 gen_rtx_REG (DImode
, LR_REGNUM
));
2098 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
,
2100 RTX_FRAME_RELATED_P (insn
) = 1;
2105 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
,
2107 RTX_FRAME_RELATED_P (insn
) = 1;
2111 /* Stack adjustment for exception handler. */
2112 if (crtl
->calls_eh_return
)
2114 /* We need to unwind the stack by the offset computed by
2115 EH_RETURN_STACKADJ_RTX. However, at this point the CFA is
2116 based on SP. Ideally we would update the SP and define the
2117 CFA along the lines of:
2119 SP = SP + EH_RETURN_STACKADJ_RTX
2120 (regnote CFA = SP - EH_RETURN_STACKADJ_RTX)
2122 However the dwarf emitter only understands a constant
2125 The solution choosen here is to use the otherwise unused IP0
2126 as a temporary register to hold the current SP value. The
2127 CFA is described using IP0 then SP is modified. */
2129 rtx ip0
= gen_rtx_REG (DImode
, IP0_REGNUM
);
2131 insn
= emit_move_insn (ip0
, stack_pointer_rtx
);
2132 add_reg_note (insn
, REG_CFA_DEF_CFA
, ip0
);
2133 RTX_FRAME_RELATED_P (insn
) = 1;
2135 emit_insn (gen_add2_insn (stack_pointer_rtx
, EH_RETURN_STACKADJ_RTX
));
2137 /* Ensure the assignment to IP0 does not get optimized away. */
2141 if (frame_size
> -1)
2143 if (frame_size
>= 0x1000000)
2145 rtx op0
= gen_rtx_REG (Pmode
, IP0_REGNUM
);
2146 emit_move_insn (op0
, GEN_INT (frame_size
));
2147 emit_insn (gen_add2_insn (stack_pointer_rtx
, op0
));
2148 aarch64_set_frame_expr (gen_rtx_SET
2149 (Pmode
, stack_pointer_rtx
,
2150 gen_rtx_PLUS (Pmode
,
2152 GEN_INT (frame_size
))));
2154 else if (frame_size
> 0)
2156 if ((frame_size
& 0xfff) != 0)
2158 insn
= emit_insn (gen_add2_insn
2160 GEN_INT ((frame_size
2161 & (HOST_WIDE_INT
) 0xfff))));
2162 RTX_FRAME_RELATED_P (insn
) = 1;
2164 if ((frame_size
& 0xfff) != frame_size
)
2166 insn
= emit_insn (gen_add2_insn
2168 GEN_INT ((frame_size
2169 & ~ (HOST_WIDE_INT
) 0xfff))));
2170 RTX_FRAME_RELATED_P (insn
) = 1;
2174 aarch64_set_frame_expr (gen_rtx_SET (Pmode
, stack_pointer_rtx
,
2175 gen_rtx_PLUS (Pmode
,
2177 GEN_INT (offset
))));
2180 emit_use (gen_rtx_REG (DImode
, LR_REGNUM
));
2182 emit_jump_insn (ret_rtx
);
2185 /* Return the place to copy the exception unwinding return address to.
2186 This will probably be a stack slot, but could (in theory be the
2187 return register). */
2189 aarch64_final_eh_return_addr (void)
2191 HOST_WIDE_INT original_frame_size
, frame_size
, offset
, fp_offset
;
2192 aarch64_layout_frame ();
2193 original_frame_size
= get_frame_size () + cfun
->machine
->saved_varargs_size
;
2194 frame_size
= (original_frame_size
+ cfun
->machine
->frame
.saved_regs_size
2195 + crtl
->outgoing_args_size
);
2196 offset
= frame_size
= AARCH64_ROUND_UP (frame_size
,
2197 STACK_BOUNDARY
/ BITS_PER_UNIT
);
2199 - original_frame_size
2200 - cfun
->machine
->frame
.saved_regs_size
;
2202 if (cfun
->machine
->frame
.reg_offset
[LR_REGNUM
] < 0)
2203 return gen_rtx_REG (DImode
, LR_REGNUM
);
2205 /* DSE and CSELIB do not detect an alias between sp+k1 and fp+k2. This can
2206 result in a store to save LR introduced by builtin_eh_return () being
2207 incorrectly deleted because the alias is not detected.
2208 So in the calculation of the address to copy the exception unwinding
2209 return address to, we note 2 cases.
2210 If FP is needed and the fp_offset is 0, it means that SP = FP and hence
2211 we return a SP-relative location since all the addresses are SP-relative
2212 in this case. This prevents the store from being optimized away.
2213 If the fp_offset is not 0, then the addresses will be FP-relative and
2214 therefore we return a FP-relative location. */
2216 if (frame_pointer_needed
)
2219 return gen_frame_mem (DImode
,
2220 plus_constant (Pmode
, hard_frame_pointer_rtx
, UNITS_PER_WORD
));
2222 return gen_frame_mem (DImode
,
2223 plus_constant (Pmode
, stack_pointer_rtx
, UNITS_PER_WORD
));
2226 /* If FP is not needed, we calculate the location of LR, which would be
2227 at the top of the saved registers block. */
2229 return gen_frame_mem (DImode
,
2230 plus_constant (Pmode
,
2233 + cfun
->machine
->frame
.saved_regs_size
2234 - 2 * UNITS_PER_WORD
));
2237 /* Output code to build up a constant in a register. */
2239 aarch64_build_constant (FILE *file
,
2243 if (aarch64_bitmask_imm (val
, DImode
))
2244 asm_fprintf (file
, "\tmovi\t%r, %wd\n", regnum
, val
);
2250 HOST_WIDE_INT valp
= val
>> 16;
2254 for (i
= 16; i
< 64; i
+= 16)
2256 valm
= (valp
& 0xffff);
2267 /* zcount contains the number of additional MOVK instructions
2268 required if the constant is built up with an initial MOVZ instruction,
2269 while ncount is the number of MOVK instructions required if starting
2270 with a MOVN instruction. Choose the sequence that yields the fewest
2271 number of instructions, preferring MOVZ instructions when they are both
2273 if (ncount
< zcount
)
2275 asm_fprintf (file
, "\tmovn\t%r, %wd\n", regnum
, (~val
) & 0xffff);
2280 asm_fprintf (file
, "\tmovz\t%r, %wd\n", regnum
, val
& 0xffff);
2286 for (i
= 16; i
< 64; i
+= 16)
2288 if ((val
& 0xffff) != tval
)
2289 asm_fprintf (file
, "\tmovk\t%r, %wd, lsl %d\n",
2290 regnum
, val
& 0xffff, i
);
2297 aarch64_add_constant (FILE *file
, int regnum
, int scratchreg
,
2298 HOST_WIDE_INT delta
)
2300 HOST_WIDE_INT mdelta
= delta
;
2305 if (mdelta
>= 4096 * 4096)
2307 aarch64_build_constant (file
, scratchreg
, delta
);
2308 asm_fprintf (file
, "\tadd\t%r, %r, %r\n", regnum
, regnum
,
2311 else if (mdelta
> 0)
2313 const char *const mi_op
= delta
< 0 ? "sub" : "add";
2316 asm_fprintf (file
, "\t%s\t%r, %r, %wd, lsl 12\n", mi_op
, regnum
, regnum
,
2319 if (mdelta
% 4096 != 0)
2320 asm_fprintf (file
, "\t%s\t%r, %r, %wd\n", mi_op
, regnum
, regnum
,
2325 /* Output code to add DELTA to the first argument, and then jump
2326 to FUNCTION. Used for C++ multiple inheritance. */
2328 aarch64_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
2329 HOST_WIDE_INT delta
,
2330 HOST_WIDE_INT vcall_offset
,
2333 /* The this pointer is always in x0. Note that this differs from
2334 Arm where the this pointer maybe bumped to r1 if r0 is required
2335 to return a pointer to an aggregate. On AArch64 a result value
2336 pointer will be in x8. */
2337 int this_regno
= R0_REGNUM
;
2338 rtx this_rtx
, temp0
, temp1
, addr
, insn
, funexp
;
2340 reload_completed
= 1;
2341 emit_note (NOTE_INSN_PROLOGUE_END
);
2343 if (vcall_offset
== 0)
2344 aarch64_add_constant (file
, this_regno
, IP1_REGNUM
, delta
);
2347 gcc_assert ((vcall_offset
& 0x7) == 0);
2349 this_rtx
= gen_rtx_REG (Pmode
, this_regno
);
2350 temp0
= gen_rtx_REG (Pmode
, IP0_REGNUM
);
2351 temp1
= gen_rtx_REG (Pmode
, IP1_REGNUM
);
2356 if (delta
>= -256 && delta
< 256)
2357 addr
= gen_rtx_PRE_MODIFY (Pmode
, this_rtx
,
2358 plus_constant (Pmode
, this_rtx
, delta
));
2360 aarch64_add_constant (file
, this_regno
, IP1_REGNUM
, delta
);
2363 aarch64_emit_move (temp0
, gen_rtx_MEM (Pmode
, addr
));
2365 if (vcall_offset
>= -256 && vcall_offset
< 32768)
2366 addr
= plus_constant (Pmode
, temp0
, vcall_offset
);
2369 aarch64_build_constant (file
, IP1_REGNUM
, vcall_offset
);
2370 addr
= gen_rtx_PLUS (Pmode
, temp0
, temp1
);
2373 aarch64_emit_move (temp1
, gen_rtx_MEM (Pmode
,addr
));
2374 emit_insn (gen_add2_insn (this_rtx
, temp1
));
2377 /* Generate a tail call to the target function. */
2378 if (!TREE_USED (function
))
2380 assemble_external (function
);
2381 TREE_USED (function
) = 1;
2383 funexp
= XEXP (DECL_RTL (function
), 0);
2384 funexp
= gen_rtx_MEM (FUNCTION_MODE
, funexp
);
2385 insn
= emit_call_insn (gen_sibcall (funexp
, const0_rtx
, NULL_RTX
));
2386 SIBLING_CALL_P (insn
) = 1;
2388 insn
= get_insns ();
2389 shorten_branches (insn
);
2390 final_start_function (insn
, file
, 1);
2391 final (insn
, file
, 1);
2392 final_end_function ();
2394 /* Stop pretending to be a post-reload pass. */
2395 reload_completed
= 0;
2399 aarch64_tls_operand_p_1 (rtx
*x
, void *data ATTRIBUTE_UNUSED
)
2401 if (GET_CODE (*x
) == SYMBOL_REF
)
2402 return SYMBOL_REF_TLS_MODEL (*x
) != 0;
2404 /* Don't recurse into UNSPEC_TLS looking for TLS symbols; these are
2405 TLS offsets, not real symbol references. */
2406 if (GET_CODE (*x
) == UNSPEC
2407 && XINT (*x
, 1) == UNSPEC_TLS
)
2414 aarch64_tls_referenced_p (rtx x
)
2416 if (!TARGET_HAVE_TLS
)
2419 return for_each_rtx (&x
, aarch64_tls_operand_p_1
, NULL
);
2424 aarch64_bitmasks_cmp (const void *i1
, const void *i2
)
2426 const unsigned HOST_WIDE_INT
*imm1
= (const unsigned HOST_WIDE_INT
*) i1
;
2427 const unsigned HOST_WIDE_INT
*imm2
= (const unsigned HOST_WIDE_INT
*) i2
;
2438 aarch64_build_bitmask_table (void)
2440 unsigned HOST_WIDE_INT mask
, imm
;
2441 unsigned int log_e
, e
, s
, r
;
2442 unsigned int nimms
= 0;
2444 for (log_e
= 1; log_e
<= 6; log_e
++)
2448 mask
= ~(HOST_WIDE_INT
) 0;
2450 mask
= ((HOST_WIDE_INT
) 1 << e
) - 1;
2451 for (s
= 1; s
< e
; s
++)
2453 for (r
= 0; r
< e
; r
++)
2455 /* set s consecutive bits to 1 (s < 64) */
2456 imm
= ((unsigned HOST_WIDE_INT
)1 << s
) - 1;
2457 /* rotate right by r */
2459 imm
= ((imm
>> r
) | (imm
<< (e
- r
))) & mask
;
2460 /* replicate the constant depending on SIMD size */
2462 case 1: imm
|= (imm
<< 2);
2463 case 2: imm
|= (imm
<< 4);
2464 case 3: imm
|= (imm
<< 8);
2465 case 4: imm
|= (imm
<< 16);
2466 case 5: imm
|= (imm
<< 32);
2472 gcc_assert (nimms
< AARCH64_NUM_BITMASKS
);
2473 aarch64_bitmasks
[nimms
++] = imm
;
2478 gcc_assert (nimms
== AARCH64_NUM_BITMASKS
);
2479 qsort (aarch64_bitmasks
, nimms
, sizeof (aarch64_bitmasks
[0]),
2480 aarch64_bitmasks_cmp
);
2484 /* Return true if val can be encoded as a 12-bit unsigned immediate with
2485 a left shift of 0 or 12 bits. */
2487 aarch64_uimm12_shift (HOST_WIDE_INT val
)
2489 return ((val
& (((HOST_WIDE_INT
) 0xfff) << 0)) == val
2490 || (val
& (((HOST_WIDE_INT
) 0xfff) << 12)) == val
2495 /* Return true if val is an immediate that can be loaded into a
2496 register by a MOVZ instruction. */
2498 aarch64_movw_imm (HOST_WIDE_INT val
, enum machine_mode mode
)
2500 if (GET_MODE_SIZE (mode
) > 4)
2502 if ((val
& (((HOST_WIDE_INT
) 0xffff) << 32)) == val
2503 || (val
& (((HOST_WIDE_INT
) 0xffff) << 48)) == val
)
2508 /* Ignore sign extension. */
2509 val
&= (HOST_WIDE_INT
) 0xffffffff;
2511 return ((val
& (((HOST_WIDE_INT
) 0xffff) << 0)) == val
2512 || (val
& (((HOST_WIDE_INT
) 0xffff) << 16)) == val
);
2516 /* Return true if val is a valid bitmask immediate. */
2518 aarch64_bitmask_imm (HOST_WIDE_INT val
, enum machine_mode mode
)
2520 if (GET_MODE_SIZE (mode
) < 8)
2522 /* Replicate bit pattern. */
2523 val
&= (HOST_WIDE_INT
) 0xffffffff;
2526 return bsearch (&val
, aarch64_bitmasks
, AARCH64_NUM_BITMASKS
,
2527 sizeof (aarch64_bitmasks
[0]), aarch64_bitmasks_cmp
) != NULL
;
2531 /* Return true if val is an immediate that can be loaded into a
2532 register in a single instruction. */
2534 aarch64_move_imm (HOST_WIDE_INT val
, enum machine_mode mode
)
2536 if (aarch64_movw_imm (val
, mode
) || aarch64_movw_imm (~val
, mode
))
2538 return aarch64_bitmask_imm (val
, mode
);
2542 aarch64_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED
, rtx x
)
2545 if (GET_CODE (x
) == HIGH
)
2548 split_const (x
, &base
, &offset
);
2549 if (GET_CODE (base
) == SYMBOL_REF
|| GET_CODE (base
) == LABEL_REF
)
2550 return (aarch64_classify_symbol (base
, SYMBOL_CONTEXT_ADR
) != SYMBOL_FORCE_TO_MEM
);
2552 return aarch64_tls_referenced_p (x
);
2555 /* Return true if register REGNO is a valid index register.
2556 STRICT_P is true if REG_OK_STRICT is in effect. */
2559 aarch64_regno_ok_for_index_p (int regno
, bool strict_p
)
2561 if (!HARD_REGISTER_NUM_P (regno
))
2569 regno
= reg_renumber
[regno
];
2571 return GP_REGNUM_P (regno
);
2574 /* Return true if register REGNO is a valid base register for mode MODE.
2575 STRICT_P is true if REG_OK_STRICT is in effect. */
2578 aarch64_regno_ok_for_base_p (int regno
, bool strict_p
)
2580 if (!HARD_REGISTER_NUM_P (regno
))
2588 regno
= reg_renumber
[regno
];
2591 /* The fake registers will be eliminated to either the stack or
2592 hard frame pointer, both of which are usually valid base registers.
2593 Reload deals with the cases where the eliminated form isn't valid. */
2594 return (GP_REGNUM_P (regno
)
2595 || regno
== SP_REGNUM
2596 || regno
== FRAME_POINTER_REGNUM
2597 || regno
== ARG_POINTER_REGNUM
);
2600 /* Return true if X is a valid base register for mode MODE.
2601 STRICT_P is true if REG_OK_STRICT is in effect. */
2604 aarch64_base_register_rtx_p (rtx x
, bool strict_p
)
2606 if (!strict_p
&& GET_CODE (x
) == SUBREG
)
2609 return (REG_P (x
) && aarch64_regno_ok_for_base_p (REGNO (x
), strict_p
));
2612 /* Return true if address offset is a valid index. If it is, fill in INFO
2613 appropriately. STRICT_P is true if REG_OK_STRICT is in effect. */
2616 aarch64_classify_index (struct aarch64_address_info
*info
, rtx x
,
2617 enum machine_mode mode
, bool strict_p
)
2619 enum aarch64_address_type type
;
2624 if ((REG_P (x
) || GET_CODE (x
) == SUBREG
)
2625 && GET_MODE (x
) == Pmode
)
2627 type
= ADDRESS_REG_REG
;
2631 /* (sign_extend:DI (reg:SI)) */
2632 else if ((GET_CODE (x
) == SIGN_EXTEND
2633 || GET_CODE (x
) == ZERO_EXTEND
)
2634 && GET_MODE (x
) == DImode
2635 && GET_MODE (XEXP (x
, 0)) == SImode
)
2637 type
= (GET_CODE (x
) == SIGN_EXTEND
)
2638 ? ADDRESS_REG_SXTW
: ADDRESS_REG_UXTW
;
2639 index
= XEXP (x
, 0);
2642 /* (mult:DI (sign_extend:DI (reg:SI)) (const_int scale)) */
2643 else if (GET_CODE (x
) == MULT
2644 && (GET_CODE (XEXP (x
, 0)) == SIGN_EXTEND
2645 || GET_CODE (XEXP (x
, 0)) == ZERO_EXTEND
)
2646 && GET_MODE (XEXP (x
, 0)) == DImode
2647 && GET_MODE (XEXP (XEXP (x
, 0), 0)) == SImode
2648 && CONST_INT_P (XEXP (x
, 1)))
2650 type
= (GET_CODE (XEXP (x
, 0)) == SIGN_EXTEND
)
2651 ? ADDRESS_REG_SXTW
: ADDRESS_REG_UXTW
;
2652 index
= XEXP (XEXP (x
, 0), 0);
2653 shift
= exact_log2 (INTVAL (XEXP (x
, 1)));
2655 /* (ashift:DI (sign_extend:DI (reg:SI)) (const_int shift)) */
2656 else if (GET_CODE (x
) == ASHIFT
2657 && (GET_CODE (XEXP (x
, 0)) == SIGN_EXTEND
2658 || GET_CODE (XEXP (x
, 0)) == ZERO_EXTEND
)
2659 && GET_MODE (XEXP (x
, 0)) == DImode
2660 && GET_MODE (XEXP (XEXP (x
, 0), 0)) == SImode
2661 && CONST_INT_P (XEXP (x
, 1)))
2663 type
= (GET_CODE (XEXP (x
, 0)) == SIGN_EXTEND
)
2664 ? ADDRESS_REG_SXTW
: ADDRESS_REG_UXTW
;
2665 index
= XEXP (XEXP (x
, 0), 0);
2666 shift
= INTVAL (XEXP (x
, 1));
2668 /* (sign_extract:DI (mult:DI (reg:DI) (const_int scale)) 32+shift 0) */
2669 else if ((GET_CODE (x
) == SIGN_EXTRACT
2670 || GET_CODE (x
) == ZERO_EXTRACT
)
2671 && GET_MODE (x
) == DImode
2672 && GET_CODE (XEXP (x
, 0)) == MULT
2673 && GET_MODE (XEXP (XEXP (x
, 0), 0)) == DImode
2674 && CONST_INT_P (XEXP (XEXP (x
, 0), 1)))
2676 type
= (GET_CODE (x
) == SIGN_EXTRACT
)
2677 ? ADDRESS_REG_SXTW
: ADDRESS_REG_UXTW
;
2678 index
= XEXP (XEXP (x
, 0), 0);
2679 shift
= exact_log2 (INTVAL (XEXP (XEXP (x
, 0), 1)));
2680 if (INTVAL (XEXP (x
, 1)) != 32 + shift
2681 || INTVAL (XEXP (x
, 2)) != 0)
2684 /* (and:DI (mult:DI (reg:DI) (const_int scale))
2685 (const_int 0xffffffff<<shift)) */
2686 else if (GET_CODE (x
) == AND
2687 && GET_MODE (x
) == DImode
2688 && GET_CODE (XEXP (x
, 0)) == MULT
2689 && GET_MODE (XEXP (XEXP (x
, 0), 0)) == DImode
2690 && CONST_INT_P (XEXP (XEXP (x
, 0), 1))
2691 && CONST_INT_P (XEXP (x
, 1)))
2693 type
= ADDRESS_REG_UXTW
;
2694 index
= XEXP (XEXP (x
, 0), 0);
2695 shift
= exact_log2 (INTVAL (XEXP (XEXP (x
, 0), 1)));
2696 if (INTVAL (XEXP (x
, 1)) != (HOST_WIDE_INT
)0xffffffff << shift
)
2699 /* (sign_extract:DI (ashift:DI (reg:DI) (const_int shift)) 32+shift 0) */
2700 else if ((GET_CODE (x
) == SIGN_EXTRACT
2701 || GET_CODE (x
) == ZERO_EXTRACT
)
2702 && GET_MODE (x
) == DImode
2703 && GET_CODE (XEXP (x
, 0)) == ASHIFT
2704 && GET_MODE (XEXP (XEXP (x
, 0), 0)) == DImode
2705 && CONST_INT_P (XEXP (XEXP (x
, 0), 1)))
2707 type
= (GET_CODE (x
) == SIGN_EXTRACT
)
2708 ? ADDRESS_REG_SXTW
: ADDRESS_REG_UXTW
;
2709 index
= XEXP (XEXP (x
, 0), 0);
2710 shift
= INTVAL (XEXP (XEXP (x
, 0), 1));
2711 if (INTVAL (XEXP (x
, 1)) != 32 + shift
2712 || INTVAL (XEXP (x
, 2)) != 0)
2715 /* (and:DI (ashift:DI (reg:DI) (const_int shift))
2716 (const_int 0xffffffff<<shift)) */
2717 else if (GET_CODE (x
) == AND
2718 && GET_MODE (x
) == DImode
2719 && GET_CODE (XEXP (x
, 0)) == ASHIFT
2720 && GET_MODE (XEXP (XEXP (x
, 0), 0)) == DImode
2721 && CONST_INT_P (XEXP (XEXP (x
, 0), 1))
2722 && CONST_INT_P (XEXP (x
, 1)))
2724 type
= ADDRESS_REG_UXTW
;
2725 index
= XEXP (XEXP (x
, 0), 0);
2726 shift
= INTVAL (XEXP (XEXP (x
, 0), 1));
2727 if (INTVAL (XEXP (x
, 1)) != (HOST_WIDE_INT
)0xffffffff << shift
)
2730 /* (mult:P (reg:P) (const_int scale)) */
2731 else if (GET_CODE (x
) == MULT
2732 && GET_MODE (x
) == Pmode
2733 && GET_MODE (XEXP (x
, 0)) == Pmode
2734 && CONST_INT_P (XEXP (x
, 1)))
2736 type
= ADDRESS_REG_REG
;
2737 index
= XEXP (x
, 0);
2738 shift
= exact_log2 (INTVAL (XEXP (x
, 1)));
2740 /* (ashift:P (reg:P) (const_int shift)) */
2741 else if (GET_CODE (x
) == ASHIFT
2742 && GET_MODE (x
) == Pmode
2743 && GET_MODE (XEXP (x
, 0)) == Pmode
2744 && CONST_INT_P (XEXP (x
, 1)))
2746 type
= ADDRESS_REG_REG
;
2747 index
= XEXP (x
, 0);
2748 shift
= INTVAL (XEXP (x
, 1));
2753 if (GET_CODE (index
) == SUBREG
)
2754 index
= SUBREG_REG (index
);
2757 (shift
> 0 && shift
<= 3
2758 && (1 << shift
) == GET_MODE_SIZE (mode
)))
2760 && aarch64_regno_ok_for_index_p (REGNO (index
), strict_p
))
2763 info
->offset
= index
;
2764 info
->shift
= shift
;
2772 offset_7bit_signed_scaled_p (enum machine_mode mode
, HOST_WIDE_INT offset
)
2774 return (offset
>= -64 * GET_MODE_SIZE (mode
)
2775 && offset
< 64 * GET_MODE_SIZE (mode
)
2776 && offset
% GET_MODE_SIZE (mode
) == 0);
2780 offset_9bit_signed_unscaled_p (enum machine_mode mode ATTRIBUTE_UNUSED
,
2781 HOST_WIDE_INT offset
)
2783 return offset
>= -256 && offset
< 256;
2787 offset_12bit_unsigned_scaled_p (enum machine_mode mode
, HOST_WIDE_INT offset
)
2790 && offset
< 4096 * GET_MODE_SIZE (mode
)
2791 && offset
% GET_MODE_SIZE (mode
) == 0);
2794 /* Return true if X is a valid address for machine mode MODE. If it is,
2795 fill in INFO appropriately. STRICT_P is true if REG_OK_STRICT is in
2796 effect. OUTER_CODE is PARALLEL for a load/store pair. */
2799 aarch64_classify_address (struct aarch64_address_info
*info
,
2800 rtx x
, enum machine_mode mode
,
2801 RTX_CODE outer_code
, bool strict_p
)
2803 enum rtx_code code
= GET_CODE (x
);
2805 bool allow_reg_index_p
=
2806 outer_code
!= PARALLEL
&& GET_MODE_SIZE(mode
) != 16;
2808 /* Don't support anything other than POST_INC or REG addressing for
2810 if (aarch64_vector_mode_p (mode
)
2811 && (code
!= POST_INC
&& code
!= REG
))
2818 info
->type
= ADDRESS_REG_IMM
;
2820 info
->offset
= const0_rtx
;
2821 return aarch64_base_register_rtx_p (x
, strict_p
);
2826 if (GET_MODE_SIZE (mode
) != 0
2827 && CONST_INT_P (op1
)
2828 && aarch64_base_register_rtx_p (op0
, strict_p
))
2830 HOST_WIDE_INT offset
= INTVAL (op1
);
2832 info
->type
= ADDRESS_REG_IMM
;
2836 /* TImode and TFmode values are allowed in both pairs of X
2837 registers and individual Q registers. The available
2839 X,X: 7-bit signed scaled offset
2840 Q: 9-bit signed offset
2841 We conservatively require an offset representable in either mode.
2843 if (mode
== TImode
|| mode
== TFmode
)
2844 return (offset_7bit_signed_scaled_p (mode
, offset
)
2845 && offset_9bit_signed_unscaled_p (mode
, offset
));
2847 if (outer_code
== PARALLEL
)
2848 return ((GET_MODE_SIZE (mode
) == 4 || GET_MODE_SIZE (mode
) == 8)
2849 && offset_7bit_signed_scaled_p (mode
, offset
));
2851 return (offset_9bit_signed_unscaled_p (mode
, offset
)
2852 || offset_12bit_unsigned_scaled_p (mode
, offset
));
2855 if (allow_reg_index_p
)
2857 /* Look for base + (scaled/extended) index register. */
2858 if (aarch64_base_register_rtx_p (op0
, strict_p
)
2859 && aarch64_classify_index (info
, op1
, mode
, strict_p
))
2864 if (aarch64_base_register_rtx_p (op1
, strict_p
)
2865 && aarch64_classify_index (info
, op0
, mode
, strict_p
))
2878 info
->type
= ADDRESS_REG_WB
;
2879 info
->base
= XEXP (x
, 0);
2880 info
->offset
= NULL_RTX
;
2881 return aarch64_base_register_rtx_p (info
->base
, strict_p
);
2885 info
->type
= ADDRESS_REG_WB
;
2886 info
->base
= XEXP (x
, 0);
2887 if (GET_CODE (XEXP (x
, 1)) == PLUS
2888 && CONST_INT_P (XEXP (XEXP (x
, 1), 1))
2889 && rtx_equal_p (XEXP (XEXP (x
, 1), 0), info
->base
)
2890 && aarch64_base_register_rtx_p (info
->base
, strict_p
))
2892 HOST_WIDE_INT offset
;
2893 info
->offset
= XEXP (XEXP (x
, 1), 1);
2894 offset
= INTVAL (info
->offset
);
2896 /* TImode and TFmode values are allowed in both pairs of X
2897 registers and individual Q registers. The available
2899 X,X: 7-bit signed scaled offset
2900 Q: 9-bit signed offset
2901 We conservatively require an offset representable in either mode.
2903 if (mode
== TImode
|| mode
== TFmode
)
2904 return (offset_7bit_signed_scaled_p (mode
, offset
)
2905 && offset_9bit_signed_unscaled_p (mode
, offset
));
2907 if (outer_code
== PARALLEL
)
2908 return ((GET_MODE_SIZE (mode
) == 4 || GET_MODE_SIZE (mode
) == 8)
2909 && offset_7bit_signed_scaled_p (mode
, offset
));
2911 return offset_9bit_signed_unscaled_p (mode
, offset
);
2918 /* load literal: pc-relative constant pool entry. */
2919 info
->type
= ADDRESS_SYMBOLIC
;
2920 if (outer_code
!= PARALLEL
)
2924 split_const (x
, &sym
, &addend
);
2925 return (GET_CODE (sym
) == LABEL_REF
2926 || (GET_CODE (sym
) == SYMBOL_REF
2927 && CONSTANT_POOL_ADDRESS_P (sym
)));
2932 info
->type
= ADDRESS_LO_SUM
;
2933 info
->base
= XEXP (x
, 0);
2934 info
->offset
= XEXP (x
, 1);
2935 if (allow_reg_index_p
2936 && aarch64_base_register_rtx_p (info
->base
, strict_p
))
2939 split_const (info
->offset
, &sym
, &offs
);
2940 if (GET_CODE (sym
) == SYMBOL_REF
2941 && (aarch64_classify_symbol (sym
, SYMBOL_CONTEXT_MEM
)
2942 == SYMBOL_SMALL_ABSOLUTE
))
2944 /* The symbol and offset must be aligned to the access size. */
2946 unsigned int ref_size
;
2948 if (CONSTANT_POOL_ADDRESS_P (sym
))
2949 align
= GET_MODE_ALIGNMENT (get_pool_mode (sym
));
2950 else if (TREE_CONSTANT_POOL_ADDRESS_P (sym
))
2952 tree exp
= SYMBOL_REF_DECL (sym
);
2953 align
= TYPE_ALIGN (TREE_TYPE (exp
));
2954 align
= CONSTANT_ALIGNMENT (exp
, align
);
2956 else if (SYMBOL_REF_DECL (sym
))
2957 align
= DECL_ALIGN (SYMBOL_REF_DECL (sym
));
2959 align
= BITS_PER_UNIT
;
2961 ref_size
= GET_MODE_SIZE (mode
);
2963 ref_size
= GET_MODE_SIZE (DImode
);
2965 return ((INTVAL (offs
) & (ref_size
- 1)) == 0
2966 && ((align
/ BITS_PER_UNIT
) & (ref_size
- 1)) == 0);
2977 aarch64_symbolic_address_p (rtx x
)
2981 split_const (x
, &x
, &offset
);
2982 return GET_CODE (x
) == SYMBOL_REF
|| GET_CODE (x
) == LABEL_REF
;
2985 /* Classify the base of symbolic expression X, given that X appears in
2987 static enum aarch64_symbol_type
2988 aarch64_classify_symbolic_expression (rtx x
, enum aarch64_symbol_context context
)
2991 split_const (x
, &x
, &offset
);
2992 return aarch64_classify_symbol (x
, context
);
2996 /* Return TRUE if X is a legitimate address for accessing memory in
2999 aarch64_legitimate_address_hook_p (enum machine_mode mode
, rtx x
, bool strict_p
)
3001 struct aarch64_address_info addr
;
3003 return aarch64_classify_address (&addr
, x
, mode
, MEM
, strict_p
);
3006 /* Return TRUE if X is a legitimate address for accessing memory in
3007 mode MODE. OUTER_CODE will be PARALLEL if this is a load/store
3010 aarch64_legitimate_address_p (enum machine_mode mode
, rtx x
,
3011 RTX_CODE outer_code
, bool strict_p
)
3013 struct aarch64_address_info addr
;
3015 return aarch64_classify_address (&addr
, x
, mode
, outer_code
, strict_p
);
3018 /* Return TRUE if rtx X is immediate constant 0.0 */
3020 aarch64_const_double_zero_rtx_p (rtx x
)
3024 if (GET_MODE (x
) == VOIDmode
)
3027 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
3028 if (REAL_VALUE_MINUS_ZERO (r
))
3029 return !HONOR_SIGNED_ZEROS (GET_MODE (x
));
3030 return REAL_VALUES_EQUAL (r
, dconst0
);
3034 aarch64_select_cc_mode (RTX_CODE code
, rtx x
, rtx y
)
3036 /* All floating point compares return CCFP if it is an equality
3037 comparison, and CCFPE otherwise. */
3038 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
)
3065 if ((GET_MODE (x
) == SImode
|| GET_MODE (x
) == DImode
)
3067 && (code
== EQ
|| code
== NE
|| code
== LT
|| code
== GE
)
3068 && (GET_CODE (x
) == PLUS
|| GET_CODE (x
) == MINUS
))
3071 /* A compare with a shifted operand. Because of canonicalization,
3072 the comparison will have to be swapped when we emit the assembly
3074 if ((GET_MODE (x
) == SImode
|| GET_MODE (x
) == DImode
)
3075 && (GET_CODE (y
) == REG
|| GET_CODE (y
) == SUBREG
)
3076 && (GET_CODE (x
) == ASHIFT
|| GET_CODE (x
) == ASHIFTRT
3077 || GET_CODE (x
) == LSHIFTRT
3078 || GET_CODE (x
) == ZERO_EXTEND
|| GET_CODE (x
) == SIGN_EXTEND
))
3081 /* A compare of a mode narrower than SI mode against zero can be done
3082 by extending the value in the comparison. */
3083 if ((GET_MODE (x
) == QImode
|| GET_MODE (x
) == HImode
)
3085 /* Only use sign-extension if we really need it. */
3086 return ((code
== GT
|| code
== GE
|| code
== LE
|| code
== LT
)
3087 ? CC_SESWPmode
: CC_ZESWPmode
);
3089 /* For everything else, return CCmode. */
3094 aarch64_get_condition_code (rtx x
)
3096 enum machine_mode mode
= GET_MODE (XEXP (x
, 0));
3097 enum rtx_code comp_code
= GET_CODE (x
);
3099 if (GET_MODE_CLASS (mode
) != MODE_CC
)
3100 mode
= SELECT_CC_MODE (comp_code
, XEXP (x
, 0), XEXP (x
, 1));
3108 case GE
: return AARCH64_GE
;
3109 case GT
: return AARCH64_GT
;
3110 case LE
: return AARCH64_LS
;
3111 case LT
: return AARCH64_MI
;
3112 case NE
: return AARCH64_NE
;
3113 case EQ
: return AARCH64_EQ
;
3114 case ORDERED
: return AARCH64_VC
;
3115 case UNORDERED
: return AARCH64_VS
;
3116 case UNLT
: return AARCH64_LT
;
3117 case UNLE
: return AARCH64_LE
;
3118 case UNGT
: return AARCH64_HI
;
3119 case UNGE
: return AARCH64_PL
;
3120 default: gcc_unreachable ();
3127 case NE
: return AARCH64_NE
;
3128 case EQ
: return AARCH64_EQ
;
3129 case GE
: return AARCH64_GE
;
3130 case GT
: return AARCH64_GT
;
3131 case LE
: return AARCH64_LE
;
3132 case LT
: return AARCH64_LT
;
3133 case GEU
: return AARCH64_CS
;
3134 case GTU
: return AARCH64_HI
;
3135 case LEU
: return AARCH64_LS
;
3136 case LTU
: return AARCH64_CC
;
3137 default: gcc_unreachable ();
3146 case NE
: return AARCH64_NE
;
3147 case EQ
: return AARCH64_EQ
;
3148 case GE
: return AARCH64_LE
;
3149 case GT
: return AARCH64_LT
;
3150 case LE
: return AARCH64_GE
;
3151 case LT
: return AARCH64_GT
;
3152 case GEU
: return AARCH64_LS
;
3153 case GTU
: return AARCH64_CC
;
3154 case LEU
: return AARCH64_CS
;
3155 case LTU
: return AARCH64_HI
;
3156 default: gcc_unreachable ();
3163 case NE
: return AARCH64_NE
;
3164 case EQ
: return AARCH64_EQ
;
3165 case GE
: return AARCH64_PL
;
3166 case LT
: return AARCH64_MI
;
3167 default: gcc_unreachable ();
3178 bit_count (unsigned HOST_WIDE_INT value
)
3192 aarch64_print_operand (FILE *f
, rtx x
, char code
)
3197 /* Print the sign/zero-extend size as a character 8->b, 16->h, 32->w. */
3201 if (GET_CODE (x
) != CONST_INT
3202 || (n
= exact_log2 (INTVAL (x
) & ~7)) <= 0)
3204 output_operand_lossage ("invalid operand for '%%%c'", code
);
3220 output_operand_lossage ("invalid operand for '%%%c'", code
);
3230 /* Print N such that 2^N == X. */
3231 if (GET_CODE (x
) != CONST_INT
|| (n
= exact_log2 (INTVAL (x
))) < 0)
3233 output_operand_lossage ("invalid operand for '%%%c'", code
);
3237 asm_fprintf (f
, "%d", n
);
3242 /* Print the number of non-zero bits in X (a const_int). */
3243 if (GET_CODE (x
) != CONST_INT
)
3245 output_operand_lossage ("invalid operand for '%%%c'", code
);
3249 asm_fprintf (f
, "%u", bit_count (INTVAL (x
)));
3253 /* Print the higher numbered register of a pair (TImode) of regs. */
3254 if (GET_CODE (x
) != REG
|| !GP_REGNUM_P (REGNO (x
) + 1))
3256 output_operand_lossage ("invalid operand for '%%%c'", code
);
3260 asm_fprintf (f
, "%r", REGNO (x
) + 1);
3264 /* Print the least significant register of a pair (TImode) of regs. */
3265 if (GET_CODE (x
) != REG
|| !GP_REGNUM_P (REGNO (x
) + 1))
3267 output_operand_lossage ("invalid operand for '%%%c'", code
);
3270 asm_fprintf (f
, "%r", REGNO (x
) + (WORDS_BIG_ENDIAN
? 1 : 0));
3274 /* Print the most significant register of a pair (TImode) of regs. */
3275 if (GET_CODE (x
) != REG
|| !GP_REGNUM_P (REGNO (x
) + 1))
3277 output_operand_lossage ("invalid operand for '%%%c'", code
);
3280 asm_fprintf (f
, "%r", REGNO (x
) + (WORDS_BIG_ENDIAN
? 0 : 1));
3284 /* Print a condition (eq, ne, etc). */
3286 /* CONST_TRUE_RTX means always -- that's the default. */
3287 if (x
== const_true_rtx
)
3290 if (!COMPARISON_P (x
))
3292 output_operand_lossage ("invalid operand for '%%%c'", code
);
3296 fputs (aarch64_condition_codes
[aarch64_get_condition_code (x
)], f
);
3300 /* Print the inverse of a condition (eq <-> ne, etc). */
3302 /* CONST_TRUE_RTX means never -- that's the default. */
3303 if (x
== const_true_rtx
)
3309 if (!COMPARISON_P (x
))
3311 output_operand_lossage ("invalid operand for '%%%c'", code
);
3315 fputs (aarch64_condition_codes
[AARCH64_INVERSE_CONDITION_CODE
3316 (aarch64_get_condition_code (x
))], f
);
3324 /* Print a scalar FP/SIMD register name. */
3325 if (!REG_P (x
) || !FP_REGNUM_P (REGNO (x
)))
3327 output_operand_lossage ("incompatible floating point / vector register operand for '%%%c'", code
);
3330 asm_fprintf (f
, "%s%c%d", REGISTER_PREFIX
, code
, REGNO (x
) - V0_REGNUM
);
3337 /* Print the first FP/SIMD register name in a list. */
3338 if (!REG_P (x
) || !FP_REGNUM_P (REGNO (x
)))
3340 output_operand_lossage ("incompatible floating point / vector register operand for '%%%c'", code
);
3343 asm_fprintf (f
, "%sv%d", REGISTER_PREFIX
,
3344 REGNO (x
) - V0_REGNUM
+ (code
- 'S'));
3349 /* Print a general register name or the zero register (32-bit or
3351 if (x
== const0_rtx
)
3353 asm_fprintf (f
, "%s%czr", REGISTER_PREFIX
, code
);
3357 if (REG_P (x
) && GP_REGNUM_P (REGNO (x
)))
3359 asm_fprintf (f
, "%s%c%d", REGISTER_PREFIX
, code
,
3360 REGNO (x
) - R0_REGNUM
);
3364 if (REG_P (x
) && REGNO (x
) == SP_REGNUM
)
3366 asm_fprintf (f
, "%s%ssp", REGISTER_PREFIX
, code
== 'w' ? "w" : "");
3373 /* Print a normal operand, if it's a general register, then we
3377 output_operand_lossage ("missing operand");
3381 switch (GET_CODE (x
))
3384 asm_fprintf (f
, "%r", REGNO (x
));
3388 aarch64_memory_reference_mode
= GET_MODE (x
);
3389 output_address (XEXP (x
, 0));
3394 output_addr_const (asm_out_file
, x
);
3398 asm_fprintf (f
, "%wd", INTVAL (x
));
3402 gcc_assert (aarch64_const_vec_all_same_int_p (x
, HOST_WIDE_INT_MIN
,
3403 HOST_WIDE_INT_MAX
));
3404 asm_fprintf (f
, "%wd", INTVAL (CONST_VECTOR_ELT (x
, 0)));
3408 output_operand_lossage ("invalid operand");
3414 if (GET_CODE (x
) == HIGH
)
3417 switch (aarch64_classify_symbolic_expression (x
, SYMBOL_CONTEXT_ADR
))
3419 case SYMBOL_SMALL_GOT
:
3420 asm_fprintf (asm_out_file
, ":got:");
3423 case SYMBOL_SMALL_TLSGD
:
3424 asm_fprintf (asm_out_file
, ":tlsgd:");
3427 case SYMBOL_SMALL_TLSDESC
:
3428 asm_fprintf (asm_out_file
, ":tlsdesc:");
3431 case SYMBOL_SMALL_GOTTPREL
:
3432 asm_fprintf (asm_out_file
, ":gottprel:");
3435 case SYMBOL_SMALL_TPREL
:
3436 asm_fprintf (asm_out_file
, ":tprel:");
3442 output_addr_const (asm_out_file
, x
);
3446 switch (aarch64_classify_symbolic_expression (x
, SYMBOL_CONTEXT_ADR
))
3448 case SYMBOL_SMALL_GOT
:
3449 asm_fprintf (asm_out_file
, ":lo12:");
3452 case SYMBOL_SMALL_TLSGD
:
3453 asm_fprintf (asm_out_file
, ":tlsgd_lo12:");
3456 case SYMBOL_SMALL_TLSDESC
:
3457 asm_fprintf (asm_out_file
, ":tlsdesc_lo12:");
3460 case SYMBOL_SMALL_GOTTPREL
:
3461 asm_fprintf (asm_out_file
, ":gottprel_lo12:");
3464 case SYMBOL_SMALL_TPREL
:
3465 asm_fprintf (asm_out_file
, ":tprel_lo12_nc:");
3471 output_addr_const (asm_out_file
, x
);
3476 switch (aarch64_classify_symbolic_expression (x
, SYMBOL_CONTEXT_ADR
))
3478 case SYMBOL_SMALL_TPREL
:
3479 asm_fprintf (asm_out_file
, ":tprel_hi12:");
3484 output_addr_const (asm_out_file
, x
);
3488 output_operand_lossage ("invalid operand prefix '%%%c'", code
);
3494 aarch64_print_operand_address (FILE *f
, rtx x
)
3496 struct aarch64_address_info addr
;
3498 if (aarch64_classify_address (&addr
, x
, aarch64_memory_reference_mode
,
3502 case ADDRESS_REG_IMM
:
3503 if (addr
.offset
== const0_rtx
)
3504 asm_fprintf (f
, "[%r]", REGNO (addr
.base
));
3506 asm_fprintf (f
, "[%r,%wd]", REGNO (addr
.base
),
3507 INTVAL (addr
.offset
));
3510 case ADDRESS_REG_REG
:
3511 if (addr
.shift
== 0)
3512 asm_fprintf (f
, "[%r,%r]", REGNO (addr
.base
),
3513 REGNO (addr
.offset
));
3515 asm_fprintf (f
, "[%r,%r,lsl %u]", REGNO (addr
.base
),
3516 REGNO (addr
.offset
), addr
.shift
);
3519 case ADDRESS_REG_UXTW
:
3520 if (addr
.shift
== 0)
3521 asm_fprintf (f
, "[%r,w%d,uxtw]", REGNO (addr
.base
),
3522 REGNO (addr
.offset
) - R0_REGNUM
);
3524 asm_fprintf (f
, "[%r,w%d,uxtw %u]", REGNO (addr
.base
),
3525 REGNO (addr
.offset
) - R0_REGNUM
, addr
.shift
);
3528 case ADDRESS_REG_SXTW
:
3529 if (addr
.shift
== 0)
3530 asm_fprintf (f
, "[%r,w%d,sxtw]", REGNO (addr
.base
),
3531 REGNO (addr
.offset
) - R0_REGNUM
);
3533 asm_fprintf (f
, "[%r,w%d,sxtw %u]", REGNO (addr
.base
),
3534 REGNO (addr
.offset
) - R0_REGNUM
, addr
.shift
);
3537 case ADDRESS_REG_WB
:
3538 switch (GET_CODE (x
))
3541 asm_fprintf (f
, "[%r,%d]!", REGNO (addr
.base
),
3542 GET_MODE_SIZE (aarch64_memory_reference_mode
));
3545 asm_fprintf (f
, "[%r],%d", REGNO (addr
.base
),
3546 GET_MODE_SIZE (aarch64_memory_reference_mode
));
3549 asm_fprintf (f
, "[%r,-%d]!", REGNO (addr
.base
),
3550 GET_MODE_SIZE (aarch64_memory_reference_mode
));
3553 asm_fprintf (f
, "[%r],-%d", REGNO (addr
.base
),
3554 GET_MODE_SIZE (aarch64_memory_reference_mode
));
3557 asm_fprintf (f
, "[%r,%wd]!", REGNO (addr
.base
),
3558 INTVAL (addr
.offset
));
3561 asm_fprintf (f
, "[%r],%wd", REGNO (addr
.base
),
3562 INTVAL (addr
.offset
));
3569 case ADDRESS_LO_SUM
:
3570 asm_fprintf (f
, "[%r,#:lo12:", REGNO (addr
.base
));
3571 output_addr_const (f
, addr
.offset
);
3572 asm_fprintf (f
, "]");
3575 case ADDRESS_SYMBOLIC
:
3579 output_addr_const (f
, x
);
3583 aarch64_function_profiler (FILE *f ATTRIBUTE_UNUSED
,
3584 int labelno ATTRIBUTE_UNUSED
)
3586 sorry ("function profiling");
3590 aarch64_label_mentioned_p (rtx x
)
3595 if (GET_CODE (x
) == LABEL_REF
)
3598 /* UNSPEC_TLS entries for a symbol include a LABEL_REF for the
3599 referencing instruction, but they are constant offsets, not
3601 if (GET_CODE (x
) == UNSPEC
&& XINT (x
, 1) == UNSPEC_TLS
)
3604 fmt
= GET_RTX_FORMAT (GET_CODE (x
));
3605 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
3611 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
3612 if (aarch64_label_mentioned_p (XVECEXP (x
, i
, j
)))
3615 else if (fmt
[i
] == 'e' && aarch64_label_mentioned_p (XEXP (x
, i
)))
3622 /* Implement REGNO_REG_CLASS. */
3625 aarch64_regno_regclass (unsigned regno
)
3627 if (GP_REGNUM_P (regno
))
3630 if (regno
== SP_REGNUM
)
3633 if (regno
== FRAME_POINTER_REGNUM
3634 || regno
== ARG_POINTER_REGNUM
)
3637 if (FP_REGNUM_P (regno
))
3638 return FP_LO_REGNUM_P (regno
) ? FP_LO_REGS
: FP_REGS
;
3643 /* Try a machine-dependent way of reloading an illegitimate address
3644 operand. If we find one, push the reload and return the new rtx. */
3647 aarch64_legitimize_reload_address (rtx
*x_p
,
3648 enum machine_mode mode
,
3649 int opnum
, int type
,
3650 int ind_levels ATTRIBUTE_UNUSED
)
3654 /* Do not allow mem (plus (reg, const)) if vector mode. */
3655 if (aarch64_vector_mode_p (mode
)
3656 && GET_CODE (x
) == PLUS
3657 && REG_P (XEXP (x
, 0))
3658 && CONST_INT_P (XEXP (x
, 1)))
3662 push_reload (orig_rtx
, NULL_RTX
, x_p
, NULL
,
3663 BASE_REG_CLASS
, GET_MODE (x
), VOIDmode
, 0, 0,
3664 opnum
, (enum reload_type
) type
);
3668 /* We must recognize output that we have already generated ourselves. */
3669 if (GET_CODE (x
) == PLUS
3670 && GET_CODE (XEXP (x
, 0)) == PLUS
3671 && REG_P (XEXP (XEXP (x
, 0), 0))
3672 && CONST_INT_P (XEXP (XEXP (x
, 0), 1))
3673 && CONST_INT_P (XEXP (x
, 1)))
3675 push_reload (XEXP (x
, 0), NULL_RTX
, &XEXP (x
, 0), NULL
,
3676 BASE_REG_CLASS
, GET_MODE (x
), VOIDmode
, 0, 0,
3677 opnum
, (enum reload_type
) type
);
3681 /* We wish to handle large displacements off a base register by splitting
3682 the addend across an add and the mem insn. This can cut the number of
3683 extra insns needed from 3 to 1. It is only useful for load/store of a
3684 single register with 12 bit offset field. */
3685 if (GET_CODE (x
) == PLUS
3686 && REG_P (XEXP (x
, 0))
3687 && CONST_INT_P (XEXP (x
, 1))
3688 && HARD_REGISTER_P (XEXP (x
, 0))
3691 && aarch64_regno_ok_for_base_p (REGNO (XEXP (x
, 0)), true))
3693 HOST_WIDE_INT val
= INTVAL (XEXP (x
, 1));
3694 HOST_WIDE_INT low
= val
& 0xfff;
3695 HOST_WIDE_INT high
= val
- low
;
3699 /* Reload non-zero BLKmode offsets. This is because we cannot ascertain
3700 BLKmode alignment. */
3701 if (GET_MODE_SIZE (mode
) == 0)
3704 offs
= low
% GET_MODE_SIZE (mode
);
3706 /* Align misaligned offset by adjusting high part to compensate. */
3709 if (aarch64_uimm12_shift (high
+ offs
))
3718 offs
= GET_MODE_SIZE (mode
) - offs
;
3720 high
= high
+ (low
& 0x1000) - offs
;
3725 /* Check for overflow. */
3726 if (high
+ low
!= val
)
3729 cst
= GEN_INT (high
);
3730 if (!aarch64_uimm12_shift (high
))
3731 cst
= force_const_mem (Pmode
, cst
);
3733 /* Reload high part into base reg, leaving the low part
3734 in the mem instruction. */
3735 x
= gen_rtx_PLUS (Pmode
,
3736 gen_rtx_PLUS (Pmode
, XEXP (x
, 0), cst
),
3739 push_reload (XEXP (x
, 0), NULL_RTX
, &XEXP (x
, 0), NULL
,
3740 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0,
3741 opnum
, (enum reload_type
) type
);
3750 aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED
, rtx x
,
3752 enum machine_mode mode
,
3753 secondary_reload_info
*sri
)
3755 /* Address expressions of the form PLUS (SP, large_offset) need two
3756 scratch registers, one for the constant, and one for holding a
3757 copy of SP, since SP cannot be used on the RHS of an add-reg
3760 && GET_CODE (x
) == PLUS
3761 && XEXP (x
, 0) == stack_pointer_rtx
3762 && CONST_INT_P (XEXP (x
, 1))
3763 && !aarch64_uimm12_shift (INTVAL (XEXP (x
, 1))))
3765 sri
->icode
= CODE_FOR_reload_sp_immediate
;
3769 /* Without the TARGET_SIMD instructions we cannot move a Q register
3770 to a Q register directly. We need a scratch. */
3771 if (REG_P (x
) && (mode
== TFmode
|| mode
== TImode
) && mode
== GET_MODE (x
)
3772 && FP_REGNUM_P (REGNO (x
)) && !TARGET_SIMD
3773 && reg_class_subset_p (rclass
, FP_REGS
))
3776 sri
->icode
= CODE_FOR_aarch64_reload_movtf
;
3777 else if (mode
== TImode
)
3778 sri
->icode
= CODE_FOR_aarch64_reload_movti
;
3782 /* A TFmode or TImode memory access should be handled via an FP_REGS
3783 because AArch64 has richer addressing modes for LDR/STR instructions
3784 than LDP/STP instructions. */
3785 if (!TARGET_GENERAL_REGS_ONLY
&& rclass
== CORE_REGS
3786 && GET_MODE_SIZE (mode
) == 16 && MEM_P (x
))
3789 if (rclass
== FP_REGS
&& (mode
== TImode
|| mode
== TFmode
) && CONSTANT_P(x
))
3796 aarch64_can_eliminate (const int from
, const int to
)
3798 /* If we need a frame pointer, we must eliminate FRAME_POINTER_REGNUM into
3799 HARD_FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */
3801 if (frame_pointer_needed
)
3803 if (from
== ARG_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
3805 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
3807 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
3808 && !cfun
->calls_alloca
)
3810 if (from
== FRAME_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
3816 /* If we decided that we didn't need a frame pointer but then used
3817 LR in the function, then we do need a frame pointer after all, so
3818 prevent this elimination to ensure a frame pointer is used. */
3820 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
3821 && df_regs_ever_live_p (LR_REGNUM
))
3828 aarch64_initial_elimination_offset (unsigned from
, unsigned to
)
3830 HOST_WIDE_INT frame_size
;
3831 HOST_WIDE_INT offset
;
3833 aarch64_layout_frame ();
3834 frame_size
= (get_frame_size () + cfun
->machine
->frame
.saved_regs_size
3835 + crtl
->outgoing_args_size
3836 + cfun
->machine
->saved_varargs_size
);
3838 frame_size
= AARCH64_ROUND_UP (frame_size
, STACK_BOUNDARY
/ BITS_PER_UNIT
);
3839 offset
= frame_size
;
3841 if (to
== HARD_FRAME_POINTER_REGNUM
)
3843 if (from
== ARG_POINTER_REGNUM
)
3844 return offset
- crtl
->outgoing_args_size
;
3846 if (from
== FRAME_POINTER_REGNUM
)
3847 return cfun
->machine
->frame
.saved_regs_size
;
3850 if (to
== STACK_POINTER_REGNUM
)
3852 if (from
== FRAME_POINTER_REGNUM
)
3854 HOST_WIDE_INT elim
= crtl
->outgoing_args_size
3855 + cfun
->machine
->frame
.saved_regs_size
3856 - cfun
->machine
->frame
.fp_lr_offset
;
3857 elim
= AARCH64_ROUND_UP (elim
, STACK_BOUNDARY
/ BITS_PER_UNIT
);
3866 /* Implement RETURN_ADDR_RTX. We do not support moving back to a
3870 aarch64_return_addr (int count
, rtx frame ATTRIBUTE_UNUSED
)
3874 return get_hard_reg_initial_val (Pmode
, LR_REGNUM
);
3879 aarch64_asm_trampoline_template (FILE *f
)
3881 asm_fprintf (f
, "\tldr\t%r, .+16\n", IP1_REGNUM
);
3882 asm_fprintf (f
, "\tldr\t%r, .+20\n", STATIC_CHAIN_REGNUM
);
3883 asm_fprintf (f
, "\tbr\t%r\n", IP1_REGNUM
);
3884 assemble_aligned_integer (4, const0_rtx
);
3885 assemble_aligned_integer (UNITS_PER_WORD
, const0_rtx
);
3886 assemble_aligned_integer (UNITS_PER_WORD
, const0_rtx
);
3890 aarch64_trampoline_size (void)
3892 return 32; /* 3 insns + padding + 2 dwords. */
3896 aarch64_trampoline_init (rtx m_tramp
, tree fndecl
, rtx chain_value
)
3898 rtx fnaddr
, mem
, a_tramp
;
3900 /* Don't need to copy the trailing D-words, we fill those in below. */
3901 emit_block_move (m_tramp
, assemble_trampoline_template (),
3902 GEN_INT (TRAMPOLINE_SIZE
- 16), BLOCK_OP_NORMAL
);
3903 mem
= adjust_address (m_tramp
, DImode
, 16);
3904 fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
3905 emit_move_insn (mem
, fnaddr
);
3907 mem
= adjust_address (m_tramp
, DImode
, 24);
3908 emit_move_insn (mem
, chain_value
);
3910 /* XXX We should really define a "clear_cache" pattern and use
3911 gen_clear_cache(). */
3912 a_tramp
= XEXP (m_tramp
, 0);
3913 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "__clear_cache"),
3914 LCT_NORMAL
, VOIDmode
, 2, a_tramp
, Pmode
,
3915 plus_constant (Pmode
, a_tramp
, TRAMPOLINE_SIZE
), Pmode
);
3918 static unsigned char
3919 aarch64_class_max_nregs (reg_class_t regclass
, enum machine_mode mode
)
3930 aarch64_vector_mode_p (mode
) ? (GET_MODE_SIZE (mode
) + 15) / 16 :
3931 (GET_MODE_SIZE (mode
) + 7) / 8;
3945 aarch64_preferred_reload_class (rtx x ATTRIBUTE_UNUSED
, reg_class_t regclass
)
3947 return ((regclass
== POINTER_REGS
|| regclass
== STACK_REG
)
3948 ? GENERAL_REGS
: regclass
);
3952 aarch64_asm_output_labelref (FILE* f
, const char *name
)
3954 asm_fprintf (f
, "%U%s", name
);
3958 aarch64_elf_asm_constructor (rtx symbol
, int priority
)
3960 if (priority
== DEFAULT_INIT_PRIORITY
)
3961 default_ctor_section_asm_out_constructor (symbol
, priority
);
3966 snprintf (buf
, sizeof (buf
), ".init_array.%.5u", priority
);
3967 s
= get_section (buf
, SECTION_WRITE
, NULL
);
3968 switch_to_section (s
);
3969 assemble_align (POINTER_SIZE
);
3970 fputs ("\t.dword\t", asm_out_file
);
3971 output_addr_const (asm_out_file
, symbol
);
3972 fputc ('\n', asm_out_file
);
3977 aarch64_elf_asm_destructor (rtx symbol
, int priority
)
3979 if (priority
== DEFAULT_INIT_PRIORITY
)
3980 default_dtor_section_asm_out_destructor (symbol
, priority
);
3985 snprintf (buf
, sizeof (buf
), ".fini_array.%.5u", priority
);
3986 s
= get_section (buf
, SECTION_WRITE
, NULL
);
3987 switch_to_section (s
);
3988 assemble_align (POINTER_SIZE
);
3989 fputs ("\t.dword\t", asm_out_file
);
3990 output_addr_const (asm_out_file
, symbol
);
3991 fputc ('\n', asm_out_file
);
3996 aarch64_output_casesi (rtx
*operands
)
4000 rtx diff_vec
= PATTERN (next_real_insn (operands
[2]));
4002 static const char *const patterns
[4][2] =
4005 "ldrb\t%w3, [%0,%w1,uxtw]",
4006 "add\t%3, %4, %w3, sxtb #2"
4009 "ldrh\t%w3, [%0,%w1,uxtw #1]",
4010 "add\t%3, %4, %w3, sxth #2"
4013 "ldr\t%w3, [%0,%w1,uxtw #2]",
4014 "add\t%3, %4, %w3, sxtw #2"
4016 /* We assume that DImode is only generated when not optimizing and
4017 that we don't really need 64-bit address offsets. That would
4018 imply an object file with 8GB of code in a single function! */
4020 "ldr\t%w3, [%0,%w1,uxtw #2]",
4021 "add\t%3, %4, %w3, sxtw #2"
4025 gcc_assert (GET_CODE (diff_vec
) == ADDR_DIFF_VEC
);
4027 index
= exact_log2 (GET_MODE_SIZE (GET_MODE (diff_vec
)));
4029 gcc_assert (index
>= 0 && index
<= 3);
4031 /* Need to implement table size reduction, by chaning the code below. */
4032 output_asm_insn (patterns
[index
][0], operands
);
4033 ASM_GENERATE_INTERNAL_LABEL (label
, "Lrtx", CODE_LABEL_NUMBER (operands
[2]));
4034 snprintf (buf
, sizeof (buf
),
4035 "adr\t%%4, %s", targetm
.strip_name_encoding (label
));
4036 output_asm_insn (buf
, operands
);
4037 output_asm_insn (patterns
[index
][1], operands
);
4038 output_asm_insn ("br\t%3", operands
);
4039 assemble_label (asm_out_file
, label
);
4044 /* Return size in bits of an arithmetic operand which is shifted/scaled and
4045 masked such that it is suitable for a UXTB, UXTH, or UXTW extend
4049 aarch64_uxt_size (int shift
, HOST_WIDE_INT mask
)
4051 if (shift
>= 0 && shift
<= 3)
4054 for (size
= 8; size
<= 32; size
*= 2)
4056 HOST_WIDE_INT bits
= ((HOST_WIDE_INT
)1U << size
) - 1;
4057 if (mask
== bits
<< shift
)
4065 aarch64_use_blocks_for_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED
,
4066 const_rtx x ATTRIBUTE_UNUSED
)
4068 /* We can't use blocks for constants when we're using a per-function
4074 aarch64_select_rtx_section (enum machine_mode mode ATTRIBUTE_UNUSED
,
4075 rtx x ATTRIBUTE_UNUSED
,
4076 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED
)
4078 /* Force all constant pool entries into the current function section. */
4079 return function_section (current_function_decl
);
4085 /* Helper function for rtx cost calculation. Strip a shift expression
4086 from X. Returns the inner operand if successful, or the original
4087 expression on failure. */
4089 aarch64_strip_shift (rtx x
)
4093 if ((GET_CODE (op
) == ASHIFT
4094 || GET_CODE (op
) == ASHIFTRT
4095 || GET_CODE (op
) == LSHIFTRT
)
4096 && CONST_INT_P (XEXP (op
, 1)))
4097 return XEXP (op
, 0);
4099 if (GET_CODE (op
) == MULT
4100 && CONST_INT_P (XEXP (op
, 1))
4101 && ((unsigned) exact_log2 (INTVAL (XEXP (op
, 1)))) < 64)
4102 return XEXP (op
, 0);
4107 /* Helper function for rtx cost calculation. Strip a shift or extend
4108 expression from X. Returns the inner operand if successful, or the
4109 original expression on failure. We deal with a number of possible
4110 canonicalization variations here. */
4112 aarch64_strip_shift_or_extend (rtx x
)
4116 /* Zero and sign extraction of a widened value. */
4117 if ((GET_CODE (op
) == ZERO_EXTRACT
|| GET_CODE (op
) == SIGN_EXTRACT
)
4118 && XEXP (op
, 2) == const0_rtx
4119 && aarch64_is_extend_from_extract (GET_MODE (op
), XEXP (XEXP (op
, 0), 1),
4121 return XEXP (XEXP (op
, 0), 0);
4123 /* It can also be represented (for zero-extend) as an AND with an
4125 if (GET_CODE (op
) == AND
4126 && GET_CODE (XEXP (op
, 0)) == MULT
4127 && CONST_INT_P (XEXP (XEXP (op
, 0), 1))
4128 && CONST_INT_P (XEXP (op
, 1))
4129 && aarch64_uxt_size (exact_log2 (INTVAL (XEXP (XEXP (op
, 0), 1))),
4130 INTVAL (XEXP (op
, 1))) != 0)
4131 return XEXP (XEXP (op
, 0), 0);
4133 /* Now handle extended register, as this may also have an optional
4134 left shift by 1..4. */
4135 if (GET_CODE (op
) == ASHIFT
4136 && CONST_INT_P (XEXP (op
, 1))
4137 && ((unsigned HOST_WIDE_INT
) INTVAL (XEXP (op
, 1))) <= 4)
4140 if (GET_CODE (op
) == ZERO_EXTEND
4141 || GET_CODE (op
) == SIGN_EXTEND
)
4147 return aarch64_strip_shift (x
);
4150 /* Calculate the cost of calculating X, storing it in *COST. Result
4151 is true if the total cost of the operation has now been calculated. */
4153 aarch64_rtx_costs (rtx x
, int code
, int outer ATTRIBUTE_UNUSED
,
4154 int param ATTRIBUTE_UNUSED
, int *cost
, bool speed
)
4157 const struct cpu_rtx_cost_table
*extra_cost
4158 = aarch64_tune_params
->insn_extra_cost
;
4166 switch (GET_CODE (op0
))
4170 *cost
+= extra_cost
->memory_store
;
4172 if (op1
!= const0_rtx
)
4173 *cost
+= rtx_cost (op1
, SET
, 1, speed
);
4177 if (! REG_P (SUBREG_REG (op0
)))
4178 *cost
+= rtx_cost (SUBREG_REG (op0
), SET
, 0, speed
);
4181 /* Cost is just the cost of the RHS of the set. */
4182 *cost
+= rtx_cost (op1
, SET
, 1, true);
4185 case ZERO_EXTRACT
: /* Bit-field insertion. */
4187 /* Strip any redundant widening of the RHS to meet the width of
4189 if (GET_CODE (op1
) == SUBREG
)
4190 op1
= SUBREG_REG (op1
);
4191 if ((GET_CODE (op1
) == ZERO_EXTEND
4192 || GET_CODE (op1
) == SIGN_EXTEND
)
4193 && GET_CODE (XEXP (op0
, 1)) == CONST_INT
4194 && (GET_MODE_BITSIZE (GET_MODE (XEXP (op1
, 0)))
4195 >= INTVAL (XEXP (op0
, 1))))
4196 op1
= XEXP (op1
, 0);
4197 *cost
+= rtx_cost (op1
, SET
, 1, speed
);
4207 *cost
+= extra_cost
->memory_load
;
4212 op0
= CONST0_RTX (GET_MODE (x
));
4220 if (op1
== const0_rtx
4221 && GET_CODE (op0
) == AND
)
4227 /* Comparisons can work if the order is swapped.
4228 Canonicalization puts the more complex operation first, but
4229 we want it in op1. */
4231 || (GET_CODE (op0
) == SUBREG
&& REG_P (SUBREG_REG (op0
)))))
4243 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_INT
4244 || (GET_MODE_CLASS (GET_MODE (x
)) == MODE_CC
4245 && GET_MODE_CLASS (GET_MODE (op0
)) == MODE_INT
))
4247 if (op0
!= const0_rtx
)
4248 *cost
+= rtx_cost (op0
, MINUS
, 0, speed
);
4250 if (CONST_INT_P (op1
))
4252 if (!aarch64_uimm12_shift (INTVAL (op1
)))
4253 *cost
+= rtx_cost (op1
, MINUS
, 1, speed
);
4257 op1
= aarch64_strip_shift_or_extend (op1
);
4258 *cost
+= rtx_cost (op1
, MINUS
, 1, speed
);
4269 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_INT
)
4271 if (CONST_INT_P (op1
) && aarch64_uimm12_shift (INTVAL (op1
)))
4273 *cost
+= rtx_cost (op0
, PLUS
, 0, speed
);
4277 rtx new_op0
= aarch64_strip_shift_or_extend (op0
);
4280 && GET_CODE (op0
) == MULT
)
4282 if ((GET_CODE (XEXP (op0
, 0)) == ZERO_EXTEND
4283 && GET_CODE (XEXP (op0
, 1)) == ZERO_EXTEND
)
4284 || (GET_CODE (XEXP (op0
, 0)) == SIGN_EXTEND
4285 && GET_CODE (XEXP (op0
, 1)) == SIGN_EXTEND
))
4287 *cost
+= (rtx_cost (XEXP (XEXP (op0
, 0), 0), MULT
, 0,
4289 + rtx_cost (XEXP (XEXP (op0
, 1), 0), MULT
, 1,
4291 + rtx_cost (op1
, PLUS
, 1, speed
));
4293 *cost
+= extra_cost
->int_multiply_extend_add
;
4296 *cost
+= (rtx_cost (XEXP (op0
, 0), MULT
, 0, speed
)
4297 + rtx_cost (XEXP (op0
, 1), MULT
, 1, speed
)
4298 + rtx_cost (op1
, PLUS
, 1, speed
));
4301 *cost
+= extra_cost
->int_multiply_add
;
4304 *cost
+= (rtx_cost (new_op0
, PLUS
, 0, speed
)
4305 + rtx_cost (op1
, PLUS
, 1, speed
));
4319 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_INT
)
4321 if (CONST_INT_P (op1
)
4322 && aarch64_bitmask_imm (INTVAL (op1
), GET_MODE (x
)))
4324 *cost
+= rtx_cost (op0
, AND
, 0, speed
);
4328 if (GET_CODE (op0
) == NOT
)
4329 op0
= XEXP (op0
, 0);
4330 op0
= aarch64_strip_shift (op0
);
4331 *cost
+= (rtx_cost (op0
, AND
, 0, speed
)
4332 + rtx_cost (op1
, AND
, 1, speed
));
4339 if ((GET_MODE (x
) == DImode
4340 && GET_MODE (XEXP (x
, 0)) == SImode
)
4341 || GET_CODE (XEXP (x
, 0)) == MEM
)
4343 *cost
+= rtx_cost (XEXP (x
, 0), ZERO_EXTEND
, 0, speed
);
4349 if (GET_CODE (XEXP (x
, 0)) == MEM
)
4351 *cost
+= rtx_cost (XEXP (x
, 0), SIGN_EXTEND
, 0, speed
);
4357 if (!CONST_INT_P (XEXP (x
, 1)))
4358 *cost
+= COSTS_N_INSNS (2);
4365 /* Shifting by a register often takes an extra cycle. */
4366 if (speed
&& !CONST_INT_P (XEXP (x
, 1)))
4367 *cost
+= extra_cost
->register_shift
;
4369 *cost
+= rtx_cost (XEXP (x
, 0), ASHIFT
, 0, speed
);
4373 if (!CONSTANT_P (XEXP (x
, 0)))
4374 *cost
+= rtx_cost (XEXP (x
, 0), HIGH
, 0, speed
);
4378 if (!CONSTANT_P (XEXP (x
, 1)))
4379 *cost
+= rtx_cost (XEXP (x
, 1), LO_SUM
, 1, speed
);
4380 *cost
+= rtx_cost (XEXP (x
, 0), LO_SUM
, 0, speed
);
4385 *cost
+= rtx_cost (XEXP (x
, 0), ZERO_EXTRACT
, 0, speed
);
4392 *cost
= COSTS_N_INSNS (1);
4393 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_INT
)
4395 if (CONST_INT_P (op1
)
4396 && exact_log2 (INTVAL (op1
)) > 0)
4398 *cost
+= rtx_cost (op0
, ASHIFT
, 0, speed
);
4402 if ((GET_CODE (op0
) == ZERO_EXTEND
4403 && GET_CODE (op1
) == ZERO_EXTEND
)
4404 || (GET_CODE (op0
) == SIGN_EXTEND
4405 && GET_CODE (op1
) == SIGN_EXTEND
))
4407 *cost
+= (rtx_cost (XEXP (op0
, 0), MULT
, 0, speed
)
4408 + rtx_cost (XEXP (op1
, 0), MULT
, 1, speed
));
4410 *cost
+= extra_cost
->int_multiply_extend
;
4415 *cost
+= extra_cost
->int_multiply
;
4419 if (GET_MODE (x
) == DFmode
)
4420 *cost
+= extra_cost
->double_multiply
;
4421 else if (GET_MODE (x
) == SFmode
)
4422 *cost
+= extra_cost
->float_multiply
;
4425 return false; /* All arguments need to be in registers. */
4429 *cost
= COSTS_N_INSNS (2);
4432 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_INT
)
4433 *cost
+= (extra_cost
->int_multiply_add
4434 + extra_cost
->int_divide
);
4435 else if (GET_MODE (x
) == DFmode
)
4436 *cost
+= (extra_cost
->double_multiply
4437 + extra_cost
->double_divide
);
4438 else if (GET_MODE (x
) == SFmode
)
4439 *cost
+= (extra_cost
->float_multiply
4440 + extra_cost
->float_divide
);
4442 return false; /* All arguments need to be in registers. */
4446 *cost
= COSTS_N_INSNS (1);
4449 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_INT
)
4450 *cost
+= extra_cost
->int_divide
;
4451 else if (GET_MODE (x
) == DFmode
)
4452 *cost
+= extra_cost
->double_divide
;
4453 else if (GET_MODE (x
) == SFmode
)
4454 *cost
+= extra_cost
->float_divide
;
4456 return false; /* All arguments need to be in registers. */
4465 aarch64_address_cost (rtx x ATTRIBUTE_UNUSED
,
4466 enum machine_mode mode ATTRIBUTE_UNUSED
,
4467 addr_space_t as ATTRIBUTE_UNUSED
, bool speed ATTRIBUTE_UNUSED
)
4469 enum rtx_code c
= GET_CODE (x
);
4470 const struct cpu_addrcost_table
*addr_cost
= aarch64_tune_params
->addr_cost
;
4472 if (c
== PRE_INC
|| c
== PRE_DEC
|| c
== PRE_MODIFY
)
4473 return addr_cost
->pre_modify
;
4475 if (c
== POST_INC
|| c
== POST_DEC
|| c
== POST_MODIFY
)
4476 return addr_cost
->post_modify
;
4480 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
4481 return addr_cost
->imm_offset
;
4482 else if (GET_CODE (XEXP (x
, 0)) == MULT
4483 || GET_CODE (XEXP (x
, 0)) == ZERO_EXTEND
4484 || GET_CODE (XEXP (x
, 0)) == SIGN_EXTEND
)
4485 return addr_cost
->register_extend
;
4487 return addr_cost
->register_offset
;
4489 else if (c
== MEM
|| c
== LABEL_REF
|| c
== SYMBOL_REF
)
4490 return addr_cost
->imm_offset
;
4496 aarch64_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED
,
4497 reg_class_t from
, reg_class_t to
)
4499 const struct cpu_regmove_cost
*regmove_cost
4500 = aarch64_tune_params
->regmove_cost
;
4502 if (from
== GENERAL_REGS
&& to
== GENERAL_REGS
)
4503 return regmove_cost
->GP2GP
;
4504 else if (from
== GENERAL_REGS
)
4505 return regmove_cost
->GP2FP
;
4506 else if (to
== GENERAL_REGS
)
4507 return regmove_cost
->FP2GP
;
4509 /* When AdvSIMD instructions are disabled it is not possible to move
4510 a 128-bit value directly between Q registers. This is handled in
4511 secondary reload. A general register is used as a scratch to move
4512 the upper DI value and the lower DI value is moved directly,
4513 hence the cost is the sum of three moves. */
4515 if (! TARGET_SIMD
&& GET_MODE_SIZE (from
) == 128 && GET_MODE_SIZE (to
) == 128)
4516 return regmove_cost
->GP2FP
+ regmove_cost
->FP2GP
+ regmove_cost
->FP2FP
;
4518 return regmove_cost
->FP2FP
;
4522 aarch64_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED
,
4523 reg_class_t rclass ATTRIBUTE_UNUSED
,
4524 bool in ATTRIBUTE_UNUSED
)
4526 return aarch64_tune_params
->memmov_cost
;
4529 static void initialize_aarch64_code_model (void);
4531 /* Parse the architecture extension string. */
4534 aarch64_parse_extension (char *str
)
4536 /* The extension string is parsed left to right. */
4537 const struct aarch64_option_extension
*opt
= NULL
;
4539 /* Flag to say whether we are adding or removing an extension. */
4540 int adding_ext
= -1;
4542 while (str
!= NULL
&& *str
!= 0)
4548 ext
= strchr (str
, '+');
4555 if (len
>= 2 && strncmp (str
, "no", 2) == 0)
4566 error ("missing feature modifier after %qs", "+no");
4570 /* Scan over the extensions table trying to find an exact match. */
4571 for (opt
= all_extensions
; opt
->name
!= NULL
; opt
++)
4573 if (strlen (opt
->name
) == len
&& strncmp (opt
->name
, str
, len
) == 0)
4575 /* Add or remove the extension. */
4577 aarch64_isa_flags
|= opt
->flags_on
;
4579 aarch64_isa_flags
&= ~(opt
->flags_off
);
4584 if (opt
->name
== NULL
)
4586 /* Extension not found in list. */
4587 error ("unknown feature modifier %qs", str
);
4597 /* Parse the ARCH string. */
4600 aarch64_parse_arch (void)
4603 const struct processor
*arch
;
4604 char *str
= (char *) alloca (strlen (aarch64_arch_string
) + 1);
4607 strcpy (str
, aarch64_arch_string
);
4609 ext
= strchr (str
, '+');
4618 error ("missing arch name in -march=%qs", str
);
4622 /* Loop through the list of supported ARCHs to find a match. */
4623 for (arch
= all_architectures
; arch
->name
!= NULL
; arch
++)
4625 if (strlen (arch
->name
) == len
&& strncmp (arch
->name
, str
, len
) == 0)
4627 selected_arch
= arch
;
4628 aarch64_isa_flags
= selected_arch
->flags
;
4629 selected_cpu
= &all_cores
[selected_arch
->core
];
4633 /* ARCH string contains at least one extension. */
4634 aarch64_parse_extension (ext
);
4641 /* ARCH name not found in list. */
4642 error ("unknown value %qs for -march", str
);
4646 /* Parse the CPU string. */
4649 aarch64_parse_cpu (void)
4652 const struct processor
*cpu
;
4653 char *str
= (char *) alloca (strlen (aarch64_cpu_string
) + 1);
4656 strcpy (str
, aarch64_cpu_string
);
4658 ext
= strchr (str
, '+');
4667 error ("missing cpu name in -mcpu=%qs", str
);
4671 /* Loop through the list of supported CPUs to find a match. */
4672 for (cpu
= all_cores
; cpu
->name
!= NULL
; cpu
++)
4674 if (strlen (cpu
->name
) == len
&& strncmp (cpu
->name
, str
, len
) == 0)
4677 aarch64_isa_flags
= selected_cpu
->flags
;
4681 /* CPU string contains at least one extension. */
4682 aarch64_parse_extension (ext
);
4689 /* CPU name not found in list. */
4690 error ("unknown value %qs for -mcpu", str
);
4694 /* Parse the TUNE string. */
4697 aarch64_parse_tune (void)
4699 const struct processor
*cpu
;
4700 char *str
= (char *) alloca (strlen (aarch64_tune_string
) + 1);
4701 strcpy (str
, aarch64_tune_string
);
4703 /* Loop through the list of supported CPUs to find a match. */
4704 for (cpu
= all_cores
; cpu
->name
!= NULL
; cpu
++)
4706 if (strcmp (cpu
->name
, str
) == 0)
4708 selected_tune
= cpu
;
4713 /* CPU name not found in list. */
4714 error ("unknown value %qs for -mtune", str
);
4719 /* Implement TARGET_OPTION_OVERRIDE. */
4722 aarch64_override_options (void)
4724 /* march wins over mcpu, so when march is defined, mcpu takes the same value,
4725 otherwise march remains undefined. mtune can be used with either march or
4728 if (aarch64_arch_string
)
4730 aarch64_parse_arch ();
4731 aarch64_cpu_string
= NULL
;
4734 if (aarch64_cpu_string
)
4736 aarch64_parse_cpu ();
4737 selected_arch
= NULL
;
4740 if (aarch64_tune_string
)
4742 aarch64_parse_tune ();
4745 initialize_aarch64_code_model ();
4747 aarch64_build_bitmask_table ();
4749 /* This target defaults to strict volatile bitfields. */
4750 if (flag_strict_volatile_bitfields
< 0 && abi_version_at_least (2))
4751 flag_strict_volatile_bitfields
= 1;
4753 /* If the user did not specify a processor, choose the default
4754 one for them. This will be the CPU set during configuration using
4755 --with-cpu, otherwise it is "generic". */
4758 selected_cpu
= &all_cores
[TARGET_CPU_DEFAULT
& 0x3f];
4759 aarch64_isa_flags
= TARGET_CPU_DEFAULT
>> 6;
4762 gcc_assert (selected_cpu
);
4764 /* The selected cpu may be an architecture, so lookup tuning by core ID. */
4766 selected_tune
= &all_cores
[selected_cpu
->core
];
4768 aarch64_tune_flags
= selected_tune
->flags
;
4769 aarch64_tune
= selected_tune
->core
;
4770 aarch64_tune_params
= selected_tune
->tune
;
4772 aarch64_override_options_after_change ();
4775 /* Implement targetm.override_options_after_change. */
4778 aarch64_override_options_after_change (void)
4780 faked_omit_frame_pointer
= false;
4782 /* To omit leaf frame pointers, we need to turn flag_omit_frame_pointer on so
4783 that aarch64_frame_pointer_required will be called. We need to remember
4784 whether flag_omit_frame_pointer was turned on normally or just faked. */
4786 if (flag_omit_leaf_frame_pointer
&& !flag_omit_frame_pointer
)
4788 flag_omit_frame_pointer
= true;
4789 faked_omit_frame_pointer
= true;
4793 static struct machine_function
*
4794 aarch64_init_machine_status (void)
4796 struct machine_function
*machine
;
4797 machine
= ggc_alloc_cleared_machine_function ();
4802 aarch64_init_expanders (void)
4804 init_machine_status
= aarch64_init_machine_status
;
4807 /* A checking mechanism for the implementation of the various code models. */
4809 initialize_aarch64_code_model (void)
4813 switch (aarch64_cmodel_var
)
4815 case AARCH64_CMODEL_TINY
:
4816 aarch64_cmodel
= AARCH64_CMODEL_TINY_PIC
;
4818 case AARCH64_CMODEL_SMALL
:
4819 aarch64_cmodel
= AARCH64_CMODEL_SMALL_PIC
;
4821 case AARCH64_CMODEL_LARGE
:
4822 sorry ("code model %qs with -f%s", "large",
4823 flag_pic
> 1 ? "PIC" : "pic");
4829 aarch64_cmodel
= aarch64_cmodel_var
;
4832 /* Return true if SYMBOL_REF X binds locally. */
4835 aarch64_symbol_binds_local_p (const_rtx x
)
4837 return (SYMBOL_REF_DECL (x
)
4838 ? targetm
.binds_local_p (SYMBOL_REF_DECL (x
))
4839 : SYMBOL_REF_LOCAL_P (x
));
4842 /* Return true if SYMBOL_REF X is thread local */
4844 aarch64_tls_symbol_p (rtx x
)
4846 if (! TARGET_HAVE_TLS
)
4849 if (GET_CODE (x
) != SYMBOL_REF
)
4852 return SYMBOL_REF_TLS_MODEL (x
) != 0;
4855 /* Classify a TLS symbol into one of the TLS kinds. */
4856 enum aarch64_symbol_type
4857 aarch64_classify_tls_symbol (rtx x
)
4859 enum tls_model tls_kind
= tls_symbolic_operand_type (x
);
4863 case TLS_MODEL_GLOBAL_DYNAMIC
:
4864 case TLS_MODEL_LOCAL_DYNAMIC
:
4865 return TARGET_TLS_DESC
? SYMBOL_SMALL_TLSDESC
: SYMBOL_SMALL_TLSGD
;
4867 case TLS_MODEL_INITIAL_EXEC
:
4868 return SYMBOL_SMALL_GOTTPREL
;
4870 case TLS_MODEL_LOCAL_EXEC
:
4871 return SYMBOL_SMALL_TPREL
;
4873 case TLS_MODEL_EMULATED
:
4874 case TLS_MODEL_NONE
:
4875 return SYMBOL_FORCE_TO_MEM
;
4882 /* Return the method that should be used to access SYMBOL_REF or
4883 LABEL_REF X in context CONTEXT. */
4884 enum aarch64_symbol_type
4885 aarch64_classify_symbol (rtx x
,
4886 enum aarch64_symbol_context context ATTRIBUTE_UNUSED
)
4888 if (GET_CODE (x
) == LABEL_REF
)
4890 switch (aarch64_cmodel
)
4892 case AARCH64_CMODEL_LARGE
:
4893 return SYMBOL_FORCE_TO_MEM
;
4895 case AARCH64_CMODEL_TINY_PIC
:
4896 case AARCH64_CMODEL_TINY
:
4897 case AARCH64_CMODEL_SMALL_PIC
:
4898 case AARCH64_CMODEL_SMALL
:
4899 return SYMBOL_SMALL_ABSOLUTE
;
4906 gcc_assert (GET_CODE (x
) == SYMBOL_REF
);
4908 switch (aarch64_cmodel
)
4910 case AARCH64_CMODEL_LARGE
:
4911 return SYMBOL_FORCE_TO_MEM
;
4913 case AARCH64_CMODEL_TINY
:
4914 case AARCH64_CMODEL_SMALL
:
4916 /* This is needed to get DFmode, TImode constants to be loaded off
4917 the constant pool. Is it necessary to dump TImode values into
4918 the constant pool. We don't handle TImode constant loads properly
4919 yet and hence need to use the constant pool. */
4920 if (CONSTANT_POOL_ADDRESS_P (x
))
4921 return SYMBOL_FORCE_TO_MEM
;
4923 if (aarch64_tls_symbol_p (x
))
4924 return aarch64_classify_tls_symbol (x
);
4926 if (SYMBOL_REF_WEAK (x
))
4927 return SYMBOL_FORCE_TO_MEM
;
4929 return SYMBOL_SMALL_ABSOLUTE
;
4931 case AARCH64_CMODEL_TINY_PIC
:
4932 case AARCH64_CMODEL_SMALL_PIC
:
4934 if (CONSTANT_POOL_ADDRESS_P (x
))
4935 return SYMBOL_FORCE_TO_MEM
;
4937 if (aarch64_tls_symbol_p (x
))
4938 return aarch64_classify_tls_symbol (x
);
4940 if (!aarch64_symbol_binds_local_p (x
))
4941 return SYMBOL_SMALL_GOT
;
4943 return SYMBOL_SMALL_ABSOLUTE
;
4948 /* By default push everything into the constant pool. */
4949 return SYMBOL_FORCE_TO_MEM
;
4952 /* Return true if X is a symbolic constant that can be used in context
4953 CONTEXT. If it is, store the type of the symbol in *SYMBOL_TYPE. */
4956 aarch64_symbolic_constant_p (rtx x
, enum aarch64_symbol_context context
,
4957 enum aarch64_symbol_type
*symbol_type
)
4960 split_const (x
, &x
, &offset
);
4961 if (GET_CODE (x
) == SYMBOL_REF
|| GET_CODE (x
) == LABEL_REF
)
4962 *symbol_type
= aarch64_classify_symbol (x
, context
);
4966 /* No checking of offset at this point. */
4971 aarch64_constant_address_p (rtx x
)
4973 return (CONSTANT_P (x
) && memory_address_p (DImode
, x
));
4977 aarch64_legitimate_pic_operand_p (rtx x
)
4979 if (GET_CODE (x
) == SYMBOL_REF
4980 || (GET_CODE (x
) == CONST
4981 && GET_CODE (XEXP (x
, 0)) == PLUS
4982 && GET_CODE (XEXP (XEXP (x
, 0), 0)) == SYMBOL_REF
))
4989 aarch64_legitimate_constant_p (enum machine_mode mode
, rtx x
)
4991 /* Do not allow vector struct mode constants. We could support
4992 0 and -1 easily, but they need support in aarch64-simd.md. */
4993 if (TARGET_SIMD
&& aarch64_vect_struct_mode_p (mode
))
4996 /* This could probably go away because
4997 we now decompose CONST_INTs according to expand_mov_immediate. */
4998 if ((GET_CODE (x
) == CONST_VECTOR
4999 && aarch64_simd_valid_immediate (x
, mode
, false,
5000 NULL
, NULL
, NULL
, NULL
, NULL
) != -1)
5002 return !targetm
.cannot_force_const_mem (mode
, x
);
5004 if (GET_CODE (x
) == HIGH
5005 && aarch64_valid_symref (XEXP (x
, 0), GET_MODE (XEXP (x
, 0))))
5008 return aarch64_constant_address_p (x
);
5012 aarch64_init_builtins (void)
5015 init_aarch64_simd_builtins ();
5019 aarch64_load_tp (rtx target
)
5022 || GET_MODE (target
) != Pmode
5023 || !register_operand (target
, Pmode
))
5024 target
= gen_reg_rtx (Pmode
);
5026 /* Can return in any reg. */
5027 emit_insn (gen_aarch64_load_tp_hard (target
));
5031 /* Expand an expression EXP that calls a built-in function,
5032 with result going to TARGET if that's convenient. */
5034 aarch64_expand_builtin (tree exp
,
5036 rtx subtarget ATTRIBUTE_UNUSED
,
5037 enum machine_mode mode ATTRIBUTE_UNUSED
,
5038 int ignore ATTRIBUTE_UNUSED
)
5040 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
5041 int fcode
= DECL_FUNCTION_CODE (fndecl
);
5043 if (fcode
>= AARCH64_SIMD_BUILTIN_BASE
)
5044 return aarch64_simd_expand_builtin (fcode
, exp
, target
);
5049 /* On AAPCS systems, this is the "struct __va_list". */
5050 static GTY(()) tree va_list_type
;
5052 /* Implement TARGET_BUILD_BUILTIN_VA_LIST.
5053 Return the type to use as __builtin_va_list.
5055 AAPCS64 \S 7.1.4 requires that va_list be a typedef for a type defined as:
5067 aarch64_build_builtin_va_list (void)
5070 tree f_stack
, f_grtop
, f_vrtop
, f_groff
, f_vroff
;
5072 /* Create the type. */
5073 va_list_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
5074 /* Give it the required name. */
5075 va_list_name
= build_decl (BUILTINS_LOCATION
,
5077 get_identifier ("__va_list"),
5079 DECL_ARTIFICIAL (va_list_name
) = 1;
5080 TYPE_NAME (va_list_type
) = va_list_name
;
5082 /* Create the fields. */
5083 f_stack
= build_decl (BUILTINS_LOCATION
,
5084 FIELD_DECL
, get_identifier ("__stack"),
5086 f_grtop
= build_decl (BUILTINS_LOCATION
,
5087 FIELD_DECL
, get_identifier ("__gr_top"),
5089 f_vrtop
= build_decl (BUILTINS_LOCATION
,
5090 FIELD_DECL
, get_identifier ("__vr_top"),
5092 f_groff
= build_decl (BUILTINS_LOCATION
,
5093 FIELD_DECL
, get_identifier ("__gr_offs"),
5095 f_vroff
= build_decl (BUILTINS_LOCATION
,
5096 FIELD_DECL
, get_identifier ("__vr_offs"),
5099 DECL_ARTIFICIAL (f_stack
) = 1;
5100 DECL_ARTIFICIAL (f_grtop
) = 1;
5101 DECL_ARTIFICIAL (f_vrtop
) = 1;
5102 DECL_ARTIFICIAL (f_groff
) = 1;
5103 DECL_ARTIFICIAL (f_vroff
) = 1;
5105 DECL_FIELD_CONTEXT (f_stack
) = va_list_type
;
5106 DECL_FIELD_CONTEXT (f_grtop
) = va_list_type
;
5107 DECL_FIELD_CONTEXT (f_vrtop
) = va_list_type
;
5108 DECL_FIELD_CONTEXT (f_groff
) = va_list_type
;
5109 DECL_FIELD_CONTEXT (f_vroff
) = va_list_type
;
5111 TYPE_FIELDS (va_list_type
) = f_stack
;
5112 DECL_CHAIN (f_stack
) = f_grtop
;
5113 DECL_CHAIN (f_grtop
) = f_vrtop
;
5114 DECL_CHAIN (f_vrtop
) = f_groff
;
5115 DECL_CHAIN (f_groff
) = f_vroff
;
5117 /* Compute its layout. */
5118 layout_type (va_list_type
);
5120 return va_list_type
;
5123 /* Implement TARGET_EXPAND_BUILTIN_VA_START. */
5125 aarch64_expand_builtin_va_start (tree valist
, rtx nextarg ATTRIBUTE_UNUSED
)
5127 const CUMULATIVE_ARGS
*cum
;
5128 tree f_stack
, f_grtop
, f_vrtop
, f_groff
, f_vroff
;
5129 tree stack
, grtop
, vrtop
, groff
, vroff
;
5131 int gr_save_area_size
;
5132 int vr_save_area_size
;
5135 cum
= &crtl
->args
.info
;
5137 = (NUM_ARG_REGS
- cum
->aapcs_ncrn
) * UNITS_PER_WORD
;
5139 = (NUM_FP_ARG_REGS
- cum
->aapcs_nvrn
) * UNITS_PER_VREG
;
5141 if (TARGET_GENERAL_REGS_ONLY
)
5143 if (cum
->aapcs_nvrn
> 0)
5144 sorry ("%qs and floating point or vector arguments",
5145 "-mgeneral-regs-only");
5146 vr_save_area_size
= 0;
5149 f_stack
= TYPE_FIELDS (va_list_type_node
);
5150 f_grtop
= DECL_CHAIN (f_stack
);
5151 f_vrtop
= DECL_CHAIN (f_grtop
);
5152 f_groff
= DECL_CHAIN (f_vrtop
);
5153 f_vroff
= DECL_CHAIN (f_groff
);
5155 stack
= build3 (COMPONENT_REF
, TREE_TYPE (f_stack
), valist
, f_stack
,
5157 grtop
= build3 (COMPONENT_REF
, TREE_TYPE (f_grtop
), valist
, f_grtop
,
5159 vrtop
= build3 (COMPONENT_REF
, TREE_TYPE (f_vrtop
), valist
, f_vrtop
,
5161 groff
= build3 (COMPONENT_REF
, TREE_TYPE (f_groff
), valist
, f_groff
,
5163 vroff
= build3 (COMPONENT_REF
, TREE_TYPE (f_vroff
), valist
, f_vroff
,
5166 /* Emit code to initialize STACK, which points to the next varargs stack
5167 argument. CUM->AAPCS_STACK_SIZE gives the number of stack words used
5168 by named arguments. STACK is 8-byte aligned. */
5169 t
= make_tree (TREE_TYPE (stack
), virtual_incoming_args_rtx
);
5170 if (cum
->aapcs_stack_size
> 0)
5171 t
= fold_build_pointer_plus_hwi (t
, cum
->aapcs_stack_size
* UNITS_PER_WORD
);
5172 t
= build2 (MODIFY_EXPR
, TREE_TYPE (stack
), stack
, t
);
5173 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
5175 /* Emit code to initialize GRTOP, the top of the GR save area.
5176 virtual_incoming_args_rtx should have been 16 byte aligned. */
5177 t
= make_tree (TREE_TYPE (grtop
), virtual_incoming_args_rtx
);
5178 t
= build2 (MODIFY_EXPR
, TREE_TYPE (grtop
), grtop
, t
);
5179 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
5181 /* Emit code to initialize VRTOP, the top of the VR save area.
5182 This address is gr_save_area_bytes below GRTOP, rounded
5183 down to the next 16-byte boundary. */
5184 t
= make_tree (TREE_TYPE (vrtop
), virtual_incoming_args_rtx
);
5185 vr_offset
= AARCH64_ROUND_UP (gr_save_area_size
,
5186 STACK_BOUNDARY
/ BITS_PER_UNIT
);
5189 t
= fold_build_pointer_plus_hwi (t
, -vr_offset
);
5190 t
= build2 (MODIFY_EXPR
, TREE_TYPE (vrtop
), vrtop
, t
);
5191 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
5193 /* Emit code to initialize GROFF, the offset from GRTOP of the
5194 next GPR argument. */
5195 t
= build2 (MODIFY_EXPR
, TREE_TYPE (groff
), groff
,
5196 build_int_cst (TREE_TYPE (groff
), -gr_save_area_size
));
5197 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
5199 /* Likewise emit code to initialize VROFF, the offset from FTOP
5200 of the next VR argument. */
5201 t
= build2 (MODIFY_EXPR
, TREE_TYPE (vroff
), vroff
,
5202 build_int_cst (TREE_TYPE (vroff
), -vr_save_area_size
));
5203 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
5206 /* Implement TARGET_GIMPLIFY_VA_ARG_EXPR. */
5209 aarch64_gimplify_va_arg_expr (tree valist
, tree type
, gimple_seq
*pre_p
,
5210 gimple_seq
*post_p ATTRIBUTE_UNUSED
)
5214 bool is_ha
; /* is HFA or HVA. */
5215 bool dw_align
; /* double-word align. */
5216 enum machine_mode ag_mode
= VOIDmode
;
5218 enum machine_mode mode
;
5220 tree f_stack
, f_grtop
, f_vrtop
, f_groff
, f_vroff
;
5221 tree stack
, f_top
, f_off
, off
, arg
, roundup
, on_stack
;
5222 HOST_WIDE_INT size
, rsize
, adjust
, align
;
5223 tree t
, u
, cond1
, cond2
;
5225 indirect_p
= pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
5227 type
= build_pointer_type (type
);
5229 mode
= TYPE_MODE (type
);
5231 f_stack
= TYPE_FIELDS (va_list_type_node
);
5232 f_grtop
= DECL_CHAIN (f_stack
);
5233 f_vrtop
= DECL_CHAIN (f_grtop
);
5234 f_groff
= DECL_CHAIN (f_vrtop
);
5235 f_vroff
= DECL_CHAIN (f_groff
);
5237 stack
= build3 (COMPONENT_REF
, TREE_TYPE (f_stack
), unshare_expr (valist
),
5238 f_stack
, NULL_TREE
);
5239 size
= int_size_in_bytes (type
);
5240 align
= aarch64_function_arg_alignment (mode
, type
) / BITS_PER_UNIT
;
5244 if (aarch64_vfp_is_call_or_return_candidate (mode
,
5250 /* TYPE passed in fp/simd registers. */
5251 if (TARGET_GENERAL_REGS_ONLY
)
5252 sorry ("%qs and floating point or vector arguments",
5253 "-mgeneral-regs-only");
5255 f_top
= build3 (COMPONENT_REF
, TREE_TYPE (f_vrtop
),
5256 unshare_expr (valist
), f_vrtop
, NULL_TREE
);
5257 f_off
= build3 (COMPONENT_REF
, TREE_TYPE (f_vroff
),
5258 unshare_expr (valist
), f_vroff
, NULL_TREE
);
5260 rsize
= nregs
* UNITS_PER_VREG
;
5264 if (BYTES_BIG_ENDIAN
&& GET_MODE_SIZE (ag_mode
) < UNITS_PER_VREG
)
5265 adjust
= UNITS_PER_VREG
- GET_MODE_SIZE (ag_mode
);
5267 else if (BLOCK_REG_PADDING (mode
, type
, 1) == downward
5268 && size
< UNITS_PER_VREG
)
5270 adjust
= UNITS_PER_VREG
- size
;
5275 /* TYPE passed in general registers. */
5276 f_top
= build3 (COMPONENT_REF
, TREE_TYPE (f_grtop
),
5277 unshare_expr (valist
), f_grtop
, NULL_TREE
);
5278 f_off
= build3 (COMPONENT_REF
, TREE_TYPE (f_groff
),
5279 unshare_expr (valist
), f_groff
, NULL_TREE
);
5280 rsize
= (size
+ UNITS_PER_WORD
- 1) & -UNITS_PER_WORD
;
5281 nregs
= rsize
/ UNITS_PER_WORD
;
5286 if (BLOCK_REG_PADDING (mode
, type
, 1) == downward
5287 && size
< UNITS_PER_WORD
)
5289 adjust
= UNITS_PER_WORD
- size
;
5293 /* Get a local temporary for the field value. */
5294 off
= get_initialized_tmp_var (f_off
, pre_p
, NULL
);
5296 /* Emit code to branch if off >= 0. */
5297 t
= build2 (GE_EXPR
, boolean_type_node
, off
,
5298 build_int_cst (TREE_TYPE (off
), 0));
5299 cond1
= build3 (COND_EXPR
, ptr_type_node
, t
, NULL_TREE
, NULL_TREE
);
5303 /* Emit: offs = (offs + 15) & -16. */
5304 t
= build2 (PLUS_EXPR
, TREE_TYPE (off
), off
,
5305 build_int_cst (TREE_TYPE (off
), 15));
5306 t
= build2 (BIT_AND_EXPR
, TREE_TYPE (off
), t
,
5307 build_int_cst (TREE_TYPE (off
), -16));
5308 roundup
= build2 (MODIFY_EXPR
, TREE_TYPE (off
), off
, t
);
5313 /* Update ap.__[g|v]r_offs */
5314 t
= build2 (PLUS_EXPR
, TREE_TYPE (off
), off
,
5315 build_int_cst (TREE_TYPE (off
), rsize
));
5316 t
= build2 (MODIFY_EXPR
, TREE_TYPE (f_off
), unshare_expr (f_off
), t
);
5320 t
= build2 (COMPOUND_EXPR
, TREE_TYPE (t
), roundup
, t
);
5322 /* [cond2] if (ap.__[g|v]r_offs > 0) */
5323 u
= build2 (GT_EXPR
, boolean_type_node
, unshare_expr (f_off
),
5324 build_int_cst (TREE_TYPE (f_off
), 0));
5325 cond2
= build3 (COND_EXPR
, ptr_type_node
, u
, NULL_TREE
, NULL_TREE
);
5327 /* String up: make sure the assignment happens before the use. */
5328 t
= build2 (COMPOUND_EXPR
, TREE_TYPE (cond2
), t
, cond2
);
5329 COND_EXPR_ELSE (cond1
) = t
;
5331 /* Prepare the trees handling the argument that is passed on the stack;
5332 the top level node will store in ON_STACK. */
5333 arg
= get_initialized_tmp_var (stack
, pre_p
, NULL
);
5336 /* if (alignof(type) > 8) (arg = arg + 15) & -16; */
5337 t
= fold_convert (intDI_type_node
, arg
);
5338 t
= build2 (PLUS_EXPR
, TREE_TYPE (t
), t
,
5339 build_int_cst (TREE_TYPE (t
), 15));
5340 t
= build2 (BIT_AND_EXPR
, TREE_TYPE (t
), t
,
5341 build_int_cst (TREE_TYPE (t
), -16));
5342 t
= fold_convert (TREE_TYPE (arg
), t
);
5343 roundup
= build2 (MODIFY_EXPR
, TREE_TYPE (arg
), arg
, t
);
5347 /* Advance ap.__stack */
5348 t
= fold_convert (intDI_type_node
, arg
);
5349 t
= build2 (PLUS_EXPR
, TREE_TYPE (t
), t
,
5350 build_int_cst (TREE_TYPE (t
), size
+ 7));
5351 t
= build2 (BIT_AND_EXPR
, TREE_TYPE (t
), t
,
5352 build_int_cst (TREE_TYPE (t
), -8));
5353 t
= fold_convert (TREE_TYPE (arg
), t
);
5354 t
= build2 (MODIFY_EXPR
, TREE_TYPE (stack
), unshare_expr (stack
), t
);
5355 /* String up roundup and advance. */
5357 t
= build2 (COMPOUND_EXPR
, TREE_TYPE (t
), roundup
, t
);
5358 /* String up with arg */
5359 on_stack
= build2 (COMPOUND_EXPR
, TREE_TYPE (arg
), t
, arg
);
5360 /* Big-endianness related address adjustment. */
5361 if (BLOCK_REG_PADDING (mode
, type
, 1) == downward
5362 && size
< UNITS_PER_WORD
)
5364 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (arg
), arg
,
5365 size_int (UNITS_PER_WORD
- size
));
5366 on_stack
= build2 (COMPOUND_EXPR
, TREE_TYPE (arg
), on_stack
, t
);
5369 COND_EXPR_THEN (cond1
) = unshare_expr (on_stack
);
5370 COND_EXPR_THEN (cond2
) = unshare_expr (on_stack
);
5372 /* Adjustment to OFFSET in the case of BIG_ENDIAN. */
5375 t
= build2 (PREINCREMENT_EXPR
, TREE_TYPE (off
), off
,
5376 build_int_cst (TREE_TYPE (off
), adjust
));
5378 t
= fold_convert (sizetype
, t
);
5379 t
= build2 (POINTER_PLUS_EXPR
, TREE_TYPE (f_top
), f_top
, t
);
5383 /* type ha; // treat as "struct {ftype field[n];}"
5384 ... [computing offs]
5385 for (i = 0; i <nregs; ++i, offs += 16)
5386 ha.field[i] = *((ftype *)(ap.__vr_top + offs));
5389 tree tmp_ha
, field_t
, field_ptr_t
;
5391 /* Declare a local variable. */
5392 tmp_ha
= create_tmp_var_raw (type
, "ha");
5393 gimple_add_tmp_var (tmp_ha
);
5395 /* Establish the base type. */
5399 field_t
= float_type_node
;
5400 field_ptr_t
= float_ptr_type_node
;
5403 field_t
= double_type_node
;
5404 field_ptr_t
= double_ptr_type_node
;
5407 field_t
= long_double_type_node
;
5408 field_ptr_t
= long_double_ptr_type_node
;
5410 /* The half precision and quad precision are not fully supported yet. Enable
5411 the following code after the support is complete. Need to find the correct
5412 type node for __fp16 *. */
5415 field_t
= float_type_node
;
5416 field_ptr_t
= float_ptr_type_node
;
5422 tree innertype
= make_signed_type (GET_MODE_PRECISION (SImode
));
5423 field_t
= build_vector_type_for_mode (innertype
, ag_mode
);
5424 field_ptr_t
= build_pointer_type (field_t
);
5431 /* *(field_ptr_t)&ha = *((field_ptr_t)vr_saved_area */
5432 tmp_ha
= build1 (ADDR_EXPR
, field_ptr_t
, tmp_ha
);
5434 t
= fold_convert (field_ptr_t
, addr
);
5435 t
= build2 (MODIFY_EXPR
, field_t
,
5436 build1 (INDIRECT_REF
, field_t
, tmp_ha
),
5437 build1 (INDIRECT_REF
, field_t
, t
));
5439 /* ha.field[i] = *((field_ptr_t)vr_saved_area + i) */
5440 for (i
= 1; i
< nregs
; ++i
)
5442 addr
= fold_build_pointer_plus_hwi (addr
, UNITS_PER_VREG
);
5443 u
= fold_convert (field_ptr_t
, addr
);
5444 u
= build2 (MODIFY_EXPR
, field_t
,
5445 build2 (MEM_REF
, field_t
, tmp_ha
,
5446 build_int_cst (field_ptr_t
,
5448 int_size_in_bytes (field_t
)))),
5449 build1 (INDIRECT_REF
, field_t
, u
));
5450 t
= build2 (COMPOUND_EXPR
, TREE_TYPE (t
), t
, u
);
5453 u
= fold_convert (TREE_TYPE (f_top
), tmp_ha
);
5454 t
= build2 (COMPOUND_EXPR
, TREE_TYPE (f_top
), t
, u
);
5457 COND_EXPR_ELSE (cond2
) = t
;
5458 addr
= fold_convert (build_pointer_type (type
), cond1
);
5459 addr
= build_va_arg_indirect_ref (addr
);
5462 addr
= build_va_arg_indirect_ref (addr
);
5467 /* Implement TARGET_SETUP_INCOMING_VARARGS. */
5470 aarch64_setup_incoming_varargs (cumulative_args_t cum_v
, enum machine_mode mode
,
5471 tree type
, int *pretend_size ATTRIBUTE_UNUSED
,
5474 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
5475 CUMULATIVE_ARGS local_cum
;
5476 int gr_saved
, vr_saved
;
5478 /* The caller has advanced CUM up to, but not beyond, the last named
5479 argument. Advance a local copy of CUM past the last "real" named
5480 argument, to find out how many registers are left over. */
5482 aarch64_function_arg_advance (pack_cumulative_args(&local_cum
), mode
, type
, true);
5484 /* Found out how many registers we need to save. */
5485 gr_saved
= NUM_ARG_REGS
- local_cum
.aapcs_ncrn
;
5486 vr_saved
= NUM_FP_ARG_REGS
- local_cum
.aapcs_nvrn
;
5488 if (TARGET_GENERAL_REGS_ONLY
)
5490 if (local_cum
.aapcs_nvrn
> 0)
5491 sorry ("%qs and floating point or vector arguments",
5492 "-mgeneral-regs-only");
5502 /* virtual_incoming_args_rtx should have been 16-byte aligned. */
5503 ptr
= plus_constant (Pmode
, virtual_incoming_args_rtx
,
5504 - gr_saved
* UNITS_PER_WORD
);
5505 mem
= gen_frame_mem (BLKmode
, ptr
);
5506 set_mem_alias_set (mem
, get_varargs_alias_set ());
5508 move_block_from_reg (local_cum
.aapcs_ncrn
+ R0_REGNUM
,
5513 /* We can't use move_block_from_reg, because it will use
5514 the wrong mode, storing D regs only. */
5515 enum machine_mode mode
= TImode
;
5518 /* Set OFF to the offset from virtual_incoming_args_rtx of
5519 the first vector register. The VR save area lies below
5520 the GR one, and is aligned to 16 bytes. */
5521 off
= -AARCH64_ROUND_UP (gr_saved
* UNITS_PER_WORD
,
5522 STACK_BOUNDARY
/ BITS_PER_UNIT
);
5523 off
-= vr_saved
* UNITS_PER_VREG
;
5525 for (i
= local_cum
.aapcs_nvrn
; i
< NUM_FP_ARG_REGS
; ++i
)
5529 ptr
= plus_constant (Pmode
, virtual_incoming_args_rtx
, off
);
5530 mem
= gen_frame_mem (mode
, ptr
);
5531 set_mem_alias_set (mem
, get_varargs_alias_set ());
5532 aarch64_emit_move (mem
, gen_rtx_REG (mode
, V0_REGNUM
+ i
));
5533 off
+= UNITS_PER_VREG
;
5538 /* We don't save the size into *PRETEND_SIZE because we want to avoid
5539 any complication of having crtl->args.pretend_args_size changed. */
5540 cfun
->machine
->saved_varargs_size
5541 = (AARCH64_ROUND_UP (gr_saved
* UNITS_PER_WORD
,
5542 STACK_BOUNDARY
/ BITS_PER_UNIT
)
5543 + vr_saved
* UNITS_PER_VREG
);
5547 aarch64_conditional_register_usage (void)
5552 for (i
= V0_REGNUM
; i
<= V31_REGNUM
; i
++)
5555 call_used_regs
[i
] = 1;
5560 /* Walk down the type tree of TYPE counting consecutive base elements.
5561 If *MODEP is VOIDmode, then set it to the first valid floating point
5562 type. If a non-floating point type is found, or if a floating point
5563 type that doesn't match a non-VOIDmode *MODEP is found, then return -1,
5564 otherwise return the count in the sub-tree. */
5566 aapcs_vfp_sub_candidate (const_tree type
, enum machine_mode
*modep
)
5568 enum machine_mode mode
;
5571 switch (TREE_CODE (type
))
5574 mode
= TYPE_MODE (type
);
5575 if (mode
!= DFmode
&& mode
!= SFmode
&& mode
!= TFmode
)
5578 if (*modep
== VOIDmode
)
5587 mode
= TYPE_MODE (TREE_TYPE (type
));
5588 if (mode
!= DFmode
&& mode
!= SFmode
&& mode
!= TFmode
)
5591 if (*modep
== VOIDmode
)
5600 /* Use V2SImode and V4SImode as representatives of all 64-bit
5601 and 128-bit vector types. */
5602 size
= int_size_in_bytes (type
);
5615 if (*modep
== VOIDmode
)
5618 /* Vector modes are considered to be opaque: two vectors are
5619 equivalent for the purposes of being homogeneous aggregates
5620 if they are the same size. */
5629 tree index
= TYPE_DOMAIN (type
);
5631 /* Can't handle incomplete types. */
5632 if (!COMPLETE_TYPE_P (type
))
5635 count
= aapcs_vfp_sub_candidate (TREE_TYPE (type
), modep
);
5638 || !TYPE_MAX_VALUE (index
)
5639 || !host_integerp (TYPE_MAX_VALUE (index
), 1)
5640 || !TYPE_MIN_VALUE (index
)
5641 || !host_integerp (TYPE_MIN_VALUE (index
), 1)
5645 count
*= (1 + tree_low_cst (TYPE_MAX_VALUE (index
), 1)
5646 - tree_low_cst (TYPE_MIN_VALUE (index
), 1));
5648 /* There must be no padding. */
5649 if (!host_integerp (TYPE_SIZE (type
), 1)
5650 || (tree_low_cst (TYPE_SIZE (type
), 1)
5651 != count
* GET_MODE_BITSIZE (*modep
)))
5663 /* Can't handle incomplete types. */
5664 if (!COMPLETE_TYPE_P (type
))
5667 for (field
= TYPE_FIELDS (type
); field
; field
= TREE_CHAIN (field
))
5669 if (TREE_CODE (field
) != FIELD_DECL
)
5672 sub_count
= aapcs_vfp_sub_candidate (TREE_TYPE (field
), modep
);
5678 /* There must be no padding. */
5679 if (!host_integerp (TYPE_SIZE (type
), 1)
5680 || (tree_low_cst (TYPE_SIZE (type
), 1)
5681 != count
* GET_MODE_BITSIZE (*modep
)))
5688 case QUAL_UNION_TYPE
:
5690 /* These aren't very interesting except in a degenerate case. */
5695 /* Can't handle incomplete types. */
5696 if (!COMPLETE_TYPE_P (type
))
5699 for (field
= TYPE_FIELDS (type
); field
; field
= TREE_CHAIN (field
))
5701 if (TREE_CODE (field
) != FIELD_DECL
)
5704 sub_count
= aapcs_vfp_sub_candidate (TREE_TYPE (field
), modep
);
5707 count
= count
> sub_count
? count
: sub_count
;
5710 /* There must be no padding. */
5711 if (!host_integerp (TYPE_SIZE (type
), 1)
5712 || (tree_low_cst (TYPE_SIZE (type
), 1)
5713 != count
* GET_MODE_BITSIZE (*modep
)))
5726 /* Return TRUE if the type, as described by TYPE and MODE, is a composite
5727 type as described in AAPCS64 \S 4.3. This includes aggregate, union and
5728 array types. The C99 floating-point complex types are also considered
5729 as composite types, according to AAPCS64 \S 7.1.1. The complex integer
5730 types, which are GCC extensions and out of the scope of AAPCS64, are
5731 treated as composite types here as well.
5733 Note that MODE itself is not sufficient in determining whether a type
5734 is such a composite type or not. This is because
5735 stor-layout.c:compute_record_mode may have already changed the MODE
5736 (BLKmode) of a RECORD_TYPE TYPE to some other mode. For example, a
5737 structure with only one field may have its MODE set to the mode of the
5738 field. Also an integer mode whose size matches the size of the
5739 RECORD_TYPE type may be used to substitute the original mode
5740 (i.e. BLKmode) in certain circumstances. In other words, MODE cannot be
5741 solely relied on. */
5744 aarch64_composite_type_p (const_tree type
,
5745 enum machine_mode mode
)
5747 if (type
&& (AGGREGATE_TYPE_P (type
) || TREE_CODE (type
) == COMPLEX_TYPE
))
5751 || GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
5752 || GET_MODE_CLASS (mode
) == MODE_COMPLEX_INT
)
5758 /* Return TRUE if the type, as described by TYPE and MODE, is a short vector
5759 type as described in AAPCS64 \S 4.1.2.
5761 See the comment above aarch64_composite_type_p for the notes on MODE. */
5764 aarch64_short_vector_p (const_tree type
,
5765 enum machine_mode mode
)
5767 HOST_WIDE_INT size
= -1;
5769 if (type
&& TREE_CODE (type
) == VECTOR_TYPE
)
5770 size
= int_size_in_bytes (type
);
5771 else if (!aarch64_composite_type_p (type
, mode
)
5772 && (GET_MODE_CLASS (mode
) == MODE_VECTOR_INT
5773 || GET_MODE_CLASS (mode
) == MODE_VECTOR_FLOAT
))
5774 size
= GET_MODE_SIZE (mode
);
5776 return (size
== 8 || size
== 16) ? true : false;
5779 /* Return TRUE if an argument, whose type is described by TYPE and MODE,
5780 shall be passed or returned in simd/fp register(s) (providing these
5781 parameter passing registers are available).
5783 Upon successful return, *COUNT returns the number of needed registers,
5784 *BASE_MODE returns the mode of the individual register and when IS_HAF
5785 is not NULL, *IS_HA indicates whether or not the argument is a homogeneous
5786 floating-point aggregate or a homogeneous short-vector aggregate. */
5789 aarch64_vfp_is_call_or_return_candidate (enum machine_mode mode
,
5791 enum machine_mode
*base_mode
,
5795 enum machine_mode new_mode
= VOIDmode
;
5796 bool composite_p
= aarch64_composite_type_p (type
, mode
);
5798 if (is_ha
!= NULL
) *is_ha
= false;
5800 if ((!composite_p
&& GET_MODE_CLASS (mode
) == MODE_FLOAT
)
5801 || aarch64_short_vector_p (type
, mode
))
5806 else if (GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
)
5808 if (is_ha
!= NULL
) *is_ha
= true;
5810 new_mode
= GET_MODE_INNER (mode
);
5812 else if (type
&& composite_p
)
5814 int ag_count
= aapcs_vfp_sub_candidate (type
, &new_mode
);
5816 if (ag_count
> 0 && ag_count
<= HA_MAX_NUM_FLDS
)
5818 if (is_ha
!= NULL
) *is_ha
= true;
5827 *base_mode
= new_mode
;
5831 /* Implement TARGET_STRUCT_VALUE_RTX. */
5834 aarch64_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED
,
5835 int incoming ATTRIBUTE_UNUSED
)
5837 return gen_rtx_REG (Pmode
, AARCH64_STRUCT_VALUE_REGNUM
);
5840 /* Implements target hook vector_mode_supported_p. */
5842 aarch64_vector_mode_supported_p (enum machine_mode mode
)
5845 && (mode
== V4SImode
|| mode
== V8HImode
5846 || mode
== V16QImode
|| mode
== V2DImode
5847 || mode
== V2SImode
|| mode
== V4HImode
5848 || mode
== V8QImode
|| mode
== V2SFmode
5849 || mode
== V4SFmode
|| mode
== V2DFmode
))
5855 /* Return quad mode as the preferred SIMD mode. */
5856 static enum machine_mode
5857 aarch64_preferred_simd_mode (enum machine_mode mode
)
5881 /* Return the equivalent letter for size. */
5882 static unsigned char
5883 sizetochar (int size
)
5887 case 64: return 'd';
5888 case 32: return 's';
5889 case 16: return 'h';
5890 case 8 : return 'b';
5891 default: gcc_unreachable ();
5896 aarch64_simd_valid_immediate (rtx op
, enum machine_mode mode
, int inverse
,
5897 rtx
*modconst
, int *elementwidth
,
5898 unsigned char *elementchar
,
5899 int *mvn
, int *shift
)
5901 #define CHECK(STRIDE, ELSIZE, CLASS, TEST, SHIFT, NEG) \
5903 for (i = 0; i < idx; i += (STRIDE)) \
5908 immtype = (CLASS); \
5909 elsize = (ELSIZE); \
5910 elchar = sizetochar (elsize); \
5916 unsigned int i
, elsize
= 0, idx
= 0, n_elts
= CONST_VECTOR_NUNITS (op
);
5917 unsigned int innersize
= GET_MODE_SIZE (GET_MODE_INNER (mode
));
5918 unsigned char bytes
[16];
5919 unsigned char elchar
= 0;
5920 int immtype
= -1, matches
;
5921 unsigned int invmask
= inverse
? 0xff : 0;
5924 /* TODO: Vectors of float constants. */
5925 if (GET_MODE_CLASS (mode
) == MODE_VECTOR_FLOAT
)
5928 /* Splat vector constant out into a byte vector. */
5929 for (i
= 0; i
< n_elts
; i
++)
5931 rtx el
= CONST_VECTOR_ELT (op
, i
);
5932 unsigned HOST_WIDE_INT elpart
;
5933 unsigned int part
, parts
;
5935 if (GET_CODE (el
) == CONST_INT
)
5937 elpart
= INTVAL (el
);
5940 else if (GET_CODE (el
) == CONST_DOUBLE
)
5942 elpart
= CONST_DOUBLE_LOW (el
);
5948 for (part
= 0; part
< parts
; part
++)
5951 for (byte
= 0; byte
< innersize
; byte
++)
5953 bytes
[idx
++] = (elpart
& 0xff) ^ invmask
;
5954 elpart
>>= BITS_PER_UNIT
;
5956 if (GET_CODE (el
) == CONST_DOUBLE
)
5957 elpart
= CONST_DOUBLE_HIGH (el
);
5962 gcc_assert (idx
== GET_MODE_SIZE (mode
));
5966 CHECK (4, 32, 0, bytes
[i
] == bytes
[0] && bytes
[i
+ 1] == 0
5967 && bytes
[i
+ 2] == 0 && bytes
[i
+ 3] == 0, 0, 0);
5969 CHECK (4, 32, 1, bytes
[i
] == 0 && bytes
[i
+ 1] == bytes
[1]
5970 && bytes
[i
+ 2] == 0 && bytes
[i
+ 3] == 0, 8, 0);
5972 CHECK (4, 32, 2, bytes
[i
] == 0 && bytes
[i
+ 1] == 0
5973 && bytes
[i
+ 2] == bytes
[2] && bytes
[i
+ 3] == 0, 16, 0);
5975 CHECK (4, 32, 3, bytes
[i
] == 0 && bytes
[i
+ 1] == 0
5976 && bytes
[i
+ 2] == 0 && bytes
[i
+ 3] == bytes
[3], 24, 0);
5978 CHECK (2, 16, 4, bytes
[i
] == bytes
[0] && bytes
[i
+ 1] == 0, 0, 0);
5980 CHECK (2, 16, 5, bytes
[i
] == 0 && bytes
[i
+ 1] == bytes
[1], 8, 0);
5982 CHECK (4, 32, 6, bytes
[i
] == bytes
[0] && bytes
[i
+ 1] == 0xff
5983 && bytes
[i
+ 2] == 0xff && bytes
[i
+ 3] == 0xff, 0, 1);
5985 CHECK (4, 32, 7, bytes
[i
] == 0xff && bytes
[i
+ 1] == bytes
[1]
5986 && bytes
[i
+ 2] == 0xff && bytes
[i
+ 3] == 0xff, 8, 1);
5988 CHECK (4, 32, 8, bytes
[i
] == 0xff && bytes
[i
+ 1] == 0xff
5989 && bytes
[i
+ 2] == bytes
[2] && bytes
[i
+ 3] == 0xff, 16, 1);
5991 CHECK (4, 32, 9, bytes
[i
] == 0xff && bytes
[i
+ 1] == 0xff
5992 && bytes
[i
+ 2] == 0xff && bytes
[i
+ 3] == bytes
[3], 24, 1);
5994 CHECK (2, 16, 10, bytes
[i
] == bytes
[0] && bytes
[i
+ 1] == 0xff, 0, 1);
5996 CHECK (2, 16, 11, bytes
[i
] == 0xff && bytes
[i
+ 1] == bytes
[1], 8, 1);
5998 CHECK (4, 32, 12, bytes
[i
] == 0xff && bytes
[i
+ 1] == bytes
[1]
5999 && bytes
[i
+ 2] == 0 && bytes
[i
+ 3] == 0, 0, 0);
6001 CHECK (4, 32, 13, bytes
[i
] == 0 && bytes
[i
+ 1] == bytes
[1]
6002 && bytes
[i
+ 2] == 0xff && bytes
[i
+ 3] == 0xff, 0, 1);
6004 CHECK (4, 32, 14, bytes
[i
] == 0xff && bytes
[i
+ 1] == 0xff
6005 && bytes
[i
+ 2] == bytes
[2] && bytes
[i
+ 3] == 0, 0, 0);
6007 CHECK (4, 32, 15, bytes
[i
] == 0 && bytes
[i
+ 1] == 0
6008 && bytes
[i
+ 2] == bytes
[2] && bytes
[i
+ 3] == 0xff, 0, 1);
6010 CHECK (1, 8, 16, bytes
[i
] == bytes
[0], 0, 0);
6012 CHECK (1, 64, 17, (bytes
[i
] == 0 || bytes
[i
] == 0xff)
6013 && bytes
[i
] == bytes
[(i
+ 8) % idx
], 0, 0);
6017 /* TODO: Currently the assembler cannot handle types 12 to 15.
6018 And there is no way to specify cmode through the compiler.
6019 Disable them till there is support in the assembler. */
6021 || (immtype
>= 12 && immtype
<= 15)
6027 *elementwidth
= elsize
;
6030 *elementchar
= elchar
;
6040 unsigned HOST_WIDE_INT imm
= 0;
6042 /* Un-invert bytes of recognized vector, if necessary. */
6044 for (i
= 0; i
< idx
; i
++)
6045 bytes
[i
] ^= invmask
;
6049 /* FIXME: Broken on 32-bit H_W_I hosts. */
6050 gcc_assert (sizeof (HOST_WIDE_INT
) == 8);
6052 for (i
= 0; i
< 8; i
++)
6053 imm
|= (unsigned HOST_WIDE_INT
) (bytes
[i
] ? 0xff : 0)
6054 << (i
* BITS_PER_UNIT
);
6056 *modconst
= GEN_INT (imm
);
6060 unsigned HOST_WIDE_INT imm
= 0;
6062 for (i
= 0; i
< elsize
/ BITS_PER_UNIT
; i
++)
6063 imm
|= (unsigned HOST_WIDE_INT
) bytes
[i
] << (i
* BITS_PER_UNIT
);
6065 /* Construct 'abcdefgh' because the assembler cannot handle
6066 generic constants. */
6067 gcc_assert (shift
!= NULL
&& mvn
!= NULL
);
6070 imm
= (imm
>> *shift
) & 0xff;
6071 *modconst
= GEN_INT (imm
);
6079 /* Return TRUE if rtx X is legal for use as either a AdvSIMD MOVI instruction
6080 (or, implicitly, MVNI) immediate. Write back width per element
6081 to *ELEMENTWIDTH (or zero for float elements), and a modified constant
6082 (whatever should be output for a MOVI instruction) in *MODCONST. */
6084 aarch64_simd_immediate_valid_for_move (rtx op
, enum machine_mode mode
,
6085 rtx
*modconst
, int *elementwidth
,
6086 unsigned char *elementchar
,
6087 int *mvn
, int *shift
)
6091 unsigned char tmpwidthc
;
6092 int tmpmvn
= 0, tmpshift
= 0;
6093 int retval
= aarch64_simd_valid_immediate (op
, mode
, 0, &tmpconst
,
6094 &tmpwidth
, &tmpwidthc
,
6095 &tmpmvn
, &tmpshift
);
6101 *modconst
= tmpconst
;
6104 *elementwidth
= tmpwidth
;
6107 *elementchar
= tmpwidthc
;
6119 aarch64_const_vec_all_same_int_p (rtx x
,
6120 HOST_WIDE_INT minval
,
6121 HOST_WIDE_INT maxval
)
6123 HOST_WIDE_INT firstval
;
6126 if (GET_CODE (x
) != CONST_VECTOR
6127 || GET_MODE_CLASS (GET_MODE (x
)) != MODE_VECTOR_INT
)
6130 firstval
= INTVAL (CONST_VECTOR_ELT (x
, 0));
6131 if (firstval
< minval
|| firstval
> maxval
)
6134 count
= CONST_VECTOR_NUNITS (x
);
6135 for (i
= 1; i
< count
; i
++)
6136 if (INTVAL (CONST_VECTOR_ELT (x
, i
)) != firstval
)
6142 /* Check of immediate shift constants are within range. */
6144 aarch64_simd_shift_imm_p (rtx x
, enum machine_mode mode
, bool left
)
6146 int bit_width
= GET_MODE_UNIT_SIZE (mode
) * BITS_PER_UNIT
;
6148 return aarch64_const_vec_all_same_int_p (x
, 0, bit_width
- 1);
6150 return aarch64_const_vec_all_same_int_p (x
, 1, bit_width
);
6154 aarch64_simd_imm_zero_p (rtx x
, enum machine_mode mode
)
6159 if (GET_CODE (x
) != CONST_VECTOR
)
6162 nunits
= GET_MODE_NUNITS (mode
);
6164 for (i
= 0; i
< nunits
; i
++)
6165 if (INTVAL (CONST_VECTOR_ELT (x
, i
)) != 0)
6172 aarch64_simd_imm_scalar_p (rtx x
, enum machine_mode mode ATTRIBUTE_UNUSED
)
6174 HOST_WIDE_INT imm
= INTVAL (x
);
6177 for (i
= 0; i
< 8; i
++)
6179 unsigned int byte
= imm
& 0xff;
6180 if (byte
!= 0xff && byte
!= 0)
6188 /* Return a const_int vector of VAL. */
6190 aarch64_simd_gen_const_vector_dup (enum machine_mode mode
, int val
)
6192 int nunits
= GET_MODE_NUNITS (mode
);
6193 rtvec v
= rtvec_alloc (nunits
);
6196 for (i
=0; i
< nunits
; i
++)
6197 RTVEC_ELT (v
, i
) = GEN_INT (val
);
6199 return gen_rtx_CONST_VECTOR (mode
, v
);
6202 /* Construct and return a PARALLEL RTX vector. */
6204 aarch64_simd_vect_par_cnst_half (enum machine_mode mode
, bool high
)
6206 int nunits
= GET_MODE_NUNITS (mode
);
6207 rtvec v
= rtvec_alloc (nunits
/ 2);
6208 int base
= high
? nunits
/ 2 : 0;
6212 for (i
=0; i
< nunits
/ 2; i
++)
6213 RTVEC_ELT (v
, i
) = GEN_INT (base
+ i
);
6215 t1
= gen_rtx_PARALLEL (mode
, v
);
6219 /* Bounds-check lanes. Ensure OPERAND lies between LOW (inclusive) and
6220 HIGH (exclusive). */
6222 aarch64_simd_lane_bounds (rtx operand
, HOST_WIDE_INT low
, HOST_WIDE_INT high
)
6225 gcc_assert (GET_CODE (operand
) == CONST_INT
);
6226 lane
= INTVAL (operand
);
6228 if (lane
< low
|| lane
>= high
)
6229 error ("lane out of range");
6233 aarch64_simd_const_bounds (rtx operand
, HOST_WIDE_INT low
, HOST_WIDE_INT high
)
6235 gcc_assert (GET_CODE (operand
) == CONST_INT
);
6236 HOST_WIDE_INT lane
= INTVAL (operand
);
6238 if (lane
< low
|| lane
>= high
)
6239 error ("constant out of range");
6242 /* Emit code to reinterpret one AdvSIMD type as another,
6243 without altering bits. */
6245 aarch64_simd_reinterpret (rtx dest
, rtx src
)
6247 emit_move_insn (dest
, gen_lowpart (GET_MODE (dest
), src
));
6250 /* Emit code to place a AdvSIMD pair result in memory locations (with equal
6253 aarch64_simd_emit_pair_result_insn (enum machine_mode mode
,
6254 rtx (*intfn
) (rtx
, rtx
, rtx
), rtx destaddr
,
6257 rtx mem
= gen_rtx_MEM (mode
, destaddr
);
6258 rtx tmp1
= gen_reg_rtx (mode
);
6259 rtx tmp2
= gen_reg_rtx (mode
);
6261 emit_insn (intfn (tmp1
, op1
, tmp2
));
6263 emit_move_insn (mem
, tmp1
);
6264 mem
= adjust_address (mem
, mode
, GET_MODE_SIZE (mode
));
6265 emit_move_insn (mem
, tmp2
);
6268 /* Return TRUE if OP is a valid vector addressing mode. */
6270 aarch64_simd_mem_operand_p (rtx op
)
6272 return MEM_P (op
) && (GET_CODE (XEXP (op
, 0)) == POST_INC
6273 || GET_CODE (XEXP (op
, 0)) == REG
);
6276 /* Set up OPERANDS for a register copy from SRC to DEST, taking care
6277 not to early-clobber SRC registers in the process.
6279 We assume that the operands described by SRC and DEST represent a
6280 decomposed copy of OPERANDS[1] into OPERANDS[0]. COUNT is the
6281 number of components into which the copy has been decomposed. */
6283 aarch64_simd_disambiguate_copy (rtx
*operands
, rtx
*dest
,
6284 rtx
*src
, unsigned int count
)
6288 if (!reg_overlap_mentioned_p (operands
[0], operands
[1])
6289 || REGNO (operands
[0]) < REGNO (operands
[1]))
6291 for (i
= 0; i
< count
; i
++)
6293 operands
[2 * i
] = dest
[i
];
6294 operands
[2 * i
+ 1] = src
[i
];
6299 for (i
= 0; i
< count
; i
++)
6301 operands
[2 * i
] = dest
[count
- i
- 1];
6302 operands
[2 * i
+ 1] = src
[count
- i
- 1];
6307 /* Compute and return the length of aarch64_simd_mov<mode>, where <mode> is
6308 one of VSTRUCT modes: OI, CI or XI. */
6310 aarch64_simd_attr_length_move (rtx insn
)
6314 enum machine_mode mode
;
6316 extract_insn_cached (insn
);
6318 if (REG_P (recog_data
.operand
[0]) && REG_P (recog_data
.operand
[1]))
6320 mode
= GET_MODE (recog_data
.operand
[0]);
6336 static unsigned HOST_WIDE_INT
6337 aarch64_shift_truncation_mask (enum machine_mode mode
)
6340 (aarch64_vector_mode_supported_p (mode
)
6341 || aarch64_vect_struct_mode_p (mode
)) ? 0 : (GET_MODE_BITSIZE (mode
) - 1);
6344 #ifndef TLS_SECTION_ASM_FLAG
6345 #define TLS_SECTION_ASM_FLAG 'T'
6349 aarch64_elf_asm_named_section (const char *name
, unsigned int flags
,
6350 tree decl ATTRIBUTE_UNUSED
)
6352 char flagchars
[10], *f
= flagchars
;
6354 /* If we have already declared this section, we can use an
6355 abbreviated form to switch back to it -- unless this section is
6356 part of a COMDAT groups, in which case GAS requires the full
6357 declaration every time. */
6358 if (!(HAVE_COMDAT_GROUP
&& (flags
& SECTION_LINKONCE
))
6359 && (flags
& SECTION_DECLARED
))
6361 fprintf (asm_out_file
, "\t.section\t%s\n", name
);
6365 if (!(flags
& SECTION_DEBUG
))
6367 if (flags
& SECTION_WRITE
)
6369 if (flags
& SECTION_CODE
)
6371 if (flags
& SECTION_SMALL
)
6373 if (flags
& SECTION_MERGE
)
6375 if (flags
& SECTION_STRINGS
)
6377 if (flags
& SECTION_TLS
)
6378 *f
++ = TLS_SECTION_ASM_FLAG
;
6379 if (HAVE_COMDAT_GROUP
&& (flags
& SECTION_LINKONCE
))
6383 fprintf (asm_out_file
, "\t.section\t%s,\"%s\"", name
, flagchars
);
6385 if (!(flags
& SECTION_NOTYPE
))
6390 if (flags
& SECTION_BSS
)
6395 #ifdef TYPE_OPERAND_FMT
6396 format
= "," TYPE_OPERAND_FMT
;
6401 fprintf (asm_out_file
, format
, type
);
6403 if (flags
& SECTION_ENTSIZE
)
6404 fprintf (asm_out_file
, ",%d", flags
& SECTION_ENTSIZE
);
6405 if (HAVE_COMDAT_GROUP
&& (flags
& SECTION_LINKONCE
))
6407 if (TREE_CODE (decl
) == IDENTIFIER_NODE
)
6408 fprintf (asm_out_file
, ",%s,comdat", IDENTIFIER_POINTER (decl
));
6410 fprintf (asm_out_file
, ",%s,comdat",
6411 IDENTIFIER_POINTER (DECL_COMDAT_GROUP (decl
)));
6415 putc ('\n', asm_out_file
);
6418 /* Select a format to encode pointers in exception handling data. */
6420 aarch64_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED
, int global
)
6423 switch (aarch64_cmodel
)
6425 case AARCH64_CMODEL_TINY
:
6426 case AARCH64_CMODEL_TINY_PIC
:
6427 case AARCH64_CMODEL_SMALL
:
6428 case AARCH64_CMODEL_SMALL_PIC
:
6429 /* text+got+data < 4Gb. 4-byte signed relocs are sufficient
6431 type
= DW_EH_PE_sdata4
;
6434 /* No assumptions here. 8-byte relocs required. */
6435 type
= DW_EH_PE_sdata8
;
6438 return (global
? DW_EH_PE_indirect
: 0) | DW_EH_PE_pcrel
| type
;
6441 /* Emit load exclusive. */
6444 aarch64_emit_load_exclusive (enum machine_mode mode
, rtx rval
,
6445 rtx mem
, rtx model_rtx
)
6447 rtx (*gen
) (rtx
, rtx
, rtx
);
6451 case QImode
: gen
= gen_aarch64_load_exclusiveqi
; break;
6452 case HImode
: gen
= gen_aarch64_load_exclusivehi
; break;
6453 case SImode
: gen
= gen_aarch64_load_exclusivesi
; break;
6454 case DImode
: gen
= gen_aarch64_load_exclusivedi
; break;
6459 emit_insn (gen (rval
, mem
, model_rtx
));
6462 /* Emit store exclusive. */
6465 aarch64_emit_store_exclusive (enum machine_mode mode
, rtx bval
,
6466 rtx rval
, rtx mem
, rtx model_rtx
)
6468 rtx (*gen
) (rtx
, rtx
, rtx
, rtx
);
6472 case QImode
: gen
= gen_aarch64_store_exclusiveqi
; break;
6473 case HImode
: gen
= gen_aarch64_store_exclusivehi
; break;
6474 case SImode
: gen
= gen_aarch64_store_exclusivesi
; break;
6475 case DImode
: gen
= gen_aarch64_store_exclusivedi
; break;
6480 emit_insn (gen (bval
, rval
, mem
, model_rtx
));
6483 /* Mark the previous jump instruction as unlikely. */
6486 aarch64_emit_unlikely_jump (rtx insn
)
6488 rtx very_unlikely
= GEN_INT (REG_BR_PROB_BASE
/ 100 - 1);
6490 insn
= emit_jump_insn (insn
);
6491 add_reg_note (insn
, REG_BR_PROB
, very_unlikely
);
6494 /* Expand a compare and swap pattern. */
6497 aarch64_expand_compare_and_swap (rtx operands
[])
6499 rtx bval
, rval
, mem
, oldval
, newval
, is_weak
, mod_s
, mod_f
, x
;
6500 enum machine_mode mode
, cmp_mode
;
6501 rtx (*gen
) (rtx
, rtx
, rtx
, rtx
, rtx
, rtx
, rtx
);
6506 oldval
= operands
[3];
6507 newval
= operands
[4];
6508 is_weak
= operands
[5];
6509 mod_s
= operands
[6];
6510 mod_f
= operands
[7];
6511 mode
= GET_MODE (mem
);
6514 /* Normally the succ memory model must be stronger than fail, but in the
6515 unlikely event of fail being ACQUIRE and succ being RELEASE we need to
6516 promote succ to ACQ_REL so that we don't lose the acquire semantics. */
6518 if (INTVAL (mod_f
) == MEMMODEL_ACQUIRE
6519 && INTVAL (mod_s
) == MEMMODEL_RELEASE
)
6520 mod_s
= GEN_INT (MEMMODEL_ACQ_REL
);
6526 /* For short modes, we're going to perform the comparison in SImode,
6527 so do the zero-extension now. */
6529 rval
= gen_reg_rtx (SImode
);
6530 oldval
= convert_modes (SImode
, mode
, oldval
, true);
6535 /* Force the value into a register if needed. */
6536 if (!aarch64_plus_operand (oldval
, mode
))
6537 oldval
= force_reg (cmp_mode
, oldval
);
6546 case QImode
: gen
= gen_atomic_compare_and_swapqi_1
; break;
6547 case HImode
: gen
= gen_atomic_compare_and_swaphi_1
; break;
6548 case SImode
: gen
= gen_atomic_compare_and_swapsi_1
; break;
6549 case DImode
: gen
= gen_atomic_compare_and_swapdi_1
; break;
6554 emit_insn (gen (rval
, mem
, oldval
, newval
, is_weak
, mod_s
, mod_f
));
6556 if (mode
== QImode
|| mode
== HImode
)
6557 emit_move_insn (operands
[1], gen_lowpart (mode
, rval
));
6559 x
= gen_rtx_REG (CCmode
, CC_REGNUM
);
6560 x
= gen_rtx_EQ (SImode
, x
, const0_rtx
);
6561 emit_insn (gen_rtx_SET (VOIDmode
, bval
, x
));
6564 /* Split a compare and swap pattern. */
6567 aarch64_split_compare_and_swap (rtx operands
[])
6569 rtx rval
, mem
, oldval
, newval
, scratch
;
6570 enum machine_mode mode
;
6571 enum memmodel mod_s
;
6573 rtx label1
, label2
, x
, cond
;
6577 oldval
= operands
[2];
6578 newval
= operands
[3];
6579 is_weak
= (operands
[4] != const0_rtx
);
6580 mod_s
= (enum memmodel
) INTVAL (operands
[5]);
6581 scratch
= operands
[7];
6582 mode
= GET_MODE (mem
);
6587 label1
= gen_label_rtx ();
6588 emit_label (label1
);
6590 label2
= gen_label_rtx ();
6592 aarch64_emit_load_exclusive (mode
, rval
, mem
, operands
[5]);
6594 cond
= aarch64_gen_compare_reg (NE
, rval
, oldval
);
6595 x
= gen_rtx_NE (VOIDmode
, cond
, const0_rtx
);
6596 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
6597 gen_rtx_LABEL_REF (Pmode
, label2
), pc_rtx
);
6598 aarch64_emit_unlikely_jump (gen_rtx_SET (VOIDmode
, pc_rtx
, x
));
6600 aarch64_emit_store_exclusive (mode
, scratch
, mem
, newval
, operands
[5]);
6604 x
= gen_rtx_NE (VOIDmode
, scratch
, const0_rtx
);
6605 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
6606 gen_rtx_LABEL_REF (Pmode
, label1
), pc_rtx
);
6607 aarch64_emit_unlikely_jump (gen_rtx_SET (VOIDmode
, pc_rtx
, x
));
6611 cond
= gen_rtx_REG (CCmode
, CC_REGNUM
);
6612 x
= gen_rtx_COMPARE (CCmode
, scratch
, const0_rtx
);
6613 emit_insn (gen_rtx_SET (VOIDmode
, cond
, x
));
6616 emit_label (label2
);
6619 /* Split an atomic operation. */
6622 aarch64_split_atomic_op (enum rtx_code code
, rtx old_out
, rtx new_out
, rtx mem
,
6623 rtx value
, rtx model_rtx
, rtx cond
)
6625 enum machine_mode mode
= GET_MODE (mem
);
6626 enum machine_mode wmode
= (mode
== DImode
? DImode
: SImode
);
6629 label
= gen_label_rtx ();
6633 new_out
= gen_lowpart (wmode
, new_out
);
6635 old_out
= gen_lowpart (wmode
, old_out
);
6638 value
= simplify_gen_subreg (wmode
, value
, mode
, 0);
6640 aarch64_emit_load_exclusive (mode
, old_out
, mem
, model_rtx
);
6649 x
= gen_rtx_AND (wmode
, old_out
, value
);
6650 emit_insn (gen_rtx_SET (VOIDmode
, new_out
, x
));
6651 x
= gen_rtx_NOT (wmode
, new_out
);
6652 emit_insn (gen_rtx_SET (VOIDmode
, new_out
, x
));
6656 if (CONST_INT_P (value
))
6658 value
= GEN_INT (-INTVAL (value
));
6664 x
= gen_rtx_fmt_ee (code
, wmode
, old_out
, value
);
6665 emit_insn (gen_rtx_SET (VOIDmode
, new_out
, x
));
6669 aarch64_emit_store_exclusive (mode
, cond
, mem
,
6670 gen_lowpart (mode
, new_out
), model_rtx
);
6672 x
= gen_rtx_NE (VOIDmode
, cond
, const0_rtx
);
6673 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
6674 gen_rtx_LABEL_REF (Pmode
, label
), pc_rtx
);
6675 aarch64_emit_unlikely_jump (gen_rtx_SET (VOIDmode
, pc_rtx
, x
));
6679 aarch64_start_file (void)
6682 asm_fprintf (asm_out_file
, "\t.arch %s\n", selected_arch
->name
);
6683 else if (selected_cpu
)
6684 asm_fprintf (asm_out_file
, "\t.cpu %s\n", selected_cpu
->name
);
6685 default_file_start();
6688 /* Target hook for c_mode_for_suffix. */
6689 static enum machine_mode
6690 aarch64_c_mode_for_suffix (char suffix
)
6698 #undef TARGET_ADDRESS_COST
6699 #define TARGET_ADDRESS_COST aarch64_address_cost
6701 /* This hook will determines whether unnamed bitfields affect the alignment
6702 of the containing structure. The hook returns true if the structure
6703 should inherit the alignment requirements of an unnamed bitfield's
6705 #undef TARGET_ALIGN_ANON_BITFIELD
6706 #define TARGET_ALIGN_ANON_BITFIELD hook_bool_void_true
6708 #undef TARGET_ASM_ALIGNED_DI_OP
6709 #define TARGET_ASM_ALIGNED_DI_OP "\t.xword\t"
6711 #undef TARGET_ASM_ALIGNED_HI_OP
6712 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
6714 #undef TARGET_ASM_ALIGNED_SI_OP
6715 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
6717 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
6718 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
6719 hook_bool_const_tree_hwi_hwi_const_tree_true
6721 #undef TARGET_ASM_FILE_START
6722 #define TARGET_ASM_FILE_START aarch64_start_file
6724 #undef TARGET_ASM_OUTPUT_MI_THUNK
6725 #define TARGET_ASM_OUTPUT_MI_THUNK aarch64_output_mi_thunk
6727 #undef TARGET_ASM_SELECT_RTX_SECTION
6728 #define TARGET_ASM_SELECT_RTX_SECTION aarch64_select_rtx_section
6730 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
6731 #define TARGET_ASM_TRAMPOLINE_TEMPLATE aarch64_asm_trampoline_template
6733 #undef TARGET_BUILD_BUILTIN_VA_LIST
6734 #define TARGET_BUILD_BUILTIN_VA_LIST aarch64_build_builtin_va_list
6736 #undef TARGET_CALLEE_COPIES
6737 #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false
6739 #undef TARGET_CAN_ELIMINATE
6740 #define TARGET_CAN_ELIMINATE aarch64_can_eliminate
6742 #undef TARGET_CANNOT_FORCE_CONST_MEM
6743 #define TARGET_CANNOT_FORCE_CONST_MEM aarch64_cannot_force_const_mem
6745 #undef TARGET_CONDITIONAL_REGISTER_USAGE
6746 #define TARGET_CONDITIONAL_REGISTER_USAGE aarch64_conditional_register_usage
6748 /* Only the least significant bit is used for initialization guard
6750 #undef TARGET_CXX_GUARD_MASK_BIT
6751 #define TARGET_CXX_GUARD_MASK_BIT hook_bool_void_true
6753 #undef TARGET_C_MODE_FOR_SUFFIX
6754 #define TARGET_C_MODE_FOR_SUFFIX aarch64_c_mode_for_suffix
6756 #ifdef TARGET_BIG_ENDIAN_DEFAULT
6757 #undef TARGET_DEFAULT_TARGET_FLAGS
6758 #define TARGET_DEFAULT_TARGET_FLAGS (MASK_BIG_END)
6761 #undef TARGET_CLASS_MAX_NREGS
6762 #define TARGET_CLASS_MAX_NREGS aarch64_class_max_nregs
6764 #undef TARGET_EXPAND_BUILTIN
6765 #define TARGET_EXPAND_BUILTIN aarch64_expand_builtin
6767 #undef TARGET_EXPAND_BUILTIN_VA_START
6768 #define TARGET_EXPAND_BUILTIN_VA_START aarch64_expand_builtin_va_start
6770 #undef TARGET_FUNCTION_ARG
6771 #define TARGET_FUNCTION_ARG aarch64_function_arg
6773 #undef TARGET_FUNCTION_ARG_ADVANCE
6774 #define TARGET_FUNCTION_ARG_ADVANCE aarch64_function_arg_advance
6776 #undef TARGET_FUNCTION_ARG_BOUNDARY
6777 #define TARGET_FUNCTION_ARG_BOUNDARY aarch64_function_arg_boundary
6779 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
6780 #define TARGET_FUNCTION_OK_FOR_SIBCALL aarch64_function_ok_for_sibcall
6782 #undef TARGET_FUNCTION_VALUE
6783 #define TARGET_FUNCTION_VALUE aarch64_function_value
6785 #undef TARGET_FUNCTION_VALUE_REGNO_P
6786 #define TARGET_FUNCTION_VALUE_REGNO_P aarch64_function_value_regno_p
6788 #undef TARGET_FRAME_POINTER_REQUIRED
6789 #define TARGET_FRAME_POINTER_REQUIRED aarch64_frame_pointer_required
6791 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
6792 #define TARGET_GIMPLIFY_VA_ARG_EXPR aarch64_gimplify_va_arg_expr
6794 #undef TARGET_INIT_BUILTINS
6795 #define TARGET_INIT_BUILTINS aarch64_init_builtins
6797 #undef TARGET_LEGITIMATE_ADDRESS_P
6798 #define TARGET_LEGITIMATE_ADDRESS_P aarch64_legitimate_address_hook_p
6800 #undef TARGET_LEGITIMATE_CONSTANT_P
6801 #define TARGET_LEGITIMATE_CONSTANT_P aarch64_legitimate_constant_p
6803 #undef TARGET_LIBGCC_CMP_RETURN_MODE
6804 #define TARGET_LIBGCC_CMP_RETURN_MODE aarch64_libgcc_cmp_return_mode
6806 #undef TARGET_MEMORY_MOVE_COST
6807 #define TARGET_MEMORY_MOVE_COST aarch64_memory_move_cost
6809 #undef TARGET_MUST_PASS_IN_STACK
6810 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
6812 /* This target hook should return true if accesses to volatile bitfields
6813 should use the narrowest mode possible. It should return false if these
6814 accesses should use the bitfield container type. */
6815 #undef TARGET_NARROW_VOLATILE_BITFIELD
6816 #define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
6818 #undef TARGET_OPTION_OVERRIDE
6819 #define TARGET_OPTION_OVERRIDE aarch64_override_options
6821 #undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
6822 #define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE \
6823 aarch64_override_options_after_change
6825 #undef TARGET_PASS_BY_REFERENCE
6826 #define TARGET_PASS_BY_REFERENCE aarch64_pass_by_reference
6828 #undef TARGET_PREFERRED_RELOAD_CLASS
6829 #define TARGET_PREFERRED_RELOAD_CLASS aarch64_preferred_reload_class
6831 #undef TARGET_SECONDARY_RELOAD
6832 #define TARGET_SECONDARY_RELOAD aarch64_secondary_reload
6834 #undef TARGET_SHIFT_TRUNCATION_MASK
6835 #define TARGET_SHIFT_TRUNCATION_MASK aarch64_shift_truncation_mask
6837 #undef TARGET_SETUP_INCOMING_VARARGS
6838 #define TARGET_SETUP_INCOMING_VARARGS aarch64_setup_incoming_varargs
6840 #undef TARGET_STRUCT_VALUE_RTX
6841 #define TARGET_STRUCT_VALUE_RTX aarch64_struct_value_rtx
6843 #undef TARGET_REGISTER_MOVE_COST
6844 #define TARGET_REGISTER_MOVE_COST aarch64_register_move_cost
6846 #undef TARGET_RETURN_IN_MEMORY
6847 #define TARGET_RETURN_IN_MEMORY aarch64_return_in_memory
6849 #undef TARGET_RETURN_IN_MSB
6850 #define TARGET_RETURN_IN_MSB aarch64_return_in_msb
6852 #undef TARGET_RTX_COSTS
6853 #define TARGET_RTX_COSTS aarch64_rtx_costs
6855 #undef TARGET_TRAMPOLINE_INIT
6856 #define TARGET_TRAMPOLINE_INIT aarch64_trampoline_init
6858 #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
6859 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P aarch64_use_blocks_for_constant_p
6861 #undef TARGET_VECTOR_MODE_SUPPORTED_P
6862 #define TARGET_VECTOR_MODE_SUPPORTED_P aarch64_vector_mode_supported_p
6864 #undef TARGET_ARRAY_MODE_SUPPORTED_P
6865 #define TARGET_ARRAY_MODE_SUPPORTED_P aarch64_array_mode_supported_p
6867 #undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE
6868 #define TARGET_VECTORIZE_PREFERRED_SIMD_MODE aarch64_preferred_simd_mode
6870 /* Section anchor support. */
6872 #undef TARGET_MIN_ANCHOR_OFFSET
6873 #define TARGET_MIN_ANCHOR_OFFSET -256
6875 /* Limit the maximum anchor offset to 4k-1, since that's the limit for a
6876 byte offset; we can do much more for larger data types, but have no way
6877 to determine the size of the access. We assume accesses are aligned. */
6878 #undef TARGET_MAX_ANCHOR_OFFSET
6879 #define TARGET_MAX_ANCHOR_OFFSET 4095
6881 struct gcc_target targetm
= TARGET_INITIALIZER
;
6883 #include "gt-aarch64.h"