1 /* Output routines for GCC for ARM.
2 Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
4 Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 and Martin Simmons (@harleqn.co.uk).
6 More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published
12 by the Free Software Foundation; either version 2, or (at your
13 option) any later version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING. If not, write to
22 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 Boston, MA 02110-1301, USA. */
25 /* APPLE LOCAL begin 6902792 Q register clobbers in inline asm */
27 /* APPLE LOCAL end 6902792 Q register clobbers in inline asm */
30 #include "coretypes.h"
36 #include "hard-reg-set.h"
38 #include "insn-config.h"
39 #include "conditions.h"
41 #include "insn-attr.h"
52 #include "integrate.h"
55 #include "target-def.h"
57 #include "langhooks.h"
58 /* APPLE LOCAL ARM needed for SUBSUBTARGET_OVERRIDE_OPTIONS */
59 #include "../../libcpp/internal.h"
60 /* APPLE LOCAL ARM needed for set_param_value */
63 /* Forward definitions of types. */
64 typedef struct minipool_node Mnode
;
65 typedef struct minipool_fixup Mfix
;
67 const struct attribute_spec arm_attribute_table
[];
69 /* Forward function declarations. */
70 static arm_stack_offsets
*arm_get_frame_offsets (void);
71 static void arm_add_gc_roots (void);
72 static int arm_gen_constant (enum rtx_code
, enum machine_mode
, rtx
,
73 HOST_WIDE_INT
, rtx
, rtx
, int, int);
74 static unsigned bit_count (unsigned long);
75 static int arm_address_register_rtx_p (rtx
, int);
76 static int arm_legitimate_index_p (enum machine_mode
, rtx
, RTX_CODE
, int);
77 /* APPLE LOCAL begin v7 support. Merge from mainline */
78 static int thumb2_legitimate_index_p (enum machine_mode
, rtx
, int);
79 static int thumb1_base_register_rtx_p (rtx
, enum machine_mode
, int);
80 inline static int thumb1_index_register_rtx_p (rtx
, int);
81 static int thumb_far_jump_used_p (void);
82 static bool thumb_force_lr_save (void);
83 static unsigned long thumb1_compute_save_reg_mask (void);
84 /* APPLE LOCAL end v7 support. Merge from mainline */
85 static int const_ok_for_op (HOST_WIDE_INT
, enum rtx_code
);
86 static rtx
emit_sfm (int, int);
87 static int arm_size_return_regs (void);
89 static bool arm_assemble_integer (rtx
, unsigned int, int);
91 static const char *fp_const_from_val (REAL_VALUE_TYPE
*);
92 static arm_cc
get_arm_condition_code (rtx
);
93 static HOST_WIDE_INT
int_log2 (HOST_WIDE_INT
);
94 /* LLVM LOCAL begin */
96 static rtx
is_jump_table (rtx
);
99 static const char *output_multi_immediate (rtx
*, const char *, const char *,
101 static const char *shift_op (rtx
, HOST_WIDE_INT
*);
102 static struct machine_function
*arm_init_machine_status (void);
103 /* APPLE LOCAL begin compact switch tables */
104 static int handle_thumb_unexpanded_prologue (FILE *, bool);
105 static int handle_thumb_unexpanded_epilogue (bool);
106 static int handle_thumb_exit (FILE *, int, bool);
107 static int handle_thumb_pushpop (FILE *, unsigned long, int, int *, unsigned long, bool);
108 /* APPLE LOCAL end compact switch tables */
109 /* LLVM LOCAL begin */
111 static HOST_WIDE_INT
get_jump_table_size (rtx
);
112 static Mnode
*move_minipool_fix_forward_ref (Mnode
*, Mnode
*, HOST_WIDE_INT
);
113 static Mnode
*add_minipool_forward_ref (Mfix
*);
114 static Mnode
*move_minipool_fix_backward_ref (Mnode
*, Mnode
*, HOST_WIDE_INT
);
115 static Mnode
*add_minipool_backward_ref (Mfix
*);
116 static void assign_minipool_offsets (Mfix
*);
117 static void arm_print_value (FILE *, rtx
);
118 static void dump_minipool (rtx
);
119 static int arm_barrier_cost (rtx
);
120 static Mfix
*create_fix_barrier (Mfix
*, HOST_WIDE_INT
);
121 static void push_minipool_barrier (rtx
, HOST_WIDE_INT
);
122 static void push_minipool_fix (rtx
, HOST_WIDE_INT
, rtx
*, enum machine_mode
,
126 static void arm_reorg (void);
127 /* LLVM LOCAL begin */
129 static bool note_invalid_constants (rtx
, HOST_WIDE_INT
, int);
132 static int current_file_function_operand (rtx
);
133 static unsigned long arm_compute_save_reg0_reg12_mask (void);
134 static unsigned long arm_compute_save_reg_mask (void);
135 static unsigned long arm_isr_value (tree
);
136 static unsigned long arm_compute_func_type (void);
137 static tree
arm_handle_fndecl_attribute (tree
*, tree
, tree
, int, bool *);
138 static tree
arm_handle_isr_attribute (tree
*, tree
, tree
, int, bool *);
139 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
140 static tree
arm_handle_notshared_attribute (tree
*, tree
, tree
, int, bool *);
142 static void arm_output_function_epilogue (FILE *, HOST_WIDE_INT
);
143 static void arm_output_function_prologue (FILE *, HOST_WIDE_INT
);
144 /* APPLE LOCAL v7 support. Merge from mainline */
145 static void thumb1_output_function_prologue (FILE *, HOST_WIDE_INT
);
146 static int arm_comp_type_attributes (tree
, tree
);
147 static void arm_set_default_type_attributes (tree
);
148 static int arm_adjust_cost (rtx
, rtx
, rtx
, int);
149 static int count_insns_for_constant (HOST_WIDE_INT
, int);
150 static int arm_get_strip_length (int);
151 static bool arm_function_ok_for_sibcall (tree
, tree
);
152 static void arm_internal_label (FILE *, const char *, unsigned long);
153 static void arm_output_mi_thunk (FILE *, tree
, HOST_WIDE_INT
, HOST_WIDE_INT
,
155 static int arm_rtx_costs_1 (rtx
, enum rtx_code
, enum rtx_code
);
156 static bool arm_size_rtx_costs (rtx
, int, int, int *);
157 static bool arm_slowmul_rtx_costs (rtx
, int, int, int *);
158 static bool arm_fastmul_rtx_costs (rtx
, int, int, int *);
159 static bool arm_xscale_rtx_costs (rtx
, int, int, int *);
160 static bool arm_9e_rtx_costs (rtx
, int, int, int *);
161 static int arm_address_cost (rtx
);
162 /* LLVM LOCAL begin */
164 static bool arm_memory_load_p (rtx
);
165 static bool arm_cirrus_insn_p (rtx
);
166 static void cirrus_reorg (rtx
);
169 static void arm_init_builtins (void);
170 static rtx
arm_expand_builtin (tree
, rtx
, rtx
, enum machine_mode
, int);
171 static void arm_init_iwmmxt_builtins (void);
172 static rtx
safe_vector_operand (rtx
, enum machine_mode
);
173 static rtx
arm_expand_binop_builtin (enum insn_code
, tree
, rtx
);
174 static rtx
arm_expand_unop_builtin (enum insn_code
, tree
, rtx
, int);
175 static rtx
arm_expand_builtin (tree
, rtx
, rtx
, enum machine_mode
, int);
176 static void emit_constant_insn (rtx cond
, rtx pattern
);
177 static rtx
emit_set_insn (rtx
, rtx
);
178 static int arm_arg_partial_bytes (CUMULATIVE_ARGS
*, enum machine_mode
,
181 #ifdef OBJECT_FORMAT_ELF
182 static void arm_elf_asm_constructor (rtx
, int);
184 /* APPLE LOCAL begin ARM darwin section_info */
186 static void arm_darwin_encode_section_info (tree
, rtx
, int);
187 #elif !defined(ARM_PE)
188 static void arm_encode_section_info (tree
, rtx
, int);
190 /* APPLE LOCAL end ARM darwin section_info */
192 static void arm_file_end (void);
193 /* APPLE LOCAL v7 support. Merge from mainline */
194 static void arm_file_start (void);
196 /* APPLE LOCAL begin ARM asm file hooks */
198 static void arm_darwin_file_start (void);
199 static void arm_darwin_file_end (void);
201 /* APPLE LOCAL end ARM asm file hooks */
204 static void aof_globalize_label (FILE *, const char *);
205 static void aof_dump_imports (FILE *);
206 static void aof_dump_pic_table (FILE *);
207 static void aof_file_start (void);
208 static void aof_file_end (void);
209 static void aof_asm_init_sections (void);
211 static void arm_setup_incoming_varargs (CUMULATIVE_ARGS
*, enum machine_mode
,
213 static bool arm_pass_by_reference (CUMULATIVE_ARGS
*,
214 enum machine_mode
, tree
, bool);
215 static bool arm_promote_prototypes (tree
);
216 static bool arm_default_short_enums (void);
217 static bool arm_align_anon_bitfield (void);
218 static bool arm_return_in_msb (tree
);
219 static bool arm_must_pass_in_stack (enum machine_mode
, tree
);
220 #ifdef TARGET_UNWIND_INFO
221 static void arm_unwind_emit (FILE *, rtx
);
222 static bool arm_output_ttype (rtx
);
224 /* APPLE LOCAL v7 support. Merge from mainline */
225 static void arm_dwarf_handle_frame_unspec (const char *, rtx
, int);
226 /* APPLE LOCAL v7 support. Merge from Codesourcery */
227 static rtx
arm_dwarf_register_span(rtx
);
229 static tree
arm_cxx_guard_type (void);
230 static bool arm_cxx_guard_mask_bit (void);
231 static tree
arm_get_cookie_size (tree
);
232 static bool arm_cookie_has_size (void);
233 static bool arm_cxx_cdtor_returns_this (void);
234 static bool arm_cxx_key_method_may_be_inline (void);
235 static void arm_cxx_determine_class_data_visibility (tree
);
236 static bool arm_cxx_class_data_always_comdat (void);
237 static bool arm_cxx_use_aeabi_atexit (void);
238 static void arm_init_libfuncs (void);
239 static bool arm_handle_option (size_t, const char *, int);
240 static unsigned HOST_WIDE_INT
arm_shift_truncation_mask (enum machine_mode
);
241 static bool arm_cannot_copy_insn_p (rtx
);
242 static bool arm_tls_symbol_p (rtx x
);
243 /* APPLE LOCAL begin ARM -mdynamic-no-pic support */
244 static int symbol_mentioned_with_filter (rtx
, int);
245 static bool arm_cannot_force_const_mem (rtx x
);
246 /* APPLE LOCAL end ARM -mdynamic-no-pic support */
247 /* APPLE LOCAL ARM reliable backtraces */
248 static rtx
arm_builtin_setjmp_frame_value (void);
249 /* APPLE LOCAL begin ARM darwin local binding */
251 static bool arm_binds_local_p (tree
);
253 /* APPLE LOCAL end ARM darwin local binding */
254 /* APPLE LOCAL begin 5946347 ms_struct support */
255 static tree
arm_handle_ms_struct_attribute (tree
*, tree
, tree
, int, bool *);
256 static tree
arm_handle_gcc_struct_attribute (tree
*, tree
, tree
, int, bool *);
257 static bool arm_ms_bitfield_layout_p (tree
);
258 /* APPLE LOCAL end 5946347 ms_struct support */
259 /* APPLE LOCAL ARM 6008578 */
260 /* LLVM LOCAL begin */
262 static HOST_WIDE_INT
get_label_pad (rtx
, HOST_WIDE_INT
);
266 /* APPLE LOCAL 6902792 Q register clobbers in inline asm */
267 static tree
arm_md_asm_clobbers (tree
, tree
, tree
);
269 /* Initialize the GCC target structure. */
270 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
271 #undef TARGET_MERGE_DECL_ATTRIBUTES
272 #define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
275 #undef TARGET_ATTRIBUTE_TABLE
276 #define TARGET_ATTRIBUTE_TABLE arm_attribute_table
278 #undef TARGET_ASM_FILE_END
279 #define TARGET_ASM_FILE_END arm_file_end
281 /* APPLE LOCAL begin ARM asm file hooks */
283 #undef TARGET_ASM_FILE_START
284 #define TARGET_ASM_FILE_START arm_darwin_file_start
285 #undef TARGET_ASM_FILE_END
286 #define TARGET_ASM_FILE_END arm_darwin_file_end
288 /* APPLE LOCAL end ARM asm file hooks */
291 #undef TARGET_ASM_BYTE_OP
292 #define TARGET_ASM_BYTE_OP "\tDCB\t"
293 #undef TARGET_ASM_ALIGNED_HI_OP
294 #define TARGET_ASM_ALIGNED_HI_OP "\tDCW\t"
295 #undef TARGET_ASM_ALIGNED_SI_OP
296 #define TARGET_ASM_ALIGNED_SI_OP "\tDCD\t"
297 #undef TARGET_ASM_GLOBALIZE_LABEL
298 #define TARGET_ASM_GLOBALIZE_LABEL aof_globalize_label
299 #undef TARGET_ASM_FILE_START
300 #define TARGET_ASM_FILE_START aof_file_start
301 #undef TARGET_ASM_FILE_END
302 #define TARGET_ASM_FILE_END aof_file_end
304 #undef TARGET_ASM_ALIGNED_SI_OP
305 #define TARGET_ASM_ALIGNED_SI_OP NULL
306 #undef TARGET_ASM_INTEGER
307 #define TARGET_ASM_INTEGER arm_assemble_integer
310 /* APPLE LOCAL begin ARM MACH assembler */
311 #ifdef OBJECT_FORMAT_MACHO
312 #undef TARGET_ASM_ALIGNED_SI_OP
313 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
315 /* APPLE LOCAL end ARM MACH assembler */
317 #undef TARGET_ASM_FUNCTION_PROLOGUE
318 #define TARGET_ASM_FUNCTION_PROLOGUE arm_output_function_prologue
320 #undef TARGET_ASM_FUNCTION_EPILOGUE
321 #define TARGET_ASM_FUNCTION_EPILOGUE arm_output_function_epilogue
323 #undef TARGET_DEFAULT_TARGET_FLAGS
324 /* APPLE LOCAL 6216388 Don't schedule prologue by default */
325 #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT)
326 #undef TARGET_HANDLE_OPTION
327 #define TARGET_HANDLE_OPTION arm_handle_option
329 #undef TARGET_COMP_TYPE_ATTRIBUTES
330 #define TARGET_COMP_TYPE_ATTRIBUTES arm_comp_type_attributes
332 #undef TARGET_SET_DEFAULT_TYPE_ATTRIBUTES
333 #define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES arm_set_default_type_attributes
335 #undef TARGET_SCHED_ADJUST_COST
336 #define TARGET_SCHED_ADJUST_COST arm_adjust_cost
338 #undef TARGET_ENCODE_SECTION_INFO
340 #define TARGET_ENCODE_SECTION_INFO arm_pe_encode_section_info
341 /* APPLE LOCAL begin ARM darwin section_info */
343 #define TARGET_ENCODE_SECTION_INFO arm_darwin_encode_section_info
344 /* APPLE LOCAL end ARM darwin section_info */
346 #define TARGET_ENCODE_SECTION_INFO arm_encode_section_info
349 #undef TARGET_STRIP_NAME_ENCODING
350 #define TARGET_STRIP_NAME_ENCODING arm_strip_name_encoding
352 #undef TARGET_ASM_INTERNAL_LABEL
353 #define TARGET_ASM_INTERNAL_LABEL arm_internal_label
355 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
356 #define TARGET_FUNCTION_OK_FOR_SIBCALL arm_function_ok_for_sibcall
358 #undef TARGET_ASM_OUTPUT_MI_THUNK
359 #define TARGET_ASM_OUTPUT_MI_THUNK arm_output_mi_thunk
360 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
361 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
363 /* This will be overridden in arm_override_options. */
364 #undef TARGET_RTX_COSTS
365 #define TARGET_RTX_COSTS arm_slowmul_rtx_costs
366 #undef TARGET_ADDRESS_COST
367 #define TARGET_ADDRESS_COST arm_address_cost
369 #undef TARGET_SHIFT_TRUNCATION_MASK
370 #define TARGET_SHIFT_TRUNCATION_MASK arm_shift_truncation_mask
371 #undef TARGET_VECTOR_MODE_SUPPORTED_P
372 #define TARGET_VECTOR_MODE_SUPPORTED_P arm_vector_mode_supported_p
374 #undef TARGET_MACHINE_DEPENDENT_REORG
375 #define TARGET_MACHINE_DEPENDENT_REORG arm_reorg
377 #undef TARGET_INIT_BUILTINS
378 #define TARGET_INIT_BUILTINS arm_init_builtins
379 #undef TARGET_EXPAND_BUILTIN
380 #define TARGET_EXPAND_BUILTIN arm_expand_builtin
382 #undef TARGET_INIT_LIBFUNCS
383 #define TARGET_INIT_LIBFUNCS arm_init_libfuncs
385 #undef TARGET_PROMOTE_FUNCTION_ARGS
386 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
387 #undef TARGET_PROMOTE_FUNCTION_RETURN
388 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
389 #undef TARGET_PROMOTE_PROTOTYPES
390 #define TARGET_PROMOTE_PROTOTYPES arm_promote_prototypes
391 #undef TARGET_PASS_BY_REFERENCE
392 #define TARGET_PASS_BY_REFERENCE arm_pass_by_reference
393 #undef TARGET_ARG_PARTIAL_BYTES
394 #define TARGET_ARG_PARTIAL_BYTES arm_arg_partial_bytes
396 #undef TARGET_SETUP_INCOMING_VARARGS
397 #define TARGET_SETUP_INCOMING_VARARGS arm_setup_incoming_varargs
399 #undef TARGET_DEFAULT_SHORT_ENUMS
400 #define TARGET_DEFAULT_SHORT_ENUMS arm_default_short_enums
402 #undef TARGET_ALIGN_ANON_BITFIELD
403 #define TARGET_ALIGN_ANON_BITFIELD arm_align_anon_bitfield
405 #undef TARGET_NARROW_VOLATILE_BITFIELD
406 #define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
408 #undef TARGET_CXX_GUARD_TYPE
409 #define TARGET_CXX_GUARD_TYPE arm_cxx_guard_type
411 #undef TARGET_CXX_GUARD_MASK_BIT
412 #define TARGET_CXX_GUARD_MASK_BIT arm_cxx_guard_mask_bit
414 #undef TARGET_CXX_GET_COOKIE_SIZE
415 #define TARGET_CXX_GET_COOKIE_SIZE arm_get_cookie_size
417 #undef TARGET_CXX_COOKIE_HAS_SIZE
418 #define TARGET_CXX_COOKIE_HAS_SIZE arm_cookie_has_size
420 #undef TARGET_CXX_CDTOR_RETURNS_THIS
421 #define TARGET_CXX_CDTOR_RETURNS_THIS arm_cxx_cdtor_returns_this
423 #undef TARGET_CXX_KEY_METHOD_MAY_BE_INLINE
424 #define TARGET_CXX_KEY_METHOD_MAY_BE_INLINE arm_cxx_key_method_may_be_inline
426 #undef TARGET_CXX_USE_AEABI_ATEXIT
427 #define TARGET_CXX_USE_AEABI_ATEXIT arm_cxx_use_aeabi_atexit
429 #undef TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY
430 #define TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY \
431 arm_cxx_determine_class_data_visibility
433 #undef TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT
434 #define TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT arm_cxx_class_data_always_comdat
436 #undef TARGET_RETURN_IN_MSB
437 #define TARGET_RETURN_IN_MSB arm_return_in_msb
439 #undef TARGET_MUST_PASS_IN_STACK
440 #define TARGET_MUST_PASS_IN_STACK arm_must_pass_in_stack
442 #ifdef TARGET_UNWIND_INFO
443 #undef TARGET_UNWIND_EMIT
444 #define TARGET_UNWIND_EMIT arm_unwind_emit
446 /* EABI unwinding tables use a different format for the typeinfo tables. */
447 #undef TARGET_ASM_TTYPE
448 #define TARGET_ASM_TTYPE arm_output_ttype
450 #undef TARGET_ARM_EABI_UNWINDER
451 #define TARGET_ARM_EABI_UNWINDER true
452 #endif /* TARGET_UNWIND_INFO */
454 /* APPLE LOCAL begin v7 support. Merge from mainline */
455 #undef TARGET_DWARF_HANDLE_FRAME_UNSPEC
456 #define TARGET_DWARF_HANDLE_FRAME_UNSPEC arm_dwarf_handle_frame_unspec
457 /* APPLE LOCAL end v7 support. Merge from mainline */
459 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
460 #undef TARGET_DWARF_REGISTER_SPAN
461 #define TARGET_DWARF_REGISTER_SPAN arm_dwarf_register_span
462 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
464 #undef TARGET_CANNOT_COPY_INSN_P
465 #define TARGET_CANNOT_COPY_INSN_P arm_cannot_copy_insn_p
468 #undef TARGET_HAVE_TLS
469 #define TARGET_HAVE_TLS true
472 #undef TARGET_CANNOT_FORCE_CONST_MEM
473 /* APPLE LOCAL ARM -mdynamic-no-pic support */
474 #define TARGET_CANNOT_FORCE_CONST_MEM arm_cannot_force_const_mem
476 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
477 #undef TARGET_MAX_ANCHOR_OFFSET
478 #define TARGET_MAX_ANCHOR_OFFSET 4095
480 /* The minimum is set such that the total size of the block
481 for a particular anchor is -4088 + 1 + 4095 bytes, which is
482 divisible by eight, ensuring natural spacing of anchors. */
483 #undef TARGET_MIN_ANCHOR_OFFSET
484 #define TARGET_MIN_ANCHOR_OFFSET -4088
486 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
487 /* APPLE LOCAL begin ARM darwin local binding */
489 #undef TARGET_BINDS_LOCAL_P
490 #define TARGET_BINDS_LOCAL_P arm_binds_local_p
492 /* APPLE LOCAL end ARM darwin local binding */
494 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
495 #undef TARGET_MANGLE_TYPE
496 #define TARGET_MANGLE_TYPE arm_mangle_type
497 /* APPLE LOCAL end support. Merge from Codesourcery */
499 /* APPLE LOCAL begin ARM reliable backtraces */
500 #undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
501 #define TARGET_BUILTIN_SETJMP_FRAME_VALUE arm_builtin_setjmp_frame_value
502 /* APPLE LOCAL end ARM reliable backtraces */
504 /* APPLE LOCAL begin 5946347 ms_struct support */
505 #undef TARGET_MS_BITFIELD_LAYOUT_P
506 #define TARGET_MS_BITFIELD_LAYOUT_P arm_ms_bitfield_layout_p
507 /* APPLE LOCAL end 5946347 ms_struct support */
509 /* APPLE LOCAL begin 6902792 Q register clobbers in inline asm */
510 #undef TARGET_MD_ASM_CLOBBERS
511 #define TARGET_MD_ASM_CLOBBERS arm_md_asm_clobbers
512 /* APPLE LOCAL end 6902792 Q register clobbers in inline asm */
514 struct gcc_target targetm
= TARGET_INITIALIZER
;
516 /* Obstack for minipool constant handling. */
517 static struct obstack minipool_obstack
;
518 static char * minipool_startobj
;
520 /* The maximum number of insns skipped which
521 will be conditionalised if possible. */
522 static int max_insns_skipped
= 5;
524 extern FILE * asm_out_file
;
526 /* APPLE LOCAL begin 6879229 disallow -fasm-blocks */
527 extern int flag_iasm_blocks
;
528 /* APPLE LOCAL end 6879229 disallow -fasm-blocks */
530 /* True if we are currently building a constant table. */
531 int making_const_table
;
533 /* Define the information needed to generate branch insns. This is
534 stored from the compare operation. */
535 rtx arm_compare_op0
, arm_compare_op1
;
537 /* The processor for which instructions should be scheduled. */
538 enum processor_type arm_tune
= arm_none
;
540 /* APPLE LOCAL begin v7 support. Merge from mainline */
541 /* The default processor used if not overriden by commandline. */
542 static enum processor_type arm_default_cpu
= arm_none
;
544 /* APPLE LOCAL end v7 support. Merge from mainline */
545 /* Which floating point model to use. */
546 enum arm_fp_model arm_fp_model
;
548 /* Which floating point hardware is available. */
549 enum fputype arm_fpu_arch
;
551 /* Which floating point hardware to schedule for. */
552 enum fputype arm_fpu_tune
;
554 /* Whether to use floating point hardware. */
555 enum float_abi_type arm_float_abi
;
557 /* Which ABI to use. */
558 enum arm_abi_type arm_abi
;
560 /* Which thread pointer model to use. */
561 enum arm_tp_type target_thread_pointer
= TP_AUTO
;
563 /* Used to parse -mstructure_size_boundary command line option. */
564 int arm_structure_size_boundary
= DEFAULT_STRUCTURE_SIZE_BOUNDARY
;
566 /* Used for Thumb call_via trampolines. */
567 rtx thumb_call_via_label
[14];
568 static int thumb_call_reg_needed
;
570 /* APPLE LOCAL 5571707 Allow R9 as caller-saved register */
571 static int darwin_reserve_r9_on_v6
= 0;
573 /* APPLE LOCAL begin ARM compact switch tables */
574 /* Keeps track of which *_switch* functions we've used, so we
575 can emit the right stubs. */
576 static GTY(()) rtx switch8_libfunc
;
577 static GTY(()) rtx switchu8_libfunc
;
578 static GTY(()) rtx switch16_libfunc
;
579 static GTY(()) rtx switch32_libfunc
;
580 /* APPLE LOCAL end ARM compact switch tables */
582 /* Bit values used to identify processor capabilities. */
583 #define FL_CO_PROC (1 << 0) /* Has external co-processor bus */
584 #define FL_ARCH3M (1 << 1) /* Extended multiply */
585 #define FL_MODE26 (1 << 2) /* 26-bit mode support */
586 #define FL_MODE32 (1 << 3) /* 32-bit mode support */
587 #define FL_ARCH4 (1 << 4) /* Architecture rel 4 */
588 #define FL_ARCH5 (1 << 5) /* Architecture rel 5 */
589 #define FL_THUMB (1 << 6) /* Thumb aware */
590 #define FL_LDSCHED (1 << 7) /* Load scheduling necessary */
591 #define FL_STRONG (1 << 8) /* StrongARM */
592 #define FL_ARCH5E (1 << 9) /* DSP extensions to v5 */
593 #define FL_XSCALE (1 << 10) /* XScale */
594 #define FL_CIRRUS (1 << 11) /* Cirrus/DSP. */
595 #define FL_ARCH6 (1 << 12) /* Architecture rel 6. Adds
596 media instructions. */
597 #define FL_VFPV2 (1 << 13) /* Vector Floating Point V2. */
598 #define FL_WBUF (1 << 14) /* Schedule for write buffer ops.
599 Note: ARM6 & 7 derivatives only. */
600 #define FL_ARCH6K (1 << 15) /* Architecture rel 6 K extensions. */
601 /* APPLE LOCAL begin v7 support. Merge from mainline */
602 #define FL_THUMB2 (1 << 16) /* Thumb-2. */
603 #define FL_NOTM (1 << 17) /* Instructions not present in the 'M'
605 #define FL_DIV (1 << 18) /* Hardware divde. */
606 #define FL_VFPV3 (1 << 19) /* Vector Floating Point V3. */
607 /* APPLE LOCAL end v7 support. Merge from mainline */
608 /* APPLE LOCAL v7 support. Merge from Codesourcery */
609 #define FL_NEON (1 << 20) /* Neon instructions. */
611 #define FL_IWMMXT (1 << 29) /* XScale v2 or "Intel Wireless MMX technology". */
613 /* APPLE LOCAL begin v7 support. Merge from mainline */
614 #define FL_FOR_ARCH2 FL_NOTM
615 #define FL_FOR_ARCH3 (FL_FOR_ARCH2 | FL_MODE32)
616 /* APPLE LOCAL end v7 support. Merge from mainline */
617 #define FL_FOR_ARCH3M (FL_FOR_ARCH3 | FL_ARCH3M)
618 #define FL_FOR_ARCH4 (FL_FOR_ARCH3M | FL_ARCH4)
619 #define FL_FOR_ARCH4T (FL_FOR_ARCH4 | FL_THUMB)
620 #define FL_FOR_ARCH5 (FL_FOR_ARCH4 | FL_ARCH5)
621 #define FL_FOR_ARCH5T (FL_FOR_ARCH5 | FL_THUMB)
622 #define FL_FOR_ARCH5E (FL_FOR_ARCH5 | FL_ARCH5E)
623 #define FL_FOR_ARCH5TE (FL_FOR_ARCH5E | FL_THUMB)
624 #define FL_FOR_ARCH5TEJ FL_FOR_ARCH5TE
625 #define FL_FOR_ARCH6 (FL_FOR_ARCH5TE | FL_ARCH6)
626 #define FL_FOR_ARCH6J FL_FOR_ARCH6
627 #define FL_FOR_ARCH6K (FL_FOR_ARCH6 | FL_ARCH6K)
628 #define FL_FOR_ARCH6Z FL_FOR_ARCH6
629 #define FL_FOR_ARCH6ZK FL_FOR_ARCH6K
630 /* APPLE LOCAL begin v7 support. Merge from mainline */
631 #define FL_FOR_ARCH6T2 (FL_FOR_ARCH6 | FL_THUMB2)
632 #define FL_FOR_ARCH7 (FL_FOR_ARCH6T2 &~ FL_NOTM)
633 /* APPLE LOCAL 6093388 -mfpu=neon default for v7a */
634 #define FL_FOR_ARCH7A (FL_FOR_ARCH7 | FL_NOTM | FL_NEON)
635 #define FL_FOR_ARCH7R (FL_FOR_ARCH7A | FL_DIV)
636 #define FL_FOR_ARCH7M (FL_FOR_ARCH7 | FL_DIV)
637 /* APPLE LOCAL end v7 support. Merge from mainline */
639 /* The bits in this mask specify which
640 instructions we are allowed to generate. */
641 static unsigned long insn_flags
= 0;
643 /* The bits in this mask specify which instruction scheduling options should
645 static unsigned long tune_flags
= 0;
647 /* The following are used in the arm.md file as equivalents to bits
648 in the above two flag variables. */
650 /* Nonzero if this chip supports the ARM Architecture 3M extensions. */
653 /* Nonzero if this chip supports the ARM Architecture 4 extensions. */
656 /* Nonzero if this chip supports the ARM Architecture 4t extensions. */
659 /* Nonzero if this chip supports the ARM Architecture 5 extensions. */
662 /* Nonzero if this chip supports the ARM Architecture 5E extensions. */
665 /* Nonzero if this chip supports the ARM Architecture 6 extensions. */
668 /* Nonzero if this chip supports the ARM 6K extensions. */
671 /* APPLE LOCAL begin 6093388 -mfpu=neon default for v7a */
672 /* Nonzero if this chip supports the ARM 7A extensions. */
674 /* APPLE LOCAL end 6093388 -mfpu=neon default for v7a */
676 /* APPLE LOCAL begin v7 support. Merge from mainline */
677 /* Nonzero if instructions not present in the 'M' profile can be used. */
678 int arm_arch_notm
= 0;
680 /* Nonzero if this chip can benefit from load scheduling. */
681 int arm_ld_sched
= 0;
683 /* APPLE LOCAL end v7 support. Merge from mainline */
684 /* Nonzero if this chip is a StrongARM. */
685 int arm_tune_strongarm
= 0;
687 /* Nonzero if this chip is a Cirrus variant. */
688 int arm_arch_cirrus
= 0;
690 /* Nonzero if this chip supports Intel Wireless MMX technology. */
691 int arm_arch_iwmmxt
= 0;
693 /* Nonzero if this chip is an XScale. */
694 int arm_arch_xscale
= 0;
696 /* Nonzero if tuning for XScale */
697 int arm_tune_xscale
= 0;
699 /* Nonzero if we want to tune for stores that access the write-buffer.
700 This typically means an ARM6 or ARM7 with MMU or MPU. */
701 int arm_tune_wbuf
= 0;
703 /* Nonzero if generating Thumb instructions. */
706 /* Nonzero if we should define __THUMB_INTERWORK__ in the
708 XXX This is a bit of a hack, it's intended to help work around
709 problems in GLD which doesn't understand that armv5t code is
710 interworking clean. */
711 int arm_cpp_interwork
= 0;
713 /* APPLE LOCAL begin v7 support. Merge from mainline */
714 /* Nonzero if chip supports Thumb 2. */
717 /* Nonzero if chip supports integer division instruction. */
720 /* APPLE LOCAL end v7 support. Merge from mainline */
721 /* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we
722 must report the mode of the memory reference from PRINT_OPERAND to
723 PRINT_OPERAND_ADDRESS. */
724 enum machine_mode output_memory_reference_mode
;
726 /* The register number to be used for the PIC offset register. */
727 unsigned arm_pic_register
= INVALID_REGNUM
;
729 /* Set to 1 when a return insn is output, this means that the epilogue
731 int return_used_this_function
;
733 /* Set to 1 after arm_reorg has started. Reset to start at the start of
734 the next function. */
735 static int after_arm_reorg
= 0;
737 /* The maximum number of insns to be used when loading a constant. */
738 static int arm_constant_limit
= 3;
740 /* For an explanation of these variables, see final_prescan_insn below. */
742 /* APPLE LOCAL begin v7 support. Merge from mainline */
743 /* arm_current_cc is also used for Thumb-2 cond_exec blocks. */
744 enum arm_cond_code arm_current_cc
;
746 int arm_target_label
;
747 /* The number of conditionally executed insns, including the current insn. */
748 int arm_condexec_count
= 0;
749 /* A bitmask specifying the patterns for the IT block.
750 Zero means do not output an IT block before this insn. */
751 int arm_condexec_mask
= 0;
752 /* The number of bits used in arm_condexec_mask. */
753 int arm_condexec_masklen
= 0;
754 /* APPLE LOCAL end v7 support. Merge from mainline */
756 /* The condition codes of the ARM, and the inverse function. */
757 static const char * const arm_condition_codes
[] =
759 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
760 "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
763 /* APPLE LOCAL begin v7 support. Merge from mainline */
764 #define ARM_LSL_NAME (TARGET_UNIFIED_ASM ? "lsl" : "asl")
765 #define streq(string1, string2) (strcmp (string1, string2) == 0)
767 #define THUMB2_WORK_REGS (0xff & ~( (1 << THUMB_HARD_FRAME_POINTER_REGNUM) \
768 | (1 << SP_REGNUM) | (1 << PC_REGNUM) \
769 | (1 << PIC_OFFSET_TABLE_REGNUM)))
770 /* APPLE LOCAL end v7 support. Merge from mainline */
772 /* Initialization code. */
776 const char *const name
;
777 enum processor_type core
;
779 const unsigned long flags
;
780 bool (* rtx_costs
) (rtx
, int, int, int *);
783 /* Not all of these give usefully different compilation alternatives,
784 but there is no simple way of generalizing them. */
785 static const struct processors all_cores
[] =
788 #define ARM_CORE(NAME, IDENT, ARCH, FLAGS, COSTS) \
789 {NAME, arm_none, #ARCH, FLAGS | FL_FOR_ARCH##ARCH, arm_##COSTS##_rtx_costs},
790 #include "arm-cores.def"
792 {NULL
, arm_none
, NULL
, 0, NULL
}
795 static const struct processors all_architectures
[] =
797 /* ARM Architectures */
798 /* We don't specify rtx_costs here as it will be figured out
801 {"armv2", arm2
, "2", FL_CO_PROC
| FL_MODE26
| FL_FOR_ARCH2
, NULL
},
802 {"armv2a", arm2
, "2", FL_CO_PROC
| FL_MODE26
| FL_FOR_ARCH2
, NULL
},
803 {"armv3", arm6
, "3", FL_CO_PROC
| FL_MODE26
| FL_FOR_ARCH3
, NULL
},
804 {"armv3m", arm7m
, "3M", FL_CO_PROC
| FL_MODE26
| FL_FOR_ARCH3M
, NULL
},
805 {"armv4", arm7tdmi
, "4", FL_CO_PROC
| FL_MODE26
| FL_FOR_ARCH4
, NULL
},
806 /* Strictly, FL_MODE26 is a permitted option for v4t, but there are no
807 implementations that support it, so we will leave it out for now. */
808 /* APPLE LOCAL begin ARM custom architectures */
810 {"armv4t", arm7tdmi
, "4T", FL_CO_PROC
| FL_FOR_ARCH4
, NULL
},
812 {"armv4t", arm7tdmi
, "4T", FL_CO_PROC
| FL_FOR_ARCH4T
, NULL
},
814 /* APPLE LOCAL end ARM custom architectures */
815 {"armv5", arm10tdmi
, "5", FL_CO_PROC
| FL_FOR_ARCH5
, NULL
},
816 {"armv5t", arm10tdmi
, "5T", FL_CO_PROC
| FL_FOR_ARCH5T
, NULL
},
817 {"armv5e", arm1026ejs
, "5E", FL_CO_PROC
| FL_FOR_ARCH5E
, NULL
},
818 {"armv5te", arm1026ejs
, "5TE", FL_CO_PROC
| FL_FOR_ARCH5TE
, NULL
},
819 /* APPLE LOCAL begin ARM custom architectures */
821 {"armv5tej",arm926ejs
, "5TEJ",FL_CO_PROC
| FL_FOR_ARCH5TEJ
, NULL
},
822 {"xscale", xscale
, "5TE", FL_CO_PROC
| FL_XSCALE
| FL_FOR_ARCH5TE
, NULL
},
823 {"armv6", arm1136jfs
, "6", FL_CO_PROC
| FL_FOR_ARCH6
, NULL
},
824 {"armv6j", arm1136js
, "6J", FL_CO_PROC
| FL_FOR_ARCH6J
, NULL
},
825 {"armv6k", arm1136jfs
, "6K", FL_CO_PROC
| FL_FOR_ARCH6K
, NULL
},
827 {"armv6", arm1136js
, "6", FL_CO_PROC
| FL_FOR_ARCH6
, NULL
},
828 {"armv6j", arm1136js
, "6J", FL_CO_PROC
| FL_FOR_ARCH6J
, NULL
},
829 {"armv6k", mpcore
, "6K", FL_CO_PROC
| FL_FOR_ARCH6K
, NULL
},
831 /* APPLE LOCAL end ARM custom architectures */
832 {"armv6z", arm1176jzs
, "6Z", FL_CO_PROC
| FL_FOR_ARCH6Z
, NULL
},
833 {"armv6zk", arm1176jzs
, "6ZK", FL_CO_PROC
| FL_FOR_ARCH6ZK
, NULL
},
834 /* APPLE LOCAL begin v7 support. Merge from mainline */
835 {"armv6t2", arm1156t2s
, "6T2", FL_CO_PROC
| FL_FOR_ARCH6T2
, NULL
},
836 {"armv7", cortexa8
, "7", FL_CO_PROC
| FL_FOR_ARCH7
, NULL
},
837 {"armv7a", cortexa8
, "7A", FL_CO_PROC
| FL_FOR_ARCH7A
, NULL
},
838 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
839 {"armv7r", cortexr4
, "7R", FL_CO_PROC
| FL_FOR_ARCH7R
, NULL
},
840 {"armv7m", cortexm3
, "7M", FL_CO_PROC
| FL_FOR_ARCH7M
, NULL
},
841 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
842 {"armv7-a", cortexa8
, "7A", FL_CO_PROC
| FL_FOR_ARCH7A
, NULL
},
843 {"armv7-r", cortexr4
, "7R", FL_CO_PROC
| FL_FOR_ARCH7R
, NULL
},
844 {"armv7-m", cortexm3
, "7M", FL_CO_PROC
| FL_FOR_ARCH7M
, NULL
},
845 /* APPLE LOCAL end v7 support. Merge from mainline */
846 {"ep9312", ep9312
, "4T", FL_LDSCHED
| FL_CIRRUS
| FL_FOR_ARCH4
, NULL
},
847 {"iwmmxt", iwmmxt
, "5TE", FL_LDSCHED
| FL_STRONG
| FL_FOR_ARCH5TE
| FL_XSCALE
| FL_IWMMXT
, NULL
},
848 {NULL
, arm_none
, NULL
, 0 , NULL
}
851 struct arm_cpu_select
855 const struct processors
* processors
;
858 /* This is a magic structure. The 'string' field is magically filled in
859 with a pointer to the value specified by the user on the command line
860 assuming that the user has specified such a value. */
862 static struct arm_cpu_select arm_select
[] =
864 /* string name processors */
865 { NULL
, "-mcpu=", all_cores
},
866 { NULL
, "-march=", all_architectures
},
867 { NULL
, "-mtune=", all_cores
}
870 /* Defines representing the indexes into the above table. */
871 #define ARM_OPT_SET_CPU 0
872 #define ARM_OPT_SET_ARCH 1
873 #define ARM_OPT_SET_TUNE 2
875 /* The name of the preprocessor macro to define for this architecture. */
877 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
878 #define ARM_ARCH_NAME_SIZE 25
879 char arm_arch_name
[ARM_ARCH_NAME_SIZE
] = "__ARM_ARCH_0UNK__";
880 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
889 /* Available values for -mfpu=. */
891 static const struct fpu_desc all_fpus
[] =
893 {"fpa", FPUTYPE_FPA
},
894 {"fpe2", FPUTYPE_FPA_EMU2
},
895 {"fpe3", FPUTYPE_FPA_EMU2
},
896 {"maverick", FPUTYPE_MAVERICK
},
897 /* APPLE LOCAL begin v7 support. Merge from mainline */
898 {"vfp", FPUTYPE_VFP
},
899 {"vfp3", FPUTYPE_VFP3
},
900 /* APPLE LOCAL end v7 support. Merge from mainline */
901 /* APPLE LOCAL v7 support. Merge from Codesourcery */
902 {"neon", FPUTYPE_NEON
}
906 /* Floating point models used by the different hardware.
907 See fputype in arm.h. */
909 static const enum fputype fp_model_for_fpu
[] =
911 /* No FP hardware. */
912 ARM_FP_MODEL_UNKNOWN
, /* FPUTYPE_NONE */
913 ARM_FP_MODEL_FPA
, /* FPUTYPE_FPA */
914 ARM_FP_MODEL_FPA
, /* FPUTYPE_FPA_EMU2 */
915 ARM_FP_MODEL_FPA
, /* FPUTYPE_FPA_EMU3 */
916 ARM_FP_MODEL_MAVERICK
, /* FPUTYPE_MAVERICK */
917 /* APPLE LOCAL v7 support. Merge from mainline */
918 ARM_FP_MODEL_VFP
, /* FPUTYPE_VFP */
919 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
920 ARM_FP_MODEL_VFP
, /* FPUTYPE_VFP3 */
921 ARM_FP_MODEL_VFP
/* FPUTYPE_NEON */
922 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
929 enum float_abi_type abi_type
;
933 /* Available values for -mfloat-abi=. */
935 static const struct float_abi all_float_abis
[] =
937 {"soft", ARM_FLOAT_ABI_SOFT
},
938 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
939 {"hard", ARM_FLOAT_ABI_HARD
}
946 enum arm_abi_type abi_type
;
950 /* Available values for -mabi=. */
952 static const struct abi_name arm_all_abis
[] =
954 {"apcs-gnu", ARM_ABI_APCS
},
955 {"atpcs", ARM_ABI_ATPCS
},
956 {"aapcs", ARM_ABI_AAPCS
},
957 {"iwmmxt", ARM_ABI_IWMMXT
},
958 {"aapcs-linux", ARM_ABI_AAPCS_LINUX
}
961 /* Supported TLS relocations. */
971 /* Emit an insn that's a simple single-set. Both the operands must be known
974 emit_set_insn (rtx x
, rtx y
)
976 return emit_insn (gen_rtx_SET (VOIDmode
, x
, y
));
979 /* Return the number of bits set in VALUE. */
981 bit_count (unsigned long value
)
983 unsigned long count
= 0;
988 value
&= value
- 1; /* Clear the least-significant set bit. */
994 /* APPLE LOCAL begin ARM custom frame layout */
995 /* Generate a bitmask that has bits end:start (inclusive) set. */
997 inclusive_bitmask (int start
, int end
)
999 return (((unsigned long) 1 << start
) - 1)
1000 ^ (((unsigned long) 1 << (end
+ 1)) - 1);
1002 /* APPLE LOCAL end ARM custom frame layout */
1004 /* APPLE LOCAL begin ARM compact switch tables */
1005 /* These are library functions, but calls to them are not
1006 represented as calls in the RTL because they do not have
1007 normal function-call semantics. We generate the
1008 Mach-O stuff lazily in this case. */
1010 void register_switch8_libfunc (void)
1013 if (switch8_libfunc
== NULL
)
1014 switch8_libfunc
= gen_rtx_SYMBOL_REF (Pmode
,
1015 ggc_alloc_string ("__switch8", sizeof ("__switch8")));
1016 if (flag_pic
|| MACHO_DYNAMIC_NO_PIC_P
)
1017 machopic_validate_stub_or_non_lazy_ptr
1018 (machopic_indirection_name (switch8_libfunc
, true));
1022 void register_switchu8_libfunc (void)
1025 if (switchu8_libfunc
== NULL
)
1026 switchu8_libfunc
= gen_rtx_SYMBOL_REF (Pmode
,
1027 ggc_alloc_string ("__switchu8", sizeof ("__switchu8")));
1028 if (flag_pic
|| MACHO_DYNAMIC_NO_PIC_P
)
1029 machopic_validate_stub_or_non_lazy_ptr
1030 (machopic_indirection_name (switchu8_libfunc
, true));
1034 void register_switch16_libfunc (void)
1037 if (switch16_libfunc
== NULL
)
1038 switch16_libfunc
= gen_rtx_SYMBOL_REF (Pmode
,
1039 ggc_alloc_string ("__switch16", sizeof ("__switch16")));
1040 if (flag_pic
|| MACHO_DYNAMIC_NO_PIC_P
)
1041 machopic_validate_stub_or_non_lazy_ptr
1042 (machopic_indirection_name (switch16_libfunc
, true));
1046 void register_switch32_libfunc (void)
1049 if (switch32_libfunc
== NULL
)
1050 switch32_libfunc
= gen_rtx_SYMBOL_REF (Pmode
,
1051 ggc_alloc_string ("__switch32", sizeof ("__switch32")));
1052 if (flag_pic
|| MACHO_DYNAMIC_NO_PIC_P
)
1053 machopic_validate_stub_or_non_lazy_ptr
1054 (machopic_indirection_name (switch32_libfunc
, true));
1057 /* APPLE LOCAL end ARM compact switch tables */
1059 /* Set up library functions unique to ARM. */
1062 arm_init_libfuncs (void)
1064 /* APPLE LOCAL begin ARM 4702983 Thumb VFP math */
1065 if (TARGET_MACHO
&& TARGET_THUMB
&& !TARGET_SOFT_FLOAT
1066 && (flag_pic
|| MACHO_DYNAMIC_NO_PIC_P
))
1068 /* Double-precision floating-point arithmetic. */
1069 set_optab_libfunc (add_optab
, DFmode
, "__adddf3vfp");
1070 set_optab_libfunc (sdiv_optab
, DFmode
, "__divdf3vfp");
1071 set_optab_libfunc (smul_optab
, DFmode
, "__muldf3vfp");
1072 set_optab_libfunc (neg_optab
, DFmode
, NULL
);
1073 set_optab_libfunc (sub_optab
, DFmode
, "__subdf3vfp");
1075 /* Double-precision comparisons. */
1076 set_optab_libfunc (eq_optab
, DFmode
, "__eqdf2vfp");
1077 set_optab_libfunc (ne_optab
, DFmode
, "__nedf2vfp");
1078 set_optab_libfunc (lt_optab
, DFmode
, "__ltdf2vfp");
1079 set_optab_libfunc (le_optab
, DFmode
, "__ledf2vfp");
1080 set_optab_libfunc (ge_optab
, DFmode
, "__gedf2vfp");
1081 set_optab_libfunc (gt_optab
, DFmode
, "__gtdf2vfp");
1082 set_optab_libfunc (unord_optab
, DFmode
, "__unorddf2vfp");
1084 /* Single-precision floating-point arithmetic. */
1085 set_optab_libfunc (add_optab
, SFmode
, "__addsf3vfp");
1086 set_optab_libfunc (sdiv_optab
, SFmode
, "__divsf3vfp");
1087 set_optab_libfunc (smul_optab
, SFmode
, "__mulsf3vfp");
1088 set_optab_libfunc (neg_optab
, SFmode
, NULL
);
1089 set_optab_libfunc (sub_optab
, SFmode
, "__subsf3vfp");
1091 /* Single-precision comparisons. */
1092 set_optab_libfunc (eq_optab
, SFmode
, "__eqsf2vfp");
1093 set_optab_libfunc (ne_optab
, SFmode
, "__nesf2vfp");
1094 set_optab_libfunc (lt_optab
, SFmode
, "__ltsf2vfp");
1095 set_optab_libfunc (le_optab
, SFmode
, "__lesf2vfp");
1096 set_optab_libfunc (ge_optab
, SFmode
, "__gesf2vfp");
1097 set_optab_libfunc (gt_optab
, SFmode
, "__gtsf2vfp");
1098 set_optab_libfunc (unord_optab
, SFmode
, "__unordsf2vfp");
1100 /* Floating-point to integer conversions. */
1101 /* DImode conversions are done via library routines even
1102 when generating VFP instructions, so use the same ones. */
1103 set_conv_libfunc (sfix_optab
, SImode
, DFmode
, "__fixdfsivfp");
1104 set_conv_libfunc (ufix_optab
, SImode
, DFmode
, "__fixunsdfsivfp");
1105 set_conv_libfunc (sfix_optab
, SImode
, SFmode
, "__fixsfsivfp");
1106 set_conv_libfunc (ufix_optab
, SImode
, SFmode
, "__fixunssfsivfp");
1108 /* Conversions between floating types. */
1109 set_conv_libfunc (trunc_optab
, SFmode
, DFmode
, "__truncdfsf2vfp");
1110 set_conv_libfunc (sext_optab
, DFmode
, SFmode
, "__extendsfdf2vfp");
1112 /* Integer to floating-point conversions. */
1113 /* DImode conversions are done via library routines even
1114 when generating VFP instructions, so use the same ones. */
1115 set_conv_libfunc (sfloat_optab
, DFmode
, SImode
, "__floatsidfvfp");
1116 set_conv_libfunc (ufloat_optab
, DFmode
, SImode
, "__floatunssidfvfp");
1117 set_conv_libfunc (sfloat_optab
, SFmode
, SImode
, "__floatsisfvfp");
1118 set_conv_libfunc (ufloat_optab
, SFmode
, SImode
, "__floatunssisfvfp");
1121 /* APPLE LOCAL end ARM 4702983 Thumb VFP math */
1123 /* There are no special library functions unless we are using the
1128 /* The functions below are described in Section 4 of the "Run-Time
1129 ABI for the ARM architecture", Version 1.0. */
1131 /* Double-precision floating-point arithmetic. Table 2. */
1132 set_optab_libfunc (add_optab
, DFmode
, "__aeabi_dadd");
1133 set_optab_libfunc (sdiv_optab
, DFmode
, "__aeabi_ddiv");
1134 set_optab_libfunc (smul_optab
, DFmode
, "__aeabi_dmul");
1135 set_optab_libfunc (neg_optab
, DFmode
, "__aeabi_dneg");
1136 set_optab_libfunc (sub_optab
, DFmode
, "__aeabi_dsub");
1138 /* Double-precision comparisons. Table 3. */
1139 set_optab_libfunc (eq_optab
, DFmode
, "__aeabi_dcmpeq");
1140 set_optab_libfunc (ne_optab
, DFmode
, NULL
);
1141 set_optab_libfunc (lt_optab
, DFmode
, "__aeabi_dcmplt");
1142 set_optab_libfunc (le_optab
, DFmode
, "__aeabi_dcmple");
1143 set_optab_libfunc (ge_optab
, DFmode
, "__aeabi_dcmpge");
1144 set_optab_libfunc (gt_optab
, DFmode
, "__aeabi_dcmpgt");
1145 set_optab_libfunc (unord_optab
, DFmode
, "__aeabi_dcmpun");
1147 /* Single-precision floating-point arithmetic. Table 4. */
1148 set_optab_libfunc (add_optab
, SFmode
, "__aeabi_fadd");
1149 set_optab_libfunc (sdiv_optab
, SFmode
, "__aeabi_fdiv");
1150 set_optab_libfunc (smul_optab
, SFmode
, "__aeabi_fmul");
1151 set_optab_libfunc (neg_optab
, SFmode
, "__aeabi_fneg");
1152 set_optab_libfunc (sub_optab
, SFmode
, "__aeabi_fsub");
1154 /* Single-precision comparisons. Table 5. */
1155 set_optab_libfunc (eq_optab
, SFmode
, "__aeabi_fcmpeq");
1156 set_optab_libfunc (ne_optab
, SFmode
, NULL
);
1157 set_optab_libfunc (lt_optab
, SFmode
, "__aeabi_fcmplt");
1158 set_optab_libfunc (le_optab
, SFmode
, "__aeabi_fcmple");
1159 set_optab_libfunc (ge_optab
, SFmode
, "__aeabi_fcmpge");
1160 set_optab_libfunc (gt_optab
, SFmode
, "__aeabi_fcmpgt");
1161 set_optab_libfunc (unord_optab
, SFmode
, "__aeabi_fcmpun");
1163 /* Floating-point to integer conversions. Table 6. */
1164 set_conv_libfunc (sfix_optab
, SImode
, DFmode
, "__aeabi_d2iz");
1165 set_conv_libfunc (ufix_optab
, SImode
, DFmode
, "__aeabi_d2uiz");
1166 set_conv_libfunc (sfix_optab
, DImode
, DFmode
, "__aeabi_d2lz");
1167 set_conv_libfunc (ufix_optab
, DImode
, DFmode
, "__aeabi_d2ulz");
1168 set_conv_libfunc (sfix_optab
, SImode
, SFmode
, "__aeabi_f2iz");
1169 set_conv_libfunc (ufix_optab
, SImode
, SFmode
, "__aeabi_f2uiz");
1170 set_conv_libfunc (sfix_optab
, DImode
, SFmode
, "__aeabi_f2lz");
1171 set_conv_libfunc (ufix_optab
, DImode
, SFmode
, "__aeabi_f2ulz");
1173 /* Conversions between floating types. Table 7. */
1174 set_conv_libfunc (trunc_optab
, SFmode
, DFmode
, "__aeabi_d2f");
1175 set_conv_libfunc (sext_optab
, DFmode
, SFmode
, "__aeabi_f2d");
1177 /* Integer to floating-point conversions. Table 8. */
1178 set_conv_libfunc (sfloat_optab
, DFmode
, SImode
, "__aeabi_i2d");
1179 set_conv_libfunc (ufloat_optab
, DFmode
, SImode
, "__aeabi_ui2d");
1180 set_conv_libfunc (sfloat_optab
, DFmode
, DImode
, "__aeabi_l2d");
1181 set_conv_libfunc (ufloat_optab
, DFmode
, DImode
, "__aeabi_ul2d");
1182 set_conv_libfunc (sfloat_optab
, SFmode
, SImode
, "__aeabi_i2f");
1183 set_conv_libfunc (ufloat_optab
, SFmode
, SImode
, "__aeabi_ui2f");
1184 set_conv_libfunc (sfloat_optab
, SFmode
, DImode
, "__aeabi_l2f");
1185 set_conv_libfunc (ufloat_optab
, SFmode
, DImode
, "__aeabi_ul2f");
1187 /* Long long. Table 9. */
1188 set_optab_libfunc (smul_optab
, DImode
, "__aeabi_lmul");
1189 set_optab_libfunc (sdivmod_optab
, DImode
, "__aeabi_ldivmod");
1190 set_optab_libfunc (udivmod_optab
, DImode
, "__aeabi_uldivmod");
1191 set_optab_libfunc (ashl_optab
, DImode
, "__aeabi_llsl");
1192 set_optab_libfunc (lshr_optab
, DImode
, "__aeabi_llsr");
1193 set_optab_libfunc (ashr_optab
, DImode
, "__aeabi_lasr");
1194 set_optab_libfunc (cmp_optab
, DImode
, "__aeabi_lcmp");
1195 set_optab_libfunc (ucmp_optab
, DImode
, "__aeabi_ulcmp");
1197 /* Integer (32/32->32) division. \S 4.3.1. */
1198 set_optab_libfunc (sdivmod_optab
, SImode
, "__aeabi_idivmod");
1199 set_optab_libfunc (udivmod_optab
, SImode
, "__aeabi_uidivmod");
1201 /* The divmod functions are designed so that they can be used for
1202 plain division, even though they return both the quotient and the
1203 remainder. The quotient is returned in the usual location (i.e.,
1204 r0 for SImode, {r0, r1} for DImode), just as would be expected
1205 for an ordinary division routine. Because the AAPCS calling
1206 conventions specify that all of { r0, r1, r2, r3 } are
1207 callee-saved registers, there is no need to tell the compiler
1208 explicitly that those registers are clobbered by these
1210 set_optab_libfunc (sdiv_optab
, DImode
, "__aeabi_ldivmod");
1211 set_optab_libfunc (udiv_optab
, DImode
, "__aeabi_uldivmod");
1213 /* For SImode division the ABI provides div-without-mod routines,
1214 which are faster. */
1215 set_optab_libfunc (sdiv_optab
, SImode
, "__aeabi_idiv");
1216 set_optab_libfunc (udiv_optab
, SImode
, "__aeabi_uidiv");
1218 /* We don't have mod libcalls. Fortunately gcc knows how to use the
1219 divmod libcalls instead. */
1220 set_optab_libfunc (smod_optab
, DImode
, NULL
);
1221 set_optab_libfunc (umod_optab
, DImode
, NULL
);
1222 set_optab_libfunc (smod_optab
, SImode
, NULL
);
1223 set_optab_libfunc (umod_optab
, SImode
, NULL
);
1226 /* Implement TARGET_HANDLE_OPTION. */
1229 arm_handle_option (size_t code
, const char *arg
, int value ATTRIBUTE_UNUSED
)
1234 arm_select
[1].string
= arg
;
1238 arm_select
[0].string
= arg
;
1241 case OPT_mhard_float
:
1242 target_float_abi_name
= "hard";
1245 case OPT_msoft_float
:
1246 target_float_abi_name
= "soft";
1250 arm_select
[2].string
= arg
;
1258 /* Fix up any incompatible options that the user has specified.
1259 This has now turned into a maze. */
1261 arm_override_options (void)
1264 /* APPLE LOCAL v7 support. Merge from Codesourcery */
1266 enum processor_type target_arch_cpu
= arm_none
;
1268 /* Set up the flags based on the cpu/architecture selected by the user. */
1269 for (i
= ARRAY_SIZE (arm_select
); i
--;)
1271 struct arm_cpu_select
* ptr
= arm_select
+ i
;
1273 if (ptr
->string
!= NULL
&& ptr
->string
[0] != '\0')
1275 const struct processors
* sel
;
1277 for (sel
= ptr
->processors
; sel
->name
!= NULL
; sel
++)
1278 if (streq (ptr
->string
, sel
->name
))
1280 /* Set the architecture define. */
1281 if (i
!= ARM_OPT_SET_TUNE
)
1282 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
1284 len
= snprintf (arm_arch_name
, ARM_ARCH_NAME_SIZE
,
1285 "__ARM_ARCH_%s__", sel
->arch
);
1286 gcc_assert (len
< ARM_ARCH_NAME_SIZE
);
1288 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
1290 /* Determine the processor core for which we should
1291 tune code-generation. */
1292 if (/* -mcpu= is a sensible default. */
1293 i
== ARM_OPT_SET_CPU
1294 /* -mtune= overrides -mcpu= and -march=. */
1295 || i
== ARM_OPT_SET_TUNE
)
1296 arm_tune
= (enum processor_type
) (sel
- ptr
->processors
);
1298 /* Remember the CPU associated with this architecture.
1299 If no other option is used to set the CPU type,
1300 we'll use this to guess the most suitable tuning
1302 if (i
== ARM_OPT_SET_ARCH
)
1303 target_arch_cpu
= sel
->core
;
1305 if (i
!= ARM_OPT_SET_TUNE
)
1307 /* APPLE LOCAL begin ARM darwin driver */
1309 /* If we have been given an architecture and a processor
1310 make sure that they are compatible. We only generate
1311 a warning though, and we prefer the CPU over the
1313 if (insn_flags
!= 0 && (insn_flags
^ sel
->flags
))
1314 warning (0, "switch -mcpu=%s conflicts with -march= switch",
1317 /* More likely the -march was inherited from -arch which
1318 had to be given to the darwin driver to get the correct
1319 compiler. So, make it relatively painless to specify
1320 -mcpu=... by not warning that it supercedes -march. */
1322 /* APPLE LOCAL end ARM darwin driver */
1324 insn_flags
= sel
->flags
;
1330 if (sel
->name
== NULL
)
1331 error ("bad value (%s) for %s switch", ptr
->string
, ptr
->name
);
1335 /* Guess the tuning options from the architecture if necessary. */
1336 if (arm_tune
== arm_none
)
1337 arm_tune
= target_arch_cpu
;
1339 /* If the user did not specify a processor, choose one for them. */
1340 if (insn_flags
== 0)
1342 const struct processors
* sel
;
1343 unsigned int sought
;
1344 enum processor_type cpu
;
1346 cpu
= TARGET_CPU_DEFAULT
;
1347 if (cpu
== arm_none
)
1349 #ifdef SUBTARGET_CPU_DEFAULT
1350 /* Use the subtarget default CPU if none was specified by
1352 cpu
= SUBTARGET_CPU_DEFAULT
;
1354 /* Default to ARM6. */
1355 if (cpu
== arm_none
)
1358 sel
= &all_cores
[cpu
];
1360 insn_flags
= sel
->flags
;
1362 /* Now check to see if the user has specified some command line
1363 switch that require certain abilities from the cpu. */
1366 if (TARGET_INTERWORK
|| TARGET_THUMB
)
1368 sought
|= (FL_THUMB
| FL_MODE32
);
1370 /* There are no ARM processors that support both APCS-26 and
1371 interworking. Therefore we force FL_MODE26 to be removed
1372 from insn_flags here (if it was set), so that the search
1373 below will always be able to find a compatible processor. */
1374 insn_flags
&= ~FL_MODE26
;
1377 if (sought
!= 0 && ((sought
& insn_flags
) != sought
))
1379 /* Try to locate a CPU type that supports all of the abilities
1380 of the default CPU, plus the extra abilities requested by
1382 for (sel
= all_cores
; sel
->name
!= NULL
; sel
++)
1383 if ((sel
->flags
& sought
) == (sought
| insn_flags
))
1386 if (sel
->name
== NULL
)
1388 unsigned current_bit_count
= 0;
1389 const struct processors
* best_fit
= NULL
;
1391 /* Ideally we would like to issue an error message here
1392 saying that it was not possible to find a CPU compatible
1393 with the default CPU, but which also supports the command
1394 line options specified by the programmer, and so they
1395 ought to use the -mcpu=<name> command line option to
1396 override the default CPU type.
1398 If we cannot find a cpu that has both the
1399 characteristics of the default cpu and the given
1400 command line options we scan the array again looking
1401 for a best match. */
1402 for (sel
= all_cores
; sel
->name
!= NULL
; sel
++)
1403 if ((sel
->flags
& sought
) == sought
)
1407 count
= bit_count (sel
->flags
& insn_flags
);
1409 if (count
>= current_bit_count
)
1412 current_bit_count
= count
;
1416 gcc_assert (best_fit
);
1420 insn_flags
= sel
->flags
;
1422 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
1424 len
= snprintf (arm_arch_name
, ARM_ARCH_NAME_SIZE
,
1425 "__ARM_ARCH_%s__", sel
->arch
);
1426 gcc_assert (len
< ARM_ARCH_NAME_SIZE
);
1428 arm_default_cpu
= (enum processor_type
) (sel
- all_cores
);
1429 if (arm_tune
== arm_none
)
1430 arm_tune
= arm_default_cpu
;
1431 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
1434 /* The processor for which we should tune should now have been
1436 gcc_assert (arm_tune
!= arm_none
);
1438 tune_flags
= all_cores
[(int)arm_tune
].flags
;
1440 targetm
.rtx_costs
= arm_size_rtx_costs
;
1442 targetm
.rtx_costs
= all_cores
[(int)arm_tune
].rtx_costs
;
1444 /* Make sure that the processor choice does not conflict with any of the
1445 other command line choices. */
1446 /* APPLE LOCAL begin v7 support. Merge from mainline */
1447 if (TARGET_ARM
&& !(insn_flags
& FL_NOTM
))
1448 error ("target CPU does not support ARM mode");
1449 /* APPLE LOCAL end v7 support. Merge from mainline */
1451 if (TARGET_INTERWORK
&& !(insn_flags
& FL_THUMB
))
1453 /* APPLE LOCAL begin ARM interworking */
1454 /* Don't emit warning for MACHO -- see radar://4825264 */
1456 warning (0, "target CPU does not support interworking" );
1458 interwork_option
= 0;
1459 /* APPLE LOCAL end ARM interworking */
1462 /* APPLE LOCAL begin 6150882 use thumb2 by default for v7 */
1463 /* If we're compiling for v7, we should default to using thumb2
1465 if ((insn_flags
& FL_FOR_ARCH7A
) == FL_FOR_ARCH7A
1466 && thumb_option
< 0)
1468 /* APPLE LOCAL end 6150882 use thumb2 by default for v7 */
1470 if (TARGET_THUMB
&& !(insn_flags
& FL_THUMB
))
1472 warning (0, "target CPU does not support THUMB instructions");
1473 /* APPLE LOCAL 6150882 use thumb2 by default for v7 */
1477 if (TARGET_APCS_FRAME
&& TARGET_THUMB
)
1479 /* warning (0, "ignoring -mapcs-frame because -mthumb was used"); */
1480 target_flags
&= ~MASK_APCS_FRAME
;
1483 /* Callee super interworking implies thumb interworking. Adding
1484 this to the flags here simplifies the logic elsewhere. */
1485 if (TARGET_THUMB
&& TARGET_CALLEE_INTERWORKING
)
1486 /* APPLE LOCAL ARM interworking */
1487 interwork_option
= 1;
1489 /* TARGET_BACKTRACE calls leaf_function_p, which causes a crash if done
1490 from here where no function is being compiled currently. */
1491 if ((TARGET_TPCS_FRAME
|| TARGET_TPCS_LEAF_FRAME
) && TARGET_ARM
)
1492 warning (0, "enabling backtrace support is only meaningful when compiling for the Thumb");
1494 if (TARGET_ARM
&& TARGET_CALLEE_INTERWORKING
)
1495 warning (0, "enabling callee interworking support is only meaningful when compiling for the Thumb");
1497 if (TARGET_ARM
&& TARGET_CALLER_INTERWORKING
)
1498 warning (0, "enabling caller interworking support is only meaningful when compiling for the Thumb");
1500 if (TARGET_APCS_STACK
&& !TARGET_APCS_FRAME
)
1502 warning (0, "-mapcs-stack-check incompatible with -mno-apcs-frame");
1503 target_flags
|= MASK_APCS_FRAME
;
1506 if (TARGET_POKE_FUNCTION_NAME
)
1507 target_flags
|= MASK_APCS_FRAME
;
1509 if (TARGET_APCS_REENT
&& flag_pic
)
1510 error ("-fpic and -mapcs-reent are incompatible");
1512 if (TARGET_APCS_REENT
)
1513 warning (0, "APCS reentrant code not supported. Ignored");
1515 /* If this target is normally configured to use APCS frames, warn if they
1516 are turned off and debugging is turned on. */
1518 && write_symbols
!= NO_DEBUG
1519 && !TARGET_APCS_FRAME
1520 && (TARGET_DEFAULT
& MASK_APCS_FRAME
))
1521 warning (0, "-g with -mno-apcs-frame may not give sensible debugging");
1523 /* APPLE LOCAL begin 6879229 disallow -fasm-blocks */
1524 if (flag_iasm_blocks
)
1525 error ("-fasm-blocks option not supported for ARM");
1526 /* APPLE LOCAL end 6879229 disallow -fasm-blocks */
1528 /* If stack checking is disabled, we can use r10 as the PIC register,
1529 which keeps r9 available. */
1530 /* APPLE LOCAL ARM pic support */
1531 if (flag_pic
&& TARGET_SINGLE_PIC_BASE
&& !TARGET_MACHO
)
1532 arm_pic_register
= TARGET_APCS_STACK
? 9 : 10;
1534 if (TARGET_APCS_FLOAT
)
1535 warning (0, "passing floating point arguments in fp regs not yet supported");
1537 /* Initialize boolean versions of the flags, for use in the arm.md file. */
1538 arm_arch3m
= (insn_flags
& FL_ARCH3M
) != 0;
1539 arm_arch4
= (insn_flags
& FL_ARCH4
) != 0;
1540 arm_arch4t
= arm_arch4
& ((insn_flags
& FL_THUMB
) != 0);
1541 arm_arch5
= (insn_flags
& FL_ARCH5
) != 0;
1542 arm_arch5e
= (insn_flags
& FL_ARCH5E
) != 0;
1543 arm_arch6
= (insn_flags
& FL_ARCH6
) != 0;
1544 arm_arch6k
= (insn_flags
& FL_ARCH6K
) != 0;
1545 /* APPLE LOCAL 6093388 -mfpu=neon default for v7a */
1546 arm_arch7a
= (insn_flags
& FL_FOR_ARCH7A
) == FL_FOR_ARCH7A
;
1547 /* APPLE LOCAL begin v7 support. Merge from mainline */
1548 arm_arch_notm
= (insn_flags
& FL_NOTM
) != 0;
1549 arm_arch_thumb2
= (insn_flags
& FL_THUMB2
) != 0;
1550 /* APPLE LOCAL end v7 support. Merge from mainline */
1551 arm_arch_xscale
= (insn_flags
& FL_XSCALE
) != 0;
1552 arm_arch_cirrus
= (insn_flags
& FL_CIRRUS
) != 0;
1554 arm_ld_sched
= (tune_flags
& FL_LDSCHED
) != 0;
1555 arm_tune_strongarm
= (tune_flags
& FL_STRONG
) != 0;
1556 thumb_code
= (TARGET_ARM
== 0);
1557 arm_tune_wbuf
= (tune_flags
& FL_WBUF
) != 0;
1558 arm_tune_xscale
= (tune_flags
& FL_XSCALE
) != 0;
1559 arm_arch_iwmmxt
= (insn_flags
& FL_IWMMXT
) != 0;
1560 /* APPLE LOCAL v7 support. Merge from mainline */
1561 arm_arch_hwdiv
= (insn_flags
& FL_DIV
) != 0;
1563 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
1564 /* If we are not using the default (ARM mode) section anchor offset
1565 ranges, then set the correct ranges now. */
1568 /* Thumb-1 LDR instructions cannot have negative offsets.
1569 Permissible positive offset ranges are 5-bit (for byte loads),
1570 6-bit (for halfword loads), or 7-bit (for word loads).
1571 Empirical results suggest a 7-bit anchor range gives the best
1572 overall code size. */
1573 targetm
.min_anchor_offset
= 0;
1574 targetm
.max_anchor_offset
= 127;
1576 else if (TARGET_THUMB2
)
1578 /* The minimum is set such that the total size of the block
1579 for a particular anchor is 248 + 1 + 4095 bytes, which is
1580 divisible by eight, ensuring natural spacing of anchors. */
1581 targetm
.min_anchor_offset
= -248;
1582 targetm
.max_anchor_offset
= 4095;
1585 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
1586 /* APPLE LOCAL begin ARM interworking */
1587 /* Choose a default interworking setting if not specified on the
1589 if (interwork_option
== -1)
1590 interwork_option
= arm_arch5
? 1 : 0;
1592 /* XXX However, we must pass the right pre-processor defines to CPP
1593 or GLD can get confused. This is a hack. */
1594 if (TARGET_INTERWORK
)
1595 arm_cpp_interwork
= 1;
1596 /* APPLE LOCAL end ARM interworking */
1598 if (target_abi_name
)
1600 for (i
= 0; i
< ARRAY_SIZE (arm_all_abis
); i
++)
1602 if (streq (arm_all_abis
[i
].name
, target_abi_name
))
1604 arm_abi
= arm_all_abis
[i
].abi_type
;
1608 if (i
== ARRAY_SIZE (arm_all_abis
))
1609 error ("invalid ABI option: -mabi=%s", target_abi_name
);
1612 arm_abi
= ARM_DEFAULT_ABI
;
1614 if (TARGET_IWMMXT
&& !ARM_DOUBLEWORD_ALIGN
)
1615 error ("iwmmxt requires an AAPCS compatible ABI for proper operation");
1617 if (TARGET_IWMMXT_ABI
&& !TARGET_IWMMXT
)
1618 error ("iwmmxt abi requires an iwmmxt capable cpu");
1620 arm_fp_model
= ARM_FP_MODEL_UNKNOWN
;
1621 if (target_fpu_name
== NULL
&& target_fpe_name
!= NULL
)
1623 if (streq (target_fpe_name
, "2"))
1624 target_fpu_name
= "fpe2";
1625 else if (streq (target_fpe_name
, "3"))
1626 target_fpu_name
= "fpe3";
1628 error ("invalid floating point emulation option: -mfpe=%s",
1631 if (target_fpu_name
!= NULL
)
1633 /* The user specified a FPU. */
1634 for (i
= 0; i
< ARRAY_SIZE (all_fpus
); i
++)
1636 if (streq (all_fpus
[i
].name
, target_fpu_name
))
1638 arm_fpu_arch
= all_fpus
[i
].fpu
;
1639 arm_fpu_tune
= arm_fpu_arch
;
1640 arm_fp_model
= fp_model_for_fpu
[arm_fpu_arch
];
1644 if (arm_fp_model
== ARM_FP_MODEL_UNKNOWN
)
1645 error ("invalid floating point option: -mfpu=%s", target_fpu_name
);
1649 #ifdef FPUTYPE_DEFAULT
1650 /* Use the default if it is specified for this platform. */
1651 arm_fpu_arch
= FPUTYPE_DEFAULT
;
1652 arm_fpu_tune
= FPUTYPE_DEFAULT
;
1654 /* Pick one based on CPU type. */
1655 /* ??? Some targets assume FPA is the default.
1656 if ((insn_flags & FL_VFP) != 0)
1657 arm_fpu_arch = FPUTYPE_VFP;
1660 if (arm_arch_cirrus
)
1661 arm_fpu_arch
= FPUTYPE_MAVERICK
;
1663 arm_fpu_arch
= FPUTYPE_FPA_EMU2
;
1665 if (tune_flags
& FL_CO_PROC
&& arm_fpu_arch
== FPUTYPE_FPA_EMU2
)
1666 arm_fpu_tune
= FPUTYPE_FPA
;
1668 arm_fpu_tune
= arm_fpu_arch
;
1669 arm_fp_model
= fp_model_for_fpu
[arm_fpu_arch
];
1670 gcc_assert (arm_fp_model
!= ARM_FP_MODEL_UNKNOWN
);
1673 if (target_float_abi_name
!= NULL
)
1675 /* The user specified a FP ABI. */
1676 for (i
= 0; i
< ARRAY_SIZE (all_float_abis
); i
++)
1678 if (streq (all_float_abis
[i
].name
, target_float_abi_name
))
1680 arm_float_abi
= all_float_abis
[i
].abi_type
;
1684 if (i
== ARRAY_SIZE (all_float_abis
))
1685 error ("invalid floating point abi: -mfloat-abi=%s",
1686 target_float_abi_name
);
1689 arm_float_abi
= TARGET_DEFAULT_FLOAT_ABI
;
1691 /* LLVM LOCAL begin */
1693 if (arm_float_abi
== ARM_FLOAT_ABI_HARD
&& TARGET_VFP
)
1694 sorry ("-mfloat-abi=hard and VFP");
1696 /* LLVM LOCAL end */
1698 /* FPA and iWMMXt are incompatible because the insn encodings overlap.
1699 VFP and iWMMXt can theoretically coexist, but it's unlikely such silicon
1700 will ever exist. GCC makes no attempt to support this combination. */
1701 if (TARGET_IWMMXT
&& !TARGET_SOFT_FLOAT
)
1702 sorry ("iWMMXt and hardware floating point");
1704 /* APPLE LOCAL begin v7 support. Merge from mainline */
1705 /* ??? iWMMXt insn patterns need auditing for Thumb-2. */
1706 if (TARGET_THUMB2
&& TARGET_IWMMXT
)
1707 sorry ("Thumb-2 iWMMXt");
1709 /* APPLE LOCAL end v7 support. Merge from mainline */
1710 /* If soft-float is specified then don't use FPU. */
1711 if (TARGET_SOFT_FLOAT
)
1712 arm_fpu_arch
= FPUTYPE_NONE
;
1714 /* For arm2/3 there is no need to do any scheduling if there is only
1715 a floating point emulator, or we are doing software floating-point. */
1716 if ((TARGET_SOFT_FLOAT
1717 || arm_fpu_tune
== FPUTYPE_FPA_EMU2
1718 || arm_fpu_tune
== FPUTYPE_FPA_EMU3
)
1719 && (tune_flags
& FL_MODE32
) == 0)
1720 flag_schedule_insns
= flag_schedule_insns_after_reload
= 0;
1722 if (target_thread_switch
)
1724 if (strcmp (target_thread_switch
, "soft") == 0)
1725 target_thread_pointer
= TP_SOFT
;
1726 else if (strcmp (target_thread_switch
, "auto") == 0)
1727 target_thread_pointer
= TP_AUTO
;
1728 else if (strcmp (target_thread_switch
, "cp15") == 0)
1729 target_thread_pointer
= TP_CP15
;
1731 error ("invalid thread pointer option: -mtp=%s", target_thread_switch
);
1734 /* Use the cp15 method if it is available. */
1735 if (target_thread_pointer
== TP_AUTO
)
1737 if (arm_arch6k
&& !TARGET_THUMB
)
1738 target_thread_pointer
= TP_CP15
;
1740 target_thread_pointer
= TP_SOFT
;
1743 /* APPLE LOCAL begin v7 support. Merge from mainline */
1744 if (TARGET_HARD_TP
&& TARGET_THUMB1
)
1745 error ("can not use -mtp=cp15 with 16-bit Thumb");
1746 /* APPLE LOCAL end v7 support. Merge from mainline */
1748 /* Override the default structure alignment for AAPCS ABI. */
1749 if (TARGET_AAPCS_BASED
)
1750 arm_structure_size_boundary
= 8;
1752 if (structure_size_string
!= NULL
)
1754 int size
= strtol (structure_size_string
, NULL
, 0);
1756 if (size
== 8 || size
== 32
1757 || (ARM_DOUBLEWORD_ALIGN
&& size
== 64))
1758 arm_structure_size_boundary
= size
;
1760 warning (0, "structure size boundary can only be set to %s",
1761 ARM_DOUBLEWORD_ALIGN
? "8, 32 or 64": "8 or 32");
1764 if (arm_pic_register_string
!= NULL
)
1766 int pic_register
= decode_reg_name (arm_pic_register_string
);
1769 warning (0, "-mpic-register= is useless without -fpic");
1771 /* Prevent the user from choosing an obviously stupid PIC register. */
1772 else if (pic_register
< 0 || call_used_regs
[pic_register
]
1773 || pic_register
== HARD_FRAME_POINTER_REGNUM
1774 || pic_register
== STACK_POINTER_REGNUM
1775 || pic_register
>= PC_REGNUM
)
1776 error ("unable to use '%s' for PIC register", arm_pic_register_string
);
1778 arm_pic_register
= pic_register
;
1781 /* APPLE LOCAL v7 support. Merge from mainline */
1782 /* ??? We might want scheduling for thumb2. */
1783 if (TARGET_THUMB
&& flag_schedule_insns
)
1785 /* Don't warn since it's on by default in -O2. */
1786 flag_schedule_insns
= 0;
1791 arm_constant_limit
= 1;
1793 /* If optimizing for size, bump the number of instructions that we
1794 are prepared to conditionally execute (even on a StrongARM). */
1795 max_insns_skipped
= 6;
1799 /* For processors with load scheduling, it never costs more than
1800 2 cycles to load a constant, and the load scheduler may well
1801 reduce that to 1. */
1803 arm_constant_limit
= 1;
1805 /* On XScale the longer latency of a load makes it more difficult
1806 to achieve a good schedule, so it's faster to synthesize
1807 constants that can be done in two insns. */
1808 if (arm_tune_xscale
)
1809 arm_constant_limit
= 2;
1811 /* StrongARM has early execution of branches, so a sequence
1812 that is worth skipping is shorter. */
1813 if (arm_tune_strongarm
)
1814 max_insns_skipped
= 3;
1817 /* APPLE LOCAL begin ARM darwin options */
1818 #ifdef SUBTARGET_OVERRIDE_OPTIONS
1819 SUBTARGET_OVERRIDE_OPTIONS
;
1822 #ifdef SUBSUBTARGET_OVERRIDE_OPTIONS
1823 SUBSUBTARGET_OVERRIDE_OPTIONS
;
1825 /* APPLE LOCAL end ARM darwin options */
1827 /* Register global variables with the garbage collector. */
1828 arm_add_gc_roots ();
1832 arm_add_gc_roots (void)
1834 gcc_obstack_init(&minipool_obstack
);
1835 minipool_startobj
= (char *) obstack_alloc (&minipool_obstack
, 0);
1838 /* A table of known ARM exception types.
1839 For use with the interrupt function attribute. */
1843 const char *const arg
;
1844 const unsigned long return_value
;
1848 static const isr_attribute_arg isr_attribute_args
[] =
1850 { "IRQ", ARM_FT_ISR
},
1851 { "irq", ARM_FT_ISR
},
1852 { "FIQ", ARM_FT_FIQ
},
1853 { "fiq", ARM_FT_FIQ
},
1854 { "ABORT", ARM_FT_ISR
},
1855 { "abort", ARM_FT_ISR
},
1856 { "ABORT", ARM_FT_ISR
},
1857 { "abort", ARM_FT_ISR
},
1858 { "UNDEF", ARM_FT_EXCEPTION
},
1859 { "undef", ARM_FT_EXCEPTION
},
1860 { "SWI", ARM_FT_EXCEPTION
},
1861 { "swi", ARM_FT_EXCEPTION
},
1862 { NULL
, ARM_FT_NORMAL
}
1865 /* Returns the (interrupt) function type of the current
1866 function, or ARM_FT_UNKNOWN if the type cannot be determined. */
1868 static unsigned long
1869 arm_isr_value (tree argument
)
1871 const isr_attribute_arg
* ptr
;
1874 /* APPLE LOCAL begin v7 support. Merge from mainline */
1876 return ARM_FT_NORMAL
| ARM_FT_STACKALIGN
;
1878 /* APPLE LOCAL end v7 support. Merge from mainline */
1879 /* No argument - default to IRQ. */
1880 if (argument
== NULL_TREE
)
1883 /* Get the value of the argument. */
1884 if (TREE_VALUE (argument
) == NULL_TREE
1885 || TREE_CODE (TREE_VALUE (argument
)) != STRING_CST
)
1886 return ARM_FT_UNKNOWN
;
1888 arg
= TREE_STRING_POINTER (TREE_VALUE (argument
));
1890 /* Check it against the list of known arguments. */
1891 for (ptr
= isr_attribute_args
; ptr
->arg
!= NULL
; ptr
++)
1892 if (streq (arg
, ptr
->arg
))
1893 return ptr
->return_value
;
1895 /* An unrecognized interrupt type. */
1896 return ARM_FT_UNKNOWN
;
1899 /* Computes the type of the current function. */
1901 static unsigned long
1902 arm_compute_func_type (void)
1904 unsigned long type
= ARM_FT_UNKNOWN
;
1908 gcc_assert (TREE_CODE (current_function_decl
) == FUNCTION_DECL
);
1910 /* Decide if the current function is volatile. Such functions
1911 never return, and many memory cycles can be saved by not storing
1912 register values that will never be needed again. This optimization
1913 was added to speed up context switching in a kernel application. */
1915 && (TREE_NOTHROW (current_function_decl
)
1916 || !(flag_unwind_tables
1917 || (flag_exceptions
&& !USING_SJLJ_EXCEPTIONS
)))
1918 && TREE_THIS_VOLATILE (current_function_decl
))
1919 type
|= ARM_FT_VOLATILE
;
1921 if (cfun
->static_chain_decl
!= NULL
)
1922 type
|= ARM_FT_NESTED
;
1924 attr
= DECL_ATTRIBUTES (current_function_decl
);
1926 a
= lookup_attribute ("naked", attr
);
1928 type
|= ARM_FT_NAKED
;
1930 a
= lookup_attribute ("isr", attr
);
1932 a
= lookup_attribute ("interrupt", attr
);
1935 /* APPLE LOCAL ARM interworking */
1936 type
|= (TARGET_INTERWORK
&& !arm_arch5
) ? ARM_FT_INTERWORKED
: ARM_FT_NORMAL
;
1938 type
|= arm_isr_value (TREE_VALUE (a
));
1943 /* Returns the type of the current function. */
1946 arm_current_func_type (void)
1948 if (ARM_FUNC_TYPE (cfun
->machine
->func_type
) == ARM_FT_UNKNOWN
)
1949 cfun
->machine
->func_type
= arm_compute_func_type ();
1951 return cfun
->machine
->func_type
;
1954 /* APPLE LOCAL begin ARM indirect sibcalls */
1955 /* Look for an indirect sibling call that uses a callee-saved reg.
1956 We'll need to copy this reg to IP and change the call, since
1957 the callee-saved reg will be clobbered by the restore of the old
1958 value. (This negates the code size advantage of the sibcall, but
1959 not the gain in stack size at runtime.) */
1962 indirect_sibreturn_reg (rtx sibling
, bool *is_value
)
1964 if (GET_CODE (sibling
) == CALL_INSN
1965 && GET_CODE (PATTERN (sibling
)) == PARALLEL
1966 && GET_CODE (XVECEXP (PATTERN (sibling
), 0, 0)) == CALL
1967 && GET_CODE (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 0)) == MEM
1968 && GET_CODE (XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 0), 0)) == REG
)
1971 return REGNO (XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 0), 0));
1973 if (GET_CODE (sibling
) == CALL_INSN
1974 && GET_CODE (PATTERN (sibling
)) == PARALLEL
1975 && GET_CODE (XVECEXP (PATTERN (sibling
), 0, 0)) == SET
1976 && GET_CODE (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 1)) == CALL
1977 && GET_CODE (XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 1), 0)) == MEM
1978 && GET_CODE (XEXP (XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 1), 0), 0)) == REG
)
1981 return REGNO (XEXP (XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 1), 0), 0));
1986 /* Look for an indirect sibling call that uses a memory location, at
1987 reg + or - constant; this will be a stack location, but registers
1988 other than SP and FP are possible with large stack frames.
1989 We'll need to load this location into IP and change the call, since
1990 a memory location is not valid in the instruction. (The usual approach
1991 of forcing reload to copy the value into a register through predicates
1992 and constraints will not work here, as the load would come out after
1993 the restore of FP and SP, too late.)
1994 Return value = signed offset from register *reg (usually SP or FP).
1995 Null if this case doesn't apply.
1996 We do not check for offsets too big to fit in a load, nor offsets in a
1997 register; it is believed that these cases cannot occur. */
2000 indirect_sibreturn_mem (rtx sibling
, rtx
* reg
, bool *is_value
)
2003 if (GET_CODE (sibling
) == CALL_INSN
2004 && GET_CODE (PATTERN (sibling
)) == PARALLEL
2005 && GET_CODE (XVECEXP (PATTERN (sibling
), 0, 0)) == CALL
2006 && GET_CODE (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 0)) == MEM
2007 && GET_CODE (XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 0), 0)) == MEM
)
2010 mem
= XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 0), 0);
2012 else if (GET_CODE (sibling
) == CALL_INSN
2013 && GET_CODE (PATTERN (sibling
)) == PARALLEL
2014 && GET_CODE (XVECEXP (PATTERN (sibling
), 0, 0)) == SET
2015 && GET_CODE (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 1)) == CALL
2016 && GET_CODE (XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 1), 0)) == MEM
2017 && GET_CODE (XEXP (XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 1), 0), 0)) == MEM
)
2020 mem
= XEXP (XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 1), 0), 0);
2023 && GET_CODE (XEXP (mem
, 0)) == PLUS
2024 && GET_CODE (XEXP (XEXP (mem
, 0), 0)) == REG
2025 && GET_CODE (XEXP (XEXP (mem
, 0), 1)) == CONST_INT
)
2027 *reg
= XEXP (XEXP (mem
, 0), 0);
2028 return XEXP (XEXP (mem
, 0), 1);
2030 else if (mem
&& GET_CODE (XEXP (mem
, 0)) == REG
)
2032 *reg
= XEXP (mem
, 0);
2037 /* APPLE LOCAL end ARM indirect sibcalls */
2039 /* Return 1 if it is possible to return using a single instruction.
2040 If SIBLING is non-null, this is a test for a return before a sibling
2041 call. SIBLING is the call insn, so we can examine its register usage. */
2044 use_return_insn (int iscond
, rtx sibling
)
2047 unsigned int func_type
;
2048 unsigned long saved_int_regs
;
2049 unsigned HOST_WIDE_INT stack_adjust
;
2050 arm_stack_offsets
*offsets
;
2052 /* Never use a return instruction before reload has run. */
2053 if (!reload_completed
)
2056 func_type
= arm_current_func_type ();
2058 /* APPLE LOCAL begin v7 support. Merge from mainline */
2059 /* Naked, volatile and stack alignment functions need special
2061 if (func_type
& (ARM_FT_VOLATILE
| ARM_FT_NAKED
| ARM_FT_STACKALIGN
))
2064 /* So do interrupt functions that use the frame pointer and Thumb
2065 interrupt functions. */
2066 if (IS_INTERRUPT (func_type
) && (frame_pointer_needed
|| TARGET_THUMB
))
2068 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
2070 offsets
= arm_get_frame_offsets ();
2071 stack_adjust
= offsets
->outgoing_args
- offsets
->saved_regs
;
2073 /* As do variadic functions. */
2074 if (current_function_pretend_args_size
2075 || cfun
->machine
->uses_anonymous_args
2076 /* Or if the function calls __builtin_eh_return () */
2077 || current_function_calls_eh_return
2078 /* Or if the function calls alloca */
2079 || current_function_calls_alloca
2080 /* APPLE LOCAL begin ARM custom frame layout */
2081 /* Or if there is a stack adjustment. */
2082 || !(stack_adjust
== 0))
2083 /* APPLE LOCAL end ARM custom frame layout */
2086 saved_int_regs
= arm_compute_save_reg_mask ();
2088 /* Unfortunately, the insn
2090 ldmib sp, {..., sp, ...}
2092 triggers a bug on most SA-110 based devices, such that the stack
2093 pointer won't be correctly restored if the instruction takes a
2094 page fault. We work around this problem by popping r3 along with
2095 the other registers, since that is never slower than executing
2096 another instruction.
2098 We test for !arm_arch5 here, because code for any architecture
2099 less than this could potentially be run on one of the buggy
2101 /* APPLE LOCAL v7 support. Merge from mainline */
2102 if (stack_adjust
== 4 && !arm_arch5
&& TARGET_ARM
)
2104 /* Validate that r3 is a call-clobbered register (always true in
2105 the default abi) ... */
2106 if (!call_used_regs
[3])
2109 /* ... that it isn't being used for a return value ... */
2110 if (arm_size_return_regs () >= (4 * UNITS_PER_WORD
))
2113 /* ... or for a tail-call argument ... */
2116 gcc_assert (GET_CODE (sibling
) == CALL_INSN
);
2118 if (find_regno_fusage (sibling
, USE
, 3))
2121 /* APPLE LOCAL begin ARM indirect sibcalls */
2122 /* ... or to hold the target address for an indirect sibcall. */
2125 int regno
= indirect_sibreturn_reg (sibling
, &ignored
);
2129 /* APPLE LOCAL end ARM indirect sibcalls */
2132 /* ... and that there are no call-saved registers in r0-r2
2133 (always true in the default ABI). */
2134 if (saved_int_regs
& 0x7)
2138 /* Can't be done if interworking with Thumb, and any registers have been
2140 /* APPLE LOCAL ARM interworking */
2141 if (TARGET_INTERWORK
&& !arm_arch5
&& saved_int_regs
!= 0)
2144 /* On StrongARM, conditional returns are expensive if they aren't
2145 taken and multiple registers have been stacked. */
2146 if (iscond
&& arm_tune_strongarm
)
2148 /* Conditional return when just the LR is stored is a simple
2149 conditional-load instruction, that's not expensive. */
2150 if (saved_int_regs
!= 0 && saved_int_regs
!= (1 << LR_REGNUM
))
2154 && arm_pic_register
!= INVALID_REGNUM
2155 && regs_ever_live
[PIC_OFFSET_TABLE_REGNUM
])
2159 /* If there are saved registers but the LR isn't saved, then we need
2160 two instructions for the return. */
2161 if (saved_int_regs
&& !(saved_int_regs
& (1 << LR_REGNUM
)))
2164 /* APPLE LOCAL begin ARM indirect sibcalls */
2165 /* If we have an indirect sibcall that uses a saved reg, we'll need
2166 to copy that value into IP before restoring. */
2170 int regno
= indirect_sibreturn_reg (sibling
, &ignored
);
2171 if (regno
> 3 && regno
!= 12)
2176 /* APPLE LOCAL end ARM indirect sibcalls */
2178 /* Can't be done if any of the FPA regs are pushed,
2179 since this also requires an insn. */
2180 if (TARGET_HARD_FLOAT
&& TARGET_FPA
)
2181 for (regno
= FIRST_FPA_REGNUM
; regno
<= LAST_FPA_REGNUM
; regno
++)
2182 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
2185 /* Likewise VFP regs. */
2186 if (TARGET_HARD_FLOAT
&& TARGET_VFP
)
2187 for (regno
= FIRST_VFP_REGNUM
; regno
<= LAST_VFP_REGNUM
; regno
++)
2188 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
2191 if (TARGET_REALLY_IWMMXT
)
2192 for (regno
= FIRST_IWMMXT_REGNUM
; regno
<= LAST_IWMMXT_REGNUM
; regno
++)
2193 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
2196 /* APPLE LOCAL begin ARM custom frame layout */
2197 /* If anything above the frame pointer was saved, they were saved
2198 below r0, which means we have to pop them in a separate
2200 if (saved_int_regs
& (1 << LR_REGNUM
))
2201 for (regno
= ARM_HARD_FRAME_POINTER_REGNUM
+ 1; regno
<= 11; regno
++)
2202 if (saved_int_regs
& (1 << regno
))
2204 /* APPLE LOCAL end ARM custom frame layout */
2209 /* Return TRUE if int I is a valid immediate ARM constant. */
2212 const_ok_for_arm (HOST_WIDE_INT i
)
2216 /* For machines with >32 bit HOST_WIDE_INT, the bits above bit 31 must
2217 be all zero, or all one. */
2218 if ((i
& ~(unsigned HOST_WIDE_INT
) 0xffffffff) != 0
2219 && ((i
& ~(unsigned HOST_WIDE_INT
) 0xffffffff)
2220 != ((~(unsigned HOST_WIDE_INT
) 0)
2221 & ~(unsigned HOST_WIDE_INT
) 0xffffffff)))
2224 i
&= (unsigned HOST_WIDE_INT
) 0xffffffff;
2226 /* Fast return for 0 and small values. We must do this for zero, since
2227 the code below can't handle that one case. */
2228 if ((i
& ~(unsigned HOST_WIDE_INT
) 0xff) == 0)
2231 /* APPLE LOCAL begin v7 support. Merge from mainline */
2232 /* Get the number of trailing zeros. */
2233 lowbit
= ffs((int) i
) - 1;
2235 /* Only even shifts are allowed in ARM mode so round down to the
2236 nearest even number. */
2240 if ((i
& ~(((unsigned HOST_WIDE_INT
) 0xff) << lowbit
)) == 0)
2245 /* Allow rotated constants in ARM mode. */
2247 && ((i
& ~0xc000003f) == 0
2248 || (i
& ~0xf000000f) == 0
2249 || (i
& ~0xfc000003) == 0))
2256 /* Allow repeated pattern. */
2259 if (i
== v
|| i
== (v
| (v
<< 8)))
2263 /* APPLE LOCAL end v7 support. Merge from mainline */
2267 /* Return true if I is a valid constant for the operation CODE. */
2269 const_ok_for_op (HOST_WIDE_INT i
, enum rtx_code code
)
2271 if (const_ok_for_arm (i
))
2277 return const_ok_for_arm (ARM_SIGN_EXTEND (-i
));
2279 case MINUS
: /* Should only occur with (MINUS I reg) => rsb */
2285 return const_ok_for_arm (ARM_SIGN_EXTEND (~i
));
2292 /* Emit a sequence of insns to handle a large constant.
2293 CODE is the code of the operation required, it can be any of SET, PLUS,
2294 IOR, AND, XOR, MINUS;
2295 MODE is the mode in which the operation is being performed;
2296 VAL is the integer to operate on;
2297 SOURCE is the other operand (a register, or a null-pointer for SET);
2298 SUBTARGETS means it is safe to create scratch registers if that will
2299 either produce a simpler sequence, or we will want to cse the values.
2300 Return value is the number of insns emitted. */
2302 /* APPLE LOCAL v7 support. Merge from mainline */
2303 /* ??? Tweak this for thumb2. */
2305 arm_split_constant (enum rtx_code code
, enum machine_mode mode
, rtx insn
,
2306 HOST_WIDE_INT val
, rtx target
, rtx source
, int subtargets
)
2310 if (insn
&& GET_CODE (PATTERN (insn
)) == COND_EXEC
)
2311 cond
= COND_EXEC_TEST (PATTERN (insn
));
2315 if (subtargets
|| code
== SET
2316 || (GET_CODE (target
) == REG
&& GET_CODE (source
) == REG
2317 && REGNO (target
) != REGNO (source
)))
2319 /* After arm_reorg has been called, we can't fix up expensive
2320 constants by pushing them into memory so we must synthesize
2321 them in-line, regardless of the cost. This is only likely to
2322 be more costly on chips that have load delay slots and we are
2323 compiling without running the scheduler (so no splitting
2324 occurred before the final instruction emission).
2326 Ref: gcc -O1 -mcpu=strongarm gcc.c-torture/compile/980506-2.c
2328 if (!after_arm_reorg
2330 && (arm_gen_constant (code
, mode
, NULL_RTX
, val
, target
, source
,
2332 > arm_constant_limit
+ (code
!= SET
)))
2336 /* Currently SET is the only monadic value for CODE, all
2337 the rest are diadic. */
2338 emit_set_insn (target
, GEN_INT (val
));
2343 rtx temp
= subtargets
? gen_reg_rtx (mode
) : target
;
2345 emit_set_insn (temp
, GEN_INT (val
));
2346 /* For MINUS, the value is subtracted from, since we never
2347 have subtraction of a constant. */
2349 emit_set_insn (target
, gen_rtx_MINUS (mode
, temp
, source
));
2351 emit_set_insn (target
,
2352 gen_rtx_fmt_ee (code
, mode
, source
, temp
));
2358 return arm_gen_constant (code
, mode
, cond
, val
, target
, source
, subtargets
,
2362 /* APPLE LOCAL begin v7 support. Merge from mainline */
2363 /* Return the number of ARM instructions required to synthesize the given
2365 /* APPLE LOCAL end v7 support. Merge from mainline */
2367 count_insns_for_constant (HOST_WIDE_INT remainder
, int i
)
2369 HOST_WIDE_INT temp1
;
2377 if (remainder
& (3 << (i
- 2)))
2382 temp1
= remainder
& ((0x0ff << end
)
2383 | ((i
< end
) ? (0xff >> (32 - end
)) : 0));
2384 remainder
&= ~temp1
;
2389 } while (remainder
);
2393 /* Emit an instruction with the indicated PATTERN. If COND is
2394 non-NULL, conditionalize the execution of the instruction on COND
2398 emit_constant_insn (rtx cond
, rtx pattern
)
2401 pattern
= gen_rtx_COND_EXEC (VOIDmode
, copy_rtx (cond
), pattern
);
2402 emit_insn (pattern
);
2405 /* As above, but extra parameter GENERATE which, if clear, suppresses
2407 /* APPLE LOCAL v7 support. Merge from mainline */
2408 /* ??? This needs more work for thumb2. */
2411 arm_gen_constant (enum rtx_code code
, enum machine_mode mode
, rtx cond
,
2412 HOST_WIDE_INT val
, rtx target
, rtx source
, int subtargets
,
2417 int can_negate_initial
= 0;
2420 int num_bits_set
= 0;
2421 int set_sign_bit_copies
= 0;
2422 int clear_sign_bit_copies
= 0;
2423 int clear_zero_bit_copies
= 0;
2424 int set_zero_bit_copies
= 0;
2426 unsigned HOST_WIDE_INT temp1
, temp2
;
2427 unsigned HOST_WIDE_INT remainder
= val
& 0xffffffff;
2429 /* Find out which operations are safe for a given CODE. Also do a quick
2430 check for degenerate cases; these can occur when DImode operations
2442 can_negate_initial
= 1;
2446 if (remainder
== 0xffffffff)
2449 emit_constant_insn (cond
,
2450 gen_rtx_SET (VOIDmode
, target
,
2451 GEN_INT (ARM_SIGN_EXTEND (val
))));
2456 if (reload_completed
&& rtx_equal_p (target
, source
))
2459 emit_constant_insn (cond
,
2460 gen_rtx_SET (VOIDmode
, target
, source
));
2469 emit_constant_insn (cond
,
2470 gen_rtx_SET (VOIDmode
, target
, const0_rtx
));
2473 if (remainder
== 0xffffffff)
2475 if (reload_completed
&& rtx_equal_p (target
, source
))
2478 emit_constant_insn (cond
,
2479 gen_rtx_SET (VOIDmode
, target
, source
));
2488 if (reload_completed
&& rtx_equal_p (target
, source
))
2491 emit_constant_insn (cond
,
2492 gen_rtx_SET (VOIDmode
, target
, source
));
2496 /* We don't know how to handle other cases yet. */
2497 gcc_assert (remainder
== 0xffffffff);
2500 emit_constant_insn (cond
,
2501 gen_rtx_SET (VOIDmode
, target
,
2502 gen_rtx_NOT (mode
, source
)));
2506 /* We treat MINUS as (val - source), since (source - val) is always
2507 passed as (source + (-val)). */
2511 emit_constant_insn (cond
,
2512 gen_rtx_SET (VOIDmode
, target
,
2513 gen_rtx_NEG (mode
, source
)));
2516 if (const_ok_for_arm (val
))
2519 emit_constant_insn (cond
,
2520 gen_rtx_SET (VOIDmode
, target
,
2521 gen_rtx_MINUS (mode
, GEN_INT (val
),
2533 /* If we can do it in one insn get out quickly. */
2534 if (const_ok_for_arm (val
)
2535 || (can_negate_initial
&& const_ok_for_arm (-val
))
2536 || (can_invert
&& const_ok_for_arm (~val
)))
2539 emit_constant_insn (cond
,
2540 gen_rtx_SET (VOIDmode
, target
,
2542 ? gen_rtx_fmt_ee (code
, mode
, source
,
2548 /* Calculate a few attributes that may be useful for specific
2550 for (i
= 31; i
>= 0; i
--)
2552 if ((remainder
& (1 << i
)) == 0)
2553 clear_sign_bit_copies
++;
2558 for (i
= 31; i
>= 0; i
--)
2560 if ((remainder
& (1 << i
)) != 0)
2561 set_sign_bit_copies
++;
2566 for (i
= 0; i
<= 31; i
++)
2568 if ((remainder
& (1 << i
)) == 0)
2569 clear_zero_bit_copies
++;
2574 for (i
= 0; i
<= 31; i
++)
2576 if ((remainder
& (1 << i
)) != 0)
2577 set_zero_bit_copies
++;
2585 /* APPLE LOCAL begin v7 support. Merge from mainline */
2586 /* See if we can use movw. */
2587 if (arm_arch_thumb2
&& (remainder
& 0xffff0000) == 0)
2590 emit_constant_insn (cond
, gen_rtx_SET (VOIDmode
, target
,
2595 /* APPLE LOCAL end v7 support. Merge from mainline */
2596 /* See if we can do this by sign_extending a constant that is known
2597 to be negative. This is a good, way of doing it, since the shift
2598 may well merge into a subsequent insn. */
2599 if (set_sign_bit_copies
> 1)
2601 if (const_ok_for_arm
2602 (temp1
= ARM_SIGN_EXTEND (remainder
2603 << (set_sign_bit_copies
- 1))))
2607 rtx new_src
= subtargets
? gen_reg_rtx (mode
) : target
;
2608 emit_constant_insn (cond
,
2609 gen_rtx_SET (VOIDmode
, new_src
,
2611 emit_constant_insn (cond
,
2612 gen_ashrsi3 (target
, new_src
,
2613 GEN_INT (set_sign_bit_copies
- 1)));
2617 /* For an inverted constant, we will need to set the low bits,
2618 these will be shifted out of harm's way. */
2619 temp1
|= (1 << (set_sign_bit_copies
- 1)) - 1;
2620 if (const_ok_for_arm (~temp1
))
2624 rtx new_src
= subtargets
? gen_reg_rtx (mode
) : target
;
2625 emit_constant_insn (cond
,
2626 gen_rtx_SET (VOIDmode
, new_src
,
2628 emit_constant_insn (cond
,
2629 gen_ashrsi3 (target
, new_src
,
2630 GEN_INT (set_sign_bit_copies
- 1)));
2636 /* See if we can calculate the value as the difference between two
2637 valid immediates. */
2638 if (clear_sign_bit_copies
+ clear_zero_bit_copies
<= 16)
2640 int topshift
= clear_sign_bit_copies
& ~1;
2642 temp1
= ARM_SIGN_EXTEND ((remainder
+ (0x00800000 >> topshift
))
2643 & (0xff000000 >> topshift
));
2645 /* If temp1 is zero, then that means the 9 most significant
2646 bits of remainder were 1 and we've caused it to overflow.
2647 When topshift is 0 we don't need to do anything since we
2648 can borrow from 'bit 32'. */
2649 if (temp1
== 0 && topshift
!= 0)
2650 temp1
= 0x80000000 >> (topshift
- 1);
2652 temp2
= ARM_SIGN_EXTEND (temp1
- remainder
);
2654 if (const_ok_for_arm (temp2
))
2658 rtx new_src
= subtargets
? gen_reg_rtx (mode
) : target
;
2659 emit_constant_insn (cond
,
2660 gen_rtx_SET (VOIDmode
, new_src
,
2662 emit_constant_insn (cond
,
2663 gen_addsi3 (target
, new_src
,
2671 /* See if we can generate this by setting the bottom (or the top)
2672 16 bits, and then shifting these into the other half of the
2673 word. We only look for the simplest cases, to do more would cost
2674 too much. Be careful, however, not to generate this when the
2675 alternative would take fewer insns. */
2676 if (val
& 0xffff0000)
2678 temp1
= remainder
& 0xffff0000;
2679 temp2
= remainder
& 0x0000ffff;
2681 /* Overlaps outside this range are best done using other methods. */
2682 for (i
= 9; i
< 24; i
++)
2684 if ((((temp2
| (temp2
<< i
)) & 0xffffffff) == remainder
)
2685 && !const_ok_for_arm (temp2
))
2687 rtx new_src
= (subtargets
2688 ? (generate
? gen_reg_rtx (mode
) : NULL_RTX
)
2690 insns
= arm_gen_constant (code
, mode
, cond
, temp2
, new_src
,
2691 source
, subtargets
, generate
);
2699 gen_rtx_ASHIFT (mode
, source
,
2706 /* Don't duplicate cases already considered. */
2707 for (i
= 17; i
< 24; i
++)
2709 if (((temp1
| (temp1
>> i
)) == remainder
)
2710 && !const_ok_for_arm (temp1
))
2712 rtx new_src
= (subtargets
2713 ? (generate
? gen_reg_rtx (mode
) : NULL_RTX
)
2715 insns
= arm_gen_constant (code
, mode
, cond
, temp1
, new_src
,
2716 source
, subtargets
, generate
);
2721 gen_rtx_SET (VOIDmode
, target
,
2724 gen_rtx_LSHIFTRT (mode
, source
,
2735 /* If we have IOR or XOR, and the constant can be loaded in a
2736 single instruction, and we can find a temporary to put it in,
2737 then this can be done in two instructions instead of 3-4. */
2739 /* TARGET can't be NULL if SUBTARGETS is 0 */
2740 || (reload_completed
&& !reg_mentioned_p (target
, source
)))
2742 if (const_ok_for_arm (ARM_SIGN_EXTEND (~val
)))
2746 rtx sub
= subtargets
? gen_reg_rtx (mode
) : target
;
2748 emit_constant_insn (cond
,
2749 gen_rtx_SET (VOIDmode
, sub
,
2751 emit_constant_insn (cond
,
2752 gen_rtx_SET (VOIDmode
, target
,
2753 gen_rtx_fmt_ee (code
, mode
,
2763 if (set_sign_bit_copies
> 8
2764 && (val
& (-1 << (32 - set_sign_bit_copies
))) == val
)
2768 rtx sub
= subtargets
? gen_reg_rtx (mode
) : target
;
2769 rtx shift
= GEN_INT (set_sign_bit_copies
);
2773 gen_rtx_SET (VOIDmode
, sub
,
2775 gen_rtx_ASHIFT (mode
,
2780 gen_rtx_SET (VOIDmode
, target
,
2782 gen_rtx_LSHIFTRT (mode
, sub
,
2788 if (set_zero_bit_copies
> 8
2789 && (remainder
& ((1 << set_zero_bit_copies
) - 1)) == remainder
)
2793 rtx sub
= subtargets
? gen_reg_rtx (mode
) : target
;
2794 rtx shift
= GEN_INT (set_zero_bit_copies
);
2798 gen_rtx_SET (VOIDmode
, sub
,
2800 gen_rtx_LSHIFTRT (mode
,
2805 gen_rtx_SET (VOIDmode
, target
,
2807 gen_rtx_ASHIFT (mode
, sub
,
2813 if (const_ok_for_arm (temp1
= ARM_SIGN_EXTEND (~val
)))
2817 rtx sub
= subtargets
? gen_reg_rtx (mode
) : target
;
2818 emit_constant_insn (cond
,
2819 gen_rtx_SET (VOIDmode
, sub
,
2820 gen_rtx_NOT (mode
, source
)));
2823 sub
= gen_reg_rtx (mode
);
2824 emit_constant_insn (cond
,
2825 gen_rtx_SET (VOIDmode
, sub
,
2826 gen_rtx_AND (mode
, source
,
2828 emit_constant_insn (cond
,
2829 gen_rtx_SET (VOIDmode
, target
,
2830 gen_rtx_NOT (mode
, sub
)));
2837 /* See if two shifts will do 2 or more insn's worth of work. */
2838 if (clear_sign_bit_copies
>= 16 && clear_sign_bit_copies
< 24)
2840 HOST_WIDE_INT shift_mask
= ((0xffffffff
2841 << (32 - clear_sign_bit_copies
))
2844 if ((remainder
| shift_mask
) != 0xffffffff)
2848 rtx new_src
= subtargets
? gen_reg_rtx (mode
) : target
;
2849 insns
= arm_gen_constant (AND
, mode
, cond
,
2850 remainder
| shift_mask
,
2851 new_src
, source
, subtargets
, 1);
2856 rtx targ
= subtargets
? NULL_RTX
: target
;
2857 insns
= arm_gen_constant (AND
, mode
, cond
,
2858 remainder
| shift_mask
,
2859 targ
, source
, subtargets
, 0);
2865 rtx new_src
= subtargets
? gen_reg_rtx (mode
) : target
;
2866 rtx shift
= GEN_INT (clear_sign_bit_copies
);
2868 emit_insn (gen_ashlsi3 (new_src
, source
, shift
));
2869 emit_insn (gen_lshrsi3 (target
, new_src
, shift
));
2875 if (clear_zero_bit_copies
>= 16 && clear_zero_bit_copies
< 24)
2877 HOST_WIDE_INT shift_mask
= (1 << clear_zero_bit_copies
) - 1;
2879 if ((remainder
| shift_mask
) != 0xffffffff)
2883 rtx new_src
= subtargets
? gen_reg_rtx (mode
) : target
;
2885 insns
= arm_gen_constant (AND
, mode
, cond
,
2886 remainder
| shift_mask
,
2887 new_src
, source
, subtargets
, 1);
2892 rtx targ
= subtargets
? NULL_RTX
: target
;
2894 insns
= arm_gen_constant (AND
, mode
, cond
,
2895 remainder
| shift_mask
,
2896 targ
, source
, subtargets
, 0);
2902 rtx new_src
= subtargets
? gen_reg_rtx (mode
) : target
;
2903 rtx shift
= GEN_INT (clear_zero_bit_copies
);
2905 emit_insn (gen_lshrsi3 (new_src
, source
, shift
));
2906 emit_insn (gen_ashlsi3 (target
, new_src
, shift
));
2918 for (i
= 0; i
< 32; i
++)
2919 if (remainder
& (1 << i
))
2922 if (code
== AND
|| (can_invert
&& num_bits_set
> 16))
2923 remainder
= (~remainder
) & 0xffffffff;
2924 else if (code
== PLUS
&& num_bits_set
> 16)
2925 remainder
= (-remainder
) & 0xffffffff;
2932 /* APPLE LOCAL begin v7 support. Merge from mainline */
2933 /* Now try and find a way of doing the job in either two or three
2935 We start by looking for the largest block of zeros that are aligned on
2936 a 2-bit boundary, we then fill up the temps, wrapping around to the
2937 top of the word when we drop off the bottom.
2938 In the worst case this code should produce no more than four insns.
2939 Thumb-2 constants are shifted, not rotated, so the MSB is always the
2940 best place to start. */
2942 /* ??? Use thumb2 replicated constants when the high and low halfwords are
2948 int best_consecutive_zeros
= 0;
2950 for (i
= 0; i
< 32; i
+= 2)
2952 int consecutive_zeros
= 0;
2954 if (!(remainder
& (3 << i
)))
2956 while ((i
< 32) && !(remainder
& (3 << i
)))
2958 consecutive_zeros
+= 2;
2961 if (consecutive_zeros
> best_consecutive_zeros
)
2963 best_consecutive_zeros
= consecutive_zeros
;
2964 best_start
= i
- consecutive_zeros
;
2970 /* So long as it won't require any more insns to do so, it's
2971 desirable to emit a small constant (in bits 0...9) in the last
2972 insn. This way there is more chance that it can be combined with
2973 a later addressing insn to form a pre-indexed load or store
2974 operation. Consider:
2976 *((volatile int *)0xe0000100) = 1;
2977 *((volatile int *)0xe0000110) = 2;
2979 We want this to wind up as:
2983 str rB, [rA, #0x100]
2985 str rB, [rA, #0x110]
2987 rather than having to synthesize both large constants from scratch.
2989 Therefore, we calculate how many insns would be required to emit
2990 the constant starting from `best_start', and also starting from
2991 zero (i.e. with bit 31 first to be output). If `best_start' doesn't
2992 yield a shorter sequence, we may as well use zero. */
2994 && ((((unsigned HOST_WIDE_INT
) 1) << best_start
) < remainder
)
2995 && (count_insns_for_constant (remainder
, 0) <=
2996 count_insns_for_constant (remainder
, best_start
)))
3000 /* Now start emitting the insns. */
3008 if (remainder
& (3 << (i
- 2)))
3013 temp1
= remainder
& ((0x0ff << end
)
3014 | ((i
< end
) ? (0xff >> (32 - end
)) : 0));
3015 remainder
&= ~temp1
;
3019 rtx new_src
, temp1_rtx
;
3021 if (code
== SET
|| code
== MINUS
)
3023 new_src
= (subtargets
? gen_reg_rtx (mode
) : target
);
3024 if (can_invert
&& code
!= MINUS
)
3029 if (remainder
&& subtargets
)
3030 new_src
= gen_reg_rtx (mode
);
3035 else if (can_negate
)
3039 temp1
= trunc_int_for_mode (temp1
, mode
);
3040 temp1_rtx
= GEN_INT (temp1
);
3044 else if (code
== MINUS
)
3045 temp1_rtx
= gen_rtx_MINUS (mode
, temp1_rtx
, source
);
3047 temp1_rtx
= gen_rtx_fmt_ee (code
, mode
, source
, temp1_rtx
);
3049 emit_constant_insn (cond
,
3050 gen_rtx_SET (VOIDmode
, new_src
,
3060 else if (code
== MINUS
)
3069 /* Arm allows rotates by a multiple of two. Thumb-2 allows arbitary
3078 /* APPLE LOCAL end v7 support. Merge from mainline */
3083 /* Canonicalize a comparison so that we are more likely to recognize it.
3084 This can be done for a few constant compares, where we can make the
3085 immediate value easier to load. */
3088 arm_canonicalize_comparison (enum rtx_code code
, enum machine_mode mode
,
3091 unsigned HOST_WIDE_INT i
= INTVAL (*op1
);
3092 unsigned HOST_WIDE_INT maxval
;
3093 maxval
= (((unsigned HOST_WIDE_INT
) 1) << (GET_MODE_BITSIZE(mode
) - 1)) - 1;
3104 && (const_ok_for_arm (i
+ 1) || const_ok_for_arm (-(i
+ 1))))
3106 *op1
= GEN_INT (i
+ 1);
3107 return code
== GT
? GE
: LT
;
3114 && (const_ok_for_arm (i
- 1) || const_ok_for_arm (-(i
- 1))))
3116 *op1
= GEN_INT (i
- 1);
3117 return code
== GE
? GT
: LE
;
3123 if (i
!= ~((unsigned HOST_WIDE_INT
) 0)
3124 && (const_ok_for_arm (i
+ 1) || const_ok_for_arm (-(i
+ 1))))
3126 *op1
= GEN_INT (i
+ 1);
3127 return code
== GTU
? GEU
: LTU
;
3134 && (const_ok_for_arm (i
- 1) || const_ok_for_arm (-(i
- 1))))
3136 *op1
= GEN_INT (i
- 1);
3137 return code
== GEU
? GTU
: LEU
;
3149 /* Define how to find the value returned by a function. */
3152 arm_function_value(tree type
, tree func ATTRIBUTE_UNUSED
)
3154 enum machine_mode mode
;
3155 int unsignedp ATTRIBUTE_UNUSED
;
3156 rtx r ATTRIBUTE_UNUSED
;
3158 mode
= TYPE_MODE (type
);
3159 /* Promote integer types. */
3160 if (INTEGRAL_TYPE_P (type
))
3161 PROMOTE_FUNCTION_MODE (mode
, unsignedp
, type
);
3163 /* Promotes small structs returned in a register to full-word size
3164 for big-endian AAPCS. */
3165 if (arm_return_in_msb (type
))
3167 HOST_WIDE_INT size
= int_size_in_bytes (type
);
3168 if (size
% UNITS_PER_WORD
!= 0)
3170 size
+= UNITS_PER_WORD
- size
% UNITS_PER_WORD
;
3171 mode
= mode_for_size (size
* BITS_PER_UNIT
, MODE_INT
, 0);
3175 return LIBCALL_VALUE(mode
);
3178 /* Determine the amount of memory needed to store the possible return
3179 registers of an untyped call. */
3181 arm_apply_result_size (void)
3187 if (TARGET_HARD_FLOAT_ABI
)
3191 if (TARGET_MAVERICK
)
3194 if (TARGET_IWMMXT_ABI
)
3201 /* Decide whether a type should be returned in memory (true)
3202 or in a register (false). This is called by the macro
3203 RETURN_IN_MEMORY. */
3205 arm_return_in_memory (tree type
)
3209 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
3210 size
= int_size_in_bytes (type
);
3212 /* Vector values should be returned using ARM registers, not memory (unless
3213 they're over 16 bytes, which will break since we only have four
3214 call-clobbered registers to play with). */
3215 if (TREE_CODE (type
) == VECTOR_TYPE
)
3216 return (size
< 0 || size
> (4 * UNITS_PER_WORD
));
3218 if (!AGGREGATE_TYPE_P (type
) &&
3219 !(TARGET_AAPCS_BASED
&& TREE_CODE (type
) == COMPLEX_TYPE
))
3220 /* All simple types are returned in registers.
3221 For AAPCS, complex types are treated the same as aggregates. */
3224 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
3225 if (arm_abi
!= ARM_ABI_APCS
)
3227 /* ATPCS and later return aggregate types in memory only if they are
3228 larger than a word (or are variable size). */
3229 return (size
< 0 || size
> UNITS_PER_WORD
);
3232 /* APPLE LOCAL v7 support. Merge from Codesourcery */
3234 /* For the arm-wince targets we choose to be compatible with Microsoft's
3235 ARM and Thumb compilers, which always return aggregates in memory. */
3237 /* All structures/unions bigger than one word are returned in memory.
3238 Also catch the case where int_size_in_bytes returns -1. In this case
3239 the aggregate is either huge or of variable size, and in either case
3240 we will want to return it via memory and not in a register. */
3241 if (size
< 0 || size
> UNITS_PER_WORD
)
3244 if (TREE_CODE (type
) == RECORD_TYPE
)
3248 /* For a struct the APCS says that we only return in a register
3249 if the type is 'integer like' and every addressable element
3250 has an offset of zero. For practical purposes this means
3251 that the structure can have at most one non bit-field element
3252 and that this element must be the first one in the structure. */
3254 /* Find the first field, ignoring non FIELD_DECL things which will
3255 have been created by C++. */
3256 for (field
= TYPE_FIELDS (type
);
3257 field
&& TREE_CODE (field
) != FIELD_DECL
;
3258 field
= TREE_CHAIN (field
))
3262 return 0; /* An empty structure. Allowed by an extension to ANSI C. */
3264 /* Check that the first field is valid for returning in a register. */
3266 /* ... Floats are not allowed */
3267 if (FLOAT_TYPE_P (TREE_TYPE (field
)))
3270 /* ... Aggregates that are not themselves valid for returning in
3271 a register are not allowed. */
3272 if (RETURN_IN_MEMORY (TREE_TYPE (field
)))
3275 /* Now check the remaining fields, if any. Only bitfields are allowed,
3276 since they are not addressable. */
3277 for (field
= TREE_CHAIN (field
);
3279 field
= TREE_CHAIN (field
))
3281 if (TREE_CODE (field
) != FIELD_DECL
)
3284 if (!DECL_BIT_FIELD_TYPE (field
))
3291 if (TREE_CODE (type
) == UNION_TYPE
)
3295 /* Unions can be returned in registers if every element is
3296 integral, or can be returned in an integer register. */
3297 for (field
= TYPE_FIELDS (type
);
3299 field
= TREE_CHAIN (field
))
3301 if (TREE_CODE (field
) != FIELD_DECL
)
3304 if (FLOAT_TYPE_P (TREE_TYPE (field
)))
3307 if (RETURN_IN_MEMORY (TREE_TYPE (field
)))
3313 #endif /* not ARM_WINCE */
3315 /* Return all other types in memory. */
3319 /* Indicate whether or not words of a double are in big-endian order. */
3322 arm_float_words_big_endian (void)
3324 if (TARGET_MAVERICK
)
3327 /* For FPA, float words are always big-endian. For VFP, floats words
3328 follow the memory system mode. */
3336 return (TARGET_BIG_END
? 1 : 0);
3341 /* Initialize a variable CUM of type CUMULATIVE_ARGS
3342 for a call to a function whose data type is FNTYPE.
3343 For a library call, FNTYPE is NULL. */
3345 arm_init_cumulative_args (CUMULATIVE_ARGS
*pcum
, tree fntype
,
3346 rtx libname ATTRIBUTE_UNUSED
,
3347 /* APPLE LOCAL 6738583 -mlong-calls PIC static functions */
3350 /* On the ARM, the offset starts at 0. */
3352 pcum
->iwmmxt_nregs
= 0;
3353 pcum
->can_split
= true;
3355 pcum
->call_cookie
= CALL_NORMAL
;
3357 if (TARGET_LONG_CALLS
)
3358 pcum
->call_cookie
= CALL_LONG
;
3360 /* Check for long call/short call attributes. The attributes
3361 override any command line option. */
3364 if (lookup_attribute ("short_call", TYPE_ATTRIBUTES (fntype
)))
3365 pcum
->call_cookie
= CALL_SHORT
;
3366 else if (lookup_attribute ("long_call", TYPE_ATTRIBUTES (fntype
)))
3367 pcum
->call_cookie
= CALL_LONG
;
3368 /* APPLE LOCAL begin 6738583 -mlong-calls PIC static functions */
3369 else if (fndecl
&& ! TREE_PUBLIC (fndecl
))
3370 pcum
->call_cookie
= CALL_SHORT
;
3371 /* APPLE LOCAL end 6738583 -mlong-calls PIC static functions */
3374 /* Varargs vectors are treated the same as long long.
3375 named_count avoids having to change the way arm handles 'named' */
3376 pcum
->named_count
= 0;
3379 if (TARGET_REALLY_IWMMXT
&& fntype
)
3383 for (fn_arg
= TYPE_ARG_TYPES (fntype
);
3385 fn_arg
= TREE_CHAIN (fn_arg
))
3386 pcum
->named_count
+= 1;
3388 if (! pcum
->named_count
)
3389 pcum
->named_count
= INT_MAX
;
3394 /* Return true if mode/type need doubleword alignment. */
3396 arm_needs_doubleword_align (enum machine_mode mode
, tree type
)
3398 return (GET_MODE_ALIGNMENT (mode
) > PARM_BOUNDARY
3399 || (type
&& TYPE_ALIGN (type
) > PARM_BOUNDARY
));
3403 /* Determine where to put an argument to a function.
3404 Value is zero to push the argument on the stack,
3405 or a hard register in which to store the argument.
3407 MODE is the argument's machine mode.
3408 TYPE is the data type of the argument (as a tree).
3409 This is null for libcalls where that information may
3411 CUM is a variable of type CUMULATIVE_ARGS which gives info about
3412 the preceding args and about the function being called.
3413 NAMED is nonzero if this argument is a named parameter
3414 (otherwise it is an extra parameter matching an ellipsis). */
3417 arm_function_arg (CUMULATIVE_ARGS
*pcum
, enum machine_mode mode
,
3418 tree type
, int named
)
3422 /* Varargs vectors are treated the same as long long.
3423 named_count avoids having to change the way arm handles 'named' */
3424 if (TARGET_IWMMXT_ABI
3425 && arm_vector_mode_supported_p (mode
)
3426 && pcum
->named_count
> pcum
->nargs
+ 1)
3428 if (pcum
->iwmmxt_nregs
<= 9)
3429 return gen_rtx_REG (mode
, pcum
->iwmmxt_nregs
+ FIRST_IWMMXT_REGNUM
);
3432 pcum
->can_split
= false;
3437 /* Put doubleword aligned quantities in even register pairs. */
3439 && ARM_DOUBLEWORD_ALIGN
3440 && arm_needs_doubleword_align (mode
, type
))
3443 if (mode
== VOIDmode
)
3444 /* Compute operand 2 of the call insn. */
3445 return GEN_INT (pcum
->call_cookie
);
3447 /* Only allow splitting an arg between regs and memory if all preceding
3448 args were allocated to regs. For args passed by reference we only count
3449 the reference pointer. */
3450 if (pcum
->can_split
)
3453 nregs
= ARM_NUM_REGS2 (mode
, type
);
3455 if (!named
|| pcum
->nregs
+ nregs
> NUM_ARG_REGS
)
3458 return gen_rtx_REG (mode
, pcum
->nregs
);
3462 arm_arg_partial_bytes (CUMULATIVE_ARGS
*pcum
, enum machine_mode mode
,
3463 tree type
, bool named ATTRIBUTE_UNUSED
)
3465 int nregs
= pcum
->nregs
;
3467 /* APPLE LOCAL v7 support. Merge from Codesourcery */
3468 if (TARGET_IWMMXT_ABI
&& arm_vector_mode_supported_p (mode
))
3471 if (NUM_ARG_REGS
> nregs
3472 && (NUM_ARG_REGS
< nregs
+ ARM_NUM_REGS2 (mode
, type
))
3474 return (NUM_ARG_REGS
- nregs
) * UNITS_PER_WORD
;
3479 /* Variable sized types are passed by reference. This is a GCC
3480 extension to the ARM ABI. */
3483 arm_pass_by_reference (CUMULATIVE_ARGS
*cum ATTRIBUTE_UNUSED
,
3484 enum machine_mode mode ATTRIBUTE_UNUSED
,
3485 tree type
, bool named ATTRIBUTE_UNUSED
)
3487 return type
&& TREE_CODE (TYPE_SIZE (type
)) != INTEGER_CST
;
3490 /* Encode the current state of the #pragma [no_]long_calls. */
3493 OFF
, /* No #pragma [no_]long_calls is in effect. */
3494 LONG
, /* #pragma long_calls is in effect. */
3495 SHORT
/* #pragma no_long_calls is in effect. */
3498 static arm_pragma_enum arm_pragma_long_calls
= OFF
;
3501 arm_pr_long_calls (struct cpp_reader
* pfile ATTRIBUTE_UNUSED
)
3503 arm_pragma_long_calls
= LONG
;
3507 arm_pr_no_long_calls (struct cpp_reader
* pfile ATTRIBUTE_UNUSED
)
3509 arm_pragma_long_calls
= SHORT
;
3513 arm_pr_long_calls_off (struct cpp_reader
* pfile ATTRIBUTE_UNUSED
)
3515 arm_pragma_long_calls
= OFF
;
3518 /* Table of machine attributes. */
3519 const struct attribute_spec arm_attribute_table
[] =
3521 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
3522 /* Function calls made to this symbol must be done indirectly, because
3523 it may lie outside of the 26 bit addressing range of a normal function
3525 { "long_call", 0, 0, false, true, true, NULL
},
3526 /* Whereas these functions are always known to reside within the 26 bit
3527 addressing range. */
3528 { "short_call", 0, 0, false, true, true, NULL
},
3529 /* Interrupt Service Routines have special prologue and epilogue requirements. */
3530 { "isr", 0, 1, false, false, false, arm_handle_isr_attribute
},
3531 { "interrupt", 0, 1, false, false, false, arm_handle_isr_attribute
},
3532 { "naked", 0, 0, true, false, false, arm_handle_fndecl_attribute
},
3534 /* ARM/PE has three new attributes:
3536 dllexport - for exporting a function/variable that will live in a dll
3537 dllimport - for importing a function/variable from a dll
3539 Microsoft allows multiple declspecs in one __declspec, separating
3540 them with spaces. We do NOT support this. Instead, use __declspec
3543 { "dllimport", 0, 0, true, false, false, NULL
},
3544 { "dllexport", 0, 0, true, false, false, NULL
},
3545 { "interfacearm", 0, 0, true, false, false, arm_handle_fndecl_attribute
},
3546 #elif TARGET_DLLIMPORT_DECL_ATTRIBUTES
3547 { "dllimport", 0, 0, false, false, false, handle_dll_attribute
},
3548 { "dllexport", 0, 0, false, false, false, handle_dll_attribute
},
3549 { "notshared", 0, 0, false, true, false, arm_handle_notshared_attribute
},
3551 /* APPLE LOCAL begin 5946347 ms_struct support */
3552 { "ms_struct", 0, 0, false, false, false, arm_handle_ms_struct_attribute
},
3553 { "gcc_struct", 0, 0, false, false, false, arm_handle_gcc_struct_attribute
},
3554 /* APPLE LOCAL end 5946347 ms_struct support */
3555 /* APPLE LOCAL begin ARM darwin attributes */
3556 #ifdef SUBTARGET_ATTRIBUTE_TABLE
3557 SUBTARGET_ATTRIBUTE_TABLE
,
3559 /* APPLE LOCAL end ARM darwin attributes */
3560 { NULL
, 0, 0, false, false, false, NULL
}
3563 /* Handle an attribute requiring a FUNCTION_DECL;
3564 arguments as in struct attribute_spec.handler. */
3566 arm_handle_fndecl_attribute (tree
*node
, tree name
, tree args ATTRIBUTE_UNUSED
,
3567 int flags ATTRIBUTE_UNUSED
, bool *no_add_attrs
)
3569 if (TREE_CODE (*node
) != FUNCTION_DECL
)
3571 warning (OPT_Wattributes
, "%qs attribute only applies to functions",
3572 IDENTIFIER_POINTER (name
));
3573 *no_add_attrs
= true;
3579 /* Handle an "interrupt" or "isr" attribute;
3580 arguments as in struct attribute_spec.handler. */
3582 arm_handle_isr_attribute (tree
*node
, tree name
, tree args
, int flags
,
3587 if (TREE_CODE (*node
) != FUNCTION_DECL
)
3589 warning (OPT_Wattributes
, "%qs attribute only applies to functions",
3590 IDENTIFIER_POINTER (name
));
3591 *no_add_attrs
= true;
3593 /* FIXME: the argument if any is checked for type attributes;
3594 should it be checked for decl ones? */
3598 if (TREE_CODE (*node
) == FUNCTION_TYPE
3599 || TREE_CODE (*node
) == METHOD_TYPE
)
3601 if (arm_isr_value (args
) == ARM_FT_UNKNOWN
)
3603 warning (OPT_Wattributes
, "%qs attribute ignored",
3604 IDENTIFIER_POINTER (name
));
3605 *no_add_attrs
= true;
3608 else if (TREE_CODE (*node
) == POINTER_TYPE
3609 && (TREE_CODE (TREE_TYPE (*node
)) == FUNCTION_TYPE
3610 || TREE_CODE (TREE_TYPE (*node
)) == METHOD_TYPE
)
3611 && arm_isr_value (args
) != ARM_FT_UNKNOWN
)
3613 *node
= build_variant_type_copy (*node
);
3614 TREE_TYPE (*node
) = build_type_attribute_variant
3616 tree_cons (name
, args
, TYPE_ATTRIBUTES (TREE_TYPE (*node
))));
3617 *no_add_attrs
= true;
3621 /* Possibly pass this attribute on from the type to a decl. */
3622 if (flags
& ((int) ATTR_FLAG_DECL_NEXT
3623 | (int) ATTR_FLAG_FUNCTION_NEXT
3624 | (int) ATTR_FLAG_ARRAY_NEXT
))
3626 *no_add_attrs
= true;
3627 return tree_cons (name
, args
, NULL_TREE
);
3631 warning (OPT_Wattributes
, "%qs attribute ignored",
3632 IDENTIFIER_POINTER (name
));
3640 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
3641 /* Handle the "notshared" attribute. This attribute is another way of
3642 requesting hidden visibility. ARM's compiler supports
3643 "__declspec(notshared)"; we support the same thing via an
3647 arm_handle_notshared_attribute (tree
*node
,
3648 tree name ATTRIBUTE_UNUSED
,
3649 tree args ATTRIBUTE_UNUSED
,
3650 int flags ATTRIBUTE_UNUSED
,
3653 tree decl
= TYPE_NAME (*node
);
3657 DECL_VISIBILITY (decl
) = VISIBILITY_HIDDEN
;
3658 DECL_VISIBILITY_SPECIFIED (decl
) = 1;
3659 *no_add_attrs
= false;
3665 /* Return 0 if the attributes for two types are incompatible, 1 if they
3666 are compatible, and 2 if they are nearly compatible (which causes a
3667 warning to be generated). */
3669 arm_comp_type_attributes (tree type1
, tree type2
)
3673 /* Check for mismatch of non-default calling convention. */
3674 if (TREE_CODE (type1
) != FUNCTION_TYPE
)
3677 /* Check for mismatched call attributes. */
3678 l1
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
3679 l2
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
3680 s1
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
3681 s2
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
3683 /* Only bother to check if an attribute is defined. */
3684 if (l1
| l2
| s1
| s2
)
3686 /* If one type has an attribute, the other must have the same attribute. */
3687 if ((l1
!= l2
) || (s1
!= s2
))
3690 /* Disallow mixed attributes. */
3691 if ((l1
& s2
) || (l2
& s1
))
3695 /* Check for mismatched ISR attribute. */
3696 l1
= lookup_attribute ("isr", TYPE_ATTRIBUTES (type1
)) != NULL
;
3698 l1
= lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type1
)) != NULL
;
3699 l2
= lookup_attribute ("isr", TYPE_ATTRIBUTES (type2
)) != NULL
;
3701 l1
= lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type2
)) != NULL
;
3708 /* APPLE LOCAL begin ARM longcall */
3709 /* Encode long_call or short_call attribute by prefixing
3710 symbol name in DECL with a special character FLAG. */
3712 arm_encode_call_attribute (tree decl
, int flag
)
3715 rtx sym_ref
= XEXP (DECL_RTL (decl
), 0);
3717 /* Do not allow weak functions with default visibility to be treated
3719 if (DECL_WEAK (decl
)
3720 && DECL_VISIBILITY (decl
) == VISIBILITY_DEFAULT
3721 && flag
== SYMBOL_SHORT_CALL
)
3724 SYMBOL_REF_FLAGS (sym_ref
) |= flag
;
3726 const char * str
= XSTR (XEXP (DECL_RTL (decl
), 0), 0);
3727 int len
= strlen (str
);
3730 /* Do not allow weak functions to be treated as short call. */
3731 if (DECL_WEAK (decl
) && flag
== SHORT_CALL_FLAG_CHAR
)
3734 newstr
= alloca (len
+ 2);
3736 strcpy (newstr
+ 1, str
);
3738 newstr
= (char *) ggc_alloc_string (newstr
, len
+ 1);
3739 XSTR (XEXP (DECL_RTL (decl
), 0), 0) = newstr
;
3742 /* APPLE LOCAL end ARM longcall */
3744 /* Assigns default attributes to newly defined type. This is used to
3745 set short_call/long_call attributes for function types of
3746 functions defined inside corresponding #pragma scopes. */
3748 arm_set_default_type_attributes (tree type
)
3750 /* Add __attribute__ ((long_call)) to all functions, when
3751 inside #pragma long_calls or __attribute__ ((short_call)),
3752 when inside #pragma no_long_calls. */
3753 if (TREE_CODE (type
) == FUNCTION_TYPE
|| TREE_CODE (type
) == METHOD_TYPE
)
3755 tree type_attr_list
, attr_name
;
3756 type_attr_list
= TYPE_ATTRIBUTES (type
);
3758 if (arm_pragma_long_calls
== LONG
)
3759 attr_name
= get_identifier ("long_call");
3760 else if (arm_pragma_long_calls
== SHORT
)
3761 attr_name
= get_identifier ("short_call");
3765 type_attr_list
= tree_cons (attr_name
, NULL_TREE
, type_attr_list
);
3766 TYPE_ATTRIBUTES (type
) = type_attr_list
;
3768 /* APPLE LOCAL begin 5946347 ms_struct support */
3769 /* If -mms-bitfields is active and this is a structure or union type
3770 definition, then add an ms_struct attribute. */
3772 else if ((TARGET_MS_BITFIELD_LAYOUT
|| darwin_ms_struct
)
3773 && (TREE_CODE (type
) == RECORD_TYPE
3774 || TREE_CODE (type
) == UNION_TYPE
))
3776 else if (TARGET_MS_BITFIELD_LAYOUT
3777 && (TREE_CODE (type
) == RECORD_TYPE
3778 || TREE_CODE (type
) == UNION_TYPE
))
3781 TYPE_ATTRIBUTES (type
) = tree_cons (get_identifier ("ms_struct"),
3783 TYPE_ATTRIBUTES (type
));
3785 /* APPLE LOCAL end 5946347 ms_struct support */
3788 /* Return 1 if the operand is a SYMBOL_REF for a function known to be
3789 defined within the current compilation unit. If this cannot be
3790 determined, then 0 is returned. */
3792 current_file_function_operand (rtx sym_ref
)
3794 /* This is a bit of a fib. A function will have a short call flag
3795 applied to its name if it has the short call attribute, or it has
3796 already been defined within the current compilation unit. */
3797 /* APPLE LOCAL begin ARM longcall */
3799 if (SYMBOL_SHORT_CALL_ATTR_P (sym_ref
))
3801 if (ENCODED_SHORT_CALL_ATTR_P (XSTR (sym_ref
, 0)))
3804 /* APPLE LOCAL end ARM longcall */
3806 /* The current function is always defined within the current compilation
3807 unit. If it s a weak definition however, then this may not be the real
3808 definition of the function, and so we have to say no. */
3809 if (sym_ref
== XEXP (DECL_RTL (current_function_decl
), 0)
3810 && !DECL_WEAK (current_function_decl
))
3813 /* We cannot make the determination - default to returning 0. */
3817 /* Return nonzero if a 32 bit "long_call" should be generated for
3818 this call. We generate a long_call if the function:
3820 a. has an __attribute__((long call))
3821 or b. is within the scope of a #pragma long_calls
3822 or c. the -mlong-calls command line switch has been specified
3824 1. -ffunction-sections is in effect
3825 or 2. the current function has __attribute__ ((section))
3826 or 3. the target function has __attribute__ ((section))
3828 However we do not generate a long call if the function:
3830 d. has an __attribute__ ((short_call))
3831 or e. is inside the scope of a #pragma no_long_calls
3832 or f. is defined within the current compilation unit.
3834 This function will be called by C fragments contained in the machine
3835 description file. SYM_REF and CALL_COOKIE correspond to the matched
3836 rtl operands. CALL_SYMBOL is used to distinguish between
3837 two different callers of the function. It is set to 1 in the
3838 "call_symbol" and "call_symbol_value" patterns and to 0 in the "call"
3839 and "call_value" patterns. This is because of the difference in the
3840 SYM_REFs passed by these patterns. */
3842 arm_is_longcall_p (rtx sym_ref
, int call_cookie
, int call_symbol
)
3846 if (GET_CODE (sym_ref
) != MEM
)
3849 sym_ref
= XEXP (sym_ref
, 0);
3852 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
3855 if (call_cookie
& CALL_SHORT
)
3858 if (TARGET_LONG_CALLS
)
3860 if (flag_function_sections
3861 || DECL_SECTION_NAME (current_function_decl
))
3862 /* c.3 is handled by the definition of the
3863 ARM_DECLARE_FUNCTION_SIZE macro. */
3867 if (current_file_function_operand (sym_ref
))
3870 /* APPLE LOCAL begin ARM longcall */
3872 return (call_cookie
& CALL_LONG
)
3873 || SYMBOL_LONG_CALL_ATTR_P (sym_ref
)
3874 || TARGET_LONG_CALLS
;
3876 return (call_cookie
& CALL_LONG
)
3877 || ENCODED_LONG_CALL_ATTR_P (XSTR (sym_ref
, 0))
3878 || TARGET_LONG_CALLS
;
3880 /* APPLE LOCAL end ARM longcall */
3883 /* Return nonzero if it is ok to make a tail-call to DECL. */
3885 arm_function_ok_for_sibcall (tree decl
, tree exp ATTRIBUTE_UNUSED
)
3887 int call_type
= TARGET_LONG_CALLS
? CALL_LONG
: CALL_NORMAL
;
3888 /* APPLE LOCAL v7 support. Merge from mainline */
3889 unsigned long func_type
;
3891 if (cfun
->machine
->sibcall_blocked
)
3894 /* APPLE LOCAL begin ARM indirect sibcalls */
3895 /* Never tailcall something for which we have no decl, or if we
3896 are in Thumb mode. */
3900 /* All indirect calls are within range, since we load the address into a
3904 /* APPLE LOCAL end ARM indirect sibcalls */
3906 /* Get the calling method. */
3907 if (lookup_attribute ("short_call", TYPE_ATTRIBUTES (TREE_TYPE (decl
))))
3908 call_type
= CALL_SHORT
;
3909 else if (lookup_attribute ("long_call", TYPE_ATTRIBUTES (TREE_TYPE (decl
))))
3910 call_type
= CALL_LONG
;
3912 /* Cannot tail-call to long calls, since these are out of range of
3913 a branch instruction. However, if not compiling PIC, we know
3914 we can reach the symbol if it is in this compilation unit. */
3915 if (call_type
== CALL_LONG
&& (flag_pic
|| !TREE_ASM_WRITTEN (decl
)))
3918 /* If we are interworking and the function is not declared static
3919 then we can't tail-call it unless we know that it exists in this
3920 compilation unit (since it might be a Thumb routine). */
3921 /* APPLE LOCAL begin ARM interworking */
3922 if (TREE_PUBLIC (decl
) && !TREE_ASM_WRITTEN (decl
) && TARGET_INTERWORK
)
3926 else if (!arm_arch5
)
3929 /* APPLE LOCAL end ARM interworking */
3931 /* APPLE LOCAL begin ARM 4956366 */
3932 /* If it's weak, the function called may end up being from a different
3933 compilation unit. */
3934 if (arm_cpp_interwork
&& TREE_PUBLIC (decl
) && DECL_WEAK (decl
))
3936 /* APPLE LOCAL end ARM 4956366 */
3938 /* APPLE LOCAL begin v7 support. Merge from mainline */
3939 func_type
= arm_current_func_type ();
3940 /* Never tailcall from an ISR routine - it needs a special exit sequence. */
3941 if (IS_INTERRUPT (func_type
))
3944 /* Never tailcall if function may be called with a misaligned SP. */
3945 if (IS_STACKALIGN (func_type
))
3948 /* APPLE LOCAL end v7 support. Merge from mainline */
3949 /* Everything else is ok. */
3954 /* Addressing mode support functions. */
3956 /* Return nonzero if X is a legitimate immediate operand when compiling
3957 for PIC. We know that X satisfies CONSTANT_P and flag_pic is true. */
3959 legitimate_pic_operand_p (rtx x
)
3961 if (GET_CODE (x
) == SYMBOL_REF
3962 || (GET_CODE (x
) == CONST
3963 && GET_CODE (XEXP (x
, 0)) == PLUS
3964 && GET_CODE (XEXP (XEXP (x
, 0), 0)) == SYMBOL_REF
))
3971 legitimize_pic_address (rtx orig
, enum machine_mode mode
, rtx reg
)
3973 if (GET_CODE (orig
) == SYMBOL_REF
3974 || GET_CODE (orig
) == LABEL_REF
)
3976 #ifndef AOF_ASSEMBLER
3977 rtx pic_ref
, address
;
3979 /* APPLE LOCAL ARM pic support */
3980 rtx norig
, l1
= NULL_RTX
;
3983 /* APPLE LOCAL ARM pic support */
3984 bool avoid_ind
= true;
3986 /* If this function doesn't have a pic register, create one now.
3987 A lot of the logic here is made obscure by the fact that this
3988 routine gets called as part of the rtx cost estimation
3989 process. We don't want those calls to affect any assumptions
3990 about the real function; and further, we can't call
3991 entry_of_function() until we start the real expansion
3993 /* APPLE LOCAL ARM pic support */
3994 if (!TARGET_MACHO
&& !current_function_uses_pic_offset_table
)
3996 gcc_assert (!no_new_pseudos
);
3997 if (arm_pic_register
!= INVALID_REGNUM
)
3999 cfun
->machine
->pic_reg
= gen_rtx_REG (Pmode
, arm_pic_register
);
4001 /* Play games to avoid marking the function as needing pic
4002 if we are being called as part of the cost-estimation
4005 current_function_uses_pic_offset_table
= 1;
4011 cfun
->machine
->pic_reg
= gen_reg_rtx (Pmode
);
4013 /* Play games to avoid marking the function as needing pic
4014 if we are being called as part of the cost-estimation
4018 current_function_uses_pic_offset_table
= 1;
4021 arm_load_pic_register (0UL);
4025 emit_insn_after (seq
, entry_of_function ());
4032 gcc_assert (!no_new_pseudos
);
4033 reg
= gen_reg_rtx (Pmode
);
4038 #ifdef AOF_ASSEMBLER
4039 /* The AOF assembler can generate relocations for these directly, and
4040 understands that the PIC register has to be added into the offset. */
4041 insn
= emit_insn (gen_pic_load_addr_based (reg
, orig
));
4044 address
= gen_reg_rtx (Pmode
);
4048 /* APPLE LOCAL begin ARM pic support */
4053 if (GET_CODE (orig
) == SYMBOL_REF
4054 || GET_CODE (orig
) == LABEL_REF
)
4056 rtx x
, ptr_ref
= orig
;
4058 l1
= gen_label_rtx ();
4060 if (GET_CODE (orig
) == SYMBOL_REF
)
4062 bool defined
= machopic_data_defined_p (orig
);
4064 if (defined
&& MACHO_DYNAMIC_NO_PIC_P
)
4070 ptr_ref
= gen_rtx_SYMBOL_REF (Pmode
,
4071 machopic_indirection_name (orig
, false));
4072 SET_SYMBOL_REF_DECL (ptr_ref
, SYMBOL_REF_DECL (orig
));
4073 SYMBOL_REF_FLAGS (ptr_ref
) |= MACHO_SYMBOL_FLAG_DEFINED
;
4078 if (MACHO_DYNAMIC_NO_PIC_P
)
4082 if (! MACHO_DYNAMIC_NO_PIC_P
)
4084 x
= plus_constant (gen_rtx_LABEL_REF (Pmode
, l1
), TARGET_ARM
? 8 : 4);
4085 ptr_ref
= gen_rtx_CONST (Pmode
, gen_rtx_MINUS (Pmode
, ptr_ref
, x
));
4091 if (TARGET_MACHO
&& ! MACHO_DYNAMIC_NO_PIC_P
)
4093 if (GET_CODE (orig
) == SYMBOL_REF
4094 || GET_CODE (orig
) == LABEL_REF
)
4098 emit_insn (gen_pic_load_addr_arm (address
, norig
, l1
));
4099 emit_insn (gen_pic_add_dot_plus_eight (address
, l1
, address
));
4101 /* APPLE LOCAL begin v7 support. Merge from mainline */
4102 else if (TARGET_THUMB2
)
4104 emit_insn (gen_pic_load_addr_thumb2 (address
, norig
, l1
));
4105 emit_insn (gen_pic_add_dot_plus_four (address
, l1
, address
));
4107 else /* TARGET_THUMB1 */
4109 emit_insn (gen_pic_load_addr_thumb1 (address
, norig
, l1
));
4110 emit_insn (gen_pic_add_dot_plus_four (address
, l1
, address
));
4112 /* APPLE LOCAL end v7 support. Merge from mainline */
4120 emit_insn (gen_pic_load_addr_arm (address
, norig
, l1
));
4121 /* APPLE LOCAL begin v7 support. Merge from mainline */
4122 else if (TARGET_THUMB2
)
4123 emit_insn (gen_pic_load_addr_thumb2 (address
, norig
, l1
));
4124 else /* TARGET_THUMB1 */
4125 emit_insn (gen_pic_load_addr_thumb1 (address
, norig
, l1
));
4126 /* APPLE LOCAL end v7 support. Merge from mainline */
4128 /* APPLE LOCAL end ARM pic support */
4130 if ((GET_CODE (orig
) == LABEL_REF
4131 || (GET_CODE (orig
) == SYMBOL_REF
&&
4132 SYMBOL_REF_LOCAL_P (orig
)))
4134 pic_ref
= gen_rtx_PLUS (Pmode
, cfun
->machine
->pic_reg
, address
);
4137 /* APPLE LOCAL begin ARM pic support */
4139 pic_ref
= gen_const_mem (Pmode
,
4140 gen_rtx_PLUS (Pmode
, cfun
->machine
->pic_reg
,
4145 pic_ref
= gen_const_mem (Pmode
, address
);
4146 /* APPLE LOCAL end ARM pic support */
4149 insn
= emit_move_insn (reg
, pic_ref
);
4151 /* Put a REG_EQUAL note on this insn, so that it can be optimized
4153 REG_NOTES (insn
) = gen_rtx_EXPR_LIST (REG_EQUAL
, orig
,
4157 else if (GET_CODE (orig
) == CONST
)
4161 if (GET_CODE (XEXP (orig
, 0)) == PLUS
4162 && XEXP (XEXP (orig
, 0), 0) == cfun
->machine
->pic_reg
)
4165 if (GET_CODE (XEXP (orig
, 0)) == UNSPEC
4166 && XINT (XEXP (orig
, 0), 1) == UNSPEC_TLS
)
4169 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
4170 /* Handle the case where we have:
4171 const (plus (UNSPEC_TLS) (ADDEND)). The ADDEND must be a
4173 if (GET_CODE (XEXP (orig
, 0)) == PLUS
4174 && GET_CODE (XEXP (XEXP (orig
, 0), 0)) == UNSPEC
4175 && XINT (XEXP (XEXP (orig
, 0), 0), 1) == UNSPEC_TLS
)
4177 gcc_assert (GET_CODE (XEXP (XEXP (orig
, 0), 1)) == CONST_INT
);
4181 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
4184 gcc_assert (!no_new_pseudos
);
4185 reg
= gen_reg_rtx (Pmode
);
4188 gcc_assert (GET_CODE (XEXP (orig
, 0)) == PLUS
);
4190 base
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 0), Pmode
, reg
);
4191 offset
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 1), Pmode
,
4192 base
== reg
? 0 : reg
);
4194 /* APPLE LOCAL begin 6327222 */
4195 /* #if 0 for now so it's here for reference since this is a tricky
4198 if (GET_CODE (offset
) == CONST_INT
)
4200 /* The base register doesn't really matter, we only want to
4201 test the index for the appropriate mode. */
4202 if (!arm_legitimate_index_p (mode
, offset
, SET
, 0))
4204 gcc_assert (!no_new_pseudos
);
4205 offset
= force_reg (Pmode
, offset
);
4208 if (GET_CODE (offset
) == CONST_INT
)
4209 return plus_constant (base
, INTVAL (offset
));
4212 /* APPLE LOCAL end 6327222 */
4213 if (GET_MODE_SIZE (mode
) > 4
4214 && (GET_MODE_CLASS (mode
) == MODE_INT
4215 || TARGET_SOFT_FLOAT
))
4217 emit_insn (gen_addsi3 (reg
, base
, offset
));
4221 return gen_rtx_PLUS (Pmode
, base
, offset
);
4228 /* APPLE LOCAL v7 support. Merge from mainline */
4229 /* Find a spare register to use during the prolog of a function. */
4232 thumb_find_work_register (unsigned long pushed_regs_mask
)
4236 /* Check the argument registers first as these are call-used. The
4237 register allocation order means that sometimes r3 might be used
4238 but earlier argument registers might not, so check them all. */
4239 for (reg
= LAST_ARG_REGNUM
; reg
>= 0; reg
--)
4240 if (!regs_ever_live
[reg
])
4243 /* Before going on to check the call-saved registers we can try a couple
4244 more ways of deducing that r3 is available. The first is when we are
4245 pushing anonymous arguments onto the stack and we have less than 4
4246 registers worth of fixed arguments(*). In this case r3 will be part of
4247 the variable argument list and so we can be sure that it will be
4248 pushed right at the start of the function. Hence it will be available
4249 for the rest of the prologue.
4250 (*): ie current_function_pretend_args_size is greater than 0. */
4251 if (cfun
->machine
->uses_anonymous_args
4252 && current_function_pretend_args_size
> 0)
4253 return LAST_ARG_REGNUM
;
4255 /* The other case is when we have fixed arguments but less than 4 registers
4256 worth. In this case r3 might be used in the body of the function, but
4257 it is not being used to convey an argument into the function. In theory
4258 we could just check current_function_args_size to see how many bytes are
4259 being passed in argument registers, but it seems that it is unreliable.
4260 Sometimes it will have the value 0 when in fact arguments are being
4261 passed. (See testcase execute/20021111-1.c for an example). So we also
4262 check the args_info.nregs field as well. The problem with this field is
4263 that it makes no allowances for arguments that are passed to the
4264 function but which are not used. Hence we could miss an opportunity
4265 when a function has an unused argument in r3. But it is better to be
4266 safe than to be sorry. */
4267 if (! cfun
->machine
->uses_anonymous_args
4268 && current_function_args_size
>= 0
4269 && current_function_args_size
<= (LAST_ARG_REGNUM
* UNITS_PER_WORD
)
4270 && cfun
->args_info
.nregs
< 4)
4271 return LAST_ARG_REGNUM
;
4273 /* Otherwise look for a call-saved register that is going to be pushed. */
4274 for (reg
= LAST_LO_REGNUM
; reg
> LAST_ARG_REGNUM
; reg
--)
4275 if (pushed_regs_mask
& (1 << reg
))
4278 /* APPLE LOCAL begin v7 support. Merge from mainline */
4281 /* Thumb-2 can use high regs. */
4282 for (reg
= FIRST_HI_REGNUM
; reg
< 15; reg
++)
4283 if (pushed_regs_mask
& (1 << reg
))
4286 /* APPLE LOCAL end v7 support. Merge from mainline */
4287 /* Something went wrong - thumb_compute_save_reg_mask()
4288 should have arranged for a suitable register to be pushed. */
4292 static GTY(()) int pic_labelno
;
4294 /* Generate code to load the PIC register. In thumb mode SCRATCH is a
4298 arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED
)
4300 #ifndef AOF_ASSEMBLER
4301 rtx l1
, labelno
, pic_tmp
, pic_tmp2
, pic_rtx
;
4302 rtx global_offset_table
;
4304 if (current_function_uses_pic_offset_table
== 0 || TARGET_SINGLE_PIC_BASE
)
4307 gcc_assert (flag_pic
);
4309 /* We use an UNSPEC rather than a LABEL_REF because this label never appears
4310 in the code stream. */
4312 labelno
= GEN_INT (pic_labelno
++);
4313 l1
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, labelno
), UNSPEC_PIC_LABEL
);
4314 l1
= gen_rtx_CONST (VOIDmode
, l1
);
4316 global_offset_table
= gen_rtx_SYMBOL_REF (Pmode
, "_GLOBAL_OFFSET_TABLE_");
4317 /* On the ARM the PC register contains 'dot + 8' at the time of the
4318 addition, on the Thumb it is 'dot + 4'. */
4319 pic_tmp
= plus_constant (l1
, TARGET_ARM
? 8 : 4);
4321 pic_tmp2
= gen_rtx_CONST (VOIDmode
,
4322 gen_rtx_PLUS (Pmode
, global_offset_table
, pc_rtx
));
4324 pic_tmp2
= gen_rtx_CONST (VOIDmode
, global_offset_table
);
4326 pic_rtx
= gen_rtx_CONST (Pmode
, gen_rtx_MINUS (Pmode
, pic_tmp2
, pic_tmp
));
4330 /* APPLE LOCAL begin ARM pic support */
4331 emit_insn (gen_pic_load_addr_arm (cfun
->machine
->pic_reg
, pic_rtx
, l1
));
4332 emit_insn (gen_pic_add_dot_plus_eight (cfun
->machine
->pic_reg
, l1
,
4333 cfun
->machine
->pic_reg
));
4334 /* APPLE LOCAL end ARM pic support */
4336 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
4337 else if (TARGET_THUMB2
)
4339 /* Thumb-2 only allows very limited access to the PC. Calculate the
4340 address in a temporary register. */
4341 if (arm_pic_register
!= INVALID_REGNUM
)
4343 pic_tmp
= gen_rtx_REG (SImode
,
4344 thumb_find_work_register (saved_regs
));
4348 gcc_assert (!no_new_pseudos
);
4349 pic_tmp
= gen_reg_rtx (Pmode
);
4352 emit_insn (gen_pic_load_addr_thumb2 (cfun
->machine
->pic_reg
,
4354 emit_insn (gen_pic_load_dot_plus_four (pic_tmp
, labelno
));
4355 emit_insn (gen_addsi3 (cfun
->machine
->pic_reg
, cfun
->machine
->pic_reg
,
4358 else /* TARGET_THUMB1 */
4360 /* APPLE LOCAL begin ARM pic support */
4361 if (arm_pic_register
!= INVALID_REGNUM
4362 && REGNO (cfun
->machine
->pic_reg
) > LAST_LO_REGNUM
)
4364 /* We will have pushed the pic register, so we should always be
4365 able to find a work register. */
4366 pic_tmp
= gen_rtx_REG (SImode
,
4367 thumb_find_work_register (saved_regs
));
4368 emit_insn (gen_pic_load_addr_thumb1 (pic_tmp
, pic_rtx
, l1
));
4369 emit_insn (gen_movsi (pic_offset_table_rtx
, pic_tmp
));
4372 emit_insn (gen_pic_load_addr_thumb1 (cfun
->machine
->pic_reg
, pic_rtx
, l1
));
4373 emit_insn (gen_pic_add_dot_plus_four (cfun
->machine
->pic_reg
, l1
,
4374 cfun
->machine
->pic_reg
));
4375 /* APPLE LOCAL end ARM pic support */
4377 /* APPLE LOCAL end v7 support. Merge from mainline */
4379 /* Need to emit this whether or not we obey regdecls,
4380 since setjmp/longjmp can cause life info to screw up. */
4381 emit_insn (gen_rtx_USE (VOIDmode
, cfun
->machine
->pic_reg
));
4382 #endif /* AOF_ASSEMBLER */
4386 /* Return nonzero if X is valid as an ARM state addressing register. */
4388 arm_address_register_rtx_p (rtx x
, int strict_p
)
4392 if (GET_CODE (x
) != REG
)
4398 return ARM_REGNO_OK_FOR_BASE_P (regno
);
4400 return (regno
<= LAST_ARM_REGNUM
4401 || regno
>= FIRST_PSEUDO_REGISTER
4402 || regno
== FRAME_POINTER_REGNUM
4403 || regno
== ARG_POINTER_REGNUM
);
4406 /* Return TRUE if this rtx is the difference of a symbol and a label,
4407 and will reduce to a PC-relative relocation in the object file.
4408 Expressions like this can be left alone when generating PIC, rather
4409 than forced through the GOT. */
4411 pcrel_constant_p (rtx x
)
4413 if (GET_CODE (x
) == MINUS
)
4414 return symbol_mentioned_p (XEXP (x
, 0)) && label_mentioned_p (XEXP (x
, 1));
4419 /* Return nonzero if X is a valid ARM state address operand. */
4421 arm_legitimate_address_p (enum machine_mode mode
, rtx x
, RTX_CODE outer
,
4425 enum rtx_code code
= GET_CODE (x
);
4427 if (arm_address_register_rtx_p (x
, strict_p
))
4430 use_ldrd
= (TARGET_LDRD
4432 || (mode
== DFmode
&& (TARGET_SOFT_FLOAT
|| TARGET_VFP
))));
4434 /* APPLE LOCAL begin 6293989 */
4435 if (TARGET_NEON
&& VECTOR_MODE_P (mode
)
4436 && (code
== PRE_DEC
|| code
== PRE_INC
|| code
== POST_DEC
))
4438 /* APPLE LOCAL end 6293989 */
4440 if (code
== POST_INC
|| code
== PRE_DEC
4441 || ((code
== PRE_INC
|| code
== POST_DEC
)
4442 && (use_ldrd
|| GET_MODE_SIZE (mode
) <= 4)))
4443 return arm_address_register_rtx_p (XEXP (x
, 0), strict_p
);
4445 else if ((code
== POST_MODIFY
|| code
== PRE_MODIFY
)
4446 && arm_address_register_rtx_p (XEXP (x
, 0), strict_p
)
4447 && GET_CODE (XEXP (x
, 1)) == PLUS
4448 && rtx_equal_p (XEXP (XEXP (x
, 1), 0), XEXP (x
, 0)))
4450 rtx addend
= XEXP (XEXP (x
, 1), 1);
4452 /* Don't allow ldrd post increment by register because it's hard
4453 to fixup invalid register choices. */
4455 && GET_CODE (x
) == POST_MODIFY
4456 && GET_CODE (addend
) == REG
)
4459 return ((use_ldrd
|| GET_MODE_SIZE (mode
) <= 4)
4460 && arm_legitimate_index_p (mode
, addend
, outer
, strict_p
));
4463 /* After reload constants split into minipools will have addresses
4464 from a LABEL_REF. */
4465 else if (reload_completed
4466 && (code
== LABEL_REF
4468 && GET_CODE (XEXP (x
, 0)) == PLUS
4469 && GET_CODE (XEXP (XEXP (x
, 0), 0)) == LABEL_REF
4470 && GET_CODE (XEXP (XEXP (x
, 0), 1)) == CONST_INT
)))
4473 /* APPLE LOCAL v7 support. Merge from mainline */
4474 else if (mode
== TImode
|| (TARGET_NEON
&& VALID_NEON_STRUCT_MODE (mode
)))
4477 else if (code
== PLUS
)
4479 rtx xop0
= XEXP (x
, 0);
4480 rtx xop1
= XEXP (x
, 1);
4482 return ((arm_address_register_rtx_p (xop0
, strict_p
)
4483 && arm_legitimate_index_p (mode
, xop1
, outer
, strict_p
))
4484 || (arm_address_register_rtx_p (xop1
, strict_p
)
4485 && arm_legitimate_index_p (mode
, xop0
, outer
, strict_p
)));
4489 /* Reload currently can't handle MINUS, so disable this for now */
4490 else if (GET_CODE (x
) == MINUS
)
4492 rtx xop0
= XEXP (x
, 0);
4493 rtx xop1
= XEXP (x
, 1);
4495 return (arm_address_register_rtx_p (xop0
, strict_p
)
4496 && arm_legitimate_index_p (mode
, xop1
, outer
, strict_p
));
4500 else if (GET_MODE_CLASS (mode
) != MODE_FLOAT
4501 && code
== SYMBOL_REF
4502 && CONSTANT_POOL_ADDRESS_P (x
)
4504 && symbol_mentioned_p (get_pool_constant (x
))
4505 && ! pcrel_constant_p (get_pool_constant (x
))))
4511 /* APPLE LOCAL begin v7 support. Merge from mainline */
4512 /* Return nonzero if X is a valid Thumb-2 address operand. */
4514 thumb2_legitimate_address_p (enum machine_mode mode
, rtx x
, int strict_p
)
4517 enum rtx_code code
= GET_CODE (x
);
4519 if (arm_address_register_rtx_p (x
, strict_p
))
4522 use_ldrd
= (TARGET_LDRD
4524 || (mode
== DFmode
&& (TARGET_SOFT_FLOAT
|| TARGET_VFP
))));
4526 /* APPLE LOCAL begin 6293989 */
4527 if (TARGET_NEON
&& VECTOR_MODE_P (mode
)
4528 && (code
== PRE_DEC
|| code
== PRE_INC
|| code
== POST_DEC
))
4530 /* APPLE LOCAL end 6293989 */
4532 if (code
== POST_INC
|| code
== PRE_DEC
4533 || ((code
== PRE_INC
|| code
== POST_DEC
)
4534 && (use_ldrd
|| GET_MODE_SIZE (mode
) <= 4)))
4535 return arm_address_register_rtx_p (XEXP (x
, 0), strict_p
);
4537 else if ((code
== POST_MODIFY
|| code
== PRE_MODIFY
)
4538 && arm_address_register_rtx_p (XEXP (x
, 0), strict_p
)
4539 && GET_CODE (XEXP (x
, 1)) == PLUS
4540 && rtx_equal_p (XEXP (XEXP (x
, 1), 0), XEXP (x
, 0)))
4542 /* Thumb-2 only has autoincrement by constant. */
4543 rtx addend
= XEXP (XEXP (x
, 1), 1);
4544 HOST_WIDE_INT offset
;
4546 if (GET_CODE (addend
) != CONST_INT
)
4549 offset
= INTVAL(addend
);
4550 if (GET_MODE_SIZE (mode
) <= 4)
4551 return (offset
> -256 && offset
< 256);
4553 return (use_ldrd
&& offset
> -1024 && offset
< 1024
4554 && (offset
& 3) == 0);
4557 /* After reload constants split into minipools will have addresses
4558 from a LABEL_REF. */
4559 else if (reload_completed
4560 && (code
== LABEL_REF
4562 && GET_CODE (XEXP (x
, 0)) == PLUS
4563 && GET_CODE (XEXP (XEXP (x
, 0), 0)) == LABEL_REF
4564 && GET_CODE (XEXP (XEXP (x
, 0), 1)) == CONST_INT
)))
4567 /* APPLE LOCAL v7 support. Merge from Codesourcery */
4568 else if (mode
== TImode
|| (TARGET_NEON
&& VALID_NEON_STRUCT_MODE (mode
)))
4571 else if (code
== PLUS
)
4573 rtx xop0
= XEXP (x
, 0);
4574 rtx xop1
= XEXP (x
, 1);
4576 return ((arm_address_register_rtx_p (xop0
, strict_p
)
4577 && thumb2_legitimate_index_p (mode
, xop1
, strict_p
))
4578 || (arm_address_register_rtx_p (xop1
, strict_p
)
4579 && thumb2_legitimate_index_p (mode
, xop0
, strict_p
)));
4582 else if (GET_MODE_CLASS (mode
) != MODE_FLOAT
4583 && code
== SYMBOL_REF
4584 && CONSTANT_POOL_ADDRESS_P (x
)
4586 && symbol_mentioned_p (get_pool_constant (x
))
4587 && ! pcrel_constant_p (get_pool_constant (x
))))
4593 /* APPLE LOCAL end v7 support. Merge from mainline */
4594 /* Return nonzero if INDEX is valid for an address index operand in
4597 arm_legitimate_index_p (enum machine_mode mode
, rtx index
, RTX_CODE outer
,
4600 HOST_WIDE_INT range
;
4601 enum rtx_code code
= GET_CODE (index
);
4603 /* Standard coprocessor addressing modes. */
4604 if (TARGET_HARD_FLOAT
4605 /* APPLE LOCAL ARM 4480764 */
4606 && (TARGET_FPA
|| TARGET_MAVERICK
|| TARGET_VFP
)
4607 && (GET_MODE_CLASS (mode
) == MODE_FLOAT
4608 || (TARGET_MAVERICK
&& mode
== DImode
)))
4609 return (code
== CONST_INT
&& INTVAL (index
) < 1024
4610 && INTVAL (index
) > -1024
4611 && (INTVAL (index
) & 3) == 0);
4613 if (TARGET_REALLY_IWMMXT
&& VALID_IWMMXT_REG_MODE (mode
))
4615 /* For DImode assume values will usually live in core regs
4616 and only allow LDRD addressing modes. */
4617 if (!TARGET_LDRD
|| mode
!= DImode
)
4618 return (code
== CONST_INT
4619 && INTVAL (index
) < 1024
4620 && INTVAL (index
) > -1024
4621 && (INTVAL (index
) & 3) == 0);
4624 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
4626 /* APPLE LOCAL 6150882 use thumb2 by default for v7 */
4627 && VECTOR_MODE_P (mode
)
4628 && (VALID_NEON_DREG_MODE (mode
) || VALID_NEON_QREG_MODE (mode
)))
4629 return (code
== CONST_INT
4630 && INTVAL (index
) < 1016
4631 && INTVAL (index
) > -1024
4632 && (INTVAL (index
) & 3) == 0);
4634 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
4635 if (arm_address_register_rtx_p (index
, strict_p
)
4636 && (GET_MODE_SIZE (mode
) <= 4))
4639 if (mode
== DImode
|| mode
== DFmode
)
4641 if (code
== CONST_INT
)
4643 HOST_WIDE_INT val
= INTVAL (index
);
4646 return val
> -256 && val
< 256;
4648 return val
> -4096 && val
< 4092;
4651 return TARGET_LDRD
&& arm_address_register_rtx_p (index
, strict_p
);
4654 if (GET_MODE_SIZE (mode
) <= 4
4657 || (mode
== QImode
&& outer
== SIGN_EXTEND
))))
4661 rtx xiop0
= XEXP (index
, 0);
4662 rtx xiop1
= XEXP (index
, 1);
4664 return ((arm_address_register_rtx_p (xiop0
, strict_p
)
4665 && power_of_two_operand (xiop1
, SImode
))
4666 || (arm_address_register_rtx_p (xiop1
, strict_p
)
4667 && power_of_two_operand (xiop0
, SImode
)));
4669 else if (code
== LSHIFTRT
|| code
== ASHIFTRT
4670 || code
== ASHIFT
|| code
== ROTATERT
)
4672 rtx op
= XEXP (index
, 1);
4674 return (arm_address_register_rtx_p (XEXP (index
, 0), strict_p
)
4675 && GET_CODE (op
) == CONST_INT
4677 && INTVAL (op
) <= 31);
4681 /* For ARM v4 we may be doing a sign-extend operation during the
4685 if (mode
== HImode
|| (outer
== SIGN_EXTEND
&& mode
== QImode
))
4691 range
= (mode
== HImode
) ? 4095 : 4096;
4693 return (code
== CONST_INT
4694 && INTVAL (index
) < range
4695 && INTVAL (index
) > -range
);
4698 /* APPLE LOCAL begin v7 support. Merge from mainline */
4699 /* Return true if OP is a valid index scaling factor for Thumb-2 address
4700 index operand. i.e. 1, 2, 4 or 8. */
4702 thumb2_index_mul_operand (rtx op
)
4706 if (GET_CODE(op
) != CONST_INT
)
4710 return (val
== 1 || val
== 2 || val
== 4 || val
== 8);
4713 /* Return nonzero if INDEX is a valid Thumb-2 address index operand. */
4715 thumb2_legitimate_index_p (enum machine_mode mode
, rtx index
, int strict_p
)
4717 enum rtx_code code
= GET_CODE (index
);
4719 /* ??? Combine arm and thumb2 coprocessor addressing modes. */
4720 /* Standard coprocessor addressing modes. */
4721 if (TARGET_HARD_FLOAT
4722 && (TARGET_FPA
|| TARGET_MAVERICK
)
4723 && (GET_MODE_CLASS (mode
) == MODE_FLOAT
4724 || (TARGET_MAVERICK
&& mode
== DImode
)))
4725 return (code
== CONST_INT
&& INTVAL (index
) < 1024
4726 && INTVAL (index
) > -1024
4727 && (INTVAL (index
) & 3) == 0);
4729 if (TARGET_REALLY_IWMMXT
&& VALID_IWMMXT_REG_MODE (mode
))
4730 return (code
== CONST_INT
4731 && INTVAL (index
) < 1024
4732 && INTVAL (index
) > -1024
4733 && (INTVAL (index
) & 3) == 0);
4735 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
4737 /* APPLE LOCAL 6150882 use thumb2 by default for v7 */
4738 && VECTOR_MODE_P (mode
)
4739 && (VALID_NEON_DREG_MODE (mode
) || VALID_NEON_QREG_MODE (mode
)))
4740 return (code
== CONST_INT
4741 && INTVAL (index
) < 1016
4742 && INTVAL (index
) > -1024
4743 && (INTVAL (index
) & 3) == 0);
4745 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
4746 if (arm_address_register_rtx_p (index
, strict_p
)
4747 && (GET_MODE_SIZE (mode
) <= 4))
4750 if (mode
== DImode
|| mode
== DFmode
)
4752 HOST_WIDE_INT val
= INTVAL (index
);
4753 /* ??? Can we assume ldrd for thumb2? */
4754 /* Thumb-2 ldrd only has reg+const addressing modes. */
4755 if (code
!= CONST_INT
)
4758 /* ldrd supports offsets of +-1020.
4759 However the ldr fallback does not. */
4760 return val
> -256 && val
< 256 && (val
& 3) == 0;
4765 rtx xiop0
= XEXP (index
, 0);
4766 rtx xiop1
= XEXP (index
, 1);
4768 return ((arm_address_register_rtx_p (xiop0
, strict_p
)
4769 && thumb2_index_mul_operand (xiop1
))
4770 || (arm_address_register_rtx_p (xiop1
, strict_p
)
4771 && thumb2_index_mul_operand (xiop0
)));
4773 else if (code
== ASHIFT
)
4775 rtx op
= XEXP (index
, 1);
4777 return (arm_address_register_rtx_p (XEXP (index
, 0), strict_p
)
4778 && GET_CODE (op
) == CONST_INT
4780 && INTVAL (op
) <= 3);
4783 return (code
== CONST_INT
4784 && INTVAL (index
) < 4096
4785 && INTVAL (index
) > -256);
4788 /* Return nonzero if X is valid as a 16-bit Thumb state base register. */
4790 thumb1_base_register_rtx_p (rtx x
, enum machine_mode mode
, int strict_p
)
4792 /* APPLE LOCAL end v7 support. Merge from mainline */
4795 if (GET_CODE (x
) != REG
)
4801 /* APPLE LOCAL v7 support. Merge from mainline */
4802 return THUMB1_REGNO_MODE_OK_FOR_BASE_P (regno
, mode
);
4804 return (regno
<= LAST_LO_REGNUM
4805 || regno
> LAST_VIRTUAL_REGISTER
4806 || regno
== FRAME_POINTER_REGNUM
4807 || (GET_MODE_SIZE (mode
) >= 4
4808 && (regno
== STACK_POINTER_REGNUM
4809 || regno
>= FIRST_PSEUDO_REGISTER
4810 || x
== hard_frame_pointer_rtx
4811 || x
== arg_pointer_rtx
)));
4814 /* Return nonzero if x is a legitimate index register. This is the case
4815 for any base register that can access a QImode object. */
4816 /* APPLE LOCAL begin v7 support. Merge from mainline */
4818 thumb1_index_register_rtx_p (rtx x
, int strict_p
)
4820 return thumb1_base_register_rtx_p (x
, QImode
, strict_p
);
4822 /* APPLE LOCAL end v7 support. Merge from mainline */
4824 /* APPLE LOCAL v7 support. Merge from mainline */
4825 /* Return nonzero if x is a legitimate 16-bit Thumb-state address.
4827 The AP may be eliminated to either the SP or the FP, so we use the
4828 least common denominator, e.g. SImode, and offsets from 0 to 64.
4830 ??? Verify whether the above is the right approach.
4832 ??? Also, the FP may be eliminated to the SP, so perhaps that
4833 needs special handling also.
4835 ??? Look at how the mips16 port solves this problem. It probably uses
4836 better ways to solve some of these problems.
4838 Although it is not incorrect, we don't accept QImode and HImode
4839 addresses based on the frame pointer or arg pointer until the
4840 reload pass starts. This is so that eliminating such addresses
4841 into stack based ones won't produce impossible code. */
4843 /* APPLE LOCAL v7 support. Merge from mainline */
4844 thumb1_legitimate_address_p (enum machine_mode mode
, rtx x
, int strict_p
)
4846 /* ??? Not clear if this is right. Experiment. */
4847 if (GET_MODE_SIZE (mode
) < 4
4848 && !(reload_in_progress
|| reload_completed
)
4849 && (reg_mentioned_p (frame_pointer_rtx
, x
)
4850 || reg_mentioned_p (arg_pointer_rtx
, x
)
4851 || reg_mentioned_p (virtual_incoming_args_rtx
, x
)
4852 || reg_mentioned_p (virtual_outgoing_args_rtx
, x
)
4853 || reg_mentioned_p (virtual_stack_dynamic_rtx
, x
)
4854 || reg_mentioned_p (virtual_stack_vars_rtx
, x
)))
4857 /* Accept any base register. SP only in SImode or larger. */
4858 /* APPLE LOCAL v7 support. Merge from mainline */
4859 else if (thumb1_base_register_rtx_p (x
, mode
, strict_p
))
4862 /* This is PC relative data before arm_reorg runs. */
4863 else if (GET_MODE_SIZE (mode
) >= 4 && CONSTANT_P (x
)
4864 && GET_CODE (x
) == SYMBOL_REF
4865 && CONSTANT_POOL_ADDRESS_P (x
) && !flag_pic
)
4868 /* This is PC relative data after arm_reorg runs. */
4869 else if (GET_MODE_SIZE (mode
) >= 4 && reload_completed
4870 && (GET_CODE (x
) == LABEL_REF
4871 || (GET_CODE (x
) == CONST
4872 && GET_CODE (XEXP (x
, 0)) == PLUS
4873 && GET_CODE (XEXP (XEXP (x
, 0), 0)) == LABEL_REF
4874 && GET_CODE (XEXP (XEXP (x
, 0), 1)) == CONST_INT
)))
4877 /* Post-inc indexing only supported for SImode and larger. */
4878 else if (GET_CODE (x
) == POST_INC
&& GET_MODE_SIZE (mode
) >= 4
4879 /* APPLE LOCAL v7 support. Merge from mainline */
4880 && thumb1_index_register_rtx_p (XEXP (x
, 0), strict_p
))
4883 else if (GET_CODE (x
) == PLUS
)
4885 /* REG+REG address can be any two index registers. */
4886 /* We disallow FRAME+REG addressing since we know that FRAME
4887 will be replaced with STACK, and SP relative addressing only
4888 permits SP+OFFSET. */
4889 if (GET_MODE_SIZE (mode
) <= 4
4890 && XEXP (x
, 0) != frame_pointer_rtx
4891 && XEXP (x
, 1) != frame_pointer_rtx
4892 /* APPLE LOCAL begin v7 support. Merge from mainline */
4893 && thumb1_index_register_rtx_p (XEXP (x
, 0), strict_p
)
4894 && thumb1_index_register_rtx_p (XEXP (x
, 1), strict_p
))
4895 /* APPLE LOCAL end v7 support. Merge from mainline */
4898 /* REG+const has 5-7 bit offset for non-SP registers. */
4899 /* APPLE LOCAL v7 support. Merge from mainline */
4900 else if ((thumb1_index_register_rtx_p (XEXP (x
, 0), strict_p
)
4901 || XEXP (x
, 0) == arg_pointer_rtx
)
4902 && GET_CODE (XEXP (x
, 1)) == CONST_INT
4903 && thumb_legitimate_offset_p (mode
, INTVAL (XEXP (x
, 1))))
4906 /* REG+const has 10 bit offset for SP, but only SImode and
4907 larger is supported. */
4908 /* ??? Should probably check for DI/DFmode overflow here
4909 just like GO_IF_LEGITIMATE_OFFSET does. */
4910 else if (GET_CODE (XEXP (x
, 0)) == REG
4911 && REGNO (XEXP (x
, 0)) == STACK_POINTER_REGNUM
4912 && GET_MODE_SIZE (mode
) >= 4
4913 && GET_CODE (XEXP (x
, 1)) == CONST_INT
4914 && INTVAL (XEXP (x
, 1)) >= 0
4915 && INTVAL (XEXP (x
, 1)) + GET_MODE_SIZE (mode
) <= 1024
4916 && (INTVAL (XEXP (x
, 1)) & 3) == 0)
4919 else if (GET_CODE (XEXP (x
, 0)) == REG
4920 && REGNO (XEXP (x
, 0)) == FRAME_POINTER_REGNUM
4921 && GET_MODE_SIZE (mode
) >= 4
4922 && GET_CODE (XEXP (x
, 1)) == CONST_INT
4923 && (INTVAL (XEXP (x
, 1)) & 3) == 0)
4927 else if (GET_MODE_CLASS (mode
) != MODE_FLOAT
4928 && GET_MODE_SIZE (mode
) == 4
4929 && GET_CODE (x
) == SYMBOL_REF
4930 && CONSTANT_POOL_ADDRESS_P (x
)
4932 && symbol_mentioned_p (get_pool_constant (x
))
4933 && ! pcrel_constant_p (get_pool_constant (x
))))
4939 /* Return nonzero if VAL can be used as an offset in a Thumb-state address
4940 instruction of mode MODE. */
4942 thumb_legitimate_offset_p (enum machine_mode mode
, HOST_WIDE_INT val
)
4944 switch (GET_MODE_SIZE (mode
))
4947 return val
>= 0 && val
< 32;
4950 return val
>= 0 && val
< 64 && (val
& 1) == 0;
4954 && (val
+ GET_MODE_SIZE (mode
)) <= 128
4959 /* Build the SYMBOL_REF for __tls_get_addr. */
4961 static GTY(()) rtx tls_get_addr_libfunc
;
4964 get_tls_get_addr (void)
4966 if (!tls_get_addr_libfunc
)
4967 tls_get_addr_libfunc
= init_one_libfunc ("__tls_get_addr");
4968 return tls_get_addr_libfunc
;
4972 arm_load_tp (rtx target
)
4975 target
= gen_reg_rtx (SImode
);
4979 /* Can return in any reg. */
4980 emit_insn (gen_load_tp_hard (target
));
4984 /* Always returned in r0. Immediately copy the result into a pseudo,
4985 otherwise other uses of r0 (e.g. setting up function arguments) may
4986 clobber the value. */
4990 emit_insn (gen_load_tp_soft ());
4992 tmp
= gen_rtx_REG (SImode
, 0);
4993 emit_move_insn (target
, tmp
);
4999 load_tls_operand (rtx x
, rtx reg
)
5003 if (reg
== NULL_RTX
)
5004 reg
= gen_reg_rtx (SImode
);
5006 tmp
= gen_rtx_CONST (SImode
, x
);
5008 emit_move_insn (reg
, tmp
);
5014 arm_call_tls_get_addr (rtx x
, rtx reg
, rtx
*valuep
, int reloc
)
5016 rtx insns
, label
, labelno
, sum
;
5020 labelno
= GEN_INT (pic_labelno
++);
5021 label
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, labelno
), UNSPEC_PIC_LABEL
);
5022 label
= gen_rtx_CONST (VOIDmode
, label
);
5024 sum
= gen_rtx_UNSPEC (Pmode
,
5025 gen_rtvec (4, x
, GEN_INT (reloc
), label
,
5026 GEN_INT (TARGET_ARM
? 8 : 4)),
5028 reg
= load_tls_operand (sum
, reg
);
5031 emit_insn (gen_pic_add_dot_plus_eight (reg
, reg
, labelno
));
5032 /* APPLE LOCAL begin v7 support. Merge from mainline */
5033 else if (TARGET_THUMB2
)
5036 /* Thumb-2 only allows very limited access to the PC. Calculate
5037 the address in a temporary register. */
5038 tmp
= gen_reg_rtx (SImode
);
5039 emit_insn (gen_pic_load_dot_plus_four (tmp
, labelno
));
5040 emit_insn (gen_addsi3(reg
, reg
, tmp
));
5042 else /* TARGET_THUMB1 */
5043 emit_insn (gen_pic_add_dot_plus_four (reg
, reg
, labelno
));
5044 /* APPLE LOCAL end v7 support. Merge from mainline */
5046 *valuep
= emit_library_call_value (get_tls_get_addr (), NULL_RTX
, LCT_PURE
, /* LCT_CONST? */
5047 Pmode
, 1, reg
, Pmode
);
5049 insns
= get_insns ();
5056 legitimize_tls_address (rtx x
, rtx reg
)
5058 rtx dest
, tp
, label
, labelno
, sum
, insns
, ret
, eqv
, addend
;
5059 unsigned int model
= SYMBOL_REF_TLS_MODEL (x
);
5063 case TLS_MODEL_GLOBAL_DYNAMIC
:
5064 insns
= arm_call_tls_get_addr (x
, reg
, &ret
, TLS_GD32
);
5065 dest
= gen_reg_rtx (Pmode
);
5066 emit_libcall_block (insns
, dest
, ret
, x
);
5069 case TLS_MODEL_LOCAL_DYNAMIC
:
5070 insns
= arm_call_tls_get_addr (x
, reg
, &ret
, TLS_LDM32
);
5072 /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
5073 share the LDM result with other LD model accesses. */
5074 eqv
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, const1_rtx
),
5076 dest
= gen_reg_rtx (Pmode
);
5077 emit_libcall_block (insns
, dest
, ret
, eqv
);
5079 /* Load the addend. */
5080 addend
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (2, x
, GEN_INT (TLS_LDO32
)),
5082 addend
= force_reg (SImode
, gen_rtx_CONST (SImode
, addend
));
5083 return gen_rtx_PLUS (Pmode
, dest
, addend
);
5085 case TLS_MODEL_INITIAL_EXEC
:
5086 labelno
= GEN_INT (pic_labelno
++);
5087 label
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, labelno
), UNSPEC_PIC_LABEL
);
5088 label
= gen_rtx_CONST (VOIDmode
, label
);
5089 sum
= gen_rtx_UNSPEC (Pmode
,
5090 gen_rtvec (4, x
, GEN_INT (TLS_IE32
), label
,
5091 GEN_INT (TARGET_ARM
? 8 : 4)),
5093 reg
= load_tls_operand (sum
, reg
);
5096 emit_insn (gen_tls_load_dot_plus_eight (reg
, reg
, labelno
));
5097 /* APPLE LOCAL begin v7 support. Merge from mainline */
5098 else if (TARGET_THUMB2
)
5101 /* Thumb-2 only allows very limited access to the PC. Calculate
5102 the address in a temporary register. */
5103 tmp
= gen_reg_rtx (SImode
);
5104 emit_insn (gen_pic_load_dot_plus_four (tmp
, labelno
));
5105 emit_insn (gen_addsi3(reg
, reg
, tmp
));
5106 emit_move_insn (reg
, gen_const_mem (SImode
, reg
));
5108 /* APPLE LOCAL end v7 support. Merge from mainline */
5111 emit_insn (gen_pic_add_dot_plus_four (reg
, reg
, labelno
));
5112 emit_move_insn (reg
, gen_const_mem (SImode
, reg
));
5115 tp
= arm_load_tp (NULL_RTX
);
5117 return gen_rtx_PLUS (Pmode
, tp
, reg
);
5119 case TLS_MODEL_LOCAL_EXEC
:
5120 tp
= arm_load_tp (NULL_RTX
);
5122 reg
= gen_rtx_UNSPEC (Pmode
,
5123 gen_rtvec (2, x
, GEN_INT (TLS_LE32
)),
5125 reg
= force_reg (SImode
, gen_rtx_CONST (SImode
, reg
));
5127 return gen_rtx_PLUS (Pmode
, tp
, reg
);
5134 /* Try machine-dependent ways of modifying an illegitimate address
5135 to be legitimate. If we find one, return the new, valid address. */
5137 arm_legitimize_address (rtx x
, rtx orig_x
, enum machine_mode mode
)
5139 if (arm_tls_symbol_p (x
))
5140 return legitimize_tls_address (x
, NULL_RTX
);
5142 /* APPLE LOCAL begin ARM addresses involving large constants */
5145 /* We need to find and carefully transform any SYMBOL and LABEL
5146 references; so go back to the original address expression. */
5147 rtx new_x
= legitimize_pic_address (orig_x
, mode
, NULL_RTX
);
5149 if (new_x
!= orig_x
)
5152 else if (GET_CODE (x
) == PLUS
)
5154 rtx xop0
= XEXP (x
, 0);
5155 rtx xop1
= XEXP (x
, 1);
5157 if (CONSTANT_P (xop0
) && !symbol_mentioned_p (xop0
))
5158 xop0
= force_reg (SImode
, xop0
);
5160 if (CONSTANT_P (xop1
) && !symbol_mentioned_p (xop1
)
5161 && GET_CODE (xop1
) != CONST_INT
)
5162 xop1
= force_reg (SImode
, xop1
);
5164 if (GET_CODE (xop1
) == CONST_INT
)
5166 HOST_WIDE_INT n
, low_n
;
5170 (+ (+ (foo, SFP) const)). It is better to rearrange this as
5171 (+ (foo (+ (SFP, const))). The eventual SP + const1 + const will
5174 if (GET_CODE (xop0
) == PLUS
)
5176 rtx xop00
= XEXP (xop0
, 0);
5177 rtx xop01
= XEXP (xop0
, 1);
5179 if (xop01
== virtual_stack_vars_rtx
)
5181 base_reg
= gen_reg_rtx (SImode
);
5182 val
= force_operand (gen_rtx_PLUS (SImode
, xop01
, xop1
),
5184 emit_move_insn (base_reg
, val
);
5185 /* Canonical form requires some non-reg ops to be first. */
5186 x
= gen_rtx_PLUS (SImode
, xop00
, base_reg
);
5192 /* The size of constant that fits in a load or store instruction
5193 is different for different sized operations. Break N into
5194 low_n (the part that will fit in the instruction) and n
5195 (the part that won't). */
5196 /* VFP addressing modes actually allow greater offsets, but for
5197 now we just stick with the lowest common denominator. */
5199 || ((TARGET_SOFT_FLOAT
|| TARGET_VFP
) && mode
== DFmode
))
5209 else if ((mode
== HImode
|| mode
== QImode
) && arm_arch4
)
5211 low_n
= n
>= 0 ? (n
& 0xff) : -((-n
) & 0xff);
5216 low_n
= ((mode
) == TImode
? 0
5217 : n
>= 0 ? (n
& 0xfff) : -((-n
) & 0xfff));
5223 /* Emit an auxiliary instruction to compute base+high_part
5224 into a register base_reg, then return base_reg+low_part. */
5225 base_reg
= gen_reg_rtx (SImode
);
5226 val
= force_operand (plus_constant (xop0
, n
), NULL_RTX
);
5227 emit_move_insn (base_reg
, val
);
5228 x
= plus_constant (base_reg
, low_n
);
5230 else if (xop0
!= XEXP (x
, 0) || xop1
!= XEXP (x
, 1))
5231 x
= gen_rtx_PLUS (SImode
, xop0
, xop1
);
5233 else if (xop0
!= XEXP (x
, 0) || xop1
!= XEXP (x
, 1))
5234 x
= gen_rtx_PLUS (SImode
, xop0
, xop1
);
5237 /* XXX We don't allow MINUS any more -- see comment in
5238 arm_legitimate_address_p (). */
5239 else if (GET_CODE (x
) == MINUS
)
5241 rtx xop0
= XEXP (x
, 0);
5242 rtx xop1
= XEXP (x
, 1);
5244 if (CONSTANT_P (xop0
))
5245 xop0
= force_reg (SImode
, xop0
);
5247 if (CONSTANT_P (xop1
) && ! symbol_mentioned_p (xop1
))
5248 xop1
= force_reg (SImode
, xop1
);
5250 if (xop0
!= XEXP (x
, 0) || xop1
!= XEXP (x
, 1))
5251 x
= gen_rtx_MINUS (SImode
, xop0
, xop1
);
5254 /* Make sure to take full advantage of the pre-indexed addressing mode
5255 with absolute addresses which often allows for the base register to
5256 be factorized for multiple adjacent memory references, and it might
5257 even allows for the mini pool to be avoided entirely. */
5258 else if (GET_CODE (x
) == CONST_INT
&& optimize
> 0)
5261 HOST_WIDE_INT mask
, base
, index
;
5264 /* ldr and ldrb can use a 12 bit index, ldrsb and the rest can only
5265 use a 8 bit index. So let's use a 12 bit index for SImode only and
5266 hope that arm_gen_constant will enable ldrb to use more bits. */
5267 bits
= (mode
== SImode
) ? 12 : 8;
5268 mask
= (1 << bits
) - 1;
5269 base
= INTVAL (x
) & ~mask
;
5270 index
= INTVAL (x
) & mask
;
5271 if (bit_count (base
& 0xffffffff) > (32 - bits
)/2)
5273 /* It'll most probably be more efficient to generate the base
5274 with more bits set and use a negative index instead. */
5278 base_reg
= force_reg (SImode
, GEN_INT (base
));
5279 x
= plus_constant (base_reg
, index
);
5281 /* APPLE LOCAL end ARM addresses involving large constants */
5287 /* Try machine-dependent ways of modifying an illegitimate Thumb address
5288 to be legitimate. If we find one, return the new, valid address. */
5290 thumb_legitimize_address (rtx x
, rtx orig_x
, enum machine_mode mode
)
5292 if (arm_tls_symbol_p (x
))
5293 return legitimize_tls_address (x
, NULL_RTX
);
5295 if (GET_CODE (x
) == PLUS
5296 && GET_CODE (XEXP (x
, 1)) == CONST_INT
5297 && (INTVAL (XEXP (x
, 1)) >= 32 * GET_MODE_SIZE (mode
)
5298 || INTVAL (XEXP (x
, 1)) < 0))
5300 rtx xop0
= XEXP (x
, 0);
5301 rtx xop1
= XEXP (x
, 1);
5302 HOST_WIDE_INT offset
= INTVAL (xop1
);
5304 /* Try and fold the offset into a biasing of the base register and
5305 then offsetting that. Don't do this when optimizing for space
5306 since it can cause too many CSEs. */
5307 if (optimize_size
&& offset
>= 0
5308 && offset
< 256 + 31 * GET_MODE_SIZE (mode
))
5310 HOST_WIDE_INT delta
;
5313 delta
= offset
- (256 - GET_MODE_SIZE (mode
));
5314 else if (offset
< 32 * GET_MODE_SIZE (mode
) + 8)
5315 delta
= 31 * GET_MODE_SIZE (mode
);
5317 delta
= offset
& (~31 * GET_MODE_SIZE (mode
));
5319 xop0
= force_operand (plus_constant (xop0
, offset
- delta
),
5321 x
= plus_constant (xop0
, delta
);
5323 else if (offset
< 0 && offset
> -256)
5324 /* Small negative offsets are best done with a subtract before the
5325 dereference, forcing these into a register normally takes two
5327 x
= force_operand (x
, NULL_RTX
);
5330 /* For the remaining cases, force the constant into a register. */
5331 xop1
= force_reg (SImode
, xop1
);
5332 x
= gen_rtx_PLUS (SImode
, xop0
, xop1
);
5335 else if (GET_CODE (x
) == PLUS
5336 && s_register_operand (XEXP (x
, 1), SImode
)
5337 && !s_register_operand (XEXP (x
, 0), SImode
))
5339 rtx xop0
= force_operand (XEXP (x
, 0), NULL_RTX
);
5341 x
= gen_rtx_PLUS (SImode
, xop0
, XEXP (x
, 1));
5346 /* We need to find and carefully transform any SYMBOL and LABEL
5347 references; so go back to the original address expression. */
5348 rtx new_x
= legitimize_pic_address (orig_x
, mode
, NULL_RTX
);
5350 if (new_x
!= orig_x
)
5358 thumb_legitimize_reload_address (rtx
*x_p
,
5359 enum machine_mode mode
,
5360 int opnum
, int type
,
5361 int ind_levels ATTRIBUTE_UNUSED
)
5365 if (GET_CODE (x
) == PLUS
5366 && GET_MODE_SIZE (mode
) < 4
5367 && REG_P (XEXP (x
, 0))
5368 && XEXP (x
, 0) == stack_pointer_rtx
5369 && GET_CODE (XEXP (x
, 1)) == CONST_INT
5370 && !thumb_legitimate_offset_p (mode
, INTVAL (XEXP (x
, 1))))
5375 push_reload (orig_x
, NULL_RTX
, x_p
, NULL
, MODE_BASE_REG_CLASS (mode
),
5376 Pmode
, VOIDmode
, 0, 0, opnum
, type
);
5380 /* If both registers are hi-regs, then it's better to reload the
5381 entire expression rather than each register individually. That
5382 only requires one reload register rather than two. */
5383 if (GET_CODE (x
) == PLUS
5384 && REG_P (XEXP (x
, 0))
5385 && REG_P (XEXP (x
, 1))
5386 && !REG_MODE_OK_FOR_REG_BASE_P (XEXP (x
, 0), mode
)
5387 && !REG_MODE_OK_FOR_REG_BASE_P (XEXP (x
, 1), mode
))
5392 push_reload (orig_x
, NULL_RTX
, x_p
, NULL
, MODE_BASE_REG_CLASS (mode
),
5393 Pmode
, VOIDmode
, 0, 0, opnum
, type
);
5400 /* Test for various thread-local symbols. */
5402 /* Return TRUE if X is a thread-local symbol. */
5405 arm_tls_symbol_p (rtx x
)
5407 if (! TARGET_HAVE_TLS
)
5410 if (GET_CODE (x
) != SYMBOL_REF
)
5413 return SYMBOL_REF_TLS_MODEL (x
) != 0;
5416 /* Helper for arm_tls_referenced_p. */
5419 arm_tls_operand_p_1 (rtx
*x
, void *data ATTRIBUTE_UNUSED
)
5421 if (GET_CODE (*x
) == SYMBOL_REF
)
5422 return SYMBOL_REF_TLS_MODEL (*x
) != 0;
5424 /* Don't recurse into UNSPEC_TLS looking for TLS symbols; these are
5425 TLS offsets, not real symbol references. */
5426 if (GET_CODE (*x
) == UNSPEC
5427 && XINT (*x
, 1) == UNSPEC_TLS
)
5433 /* Return TRUE if X contains any TLS symbol references. */
5436 arm_tls_referenced_p (rtx x
)
5438 if (! TARGET_HAVE_TLS
)
5441 return for_each_rtx (&x
, arm_tls_operand_p_1
, NULL
);
5444 /* APPLE LOCAL begin ARM -mdynamic-no-pic support */
5446 arm_cannot_force_const_mem (rtx x
)
5448 return arm_tls_referenced_p (x
)
5449 || ! LEGITIMATE_INDIRECT_OPERAND_P (x
);
5451 /* APPLE LOCAL end ARM -mdynamic-no-pic support */
5453 #define REG_OR_SUBREG_REG(X) \
5454 (GET_CODE (X) == REG \
5455 || (GET_CODE (X) == SUBREG && GET_CODE (SUBREG_REG (X)) == REG))
5457 #define REG_OR_SUBREG_RTX(X) \
5458 (GET_CODE (X) == REG ? (X) : SUBREG_REG (X))
5460 #ifndef COSTS_N_INSNS
5461 #define COSTS_N_INSNS(N) ((N) * 4 - 2)
5464 /* APPLE LOCAL v7 support. Merge from mainline */
5465 thumb1_rtx_costs (rtx x
, enum rtx_code code
, enum rtx_code outer
)
5467 enum machine_mode mode
= GET_MODE (x
);
5480 return COSTS_N_INSNS (1);
5483 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
5486 unsigned HOST_WIDE_INT i
= INTVAL (XEXP (x
, 1));
5493 return COSTS_N_INSNS (2) + cycles
;
5495 return COSTS_N_INSNS (1) + 16;
5498 return (COSTS_N_INSNS (1)
5499 + 4 * ((GET_CODE (SET_SRC (x
)) == MEM
)
5500 + GET_CODE (SET_DEST (x
)) == MEM
));
5505 if ((unsigned HOST_WIDE_INT
) INTVAL (x
) < 256)
5507 if (thumb_shiftable_const (INTVAL (x
)))
5508 return COSTS_N_INSNS (2);
5509 return COSTS_N_INSNS (3);
5511 else if ((outer
== PLUS
|| outer
== COMPARE
)
5512 && INTVAL (x
) < 256 && INTVAL (x
) > -256)
5514 else if (outer
== AND
5515 && INTVAL (x
) < 256 && INTVAL (x
) >= -256)
5516 return COSTS_N_INSNS (1);
5517 else if (outer
== ASHIFT
|| outer
== ASHIFTRT
5518 || outer
== LSHIFTRT
)
5520 return COSTS_N_INSNS (2);
5526 return COSTS_N_INSNS (3);
5544 /* XXX another guess. */
5545 /* Memory costs quite a lot for the first word, but subsequent words
5546 load at the equivalent of a single insn each. */
5547 return (10 + 4 * ((GET_MODE_SIZE (mode
) - 1) / UNITS_PER_WORD
)
5548 + ((GET_CODE (x
) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (x
))
5553 if (GET_CODE (XEXP (x
, 1)) == PC
|| GET_CODE (XEXP (x
, 2)) == PC
)
5558 /* XXX still guessing. */
5559 switch (GET_MODE (XEXP (x
, 0)))
5562 return (1 + (mode
== DImode
? 4 : 0)
5563 + (GET_CODE (XEXP (x
, 0)) == MEM
? 10 : 0));
5566 return (4 + (mode
== DImode
? 4 : 0)
5567 + (GET_CODE (XEXP (x
, 0)) == MEM
? 10 : 0));
5570 return (1 + (GET_CODE (XEXP (x
, 0)) == MEM
? 10 : 0));
5581 /* APPLE LOCAL begin ARM size variant of thumb costs */
5582 /* This is very much a work in progress; it is just thumb_rtx_costs
5583 with modifications for size as discovered. Currently, the costs
5584 for MULT, AND, XOR, IOR have been fixed; all of these are single
5585 instructions. (Not for DImode, but that's not taken into account
5589 thumb1_size_rtx_costs (rtx x
, enum rtx_code code
, enum rtx_code outer
)
5591 enum machine_mode mode
= GET_MODE (x
);
5608 return COSTS_N_INSNS (1);
5611 return (COSTS_N_INSNS (1)
5612 + 4 * ((GET_CODE (SET_SRC (x
)) == MEM
)
5613 + GET_CODE (SET_DEST (x
)) == MEM
));
5618 if ((unsigned HOST_WIDE_INT
) INTVAL (x
) < 256)
5620 if (thumb_shiftable_const (INTVAL (x
)))
5621 return COSTS_N_INSNS (2);
5622 return COSTS_N_INSNS (3);
5624 else if ((outer
== PLUS
|| outer
== COMPARE
)
5625 && INTVAL (x
) < 256 && INTVAL (x
) > -256)
5627 else if (outer
== AND
5628 && INTVAL (x
) < 256 && INTVAL (x
) >= -256)
5629 return COSTS_N_INSNS (1);
5630 else if (outer
== ASHIFT
|| outer
== ASHIFTRT
5631 || outer
== LSHIFTRT
)
5633 return COSTS_N_INSNS (2);
5639 return COSTS_N_INSNS (3);
5651 /* XXX another guess. */
5652 /* Memory costs quite a lot for the first word, but subsequent words
5653 load at the equivalent of a single insn each. */
5654 return (10 + 4 * ((GET_MODE_SIZE (mode
) - 1) / UNITS_PER_WORD
)
5655 + ((GET_CODE (x
) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (x
))
5660 if (GET_CODE (XEXP (x
, 1)) == PC
|| GET_CODE (XEXP (x
, 2)) == PC
)
5665 /* XXX still guessing. */
5666 switch (GET_MODE (XEXP (x
, 0)))
5669 return (1 + (mode
== DImode
? 4 : 0)
5670 + (GET_CODE (XEXP (x
, 0)) == MEM
? 10 : 0));
5673 return (4 + (mode
== DImode
? 4 : 0)
5674 + (GET_CODE (XEXP (x
, 0)) == MEM
? 10 : 0));
5677 return (1 + (GET_CODE (XEXP (x
, 0)) == MEM
? 10 : 0));
5687 /* APPLE LOCAL end ARM size variant of thumb costs */
5689 /* Worker routine for arm_rtx_costs. */
5690 /* APPLE LOCAL v7 support. Merge from mainline */
5691 /* ??? This needs updating for thumb2. */
5693 arm_rtx_costs_1 (rtx x
, enum rtx_code code
, enum rtx_code outer
)
5695 enum machine_mode mode
= GET_MODE (x
);
5696 enum rtx_code subcode
;
5702 /* Memory costs quite a lot for the first word, but subsequent words
5703 load at the equivalent of a single insn each. */
5704 return (10 + 4 * ((GET_MODE_SIZE (mode
) - 1) / UNITS_PER_WORD
)
5705 + (GET_CODE (x
) == SYMBOL_REF
5706 && CONSTANT_POOL_ADDRESS_P (x
) ? 4 : 0));
5712 return optimize_size
? COSTS_N_INSNS (2) : 100;
5715 if (mode
== SImode
&& GET_CODE (XEXP (x
, 1)) == REG
)
5722 case ASHIFT
: case LSHIFTRT
: case ASHIFTRT
:
5724 return (8 + (GET_CODE (XEXP (x
, 1)) == CONST_INT
? 0 : 8)
5725 + ((GET_CODE (XEXP (x
, 0)) == REG
5726 || (GET_CODE (XEXP (x
, 0)) == SUBREG
5727 && GET_CODE (SUBREG_REG (XEXP (x
, 0))) == REG
))
5729 return (1 + ((GET_CODE (XEXP (x
, 0)) == REG
5730 || (GET_CODE (XEXP (x
, 0)) == SUBREG
5731 && GET_CODE (SUBREG_REG (XEXP (x
, 0))) == REG
))
5733 + ((GET_CODE (XEXP (x
, 1)) == REG
5734 || (GET_CODE (XEXP (x
, 1)) == SUBREG
5735 && GET_CODE (SUBREG_REG (XEXP (x
, 1))) == REG
)
5736 || (GET_CODE (XEXP (x
, 1)) == CONST_INT
))
5740 /* APPLE LOCAL begin v7 support. Merge from mainline */
5741 if (GET_CODE (XEXP (x
, 1)) == MULT
&& mode
== SImode
&& arm_arch_thumb2
)
5743 extra_cost
= rtx_cost (XEXP (x
, 1), code
);
5744 if (!REG_OR_SUBREG_REG (XEXP (x
, 0)))
5745 extra_cost
+= 4 * ARM_NUM_REGS (mode
);
5749 /* APPLE LOCAL end v7 support. Merge from mainline */
5751 return (4 + (REG_OR_SUBREG_REG (XEXP (x
, 1)) ? 0 : 8)
5752 + ((REG_OR_SUBREG_REG (XEXP (x
, 0))
5753 || (GET_CODE (XEXP (x
, 0)) == CONST_INT
5754 && const_ok_for_arm (INTVAL (XEXP (x
, 0)))))
5757 if (GET_MODE_CLASS (mode
) == MODE_FLOAT
)
5758 return (2 + ((REG_OR_SUBREG_REG (XEXP (x
, 1))
5759 || (GET_CODE (XEXP (x
, 1)) == CONST_DOUBLE
5760 && arm_const_double_rtx (XEXP (x
, 1))))
5762 + ((REG_OR_SUBREG_REG (XEXP (x
, 0))
5763 || (GET_CODE (XEXP (x
, 0)) == CONST_DOUBLE
5764 && arm_const_double_rtx (XEXP (x
, 0))))
5767 if (((GET_CODE (XEXP (x
, 0)) == CONST_INT
5768 && const_ok_for_arm (INTVAL (XEXP (x
, 0)))
5769 && REG_OR_SUBREG_REG (XEXP (x
, 1))))
5770 || (((subcode
= GET_CODE (XEXP (x
, 1))) == ASHIFT
5771 || subcode
== ASHIFTRT
|| subcode
== LSHIFTRT
5772 || subcode
== ROTATE
|| subcode
== ROTATERT
5774 && GET_CODE (XEXP (XEXP (x
, 1), 1)) == CONST_INT
5775 && ((INTVAL (XEXP (XEXP (x
, 1), 1)) &
5776 (INTVAL (XEXP (XEXP (x
, 1), 1)) - 1)) == 0)))
5777 && REG_OR_SUBREG_REG (XEXP (XEXP (x
, 1), 0))
5778 && (REG_OR_SUBREG_REG (XEXP (XEXP (x
, 1), 1))
5779 || GET_CODE (XEXP (XEXP (x
, 1), 1)) == CONST_INT
)
5780 && REG_OR_SUBREG_REG (XEXP (x
, 0))))
5785 if (GET_CODE (XEXP (x
, 0)) == MULT
)
5787 extra_cost
= rtx_cost (XEXP (x
, 0), code
);
5788 if (!REG_OR_SUBREG_REG (XEXP (x
, 1)))
5789 extra_cost
+= 4 * ARM_NUM_REGS (mode
);
5793 if (GET_MODE_CLASS (mode
) == MODE_FLOAT
)
5794 return (2 + (REG_OR_SUBREG_REG (XEXP (x
, 0)) ? 0 : 8)
5795 + ((REG_OR_SUBREG_REG (XEXP (x
, 1))
5796 || (GET_CODE (XEXP (x
, 1)) == CONST_DOUBLE
5797 && arm_const_double_rtx (XEXP (x
, 1))))
5801 case AND
: case XOR
: case IOR
:
5804 /* Normally the frame registers will be spilt into reg+const during
5805 reload, so it is a bad idea to combine them with other instructions,
5806 since then they might not be moved outside of loops. As a compromise
5807 we allow integration with ops that have a constant as their second
5809 if ((REG_OR_SUBREG_REG (XEXP (x
, 0))
5810 && ARM_FRAME_RTX (REG_OR_SUBREG_RTX (XEXP (x
, 0)))
5811 && GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5812 || (REG_OR_SUBREG_REG (XEXP (x
, 0))
5813 && ARM_FRAME_RTX (REG_OR_SUBREG_RTX (XEXP (x
, 0)))))
5817 return (4 + extra_cost
+ (REG_OR_SUBREG_REG (XEXP (x
, 0)) ? 0 : 8)
5818 + ((REG_OR_SUBREG_REG (XEXP (x
, 1))
5819 || (GET_CODE (XEXP (x
, 1)) == CONST_INT
5820 && const_ok_for_op (INTVAL (XEXP (x
, 1)), code
)))
5823 if (REG_OR_SUBREG_REG (XEXP (x
, 0)))
5824 return (1 + (GET_CODE (XEXP (x
, 1)) == CONST_INT
? 0 : extra_cost
)
5825 + ((REG_OR_SUBREG_REG (XEXP (x
, 1))
5826 || (GET_CODE (XEXP (x
, 1)) == CONST_INT
5827 && const_ok_for_op (INTVAL (XEXP (x
, 1)), code
)))
5830 /* APPLE LOCAL begin ARM 4652753 */
5831 /* If the previous insn feeds into the shifted operand of this one,
5832 there is a 1 cycle delay. We can't tell here whether this will
5833 be the case or not. Model it for now, as this seems to lead to
5834 better decisions about splitting up multiply-by-constant. */
5835 else if (REG_OR_SUBREG_REG (XEXP (x
, 1)))
5836 return (1 + extra_cost
5837 + ((((subcode
= GET_CODE (XEXP (x
, 0))) == ASHIFT
5838 || subcode
== LSHIFTRT
|| subcode
== ASHIFTRT
5839 || subcode
== ROTATE
|| subcode
== ROTATERT
5841 && GET_CODE (XEXP (XEXP (x
, 0), 1)) == CONST_INT
5842 && ((INTVAL (XEXP (XEXP (x
, 0), 1)) &
5843 (INTVAL (XEXP (XEXP (x
, 0), 1)) - 1)) == 0)))
5844 && (REG_OR_SUBREG_REG (XEXP (XEXP (x
, 0), 0)))
5845 && ((REG_OR_SUBREG_REG (XEXP (XEXP (x
, 0), 1)))
5846 || GET_CODE (XEXP (XEXP (x
, 0), 1)) == CONST_INT
))
5848 /* APPLE LOCAL end ARM 4652753 */
5853 /* This should have been handled by the CPU specific routines. */
5857 if (arm_arch3m
&& mode
== SImode
5858 && GET_CODE (XEXP (x
, 0)) == LSHIFTRT
5859 && GET_CODE (XEXP (XEXP (x
, 0), 0)) == MULT
5860 && (GET_CODE (XEXP (XEXP (XEXP (x
, 0), 0), 0))
5861 == GET_CODE (XEXP (XEXP (XEXP (x
, 0), 0), 1)))
5862 && (GET_CODE (XEXP (XEXP (XEXP (x
, 0), 0), 0)) == ZERO_EXTEND
5863 || GET_CODE (XEXP (XEXP (XEXP (x
, 0), 0), 0)) == SIGN_EXTEND
))
5868 if (GET_MODE_CLASS (mode
) == MODE_FLOAT
)
5869 return 4 + (REG_OR_SUBREG_REG (XEXP (x
, 0)) ? 0 : 6);
5873 return 4 + (REG_OR_SUBREG_REG (XEXP (x
, 0)) ? 0 : 4);
5875 return 1 + (REG_OR_SUBREG_REG (XEXP (x
, 0)) ? 0 : 4);
5878 if (GET_CODE (XEXP (x
, 1)) == PC
|| GET_CODE (XEXP (x
, 2)) == PC
)
5886 return 4 + (mode
== DImode
? 4 : 0);
5889 /* APPLE LOCAL v7 support. Merge from mainline */
5890 /* ??? value extensions are cheaper on armv6. */
5891 if (GET_MODE (XEXP (x
, 0)) == QImode
)
5892 return (4 + (mode
== DImode
? 4 : 0)
5893 + (GET_CODE (XEXP (x
, 0)) == MEM
? 10 : 0));
5896 switch (GET_MODE (XEXP (x
, 0)))
5899 return (1 + (mode
== DImode
? 4 : 0)
5900 + (GET_CODE (XEXP (x
, 0)) == MEM
? 10 : 0));
5903 return (4 + (mode
== DImode
? 4 : 0)
5904 + (GET_CODE (XEXP (x
, 0)) == MEM
? 10 : 0));
5907 return (1 + (GET_CODE (XEXP (x
, 0)) == MEM
? 10 : 0));
5922 if (const_ok_for_arm (INTVAL (x
)))
5923 return outer
== SET
? 2 : -1;
5924 else if (outer
== AND
5925 && const_ok_for_arm (~INTVAL (x
)))
5927 else if ((outer
== COMPARE
5928 || outer
== PLUS
|| outer
== MINUS
)
5929 && const_ok_for_arm (-INTVAL (x
)))
5940 /* APPLE LOCAL v7 support. Merge from mainline */
5941 if (arm_const_double_rtx (x
) || vfp3_const_double_rtx (x
))
5942 return outer
== SET
? 2 : -1;
5943 else if ((outer
== COMPARE
|| outer
== PLUS
)
5944 && neg_const_double_rtx_ok_for_fpa (x
))
5953 /* RTX costs when optimizing for size. */
5955 arm_size_rtx_costs (rtx x
, int code
, int outer_code
, int *total
)
5957 enum machine_mode mode
= GET_MODE (x
);
5961 /* APPLE LOCAL v7 support. Merge from mainline */
5962 *total
= thumb1_size_rtx_costs (x
, code
, outer_code
);
5969 /* A memory access costs 1 insn if the mode is small, or the address is
5970 a single register, otherwise it costs one insn per word. */
5971 if (REG_P (XEXP (x
, 0)))
5972 *total
= COSTS_N_INSNS (1);
5974 *total
= COSTS_N_INSNS (ARM_NUM_REGS (mode
));
5981 /* Needs a libcall, so it costs about this. */
5982 *total
= COSTS_N_INSNS (2);
5986 if (mode
== SImode
&& GET_CODE (XEXP (x
, 1)) == REG
)
5988 *total
= COSTS_N_INSNS (2) + rtx_cost (XEXP (x
, 0), code
);
5996 if (mode
== DImode
&& GET_CODE (XEXP (x
, 1)) == CONST_INT
)
5998 *total
= COSTS_N_INSNS (3) + rtx_cost (XEXP (x
, 0), code
);
6001 else if (mode
== SImode
)
6003 *total
= COSTS_N_INSNS (1) + rtx_cost (XEXP (x
, 0), code
);
6004 /* Slightly disparage register shifts, but not by much. */
6005 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
6006 *total
+= 1 + rtx_cost (XEXP (x
, 1), code
);
6010 /* Needs a libcall. */
6011 *total
= COSTS_N_INSNS (2);
6015 if (TARGET_HARD_FLOAT
&& GET_MODE_CLASS (mode
) == MODE_FLOAT
)
6017 *total
= COSTS_N_INSNS (1);
6023 enum rtx_code subcode0
= GET_CODE (XEXP (x
, 0));
6024 enum rtx_code subcode1
= GET_CODE (XEXP (x
, 1));
6026 if (subcode0
== ROTATE
|| subcode0
== ROTATERT
|| subcode0
== ASHIFT
6027 || subcode0
== LSHIFTRT
|| subcode0
== ASHIFTRT
6028 || subcode1
== ROTATE
|| subcode1
== ROTATERT
6029 || subcode1
== ASHIFT
|| subcode1
== LSHIFTRT
6030 || subcode1
== ASHIFTRT
)
6032 /* It's just the cost of the two operands. */
6037 *total
= COSTS_N_INSNS (1);
6041 *total
= COSTS_N_INSNS (ARM_NUM_REGS (mode
));
6045 if (TARGET_HARD_FLOAT
&& GET_MODE_CLASS (mode
) == MODE_FLOAT
)
6047 *total
= COSTS_N_INSNS (1);
6052 case AND
: case XOR
: case IOR
:
6055 enum rtx_code subcode
= GET_CODE (XEXP (x
, 0));
6057 if (subcode
== ROTATE
|| subcode
== ROTATERT
|| subcode
== ASHIFT
6058 || subcode
== LSHIFTRT
|| subcode
== ASHIFTRT
6059 || (code
== AND
&& subcode
== NOT
))
6061 /* It's just the cost of the two operands. */
6067 *total
= COSTS_N_INSNS (ARM_NUM_REGS (mode
));
6070 /* APPLE LOCAL begin DImode multiply enhancement */
6074 if (((GET_CODE (XEXP (x
, 0)) == SIGN_EXTEND
6075 && GET_CODE (XEXP (x
, 1)) == SIGN_EXTEND
)
6076 || (GET_CODE (XEXP (x
, 0)) == ZERO_EXTEND
6077 && GET_CODE (XEXP (x
, 1)) == ZERO_EXTEND
))
6078 && GET_MODE (XEXP (XEXP (x
, 0), 0)) == SImode
6079 && GET_MODE (XEXP (XEXP (x
, 1), 0)) == SImode
)
6081 /* SMULL, etc., do sign extend better than free */
6082 *total
= COSTS_N_INSNS (1)
6083 + rtx_cost (XEXP (XEXP (x
, 0), 0), MULT
)
6084 + rtx_cost (XEXP (XEXP (x
, 1), 0), MULT
);
6089 /* broken into 3 insns later, plus cost of kids */
6090 /** does not allow for Cirrus instruction **/
6091 *total
= COSTS_N_INSNS (3);
6095 *total
= COSTS_N_INSNS (ARM_NUM_REGS (mode
));
6097 /* APPLE LOCAL end DImode multiply enhancement */
6100 if (TARGET_HARD_FLOAT
&& GET_MODE_CLASS (mode
) == MODE_FLOAT
)
6101 *total
= COSTS_N_INSNS (1);
6104 *total
= COSTS_N_INSNS (ARM_NUM_REGS (mode
));
6113 if (cc_register (XEXP (x
, 0), VOIDmode
))
6116 *total
= COSTS_N_INSNS (1);
6120 if (TARGET_HARD_FLOAT
&& GET_MODE_CLASS (mode
) == MODE_FLOAT
)
6121 *total
= COSTS_N_INSNS (1);
6123 *total
= COSTS_N_INSNS (1 + ARM_NUM_REGS (mode
));
6128 if (GET_MODE_SIZE (GET_MODE (XEXP (x
, 0))) < 4)
6130 if (!(arm_arch4
&& MEM_P (XEXP (x
, 0))))
6131 *total
+= COSTS_N_INSNS (arm_arch6
? 1 : 2);
6134 *total
+= COSTS_N_INSNS (1);
6139 if (!(arm_arch4
&& MEM_P (XEXP (x
, 0))))
6141 switch (GET_MODE (XEXP (x
, 0)))
6144 *total
+= COSTS_N_INSNS (1);
6148 *total
+= COSTS_N_INSNS (arm_arch6
? 1 : 2);
6154 *total
+= COSTS_N_INSNS (2);
6159 *total
+= COSTS_N_INSNS (1);
6164 if (const_ok_for_arm (INTVAL (x
)))
6165 *total
= COSTS_N_INSNS (outer_code
== SET
? 1 : 0);
6166 else if (const_ok_for_arm (~INTVAL (x
)))
6167 *total
= COSTS_N_INSNS (outer_code
== AND
? 0 : 1);
6168 else if (const_ok_for_arm (-INTVAL (x
)))
6170 if (outer_code
== COMPARE
|| outer_code
== PLUS
6171 || outer_code
== MINUS
)
6174 *total
= COSTS_N_INSNS (1);
6177 *total
= COSTS_N_INSNS (2);
6183 *total
= COSTS_N_INSNS (2);
6187 *total
= COSTS_N_INSNS (4);
6191 if (mode
!= VOIDmode
)
6192 *total
= COSTS_N_INSNS (ARM_NUM_REGS (mode
));
6194 *total
= COSTS_N_INSNS (4); /* How knows? */
6199 /* APPLE LOCAL begin v7 support. Merge from mainline */
6200 /* RTX costs for cores with a slow MUL implementation. Thumb-2 is not
6201 supported on any "slowmul" cores, so it can be ignored. */
6202 /* APPLE LOCAL end v7 support. Merge from mainline */
6205 arm_slowmul_rtx_costs (rtx x
, int code
, int outer_code
, int *total
)
6207 enum machine_mode mode
= GET_MODE (x
);
6211 /* APPLE LOCAL v7 support. Merge from mainline */
6212 *total
= thumb1_rtx_costs (x
, code
, outer_code
);
6219 if (GET_MODE_CLASS (mode
) == MODE_FLOAT
6226 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
6228 unsigned HOST_WIDE_INT i
= (INTVAL (XEXP (x
, 1))
6229 & (unsigned HOST_WIDE_INT
) 0xffffffff);
6230 int cost
, const_ok
= const_ok_for_arm (i
);
6231 int j
, booth_unit_size
;
6233 /* Tune as appropriate. */
6234 cost
= const_ok
? 4 : 8;
6235 booth_unit_size
= 2;
6236 for (j
= 0; i
&& j
< 32; j
+= booth_unit_size
)
6238 i
>>= booth_unit_size
;
6246 *total
= 30 + (REG_OR_SUBREG_REG (XEXP (x
, 0)) ? 0 : 4)
6247 + (REG_OR_SUBREG_REG (XEXP (x
, 1)) ? 0 : 4);
6251 *total
= arm_rtx_costs_1 (x
, code
, outer_code
);
6257 /* RTX cost for cores with a fast multiply unit (M variants). */
6260 arm_fastmul_rtx_costs (rtx x
, int code
, int outer_code
, int *total
)
6262 enum machine_mode mode
= GET_MODE (x
);
6264 /* APPLE LOCAL begin v7 support. Merge from mainline */
6267 *total
= thumb1_rtx_costs (x
, code
, outer_code
);
6271 /* ??? should thumb2 use different costs? */
6272 /* APPLE LOCAL end v7 support. Merge from mainline */
6276 /* There is no point basing this on the tuning, since it is always the
6277 fast variant if it exists at all. */
6279 && (GET_CODE (XEXP (x
, 0)) == GET_CODE (XEXP (x
, 1)))
6280 && (GET_CODE (XEXP (x
, 0)) == ZERO_EXTEND
6281 || GET_CODE (XEXP (x
, 0)) == SIGN_EXTEND
))
6288 if (GET_MODE_CLASS (mode
) == MODE_FLOAT
6295 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
6297 unsigned HOST_WIDE_INT i
= (INTVAL (XEXP (x
, 1))
6298 & (unsigned HOST_WIDE_INT
) 0xffffffff);
6299 int cost
, const_ok
= const_ok_for_arm (i
);
6300 int j
, booth_unit_size
;
6302 /* Tune as appropriate. */
6303 cost
= const_ok
? 4 : 8;
6304 booth_unit_size
= 8;
6305 for (j
= 0; i
&& j
< 32; j
+= booth_unit_size
)
6307 i
>>= booth_unit_size
;
6315 *total
= 8 + (REG_OR_SUBREG_REG (XEXP (x
, 0)) ? 0 : 4)
6316 + (REG_OR_SUBREG_REG (XEXP (x
, 1)) ? 0 : 4);
6320 *total
= arm_rtx_costs_1 (x
, code
, outer_code
);
6326 /* APPLE LOCAL begin v7 support. Merge from mainline */
6327 /* RTX cost for XScale CPUs. Thumb-2 is not supported on any xscale cores,
6328 so it can be ignored. */
6329 /* APPLE LOCAL end v7 support. Merge from mainline */
6332 arm_xscale_rtx_costs (rtx x
, int code
, int outer_code
, int *total
)
6334 enum machine_mode mode
= GET_MODE (x
);
6338 /* APPLE LOCAL v7 support. Merge from mainline */
6339 *total
= thumb1_rtx_costs (x
, code
, outer_code
);
6346 /* There is no point basing this on the tuning, since it is always the
6347 fast variant if it exists at all. */
6349 && (GET_CODE (XEXP (x
, 0)) == GET_CODE (XEXP (x
, 1)))
6350 && (GET_CODE (XEXP (x
, 0)) == ZERO_EXTEND
6351 || GET_CODE (XEXP (x
, 0)) == SIGN_EXTEND
))
6358 if (GET_MODE_CLASS (mode
) == MODE_FLOAT
6365 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
6367 unsigned HOST_WIDE_INT i
= (INTVAL (XEXP (x
, 1))
6368 & (unsigned HOST_WIDE_INT
) 0xffffffff);
6369 int cost
, const_ok
= const_ok_for_arm (i
);
6370 unsigned HOST_WIDE_INT masked_const
;
6372 /* The cost will be related to two insns.
6373 First a load of the constant (MOV or LDR), then a multiply. */
6376 cost
+= 1; /* LDR is probably more expensive because
6377 of longer result latency. */
6378 masked_const
= i
& 0xffff8000;
6379 if (masked_const
!= 0 && masked_const
!= 0xffff8000)
6381 masked_const
= i
& 0xf8000000;
6382 if (masked_const
== 0 || masked_const
== 0xf8000000)
6391 *total
= 8 + (REG_OR_SUBREG_REG (XEXP (x
, 0)) ? 0 : 4)
6392 + (REG_OR_SUBREG_REG (XEXP (x
, 1)) ? 0 : 4);
6396 /* A COMPARE of a MULT is slow on XScale; the muls instruction
6397 will stall until the multiplication is complete. */
6398 if (GET_CODE (XEXP (x
, 0)) == MULT
)
6399 *total
= 4 + rtx_cost (XEXP (x
, 0), code
);
6401 *total
= arm_rtx_costs_1 (x
, code
, outer_code
);
6405 *total
= arm_rtx_costs_1 (x
, code
, outer_code
);
6411 /* RTX costs for 9e (and later) cores. */
6414 arm_9e_rtx_costs (rtx x
, int code
, int outer_code
, int *total
)
6416 enum machine_mode mode
= GET_MODE (x
);
6420 /* APPLE LOCAL v7 support. Merge from mainline */
6426 *total
= COSTS_N_INSNS (3);
6430 /* APPLE LOCAL v7 support. Merge from mainline */
6431 *total
= thumb1_rtx_costs (x
, code
, outer_code
);
6439 /* There is no point basing this on the tuning, since it is always the
6440 fast variant if it exists at all. */
6442 && (GET_CODE (XEXP (x
, 0)) == GET_CODE (XEXP (x
, 1)))
6443 && (GET_CODE (XEXP (x
, 0)) == ZERO_EXTEND
6444 || GET_CODE (XEXP (x
, 0)) == SIGN_EXTEND
))
6451 if (GET_MODE_CLASS (mode
) == MODE_FLOAT
)
6468 *total
= cost
+ (REG_OR_SUBREG_REG (XEXP (x
, 0)) ? 0 : nonreg_cost
)
6469 + (REG_OR_SUBREG_REG (XEXP (x
, 1)) ? 0 : nonreg_cost
);
6473 *total
= arm_rtx_costs_1 (x
, code
, outer_code
);
6477 /* All address computations that can be done are free, but rtx cost returns
6478 the same for practically all of them. So we weight the different types
6479 of address here in the order (most pref first):
6480 PRE/POST_INC/DEC, SHIFT or NON-INT sum, INT sum, REG, MEM or LABEL. */
6482 arm_arm_address_cost (rtx x
)
6484 enum rtx_code c
= GET_CODE (x
);
6486 if (c
== PRE_INC
|| c
== PRE_DEC
|| c
== POST_INC
|| c
== POST_DEC
)
6488 if (c
== MEM
|| c
== LABEL_REF
|| c
== SYMBOL_REF
)
6491 if (c
== PLUS
|| c
== MINUS
)
6493 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
6496 if (ARITHMETIC_P (XEXP (x
, 0)) || ARITHMETIC_P (XEXP (x
, 1)))
6506 arm_thumb_address_cost (rtx x
)
6508 enum rtx_code c
= GET_CODE (x
);
6513 && GET_CODE (XEXP (x
, 0)) == REG
6514 && GET_CODE (XEXP (x
, 1)) == CONST_INT
)
6521 arm_address_cost (rtx x
)
6523 /* APPLE LOCAL v7 support. Merge from mainline */
6524 return TARGET_32BIT
? arm_arm_address_cost (x
) : arm_thumb_address_cost (x
);
6528 arm_adjust_cost (rtx insn
, rtx link
, rtx dep
, int cost
)
6530 /* LLVM LOCAL begin */
6538 /* LLVM LOCAL end */
6541 /* Some true dependencies can have a higher cost depending
6542 on precisely how certain input operands are used. */
6544 && REG_NOTE_KIND (link
) == 0
6545 && recog_memoized (insn
) >= 0
6546 && recog_memoized (dep
) >= 0)
6548 int shift_opnum
= get_attr_shift (insn
);
6549 enum attr_type attr_type
= get_attr_type (dep
);
6551 /* If nonzero, SHIFT_OPNUM contains the operand number of a shifted
6552 operand for INSN. If we have a shifted input operand and the
6553 instruction we depend on is another ALU instruction, then we may
6554 have to account for an additional stall. */
6555 if (shift_opnum
!= 0
6556 && (attr_type
== TYPE_ALU_SHIFT
|| attr_type
== TYPE_ALU_SHIFT_REG
))
6558 rtx shifted_operand
;
6561 /* Get the shifted operand. */
6562 extract_insn (insn
);
6563 shifted_operand
= recog_data
.operand
[shift_opnum
];
6565 /* Iterate over all the operands in DEP. If we write an operand
6566 that overlaps with SHIFTED_OPERAND, then we have increase the
6567 cost of this dependency. */
6569 preprocess_constraints ();
6570 for (opno
= 0; opno
< recog_data
.n_operands
; opno
++)
6572 /* We can ignore strict inputs. */
6573 if (recog_data
.operand_type
[opno
] == OP_IN
)
6576 if (reg_overlap_mentioned_p (recog_data
.operand
[opno
],
6583 /* XXX This is not strictly true for the FPA. */
6584 if (REG_NOTE_KIND (link
) == REG_DEP_ANTI
6585 || REG_NOTE_KIND (link
) == REG_DEP_OUTPUT
)
6588 /* Call insns don't incur a stall, even if they follow a load. */
6589 if (REG_NOTE_KIND (link
) == 0
6590 && GET_CODE (insn
) == CALL_INSN
)
6593 if ((i_pat
= single_set (insn
)) != NULL
6594 && GET_CODE (SET_SRC (i_pat
)) == MEM
6595 && (d_pat
= single_set (dep
)) != NULL
6596 && GET_CODE (SET_DEST (d_pat
)) == MEM
)
6598 rtx src_mem
= XEXP (SET_SRC (i_pat
), 0);
6599 /* This is a load after a store, there is no conflict if the load reads
6600 from a cached area. Assume that loads from the stack, and from the
6601 constant pool are cached, and that others will miss. This is a
6604 if ((GET_CODE (src_mem
) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (src_mem
))
6605 || reg_mentioned_p (stack_pointer_rtx
, src_mem
)
6606 || reg_mentioned_p (frame_pointer_rtx
, src_mem
)
6607 || reg_mentioned_p (hard_frame_pointer_rtx
, src_mem
))
6616 static int fp_consts_inited
= 0;
6618 /* Only zero is valid for VFP. Other values are also valid for FPA. */
6619 static const char * const strings_fp
[8] =
6622 "4", "5", "0.5", "10"
6625 static REAL_VALUE_TYPE values_fp
[8];
6628 init_fp_table (void)
6634 fp_consts_inited
= 1;
6636 fp_consts_inited
= 8;
6638 for (i
= 0; i
< fp_consts_inited
; i
++)
6640 r
= REAL_VALUE_ATOF (strings_fp
[i
], DFmode
);
6645 /* Return TRUE if rtx X is a valid immediate FP constant. */
6647 arm_const_double_rtx (rtx x
)
6652 if (!fp_consts_inited
)
6655 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
6656 if (REAL_VALUE_MINUS_ZERO (r
))
6659 for (i
= 0; i
< fp_consts_inited
; i
++)
6660 if (REAL_VALUES_EQUAL (r
, values_fp
[i
]))
6666 /* Return TRUE if rtx X is a valid immediate FPA constant. */
6668 neg_const_double_rtx_ok_for_fpa (rtx x
)
6673 if (!fp_consts_inited
)
6676 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
6677 r
= REAL_VALUE_NEGATE (r
);
6678 if (REAL_VALUE_MINUS_ZERO (r
))
6681 for (i
= 0; i
< 8; i
++)
6682 if (REAL_VALUES_EQUAL (r
, values_fp
[i
]))
6689 /* APPLE LOCAL begin v7 support. Merge from mainline */
6690 /* VFPv3 has a fairly wide range of representable immediates, formed from
6691 "quarter-precision" floating-point values. These can be evaluated using this
6692 formula (with ^ for exponentiation):
6696 Where 's' is a sign bit (0/1), 'n' and 'r' are integers such that
6697 16 <= n <= 31 and 0 <= r <= 7.
6699 These values are mapped onto an 8-bit integer ABCDEFGH s.t.
6701 - A (most-significant) is the sign bit.
6702 - BCD are the exponent (encoded as r XOR 3).
6703 - EFGH are the mantissa (encoded as n - 16).
6706 /* Return an integer index for a VFPv3 immediate operand X suitable for the
6707 fconst[sd] instruction, or -1 if X isn't suitable. */
6709 vfp3_const_double_index (rtx x
)
6711 REAL_VALUE_TYPE r
, m
;
6713 unsigned HOST_WIDE_INT mantissa
, mant_hi
;
6714 unsigned HOST_WIDE_INT mask
;
6715 HOST_WIDE_INT m1
, m2
;
6716 int point_pos
= 2 * HOST_BITS_PER_WIDE_INT
- 1;
6718 if (!TARGET_VFP3
|| GET_CODE (x
) != CONST_DOUBLE
)
6721 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
6723 /* We can't represent these things, so detect them first. */
6724 if (REAL_VALUE_ISINF (r
) || REAL_VALUE_ISNAN (r
) || REAL_VALUE_MINUS_ZERO (r
))
6727 /* Extract sign, exponent and mantissa. */
6728 sign
= REAL_VALUE_NEGATIVE (r
) ? 1 : 0;
6729 r
= REAL_VALUE_ABS (r
);
6730 exponent
= REAL_EXP (&r
);
6731 /* For the mantissa, we expand into two HOST_WIDE_INTS, apart from the
6732 highest (sign) bit, with a fixed binary point at bit point_pos.
6733 WARNING: If there's ever a VFP version which uses more than 2 * H_W_I - 1
6734 bits for the mantissa, this may fail (low bits would be lost). */
6735 real_ldexp (&m
, &r
, point_pos
- exponent
);
6736 REAL_VALUE_TO_INT (&m1
, &m2
, m
);
6740 /* If there are bits set in the low part of the mantissa, we can't
6741 represent this value. */
6745 /* Now make it so that mantissa contains the most-significant bits, and move
6746 the point_pos to indicate that the least-significant bits have been
6748 point_pos
-= HOST_BITS_PER_WIDE_INT
;
6751 /* We can permit four significant bits of mantissa only, plus a high bit
6752 which is always 1. */
6753 mask
= ((unsigned HOST_WIDE_INT
)1 << (point_pos
- 5)) - 1;
6754 if ((mantissa
& mask
) != 0)
6757 /* Now we know the mantissa is in range, chop off the unneeded bits. */
6758 mantissa
>>= point_pos
- 5;
6760 /* The mantissa may be zero. Disallow that case. (It's possible to load the
6761 floating-point immediate zero with Neon using an integer-zero load, but
6762 that case is handled elsewhere.) */
6766 gcc_assert (mantissa
>= 16 && mantissa
<= 31);
6768 /* The value of 5 here would be 4 if GCC used IEEE754-like encoding (where
6769 normalised significands are in the range [1, 2). (Our mantissa is shifted
6770 left 4 places at this point relative to normalised IEEE754 values). GCC
6771 internally uses [0.5, 1) (see real.c), so the exponent returned from
6772 REAL_EXP must be altered. */
6773 exponent
= 5 - exponent
;
6775 if (exponent
< 0 || exponent
> 7)
6778 /* Sign, mantissa and exponent are now in the correct form to plug into the
6779 formulae described in the comment above. */
6780 return (sign
<< 7) | ((exponent
^ 3) << 4) | (mantissa
- 16);
6783 /* Return TRUE if rtx X is a valid immediate VFPv3 constant. */
6785 vfp3_const_double_rtx (rtx x
)
6790 return vfp3_const_double_index (x
) != -1;
6793 /* APPLE LOCAL end v7 support. Merge from mainline */
6794 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
6795 /* Recognize immediates which can be used in various Neon instructions. Legal
6796 immediates are described by the following table (for VMVN variants, the
6797 bitwise inverse of the constant shown is recognized. In either case, VMOV
6798 is output and the correct instruction to use for a given constant is chosen
6799 by the assembler). The constant shown is replicated across all elements of
6800 the destination vector.
6802 insn elems variant constant (binary)
6803 ---- ----- ------- -----------------
6804 vmov i32 0 00000000 00000000 00000000 abcdefgh
6805 vmov i32 1 00000000 00000000 abcdefgh 00000000
6806 vmov i32 2 00000000 abcdefgh 00000000 00000000
6807 vmov i32 3 abcdefgh 00000000 00000000 00000000
6808 vmov i16 4 00000000 abcdefgh
6809 vmov i16 5 abcdefgh 00000000
6810 vmvn i32 6 00000000 00000000 00000000 abcdefgh
6811 vmvn i32 7 00000000 00000000 abcdefgh 00000000
6812 vmvn i32 8 00000000 abcdefgh 00000000 00000000
6813 vmvn i32 9 abcdefgh 00000000 00000000 00000000
6814 vmvn i16 10 00000000 abcdefgh
6815 vmvn i16 11 abcdefgh 00000000
6816 vmov i32 12 00000000 00000000 abcdefgh 11111111
6817 vmvn i32 13 00000000 00000000 abcdefgh 11111111
6818 vmov i32 14 00000000 abcdefgh 11111111 11111111
6819 vmvn i32 15 00000000 abcdefgh 11111111 11111111
6821 vmov i64 17 aaaaaaaa bbbbbbbb cccccccc dddddddd
6822 eeeeeeee ffffffff gggggggg hhhhhhhh
6823 vmov f32 18 aBbbbbbc defgh000 00000000 00000000
6825 For case 18, B = !b. Representable values are exactly those accepted by
6826 vfp3_const_double_index, but are output as floating-point numbers rather
6829 Variants 0-5 (inclusive) may also be used as immediates for the second
6830 operand of VORR/VBIC instructions.
6832 The INVERSE argument causes the bitwise inverse of the given operand to be
6833 recognized instead (used for recognizing legal immediates for the VAND/VORN
6834 pseudo-instructions). If INVERSE is true, the value placed in *MODCONST is
6835 *not* inverted (i.e. the pseudo-instruction forms vand/vorn should still be
6836 output, rather than the real insns vbic/vorr).
6838 INVERSE makes no difference to the recognition of float vectors.
6840 The return value is the variant of immediate as shown in the above table, or
6841 -1 if the given value doesn't match any of the listed patterns.
6844 neon_valid_immediate (rtx op
, enum machine_mode mode
, int inverse
,
6845 rtx
*modconst
, int *elementwidth
)
6847 #define CHECK(STRIDE, ELSIZE, CLASS, TEST) \
6849 for (i = 0; i < idx; i += (STRIDE)) \
6854 immtype = (CLASS); \
6855 elsize = (ELSIZE); \
6859 unsigned int i
, elsize
, idx
= 0, n_elts
= CONST_VECTOR_NUNITS (op
);
6860 unsigned int innersize
= GET_MODE_SIZE (GET_MODE_INNER (mode
));
6861 unsigned char bytes
[16];
6862 int immtype
= -1, matches
;
6863 unsigned int invmask
= inverse
? 0xff : 0;
6865 /* Vectors of float constants. */
6866 if (GET_MODE_CLASS (mode
) == MODE_VECTOR_FLOAT
)
6868 rtx el0
= CONST_VECTOR_ELT (op
, 0);
6871 if (!vfp3_const_double_rtx (el0
))
6874 REAL_VALUE_FROM_CONST_DOUBLE (r0
, el0
);
6876 for (i
= 1; i
< n_elts
; i
++)
6878 rtx elt
= CONST_VECTOR_ELT (op
, i
);
6881 REAL_VALUE_FROM_CONST_DOUBLE (re
, elt
);
6883 if (!REAL_VALUES_EQUAL (r0
, re
))
6888 *modconst
= CONST_VECTOR_ELT (op
, 0);
6896 /* Splat vector constant out into a byte vector. */
6897 for (i
= 0; i
< n_elts
; i
++)
6899 rtx el
= CONST_VECTOR_ELT (op
, i
);
6900 unsigned HOST_WIDE_INT elpart
;
6901 unsigned int part
, parts
;
6903 if (GET_CODE (el
) == CONST_INT
)
6905 elpart
= INTVAL (el
);
6908 else if (GET_CODE (el
) == CONST_DOUBLE
)
6910 elpart
= CONST_DOUBLE_LOW (el
);
6916 for (part
= 0; part
< parts
; part
++)
6919 for (byte
= 0; byte
< innersize
; byte
++)
6921 bytes
[idx
++] = (elpart
& 0xff) ^ invmask
;
6922 elpart
>>= BITS_PER_UNIT
;
6924 if (GET_CODE (el
) == CONST_DOUBLE
)
6925 elpart
= CONST_DOUBLE_HIGH (el
);
6930 gcc_assert (idx
== GET_MODE_SIZE (mode
));
6934 CHECK (4, 32, 0, bytes
[i
] == bytes
[0] && bytes
[i
+ 1] == 0
6935 && bytes
[i
+ 2] == 0 && bytes
[i
+ 3] == 0);
6937 CHECK (4, 32, 1, bytes
[i
] == 0 && bytes
[i
+ 1] == bytes
[1]
6938 && bytes
[i
+ 2] == 0 && bytes
[i
+ 3] == 0);
6940 CHECK (4, 32, 2, bytes
[i
] == 0 && bytes
[i
+ 1] == 0
6941 && bytes
[i
+ 2] == bytes
[2] && bytes
[i
+ 3] == 0);
6943 CHECK (4, 32, 3, bytes
[i
] == 0 && bytes
[i
+ 1] == 0
6944 && bytes
[i
+ 2] == 0 && bytes
[i
+ 3] == bytes
[3]);
6946 CHECK (2, 16, 4, bytes
[i
] == bytes
[0] && bytes
[i
+ 1] == 0);
6948 CHECK (2, 16, 5, bytes
[i
] == 0 && bytes
[i
+ 1] == bytes
[1]);
6950 CHECK (4, 32, 6, bytes
[i
] == bytes
[0] && bytes
[i
+ 1] == 0xff
6951 && bytes
[i
+ 2] == 0xff && bytes
[i
+ 3] == 0xff);
6953 CHECK (4, 32, 7, bytes
[i
] == 0xff && bytes
[i
+ 1] == bytes
[1]
6954 && bytes
[i
+ 2] == 0xff && bytes
[i
+ 3] == 0xff);
6956 CHECK (4, 32, 8, bytes
[i
] == 0xff && bytes
[i
+ 1] == 0xff
6957 && bytes
[i
+ 2] == bytes
[2] && bytes
[i
+ 3] == 0xff);
6959 CHECK (4, 32, 9, bytes
[i
] == 0xff && bytes
[i
+ 1] == 0xff
6960 && bytes
[i
+ 2] == 0xff && bytes
[i
+ 3] == bytes
[3]);
6962 CHECK (2, 16, 10, bytes
[i
] == bytes
[0] && bytes
[i
+ 1] == 0xff);
6964 CHECK (2, 16, 11, bytes
[i
] == 0xff && bytes
[i
+ 1] == bytes
[1]);
6966 CHECK (4, 32, 12, bytes
[i
] == 0xff && bytes
[i
+ 1] == bytes
[1]
6967 && bytes
[i
+ 2] == 0 && bytes
[i
+ 3] == 0);
6969 CHECK (4, 32, 13, bytes
[i
] == 0 && bytes
[i
+ 1] == bytes
[1]
6970 && bytes
[i
+ 2] == 0xff && bytes
[i
+ 3] == 0xff);
6972 CHECK (4, 32, 14, bytes
[i
] == 0xff && bytes
[i
+ 1] == 0xff
6973 && bytes
[i
+ 2] == bytes
[2] && bytes
[i
+ 3] == 0);
6975 CHECK (4, 32, 15, bytes
[i
] == 0 && bytes
[i
+ 1] == 0
6976 && bytes
[i
+ 2] == bytes
[2] && bytes
[i
+ 3] == 0xff);
6978 CHECK (1, 8, 16, bytes
[i
] == bytes
[0]);
6980 CHECK (1, 64, 17, (bytes
[i
] == 0 || bytes
[i
] == 0xff)
6981 && bytes
[i
] == bytes
[(i
+ 8) % idx
]);
6989 *elementwidth
= elsize
;
6993 unsigned HOST_WIDE_INT imm
= 0;
6995 /* Un-invert bytes of recognized vector, if neccessary. */
6997 for (i
= 0; i
< idx
; i
++)
6998 bytes
[i
] ^= invmask
;
7002 /* FIXME: Broken on 32-bit H_W_I hosts. */
7003 gcc_assert (sizeof (HOST_WIDE_INT
) == 8);
7005 for (i
= 0; i
< 8; i
++)
7006 imm
|= (unsigned HOST_WIDE_INT
) (bytes
[i
] ? 0xff : 0)
7007 << (i
* BITS_PER_UNIT
);
7009 *modconst
= GEN_INT (imm
);
7013 unsigned HOST_WIDE_INT imm
= 0;
7015 for (i
= 0; i
< elsize
/ BITS_PER_UNIT
; i
++)
7016 imm
|= (unsigned HOST_WIDE_INT
) bytes
[i
] << (i
* BITS_PER_UNIT
);
7018 *modconst
= GEN_INT (imm
);
7026 /* Return TRUE if rtx X is legal for use as either a Neon VMOV (or, implicitly,
7027 VMVN) immediate. Write back width per element to *ELEMENTWIDTH (or zero for
7028 float elements), and a modified constant (whatever should be output for a
7029 VMOV) in *MODCONST. */
7032 neon_immediate_valid_for_move (rtx op
, enum machine_mode mode
,
7033 rtx
*modconst
, int *elementwidth
)
7037 int retval
= neon_valid_immediate (op
, mode
, 0, &tmpconst
, &tmpwidth
);
7043 *modconst
= tmpconst
;
7046 *elementwidth
= tmpwidth
;
7051 /* Return TRUE if rtx X is legal for use in a VORR or VBIC instruction. If
7052 the immediate is valid, write a constant suitable for using as an operand
7053 to VORR/VBIC/VAND/VORN to *MODCONST and the corresponding element width to
7054 *ELEMENTWIDTH. See neon_valid_immediate for description of INVERSE. */
7057 neon_immediate_valid_for_logic (rtx op
, enum machine_mode mode
, int inverse
,
7058 rtx
*modconst
, int *elementwidth
)
7062 int retval
= neon_valid_immediate (op
, mode
, inverse
, &tmpconst
, &tmpwidth
);
7064 if (retval
< 0 || retval
> 5)
7068 *modconst
= tmpconst
;
7071 *elementwidth
= tmpwidth
;
7076 /* Return a string suitable for output of Neon immediate logic operation
7080 neon_output_logic_immediate (const char *mnem
, rtx
*op2
, enum machine_mode mode
,
7081 int inverse
, int quad
)
7083 int width
, is_valid
;
7084 static char templ
[40];
7086 is_valid
= neon_immediate_valid_for_logic (*op2
, mode
, inverse
, op2
, &width
);
7088 gcc_assert (is_valid
!= 0);
7091 sprintf (templ
, "%s.i%d\t%%q0, %%2", mnem
, width
);
7093 sprintf (templ
, "%s.i%d\t%%P0, %%2", mnem
, width
);
7098 /* Output a sequence of pairwise operations to implement a reduction.
7099 NOTE: We do "too much work" here, because pairwise operations work on two
7100 registers-worth of operands in one go. Unfortunately we can't exploit those
7101 extra calculations to do the full operation in fewer steps, I don't think.
7102 Although all vector elements of the result but the first are ignored, we
7103 actually calculate the same result in each of the elements. An alternative
7104 such as initially loading a vector with zero to use as each of the second
7105 operands would use up an additional register and take an extra instruction,
7106 for no particular gain. */
7109 neon_pairwise_reduce (rtx op0
, rtx op1
, enum machine_mode mode
,
7110 rtx (*reduc
) (rtx
, rtx
, rtx
))
7112 enum machine_mode inner
= GET_MODE_INNER (mode
);
7113 unsigned int i
, parts
= GET_MODE_SIZE (mode
) / GET_MODE_SIZE (inner
);
7116 for (i
= parts
/ 2; i
>= 1; i
/= 2)
7118 rtx dest
= (i
== 1) ? op0
: gen_reg_rtx (mode
);
7119 emit_insn (reduc (dest
, tmpsum
, tmpsum
));
7124 /* Initialise a vector with non-constant elements. FIXME: We can do better
7125 than the current implementation (building a vector on the stack and then
7126 loading it) in many cases. See rs6000.c. */
7129 neon_expand_vector_init (rtx target
, rtx vals
)
7131 enum machine_mode mode
= GET_MODE (target
);
7132 enum machine_mode inner
= GET_MODE_INNER (mode
);
7133 unsigned int i
, n_elts
= GET_MODE_NUNITS (mode
);
7136 gcc_assert (VECTOR_MODE_P (mode
));
7138 mem
= assign_stack_temp (mode
, GET_MODE_SIZE (mode
), 0);
7139 for (i
= 0; i
< n_elts
; i
++)
7140 emit_move_insn (adjust_address_nv (mem
, inner
, i
* GET_MODE_SIZE (inner
)),
7141 XVECEXP (vals
, 0, i
));
7143 emit_move_insn (target
, mem
);
7146 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
7148 /* Predicates for `match_operand' and `match_operator'. */
7150 /* Return nonzero if OP is a valid Cirrus memory address pattern. */
7152 cirrus_memory_offset (rtx op
)
7154 /* Reject eliminable registers. */
7155 if (! (reload_in_progress
|| reload_completed
)
7156 && ( reg_mentioned_p (frame_pointer_rtx
, op
)
7157 || reg_mentioned_p (arg_pointer_rtx
, op
)
7158 || reg_mentioned_p (virtual_incoming_args_rtx
, op
)
7159 || reg_mentioned_p (virtual_outgoing_args_rtx
, op
)
7160 || reg_mentioned_p (virtual_stack_dynamic_rtx
, op
)
7161 || reg_mentioned_p (virtual_stack_vars_rtx
, op
)))
7164 if (GET_CODE (op
) == MEM
)
7170 /* Match: (mem (reg)). */
7171 if (GET_CODE (ind
) == REG
)
7177 if (GET_CODE (ind
) == PLUS
7178 && GET_CODE (XEXP (ind
, 0)) == REG
7179 && REG_MODE_OK_FOR_BASE_P (XEXP (ind
, 0), VOIDmode
)
7180 && GET_CODE (XEXP (ind
, 1)) == CONST_INT
)
7187 /* APPLE LOCAL begin v7 support. Merge from mainline */
7188 /* Return TRUE if OP is a valid coprocessor memory address pattern.
7189 WB is true if full writeback address modes are allowed and is false
7190 if limited writeback address modes (POST_INC and PRE_DEC) are
7192 /* APPLE LOCAL end v7 support. Merge from mainline */
7195 arm_coproc_mem_operand (rtx op
, bool wb
)
7199 /* Reject eliminable registers. */
7200 if (! (reload_in_progress
|| reload_completed
)
7201 && ( reg_mentioned_p (frame_pointer_rtx
, op
)
7202 || reg_mentioned_p (arg_pointer_rtx
, op
)
7203 || reg_mentioned_p (virtual_incoming_args_rtx
, op
)
7204 || reg_mentioned_p (virtual_outgoing_args_rtx
, op
)
7205 || reg_mentioned_p (virtual_stack_dynamic_rtx
, op
)
7206 || reg_mentioned_p (virtual_stack_vars_rtx
, op
)))
7209 /* Constants are converted into offsets from labels. */
7210 if (GET_CODE (op
) != MEM
)
7215 if (reload_completed
7216 && (GET_CODE (ind
) == LABEL_REF
7217 || (GET_CODE (ind
) == CONST
7218 && GET_CODE (XEXP (ind
, 0)) == PLUS
7219 && GET_CODE (XEXP (XEXP (ind
, 0), 0)) == LABEL_REF
7220 && GET_CODE (XEXP (XEXP (ind
, 0), 1)) == CONST_INT
)))
7223 /* Match: (mem (reg)). */
7224 if (GET_CODE (ind
) == REG
)
7225 return arm_address_register_rtx_p (ind
, 0);
7227 /* APPLE LOCAL begin v7 support. Merge from mainline */
7228 /* Autoincremment addressing modes. POST_INC and PRE_DEC are
7229 acceptable in any case (subject to verification by
7230 arm_address_register_rtx_p). We need WB to be true to accept
7231 PRE_INC and POST_DEC. */
7232 if (GET_CODE (ind
) == POST_INC
7233 || GET_CODE (ind
) == PRE_DEC
7235 && (GET_CODE (ind
) == PRE_INC
7236 || GET_CODE (ind
) == POST_DEC
)))
7237 return arm_address_register_rtx_p (XEXP (ind
, 0), 0);
7238 /* APPLE LOCAL end v7 support. Merge from mainline */
7241 && (GET_CODE (ind
) == POST_MODIFY
|| GET_CODE (ind
) == PRE_MODIFY
)
7242 && arm_address_register_rtx_p (XEXP (ind
, 0), 0)
7243 && GET_CODE (XEXP (ind
, 1)) == PLUS
7244 && rtx_equal_p (XEXP (XEXP (ind
, 1), 0), XEXP (ind
, 0)))
7245 ind
= XEXP (ind
, 1);
7250 if (GET_CODE (ind
) == PLUS
7251 && GET_CODE (XEXP (ind
, 0)) == REG
7252 && REG_MODE_OK_FOR_BASE_P (XEXP (ind
, 0), VOIDmode
)
7253 && GET_CODE (XEXP (ind
, 1)) == CONST_INT
7254 && INTVAL (XEXP (ind
, 1)) > -1024
7255 && INTVAL (XEXP (ind
, 1)) < 1024
7256 && (INTVAL (XEXP (ind
, 1)) & 3) == 0)
7262 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
7263 /* Return TRUE if OP is a memory operand which we can load or store a vector
7264 to/from. If CORE is true, we're moving from ARM registers not Neon
7267 neon_vector_mem_operand (rtx op
, bool core
)
7271 /* Reject eliminable registers. */
7272 if (! (reload_in_progress
|| reload_completed
)
7273 && ( reg_mentioned_p (frame_pointer_rtx
, op
)
7274 || reg_mentioned_p (arg_pointer_rtx
, op
)
7275 || reg_mentioned_p (virtual_incoming_args_rtx
, op
)
7276 || reg_mentioned_p (virtual_outgoing_args_rtx
, op
)
7277 || reg_mentioned_p (virtual_stack_dynamic_rtx
, op
)
7278 || reg_mentioned_p (virtual_stack_vars_rtx
, op
)))
7281 /* Constants are converted into offsets from labels. */
7282 if (GET_CODE (op
) != MEM
)
7287 if (reload_completed
7288 && (GET_CODE (ind
) == LABEL_REF
7289 || (GET_CODE (ind
) == CONST
7290 && GET_CODE (XEXP (ind
, 0)) == PLUS
7291 && GET_CODE (XEXP (XEXP (ind
, 0), 0)) == LABEL_REF
7292 && GET_CODE (XEXP (XEXP (ind
, 0), 1)) == CONST_INT
)))
7295 /* Match: (mem (reg)). */
7296 if (GET_CODE (ind
) == REG
)
7297 return arm_address_register_rtx_p (ind
, 0);
7299 /* Allow post-increment with Neon registers. */
7300 if (!core
&& GET_CODE (ind
) == POST_INC
)
7301 return arm_address_register_rtx_p (XEXP (ind
, 0), 0);
7304 /* FIXME: We can support this too if we use VLD1/VST1. */
7306 && GET_CODE (ind
) == POST_MODIFY
7307 && arm_address_register_rtx_p (XEXP (ind
, 0), 0)
7308 && GET_CODE (XEXP (ind
, 1)) == PLUS
7309 && rtx_equal_p (XEXP (XEXP (ind
, 1), 0), XEXP (ind
, 0)))
7310 ind
= XEXP (ind
, 1);
7317 && GET_CODE (ind
) == PLUS
7318 && GET_CODE (XEXP (ind
, 0)) == REG
7319 && REG_MODE_OK_FOR_BASE_P (XEXP (ind
, 0), VOIDmode
)
7320 /* APPLE LOCAL begin 6160917 */
7321 /* Make call consistent with the ones used in neon_reload_{in,out} */
7322 && arm_legitimate_index_p (GET_MODE (op
), XEXP (ind
, 1), SET
, 0))
7323 /* APPLE LOCAL end 6160917 */
7329 /* Return TRUE if OP is a mem suitable for loading/storing a Neon struct
7332 neon_struct_mem_operand (rtx op
)
7336 /* Reject eliminable registers. */
7337 if (! (reload_in_progress
|| reload_completed
)
7338 && ( reg_mentioned_p (frame_pointer_rtx
, op
)
7339 || reg_mentioned_p (arg_pointer_rtx
, op
)
7340 || reg_mentioned_p (virtual_incoming_args_rtx
, op
)
7341 || reg_mentioned_p (virtual_outgoing_args_rtx
, op
)
7342 || reg_mentioned_p (virtual_stack_dynamic_rtx
, op
)
7343 || reg_mentioned_p (virtual_stack_vars_rtx
, op
)))
7346 /* Constants are converted into offsets from labels. */
7347 if (GET_CODE (op
) != MEM
)
7352 if (reload_completed
7353 && (GET_CODE (ind
) == LABEL_REF
7354 || (GET_CODE (ind
) == CONST
7355 && GET_CODE (XEXP (ind
, 0)) == PLUS
7356 && GET_CODE (XEXP (XEXP (ind
, 0), 0)) == LABEL_REF
7357 && GET_CODE (XEXP (XEXP (ind
, 0), 1)) == CONST_INT
)))
7360 /* Match: (mem (reg)). */
7361 if (GET_CODE (ind
) == REG
)
7362 return arm_address_register_rtx_p (ind
, 0);
7367 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
7368 /* Return true if X is a register that will be eliminated later on. */
7370 arm_eliminable_register (rtx x
)
7372 return REG_P (x
) && (REGNO (x
) == FRAME_POINTER_REGNUM
7373 || REGNO (x
) == ARG_POINTER_REGNUM
7374 || (REGNO (x
) >= FIRST_VIRTUAL_REGISTER
7375 && REGNO (x
) <= LAST_VIRTUAL_REGISTER
));
7378 /* Return GENERAL_REGS if a scratch register required to reload x to/from
7379 coprocessor registers. Otherwise return NO_REGS. */
7382 coproc_secondary_reload_class (enum machine_mode mode
, rtx x
, bool wb
)
7384 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
7386 && (GET_MODE_CLASS (mode
) == MODE_VECTOR_INT
7387 || GET_MODE_CLASS (mode
) == MODE_VECTOR_FLOAT
)
7388 && neon_vector_mem_operand (x
, FALSE
))
7391 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
7392 if (arm_coproc_mem_operand (x
, wb
) || s_register_operand (x
, mode
))
7395 return GENERAL_REGS
;
7398 /* Values which must be returned in the most-significant end of the return
7402 arm_return_in_msb (tree valtype
)
7404 return (TARGET_AAPCS_BASED
7406 && (AGGREGATE_TYPE_P (valtype
)
7407 || TREE_CODE (valtype
) == COMPLEX_TYPE
));
7413 /* Returns TRUE if INSN is an "LDR REG, ADDR" instruction.
7414 Use by the Cirrus Maverick code which has to workaround
7415 a hardware bug triggered by such instructions. */
7417 arm_memory_load_p (rtx insn
)
7419 rtx body
, lhs
, rhs
;;
7421 if (insn
== NULL_RTX
|| GET_CODE (insn
) != INSN
)
7424 body
= PATTERN (insn
);
7426 if (GET_CODE (body
) != SET
)
7429 lhs
= XEXP (body
, 0);
7430 rhs
= XEXP (body
, 1);
7432 lhs
= REG_OR_SUBREG_RTX (lhs
);
7434 /* If the destination is not a general purpose
7435 register we do not have to worry. */
7436 if (GET_CODE (lhs
) != REG
7437 || REGNO_REG_CLASS (REGNO (lhs
)) != GENERAL_REGS
)
7440 /* As well as loads from memory we also have to react
7441 to loads of invalid constants which will be turned
7442 into loads from the minipool. */
7443 return (GET_CODE (rhs
) == MEM
7444 || GET_CODE (rhs
) == SYMBOL_REF
7445 || note_invalid_constants (insn
, -1, false));
7448 /* Return TRUE if INSN is a Cirrus instruction. */
7450 arm_cirrus_insn_p (rtx insn
)
7452 enum attr_cirrus attr
;
7454 /* get_attr cannot accept USE or CLOBBER. */
7456 || GET_CODE (insn
) != INSN
7457 || GET_CODE (PATTERN (insn
)) == USE
7458 || GET_CODE (PATTERN (insn
)) == CLOBBER
)
7461 attr
= get_attr_cirrus (insn
);
7463 return attr
!= CIRRUS_NOT
;
7466 /* Cirrus reorg for invalid instruction combinations. */
7468 cirrus_reorg (rtx first
)
7470 enum attr_cirrus attr
;
7471 rtx body
= PATTERN (first
);
7475 /* Any branch must be followed by 2 non Cirrus instructions. */
7476 if (GET_CODE (first
) == JUMP_INSN
&& GET_CODE (body
) != RETURN
)
7479 t
= next_nonnote_insn (first
);
7481 if (arm_cirrus_insn_p (t
))
7484 if (arm_cirrus_insn_p (next_nonnote_insn (t
)))
7488 emit_insn_after (gen_nop (), first
);
7493 /* (float (blah)) is in parallel with a clobber. */
7494 if (GET_CODE (body
) == PARALLEL
&& XVECLEN (body
, 0) > 0)
7495 body
= XVECEXP (body
, 0, 0);
7497 if (GET_CODE (body
) == SET
)
7499 rtx lhs
= XEXP (body
, 0), rhs
= XEXP (body
, 1);
7501 /* cfldrd, cfldr64, cfstrd, cfstr64 must
7502 be followed by a non Cirrus insn. */
7503 if (get_attr_cirrus (first
) == CIRRUS_DOUBLE
)
7505 if (arm_cirrus_insn_p (next_nonnote_insn (first
)))
7506 emit_insn_after (gen_nop (), first
);
7510 else if (arm_memory_load_p (first
))
7512 unsigned int arm_regno
;
7514 /* Any ldr/cfmvdlr, ldr/cfmvdhr, ldr/cfmvsr, ldr/cfmv64lr,
7515 ldr/cfmv64hr combination where the Rd field is the same
7516 in both instructions must be split with a non Cirrus
7523 /* Get Arm register number for ldr insn. */
7524 if (GET_CODE (lhs
) == REG
)
7525 arm_regno
= REGNO (lhs
);
7528 gcc_assert (GET_CODE (rhs
) == REG
);
7529 arm_regno
= REGNO (rhs
);
7533 first
= next_nonnote_insn (first
);
7535 if (! arm_cirrus_insn_p (first
))
7538 body
= PATTERN (first
);
7540 /* (float (blah)) is in parallel with a clobber. */
7541 if (GET_CODE (body
) == PARALLEL
&& XVECLEN (body
, 0))
7542 body
= XVECEXP (body
, 0, 0);
7544 if (GET_CODE (body
) == FLOAT
)
7545 body
= XEXP (body
, 0);
7547 if (get_attr_cirrus (first
) == CIRRUS_MOVE
7548 && GET_CODE (XEXP (body
, 1)) == REG
7549 && arm_regno
== REGNO (XEXP (body
, 1)))
7550 emit_insn_after (gen_nop (), first
);
7556 /* get_attr cannot accept USE or CLOBBER. */
7558 || GET_CODE (first
) != INSN
7559 || GET_CODE (PATTERN (first
)) == USE
7560 || GET_CODE (PATTERN (first
)) == CLOBBER
)
7563 attr
= get_attr_cirrus (first
);
7565 /* Any coprocessor compare instruction (cfcmps, cfcmpd, ...)
7566 must be followed by a non-coprocessor instruction. */
7567 if (attr
== CIRRUS_COMPARE
)
7571 t
= next_nonnote_insn (first
);
7573 if (arm_cirrus_insn_p (t
))
7576 if (arm_cirrus_insn_p (next_nonnote_insn (t
)))
7580 emit_insn_after (gen_nop (), first
);
7589 /* APPLE LOCAL begin ARM -mdynamic-no-pic support */
7590 /* Return TRUE if X references a SYMBOL_REF. */
7592 symbol_mentioned_p (rtx x
)
7594 return symbol_mentioned_with_filter (x
, 0);
7597 /* Return TRUE if X references a non-local SYMBOL_REF. */
7599 non_local_symbol_mentioned_p (rtx x
)
7601 return symbol_mentioned_with_filter (x
, 1);
7604 /* Return TRUE if X references a SYMBOL_REF. If filter_local is set,
7605 then references to local symbols (as per machopic_data_defined_p)
7608 symbol_mentioned_with_filter (rtx x
, int filter_local
)
7613 if (GET_CODE (x
) == SYMBOL_REF
)
7616 if (filter_local
&& machopic_data_defined_p (x
))
7623 /* UNSPEC_TLS entries for a symbol include the SYMBOL_REF, but they
7624 are constant offsets, not symbols. */
7625 if (GET_CODE (x
) == UNSPEC
&& XINT (x
, 1) == UNSPEC_TLS
)
7628 fmt
= GET_RTX_FORMAT (GET_CODE (x
));
7630 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
7636 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
7637 if (symbol_mentioned_with_filter (XVECEXP (x
, i
, j
),
7641 else if (fmt
[i
] == 'e'
7642 && symbol_mentioned_with_filter (XEXP (x
, i
),
7649 /* APPLE LOCAL end ARM -mdynmaic-no-pic support */
7651 /* Return TRUE if X references a LABEL_REF. */
7653 label_mentioned_p (rtx x
)
7658 if (GET_CODE (x
) == LABEL_REF
)
7661 /* UNSPEC_TLS entries for a symbol include a LABEL_REF for the referencing
7662 instruction, but they are constant offsets, not symbols. */
7663 if (GET_CODE (x
) == UNSPEC
&& XINT (x
, 1) == UNSPEC_TLS
)
7666 fmt
= GET_RTX_FORMAT (GET_CODE (x
));
7667 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
7673 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
7674 if (label_mentioned_p (XVECEXP (x
, i
, j
)))
7677 else if (fmt
[i
] == 'e' && label_mentioned_p (XEXP (x
, i
)))
7685 tls_mentioned_p (rtx x
)
7687 switch (GET_CODE (x
))
7690 return tls_mentioned_p (XEXP (x
, 0));
7693 if (XINT (x
, 1) == UNSPEC_TLS
)
7701 /* Must not copy a SET whose source operand is PC-relative. */
7704 arm_cannot_copy_insn_p (rtx insn
)
7706 rtx pat
= PATTERN (insn
);
7708 /* APPLE LOCAL begin ARM pic support */
7709 if (GET_CODE (pat
) == SET
)
7711 rtx rhs
= SET_SRC (pat
);
7712 rtx lhs
= SET_DEST (pat
);
7714 if (GET_CODE (rhs
) == UNSPEC
7715 && XINT (rhs
, 1) == UNSPEC_PIC_BASE
)
7718 if (GET_CODE (rhs
) == MEM
7719 && GET_CODE (XEXP (rhs
, 0)) == UNSPEC
7720 && XINT (XEXP (rhs
, 0), 1) == UNSPEC_PIC_BASE
)
7723 if (GET_CODE (lhs
) == MEM
7724 && GET_CODE (XEXP (lhs
, 0)) == UNSPEC
7725 && XINT (XEXP (lhs
, 0), 1) == UNSPEC_PIC_BASE
)
7728 /* APPLE LOCAL end ARM pic support */
7730 if (GET_CODE (pat
) == PARALLEL
7731 && GET_CODE (XVECEXP (pat
, 0, 0)) == SET
)
7733 rtx rhs
= SET_SRC (XVECEXP (pat
, 0, 0));
7735 if (GET_CODE (rhs
) == UNSPEC
7736 && XINT (rhs
, 1) == UNSPEC_PIC_BASE
)
7739 if (GET_CODE (rhs
) == MEM
7740 && GET_CODE (XEXP (rhs
, 0)) == UNSPEC
7741 && XINT (XEXP (rhs
, 0), 1) == UNSPEC_PIC_BASE
)
7751 enum rtx_code code
= GET_CODE (x
);
7768 /* Return 1 if memory locations are adjacent. */
7770 adjacent_mem_locations (rtx a
, rtx b
)
7772 /* We don't guarantee to preserve the order of these memory refs. */
7773 if (volatile_refs_p (a
) || volatile_refs_p (b
))
7776 if ((GET_CODE (XEXP (a
, 0)) == REG
7777 || (GET_CODE (XEXP (a
, 0)) == PLUS
7778 && GET_CODE (XEXP (XEXP (a
, 0), 1)) == CONST_INT
))
7779 && (GET_CODE (XEXP (b
, 0)) == REG
7780 || (GET_CODE (XEXP (b
, 0)) == PLUS
7781 && GET_CODE (XEXP (XEXP (b
, 0), 1)) == CONST_INT
)))
7783 HOST_WIDE_INT val0
= 0, val1
= 0;
7787 if (GET_CODE (XEXP (a
, 0)) == PLUS
)
7789 reg0
= XEXP (XEXP (a
, 0), 0);
7790 val0
= INTVAL (XEXP (XEXP (a
, 0), 1));
7795 if (GET_CODE (XEXP (b
, 0)) == PLUS
)
7797 reg1
= XEXP (XEXP (b
, 0), 0);
7798 val1
= INTVAL (XEXP (XEXP (b
, 0), 1));
7803 /* Don't accept any offset that will require multiple
7804 instructions to handle, since this would cause the
7805 arith_adjacentmem pattern to output an overlong sequence. */
7806 if (!const_ok_for_op (PLUS
, val0
) || !const_ok_for_op (PLUS
, val1
))
7809 /* Don't allow an eliminable register: register elimination can make
7810 the offset too large. */
7811 if (arm_eliminable_register (reg0
))
7814 val_diff
= val1
- val0
;
7818 /* If the target has load delay slots, then there's no benefit
7819 to using an ldm instruction unless the offset is zero and
7820 we are optimizing for size. */
7821 return (optimize_size
&& (REGNO (reg0
) == REGNO (reg1
))
7822 && (val0
== 0 || val1
== 0 || val0
== 4 || val1
== 4)
7823 && (val_diff
== 4 || val_diff
== -4));
7826 return ((REGNO (reg0
) == REGNO (reg1
))
7827 && (val_diff
== 4 || val_diff
== -4));
7834 load_multiple_sequence (rtx
*operands
, int nops
, int *regs
, int *base
,
7835 HOST_WIDE_INT
*load_offset
)
7837 int unsorted_regs
[4];
7838 HOST_WIDE_INT unsorted_offsets
[4];
7843 /* Can only handle 2, 3, or 4 insns at present,
7844 though could be easily extended if required. */
7845 gcc_assert (nops
>= 2 && nops
<= 4);
7847 /* Loop over the operands and check that the memory references are
7848 suitable (i.e. immediate offsets from the same base register). At
7849 the same time, extract the target register, and the memory
7851 for (i
= 0; i
< nops
; i
++)
7856 /* Convert a subreg of a mem into the mem itself. */
7857 if (GET_CODE (operands
[nops
+ i
]) == SUBREG
)
7858 operands
[nops
+ i
] = alter_subreg (operands
+ (nops
+ i
));
7860 gcc_assert (GET_CODE (operands
[nops
+ i
]) == MEM
);
7862 /* Don't reorder volatile memory references; it doesn't seem worth
7863 looking for the case where the order is ok anyway. */
7864 if (MEM_VOLATILE_P (operands
[nops
+ i
]))
7867 offset
= const0_rtx
;
7869 if ((GET_CODE (reg
= XEXP (operands
[nops
+ i
], 0)) == REG
7870 || (GET_CODE (reg
) == SUBREG
7871 && GET_CODE (reg
= SUBREG_REG (reg
)) == REG
))
7872 || (GET_CODE (XEXP (operands
[nops
+ i
], 0)) == PLUS
7873 && ((GET_CODE (reg
= XEXP (XEXP (operands
[nops
+ i
], 0), 0))
7875 || (GET_CODE (reg
) == SUBREG
7876 && GET_CODE (reg
= SUBREG_REG (reg
)) == REG
))
7877 && (GET_CODE (offset
= XEXP (XEXP (operands
[nops
+ i
], 0), 1))
7882 base_reg
= REGNO (reg
);
7883 unsorted_regs
[0] = (GET_CODE (operands
[i
]) == REG
7884 ? REGNO (operands
[i
])
7885 : REGNO (SUBREG_REG (operands
[i
])));
7890 if (base_reg
!= (int) REGNO (reg
))
7891 /* Not addressed from the same base register. */
7894 unsorted_regs
[i
] = (GET_CODE (operands
[i
]) == REG
7895 ? REGNO (operands
[i
])
7896 : REGNO (SUBREG_REG (operands
[i
])));
7897 if (unsorted_regs
[i
] < unsorted_regs
[order
[0]])
7901 /* If it isn't an integer register, or if it overwrites the
7902 base register but isn't the last insn in the list, then
7903 we can't do this. */
7904 if (unsorted_regs
[i
] < 0 || unsorted_regs
[i
] > 14
7905 || (i
!= nops
- 1 && unsorted_regs
[i
] == base_reg
))
7908 unsorted_offsets
[i
] = INTVAL (offset
);
7911 /* Not a suitable memory address. */
7915 /* All the useful information has now been extracted from the
7916 operands into unsorted_regs and unsorted_offsets; additionally,
7917 order[0] has been set to the lowest numbered register in the
7918 list. Sort the registers into order, and check that the memory
7919 offsets are ascending and adjacent. */
7921 for (i
= 1; i
< nops
; i
++)
7925 order
[i
] = order
[i
- 1];
7926 for (j
= 0; j
< nops
; j
++)
7927 if (unsorted_regs
[j
] > unsorted_regs
[order
[i
- 1]]
7928 && (order
[i
] == order
[i
- 1]
7929 || unsorted_regs
[j
] < unsorted_regs
[order
[i
]]))
7932 /* Have we found a suitable register? if not, one must be used more
7934 if (order
[i
] == order
[i
- 1])
7937 /* Is the memory address adjacent and ascending? */
7938 if (unsorted_offsets
[order
[i
]] != unsorted_offsets
[order
[i
- 1]] + 4)
7946 for (i
= 0; i
< nops
; i
++)
7947 regs
[i
] = unsorted_regs
[order
[i
]];
7949 *load_offset
= unsorted_offsets
[order
[0]];
7952 if (unsorted_offsets
[order
[0]] == 0)
7953 return 1; /* ldmia */
7955 /* APPLE LOCAL v7 support. Merge from mainline */
7956 if (TARGET_ARM
&& unsorted_offsets
[order
[0]] == 4)
7957 return 2; /* ldmib */
7959 /* APPLE LOCAL v7 support. Merge from mainline */
7960 if (TARGET_ARM
&& unsorted_offsets
[order
[nops
- 1]] == 0)
7961 return 3; /* ldmda */
7963 if (unsorted_offsets
[order
[nops
- 1]] == -4)
7964 return 4; /* ldmdb */
7966 /* For ARM8,9 & StrongARM, 2 ldr instructions are faster than an ldm
7967 if the offset isn't small enough. The reason 2 ldrs are faster
7968 is because these ARMs are able to do more than one cache access
7969 in a single cycle. The ARM9 and StrongARM have Harvard caches,
7970 whilst the ARM8 has a double bandwidth cache. This means that
7971 these cores can do both an instruction fetch and a data fetch in
7972 a single cycle, so the trick of calculating the address into a
7973 scratch register (one of the result regs) and then doing a load
7974 multiple actually becomes slower (and no smaller in code size).
7975 That is the transformation
7977 ldr rd1, [rbase + offset]
7978 ldr rd2, [rbase + offset + 4]
7982 add rd1, rbase, offset
7983 ldmia rd1, {rd1, rd2}
7985 produces worse code -- '3 cycles + any stalls on rd2' instead of
7986 '2 cycles + any stalls on rd2'. On ARMs with only one cache
7987 access per cycle, the first sequence could never complete in less
7988 than 6 cycles, whereas the ldm sequence would only take 5 and
7989 would make better use of sequential accesses if not hitting the
7992 We cheat here and test 'arm_ld_sched' which we currently know to
7993 only be true for the ARM8, ARM9 and StrongARM. If this ever
7994 changes, then the test below needs to be reworked. */
7995 if (nops
== 2 && arm_ld_sched
)
7998 /* Can't do it without setting up the offset, only do this if it takes
7999 no more than one insn. */
8000 return (const_ok_for_arm (unsorted_offsets
[order
[0]])
8001 || const_ok_for_arm (-unsorted_offsets
[order
[0]])) ? 5 : 0;
8005 emit_ldm_seq (rtx
*operands
, int nops
)
8009 HOST_WIDE_INT offset
;
8013 switch (load_multiple_sequence (operands
, nops
, regs
, &base_reg
, &offset
))
8016 /* APPLE LOCAL v7 support. Merge from mainline */
8017 strcpy (buf
, "ldm%(ia%)\t");
8021 /* APPLE LOCAL v7 support. Merge from mainline */
8022 strcpy (buf
, "ldm%(ib%)\t");
8026 /* APPLE LOCAL v7 support. Merge from mainline */
8027 strcpy (buf
, "ldm%(da%)\t");
8031 /* APPLE LOCAL v7 support. Merge from mainline */
8032 strcpy (buf
, "ldm%(db%)\t");
8037 sprintf (buf
, "add%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX
,
8038 reg_names
[regs
[0]], REGISTER_PREFIX
, reg_names
[base_reg
],
8041 sprintf (buf
, "sub%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX
,
8042 reg_names
[regs
[0]], REGISTER_PREFIX
, reg_names
[base_reg
],
8044 output_asm_insn (buf
, operands
);
8046 /* APPLE LOCAL v7 support. Merge from mainline */
8047 strcpy (buf
, "ldm%(ia%)\t");
8054 sprintf (buf
+ strlen (buf
), "%s%s, {%s%s", REGISTER_PREFIX
,
8055 reg_names
[base_reg
], REGISTER_PREFIX
, reg_names
[regs
[0]]);
8057 for (i
= 1; i
< nops
; i
++)
8058 sprintf (buf
+ strlen (buf
), ", %s%s", REGISTER_PREFIX
,
8059 reg_names
[regs
[i
]]);
8061 strcat (buf
, "}\t%@ phole ldm");
8063 output_asm_insn (buf
, operands
);
8068 store_multiple_sequence (rtx
*operands
, int nops
, int *regs
, int *base
,
8069 HOST_WIDE_INT
* load_offset
)
8071 int unsorted_regs
[4];
8072 HOST_WIDE_INT unsorted_offsets
[4];
8077 /* Can only handle 2, 3, or 4 insns at present, though could be easily
8078 extended if required. */
8079 gcc_assert (nops
>= 2 && nops
<= 4);
8081 /* Loop over the operands and check that the memory references are
8082 suitable (i.e. immediate offsets from the same base register). At
8083 the same time, extract the target register, and the memory
8085 for (i
= 0; i
< nops
; i
++)
8090 /* Convert a subreg of a mem into the mem itself. */
8091 if (GET_CODE (operands
[nops
+ i
]) == SUBREG
)
8092 operands
[nops
+ i
] = alter_subreg (operands
+ (nops
+ i
));
8094 gcc_assert (GET_CODE (operands
[nops
+ i
]) == MEM
);
8096 /* Don't reorder volatile memory references; it doesn't seem worth
8097 looking for the case where the order is ok anyway. */
8098 if (MEM_VOLATILE_P (operands
[nops
+ i
]))
8101 offset
= const0_rtx
;
8103 if ((GET_CODE (reg
= XEXP (operands
[nops
+ i
], 0)) == REG
8104 || (GET_CODE (reg
) == SUBREG
8105 && GET_CODE (reg
= SUBREG_REG (reg
)) == REG
))
8106 || (GET_CODE (XEXP (operands
[nops
+ i
], 0)) == PLUS
8107 && ((GET_CODE (reg
= XEXP (XEXP (operands
[nops
+ i
], 0), 0))
8109 || (GET_CODE (reg
) == SUBREG
8110 && GET_CODE (reg
= SUBREG_REG (reg
)) == REG
))
8111 && (GET_CODE (offset
= XEXP (XEXP (operands
[nops
+ i
], 0), 1))
8116 base_reg
= REGNO (reg
);
8117 unsorted_regs
[0] = (GET_CODE (operands
[i
]) == REG
8118 ? REGNO (operands
[i
])
8119 : REGNO (SUBREG_REG (operands
[i
])));
8124 if (base_reg
!= (int) REGNO (reg
))
8125 /* Not addressed from the same base register. */
8128 unsorted_regs
[i
] = (GET_CODE (operands
[i
]) == REG
8129 ? REGNO (operands
[i
])
8130 : REGNO (SUBREG_REG (operands
[i
])));
8131 if (unsorted_regs
[i
] < unsorted_regs
[order
[0]])
8135 /* If it isn't an integer register, then we can't do this. */
8136 if (unsorted_regs
[i
] < 0 || unsorted_regs
[i
] > 14)
8139 unsorted_offsets
[i
] = INTVAL (offset
);
8142 /* Not a suitable memory address. */
8146 /* All the useful information has now been extracted from the
8147 operands into unsorted_regs and unsorted_offsets; additionally,
8148 order[0] has been set to the lowest numbered register in the
8149 list. Sort the registers into order, and check that the memory
8150 offsets are ascending and adjacent. */
8152 for (i
= 1; i
< nops
; i
++)
8156 order
[i
] = order
[i
- 1];
8157 for (j
= 0; j
< nops
; j
++)
8158 if (unsorted_regs
[j
] > unsorted_regs
[order
[i
- 1]]
8159 && (order
[i
] == order
[i
- 1]
8160 || unsorted_regs
[j
] < unsorted_regs
[order
[i
]]))
8163 /* Have we found a suitable register? if not, one must be used more
8165 if (order
[i
] == order
[i
- 1])
8168 /* Is the memory address adjacent and ascending? */
8169 if (unsorted_offsets
[order
[i
]] != unsorted_offsets
[order
[i
- 1]] + 4)
8177 for (i
= 0; i
< nops
; i
++)
8178 regs
[i
] = unsorted_regs
[order
[i
]];
8180 *load_offset
= unsorted_offsets
[order
[0]];
8183 if (unsorted_offsets
[order
[0]] == 0)
8184 return 1; /* stmia */
8186 if (unsorted_offsets
[order
[0]] == 4)
8187 return 2; /* stmib */
8189 if (unsorted_offsets
[order
[nops
- 1]] == 0)
8190 return 3; /* stmda */
8192 if (unsorted_offsets
[order
[nops
- 1]] == -4)
8193 return 4; /* stmdb */
8199 emit_stm_seq (rtx
*operands
, int nops
)
8203 HOST_WIDE_INT offset
;
8207 switch (store_multiple_sequence (operands
, nops
, regs
, &base_reg
, &offset
))
8210 /* APPLE LOCAL v7 support. Merge from mainline */
8211 strcpy (buf
, "stm%(ia%)\t");
8215 /* APPLE LOCAL v7 support. Merge from mainline */
8216 strcpy (buf
, "stm%(ib%)\t");
8220 /* APPLE LOCAL v7 support. Merge from mainline */
8221 strcpy (buf
, "stm%(da%)\t");
8225 /* APPLE LOCAL v7 support. Merge from mainline */
8226 strcpy (buf
, "stm%(db%)\t");
8233 sprintf (buf
+ strlen (buf
), "%s%s, {%s%s", REGISTER_PREFIX
,
8234 reg_names
[base_reg
], REGISTER_PREFIX
, reg_names
[regs
[0]]);
8236 for (i
= 1; i
< nops
; i
++)
8237 sprintf (buf
+ strlen (buf
), ", %s%s", REGISTER_PREFIX
,
8238 reg_names
[regs
[i
]]);
8240 strcat (buf
, "}\t%@ phole stm");
8242 output_asm_insn (buf
, operands
);
8246 /* Routines for use in generating RTL. */
8249 arm_gen_load_multiple (int base_regno
, int count
, rtx from
, int up
,
8250 int write_back
, rtx basemem
, HOST_WIDE_INT
*offsetp
)
8252 HOST_WIDE_INT offset
= *offsetp
;
8255 int sign
= up
? 1 : -1;
8258 /* XScale has load-store double instructions, but they have stricter
8259 alignment requirements than load-store multiple, so we cannot
8262 For XScale ldm requires 2 + NREGS cycles to complete and blocks
8263 the pipeline until completion.
8271 An ldr instruction takes 1-3 cycles, but does not block the
8280 Best case ldr will always win. However, the more ldr instructions
8281 we issue, the less likely we are to be able to schedule them well.
8282 Using ldr instructions also increases code size.
8284 As a compromise, we use ldr for counts of 1 or 2 regs, and ldm
8285 for counts of 3 or 4 regs. */
8286 if (arm_tune_xscale
&& count
<= 2 && ! optimize_size
)
8292 for (i
= 0; i
< count
; i
++)
8294 addr
= plus_constant (from
, i
* 4 * sign
);
8295 mem
= adjust_automodify_address (basemem
, SImode
, addr
, offset
);
8296 emit_move_insn (gen_rtx_REG (SImode
, base_regno
+ i
), mem
);
8302 emit_move_insn (from
, plus_constant (from
, count
* 4 * sign
));
8312 result
= gen_rtx_PARALLEL (VOIDmode
,
8313 rtvec_alloc (count
+ (write_back
? 1 : 0)));
8316 XVECEXP (result
, 0, 0)
8317 = gen_rtx_SET (VOIDmode
, from
, plus_constant (from
, count
* 4 * sign
));
8322 for (j
= 0; i
< count
; i
++, j
++)
8324 addr
= plus_constant (from
, j
* 4 * sign
);
8325 mem
= adjust_automodify_address_nv (basemem
, SImode
, addr
, offset
);
8326 XVECEXP (result
, 0, i
)
8327 = gen_rtx_SET (VOIDmode
, gen_rtx_REG (SImode
, base_regno
+ j
), mem
);
8338 arm_gen_store_multiple (int base_regno
, int count
, rtx to
, int up
,
8339 int write_back
, rtx basemem
, HOST_WIDE_INT
*offsetp
)
8341 HOST_WIDE_INT offset
= *offsetp
;
8344 int sign
= up
? 1 : -1;
8347 /* See arm_gen_load_multiple for discussion of
8348 the pros/cons of ldm/stm usage for XScale. */
8349 if (arm_tune_xscale
&& count
<= 2 && ! optimize_size
)
8355 for (i
= 0; i
< count
; i
++)
8357 addr
= plus_constant (to
, i
* 4 * sign
);
8358 mem
= adjust_automodify_address (basemem
, SImode
, addr
, offset
);
8359 emit_move_insn (mem
, gen_rtx_REG (SImode
, base_regno
+ i
));
8365 emit_move_insn (to
, plus_constant (to
, count
* 4 * sign
));
8375 result
= gen_rtx_PARALLEL (VOIDmode
,
8376 rtvec_alloc (count
+ (write_back
? 1 : 0)));
8379 XVECEXP (result
, 0, 0)
8380 = gen_rtx_SET (VOIDmode
, to
,
8381 plus_constant (to
, count
* 4 * sign
));
8386 for (j
= 0; i
< count
; i
++, j
++)
8388 addr
= plus_constant (to
, j
* 4 * sign
);
8389 mem
= adjust_automodify_address_nv (basemem
, SImode
, addr
, offset
);
8390 XVECEXP (result
, 0, i
)
8391 = gen_rtx_SET (VOIDmode
, mem
, gen_rtx_REG (SImode
, base_regno
+ j
));
8402 arm_gen_movmemqi (rtx
*operands
)
8404 HOST_WIDE_INT in_words_to_go
, out_words_to_go
, last_bytes
;
8405 HOST_WIDE_INT srcoffset
, dstoffset
;
8407 rtx src
, dst
, srcbase
, dstbase
;
8408 rtx part_bytes_reg
= NULL
;
8411 if (GET_CODE (operands
[2]) != CONST_INT
8412 || GET_CODE (operands
[3]) != CONST_INT
8413 || INTVAL (operands
[2]) > 64
8414 || INTVAL (operands
[3]) & 3)
8417 /* APPLE LOCAL begin ARM use memcpy more at -Os */
8418 /* At -Os we consider the size of repeated lod/sto vs memcpy call. Both ways
8419 require getting source and dest addresses into regs. Beyond that memcpy
8420 is 2 insns; lod/sto is at least 2, maybe more. But lod/sto is faster so
8421 we prefer that when it is only 2 insns; that occurs when the size is
8422 1, 2, 4, 8, 12, or 16 only. */
8424 && INTVAL (operands
[2]) != 1
8425 && INTVAL (operands
[2]) != 2
8426 && INTVAL (operands
[2]) != 4
8427 && INTVAL (operands
[2]) != 8
8428 && INTVAL (operands
[2]) != 12
8429 && INTVAL (operands
[2]) != 16)
8431 /* APPLE LOCAL end ARM use memcpy more at -Os */
8433 dstbase
= operands
[0];
8434 srcbase
= operands
[1];
8436 dst
= copy_to_mode_reg (SImode
, XEXP (dstbase
, 0));
8437 src
= copy_to_mode_reg (SImode
, XEXP (srcbase
, 0));
8439 in_words_to_go
= ARM_NUM_INTS (INTVAL (operands
[2]));
8440 out_words_to_go
= INTVAL (operands
[2]) / 4;
8441 last_bytes
= INTVAL (operands
[2]) & 3;
8442 dstoffset
= srcoffset
= 0;
8444 if (out_words_to_go
!= in_words_to_go
&& ((in_words_to_go
- 1) & 3) != 0)
8445 part_bytes_reg
= gen_rtx_REG (SImode
, (in_words_to_go
- 1) & 3);
8447 for (i
= 0; in_words_to_go
>= 2; i
+=4)
8449 if (in_words_to_go
> 4)
8450 emit_insn (arm_gen_load_multiple (0, 4, src
, TRUE
, TRUE
,
8451 srcbase
, &srcoffset
));
8453 emit_insn (arm_gen_load_multiple (0, in_words_to_go
, src
, TRUE
,
8454 FALSE
, srcbase
, &srcoffset
));
8456 if (out_words_to_go
)
8458 if (out_words_to_go
> 4)
8459 emit_insn (arm_gen_store_multiple (0, 4, dst
, TRUE
, TRUE
,
8460 dstbase
, &dstoffset
));
8461 else if (out_words_to_go
!= 1)
8462 emit_insn (arm_gen_store_multiple (0, out_words_to_go
,
8466 dstbase
, &dstoffset
));
8469 mem
= adjust_automodify_address (dstbase
, SImode
, dst
, dstoffset
);
8470 emit_move_insn (mem
, gen_rtx_REG (SImode
, 0));
8471 if (last_bytes
!= 0)
8473 emit_insn (gen_addsi3 (dst
, dst
, GEN_INT (4)));
8479 in_words_to_go
-= in_words_to_go
< 4 ? in_words_to_go
: 4;
8480 out_words_to_go
-= out_words_to_go
< 4 ? out_words_to_go
: 4;
8483 /* OUT_WORDS_TO_GO will be zero here if there are byte stores to do. */
8484 if (out_words_to_go
)
8488 mem
= adjust_automodify_address (srcbase
, SImode
, src
, srcoffset
);
8489 sreg
= copy_to_reg (mem
);
8491 mem
= adjust_automodify_address (dstbase
, SImode
, dst
, dstoffset
);
8492 emit_move_insn (mem
, sreg
);
8495 gcc_assert (!in_words_to_go
); /* Sanity check */
8500 gcc_assert (in_words_to_go
> 0);
8502 mem
= adjust_automodify_address (srcbase
, SImode
, src
, srcoffset
);
8503 part_bytes_reg
= copy_to_mode_reg (SImode
, mem
);
8506 gcc_assert (!last_bytes
|| part_bytes_reg
);
8508 if (BYTES_BIG_ENDIAN
&& last_bytes
)
8510 rtx tmp
= gen_reg_rtx (SImode
);
8512 /* The bytes we want are in the top end of the word. */
8513 emit_insn (gen_lshrsi3 (tmp
, part_bytes_reg
,
8514 GEN_INT (8 * (4 - last_bytes
))));
8515 part_bytes_reg
= tmp
;
8519 mem
= adjust_automodify_address (dstbase
, QImode
,
8520 plus_constant (dst
, last_bytes
- 1),
8521 dstoffset
+ last_bytes
- 1);
8522 emit_move_insn (mem
, gen_lowpart (QImode
, part_bytes_reg
));
8526 tmp
= gen_reg_rtx (SImode
);
8527 emit_insn (gen_lshrsi3 (tmp
, part_bytes_reg
, GEN_INT (8)));
8528 part_bytes_reg
= tmp
;
8537 mem
= adjust_automodify_address (dstbase
, HImode
, dst
, dstoffset
);
8538 emit_move_insn (mem
, gen_lowpart (HImode
, part_bytes_reg
));
8542 rtx tmp
= gen_reg_rtx (SImode
);
8543 emit_insn (gen_addsi3 (dst
, dst
, const2_rtx
));
8544 emit_insn (gen_lshrsi3 (tmp
, part_bytes_reg
, GEN_INT (16)));
8545 part_bytes_reg
= tmp
;
8552 mem
= adjust_automodify_address (dstbase
, QImode
, dst
, dstoffset
);
8553 emit_move_insn (mem
, gen_lowpart (QImode
, part_bytes_reg
));
8560 /* Select a dominance comparison mode if possible for a test of the general
8561 form (OP (COND_OR (X) (Y)) (const_int 0)). We support three forms.
8562 COND_OR == DOM_CC_X_AND_Y => (X && Y)
8563 COND_OR == DOM_CC_NX_OR_Y => ((! X) || Y)
8564 COND_OR == DOM_CC_X_OR_Y => (X || Y)
8565 In all cases OP will be either EQ or NE, but we don't need to know which
8566 here. If we are unable to support a dominance comparison we return
8567 CC mode. This will then fail to match for the RTL expressions that
8568 generate this call. */
8570 arm_select_dominance_cc_mode (rtx x
, rtx y
, HOST_WIDE_INT cond_or
)
8572 enum rtx_code cond1
, cond2
;
8575 /* Currently we will probably get the wrong result if the individual
8576 comparisons are not simple. This also ensures that it is safe to
8577 reverse a comparison if necessary. */
8578 if ((arm_select_cc_mode (cond1
= GET_CODE (x
), XEXP (x
, 0), XEXP (x
, 1))
8580 || (arm_select_cc_mode (cond2
= GET_CODE (y
), XEXP (y
, 0), XEXP (y
, 1))
8584 /* The if_then_else variant of this tests the second condition if the
8585 first passes, but is true if the first fails. Reverse the first
8586 condition to get a true "inclusive-or" expression. */
8587 if (cond_or
== DOM_CC_NX_OR_Y
)
8588 cond1
= reverse_condition (cond1
);
8590 /* If the comparisons are not equal, and one doesn't dominate the other,
8591 then we can't do this. */
8593 && !comparison_dominates_p (cond1
, cond2
)
8594 && (swapped
= 1, !comparison_dominates_p (cond2
, cond1
)))
8599 enum rtx_code temp
= cond1
;
8607 if (cond_or
== DOM_CC_X_AND_Y
)
8612 case EQ
: return CC_DEQmode
;
8613 case LE
: return CC_DLEmode
;
8614 case LEU
: return CC_DLEUmode
;
8615 case GE
: return CC_DGEmode
;
8616 case GEU
: return CC_DGEUmode
;
8617 default: gcc_unreachable ();
8621 if (cond_or
== DOM_CC_X_AND_Y
)
8637 if (cond_or
== DOM_CC_X_AND_Y
)
8653 if (cond_or
== DOM_CC_X_AND_Y
)
8669 if (cond_or
== DOM_CC_X_AND_Y
)
8684 /* The remaining cases only occur when both comparisons are the
8687 gcc_assert (cond1
== cond2
);
8691 gcc_assert (cond1
== cond2
);
8695 gcc_assert (cond1
== cond2
);
8699 gcc_assert (cond1
== cond2
);
8703 gcc_assert (cond1
== cond2
);
8712 arm_select_cc_mode (enum rtx_code op
, rtx x
, rtx y
)
8714 /* All floating point compares return CCFP if it is an equality
8715 comparison, and CCFPE otherwise. */
8716 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
)
8736 if (TARGET_HARD_FLOAT
&& TARGET_MAVERICK
)
8745 /* A compare with a shifted operand. Because of canonicalization, the
8746 comparison will have to be swapped when we emit the assembler. */
8747 if (GET_MODE (y
) == SImode
&& GET_CODE (y
) == REG
8748 && (GET_CODE (x
) == ASHIFT
|| GET_CODE (x
) == ASHIFTRT
8749 || GET_CODE (x
) == LSHIFTRT
|| GET_CODE (x
) == ROTATE
8750 || GET_CODE (x
) == ROTATERT
))
8753 /* This operation is performed swapped, but since we only rely on the Z
8754 flag we don't need an additional mode. */
8755 if (GET_MODE (y
) == SImode
&& REG_P (y
)
8756 && GET_CODE (x
) == NEG
8757 && (op
== EQ
|| op
== NE
))
8760 /* This is a special case that is used by combine to allow a
8761 comparison of a shifted byte load to be split into a zero-extend
8762 followed by a comparison of the shifted integer (only valid for
8763 equalities and unsigned inequalities). */
8764 if (GET_MODE (x
) == SImode
8765 && GET_CODE (x
) == ASHIFT
8766 && GET_CODE (XEXP (x
, 1)) == CONST_INT
&& INTVAL (XEXP (x
, 1)) == 24
8767 && GET_CODE (XEXP (x
, 0)) == SUBREG
8768 && GET_CODE (SUBREG_REG (XEXP (x
, 0))) == MEM
8769 && GET_MODE (SUBREG_REG (XEXP (x
, 0))) == QImode
8770 && (op
== EQ
|| op
== NE
8771 || op
== GEU
|| op
== GTU
|| op
== LTU
|| op
== LEU
)
8772 && GET_CODE (y
) == CONST_INT
)
8775 /* A construct for a conditional compare, if the false arm contains
8776 0, then both conditions must be true, otherwise either condition
8777 must be true. Not all conditions are possible, so CCmode is
8778 returned if it can't be done. */
8779 if (GET_CODE (x
) == IF_THEN_ELSE
8780 && (XEXP (x
, 2) == const0_rtx
8781 || XEXP (x
, 2) == const1_rtx
)
8782 && COMPARISON_P (XEXP (x
, 0))
8783 && COMPARISON_P (XEXP (x
, 1)))
8784 return arm_select_dominance_cc_mode (XEXP (x
, 0), XEXP (x
, 1),
8785 INTVAL (XEXP (x
, 2)));
8787 /* Alternate canonicalizations of the above. These are somewhat cleaner. */
8788 if (GET_CODE (x
) == AND
8789 && COMPARISON_P (XEXP (x
, 0))
8790 && COMPARISON_P (XEXP (x
, 1)))
8791 return arm_select_dominance_cc_mode (XEXP (x
, 0), XEXP (x
, 1),
8794 if (GET_CODE (x
) == IOR
8795 && COMPARISON_P (XEXP (x
, 0))
8796 && COMPARISON_P (XEXP (x
, 1)))
8797 return arm_select_dominance_cc_mode (XEXP (x
, 0), XEXP (x
, 1),
8800 /* An operation (on Thumb) where we want to test for a single bit.
8801 This is done by shifting that bit up into the top bit of a
8802 scratch register; we can then branch on the sign bit. */
8803 /* APPLE LOCAL v7 support. Merge from mainline */
8805 && GET_MODE (x
) == SImode
8806 && (op
== EQ
|| op
== NE
)
8807 && GET_CODE (x
) == ZERO_EXTRACT
8808 && XEXP (x
, 1) == const1_rtx
)
8811 /* An operation that sets the condition codes as a side-effect, the
8812 V flag is not set correctly, so we can only use comparisons where
8813 this doesn't matter. (For LT and GE we can use "mi" and "pl"
8815 /* APPLE LOCAL v7 support. Merge from mainline */
8816 /* ??? Does the ZERO_EXTRACT case really apply to thumb2? */
8817 if (GET_MODE (x
) == SImode
8819 && (op
== EQ
|| op
== NE
|| op
== LT
|| op
== GE
)
8820 && (GET_CODE (x
) == PLUS
|| GET_CODE (x
) == MINUS
8821 || GET_CODE (x
) == AND
|| GET_CODE (x
) == IOR
8822 || GET_CODE (x
) == XOR
|| GET_CODE (x
) == MULT
8823 || GET_CODE (x
) == NOT
|| GET_CODE (x
) == NEG
8824 || GET_CODE (x
) == LSHIFTRT
8825 || GET_CODE (x
) == ASHIFT
|| GET_CODE (x
) == ASHIFTRT
8826 || GET_CODE (x
) == ROTATERT
8827 /* APPLE LOCAL v7 support. Merge from mainline */
8828 || (TARGET_32BIT
&& GET_CODE (x
) == ZERO_EXTRACT
)))
8831 if (GET_MODE (x
) == QImode
&& (op
== EQ
|| op
== NE
))
8834 if (GET_MODE (x
) == SImode
&& (op
== LTU
|| op
== GEU
)
8835 && GET_CODE (x
) == PLUS
8836 && (rtx_equal_p (XEXP (x
, 0), y
) || rtx_equal_p (XEXP (x
, 1), y
)))
8842 /* X and Y are two things to compare using CODE. Emit the compare insn and
8843 return the rtx for register 0 in the proper mode. FP means this is a
8844 floating point compare: I don't think that it is needed on the arm. */
8846 arm_gen_compare_reg (enum rtx_code code
, rtx x
, rtx y
)
8848 enum machine_mode mode
= SELECT_CC_MODE (code
, x
, y
);
8849 rtx cc_reg
= gen_rtx_REG (mode
, CC_REGNUM
);
8851 emit_set_insn (cc_reg
, gen_rtx_COMPARE (mode
, x
, y
));
8856 /* Generate a sequence of insns that will generate the correct return
8857 address mask depending on the physical architecture that the program
8860 arm_gen_return_addr_mask (void)
8862 rtx reg
= gen_reg_rtx (Pmode
);
8864 emit_insn (gen_return_addr_mask (reg
));
8869 arm_reload_in_hi (rtx
*operands
)
8871 rtx ref
= operands
[1];
8873 HOST_WIDE_INT offset
= 0;
8875 if (GET_CODE (ref
) == SUBREG
)
8877 offset
= SUBREG_BYTE (ref
);
8878 ref
= SUBREG_REG (ref
);
8881 if (GET_CODE (ref
) == REG
)
8883 /* We have a pseudo which has been spilt onto the stack; there
8884 are two cases here: the first where there is a simple
8885 stack-slot replacement and a second where the stack-slot is
8886 out of range, or is used as a subreg. */
8887 if (reg_equiv_mem
[REGNO (ref
)])
8889 ref
= reg_equiv_mem
[REGNO (ref
)];
8890 base
= find_replacement (&XEXP (ref
, 0));
8893 /* The slot is out of range, or was dressed up in a SUBREG. */
8894 base
= reg_equiv_address
[REGNO (ref
)];
8897 base
= find_replacement (&XEXP (ref
, 0));
8899 /* Handle the case where the address is too complex to be offset by 1. */
8900 if (GET_CODE (base
) == MINUS
8901 || (GET_CODE (base
) == PLUS
&& GET_CODE (XEXP (base
, 1)) != CONST_INT
))
8903 rtx base_plus
= gen_rtx_REG (SImode
, REGNO (operands
[2]) + 1);
8905 emit_set_insn (base_plus
, base
);
8908 else if (GET_CODE (base
) == PLUS
)
8910 /* The addend must be CONST_INT, or we would have dealt with it above. */
8911 HOST_WIDE_INT hi
, lo
;
8913 offset
+= INTVAL (XEXP (base
, 1));
8914 base
= XEXP (base
, 0);
8916 /* Rework the address into a legal sequence of insns. */
8917 /* Valid range for lo is -4095 -> 4095 */
8920 : -((-offset
) & 0xfff));
8922 /* Corner case, if lo is the max offset then we would be out of range
8923 once we have added the additional 1 below, so bump the msb into the
8924 pre-loading insn(s). */
8928 hi
= ((((offset
- lo
) & (HOST_WIDE_INT
) 0xffffffff)
8929 ^ (HOST_WIDE_INT
) 0x80000000)
8930 - (HOST_WIDE_INT
) 0x80000000);
8932 gcc_assert (hi
+ lo
== offset
);
8936 rtx base_plus
= gen_rtx_REG (SImode
, REGNO (operands
[2]) + 1);
8938 /* Get the base address; addsi3 knows how to handle constants
8939 that require more than one insn. */
8940 emit_insn (gen_addsi3 (base_plus
, base
, GEN_INT (hi
)));
8946 /* Operands[2] may overlap operands[0] (though it won't overlap
8947 operands[1]), that's why we asked for a DImode reg -- so we can
8948 use the bit that does not overlap. */
8949 if (REGNO (operands
[2]) == REGNO (operands
[0]))
8950 scratch
= gen_rtx_REG (SImode
, REGNO (operands
[2]) + 1);
8952 scratch
= gen_rtx_REG (SImode
, REGNO (operands
[2]));
8954 emit_insn (gen_zero_extendqisi2 (scratch
,
8955 gen_rtx_MEM (QImode
,
8956 plus_constant (base
,
8958 emit_insn (gen_zero_extendqisi2 (gen_rtx_SUBREG (SImode
, operands
[0], 0),
8959 gen_rtx_MEM (QImode
,
8960 plus_constant (base
,
8962 if (!BYTES_BIG_ENDIAN
)
8963 emit_set_insn (gen_rtx_SUBREG (SImode
, operands
[0], 0),
8964 gen_rtx_IOR (SImode
,
8967 gen_rtx_SUBREG (SImode
, operands
[0], 0),
8971 emit_set_insn (gen_rtx_SUBREG (SImode
, operands
[0], 0),
8972 gen_rtx_IOR (SImode
,
8973 gen_rtx_ASHIFT (SImode
, scratch
,
8975 gen_rtx_SUBREG (SImode
, operands
[0], 0)));
8978 /* Handle storing a half-word to memory during reload by synthesizing as two
8979 byte stores. Take care not to clobber the input values until after we
8980 have moved them somewhere safe. This code assumes that if the DImode
8981 scratch in operands[2] overlaps either the input value or output address
8982 in some way, then that value must die in this insn (we absolutely need
8983 two scratch registers for some corner cases). */
8985 arm_reload_out_hi (rtx
*operands
)
8987 rtx ref
= operands
[0];
8988 rtx outval
= operands
[1];
8990 HOST_WIDE_INT offset
= 0;
8992 if (GET_CODE (ref
) == SUBREG
)
8994 offset
= SUBREG_BYTE (ref
);
8995 ref
= SUBREG_REG (ref
);
8998 if (GET_CODE (ref
) == REG
)
9000 /* We have a pseudo which has been spilt onto the stack; there
9001 are two cases here: the first where there is a simple
9002 stack-slot replacement and a second where the stack-slot is
9003 out of range, or is used as a subreg. */
9004 if (reg_equiv_mem
[REGNO (ref
)])
9006 ref
= reg_equiv_mem
[REGNO (ref
)];
9007 base
= find_replacement (&XEXP (ref
, 0));
9010 /* The slot is out of range, or was dressed up in a SUBREG. */
9011 base
= reg_equiv_address
[REGNO (ref
)];
9014 base
= find_replacement (&XEXP (ref
, 0));
9016 scratch
= gen_rtx_REG (SImode
, REGNO (operands
[2]));
9018 /* Handle the case where the address is too complex to be offset by 1. */
9019 if (GET_CODE (base
) == MINUS
9020 || (GET_CODE (base
) == PLUS
&& GET_CODE (XEXP (base
, 1)) != CONST_INT
))
9022 rtx base_plus
= gen_rtx_REG (SImode
, REGNO (operands
[2]) + 1);
9024 /* Be careful not to destroy OUTVAL. */
9025 if (reg_overlap_mentioned_p (base_plus
, outval
))
9027 /* Updating base_plus might destroy outval, see if we can
9028 swap the scratch and base_plus. */
9029 if (!reg_overlap_mentioned_p (scratch
, outval
))
9032 scratch
= base_plus
;
9037 rtx scratch_hi
= gen_rtx_REG (HImode
, REGNO (operands
[2]));
9039 /* Be conservative and copy OUTVAL into the scratch now,
9040 this should only be necessary if outval is a subreg
9041 of something larger than a word. */
9042 /* XXX Might this clobber base? I can't see how it can,
9043 since scratch is known to overlap with OUTVAL, and
9044 must be wider than a word. */
9045 emit_insn (gen_movhi (scratch_hi
, outval
));
9046 outval
= scratch_hi
;
9050 emit_set_insn (base_plus
, base
);
9053 else if (GET_CODE (base
) == PLUS
)
9055 /* The addend must be CONST_INT, or we would have dealt with it above. */
9056 HOST_WIDE_INT hi
, lo
;
9058 offset
+= INTVAL (XEXP (base
, 1));
9059 base
= XEXP (base
, 0);
9061 /* Rework the address into a legal sequence of insns. */
9062 /* Valid range for lo is -4095 -> 4095 */
9065 : -((-offset
) & 0xfff));
9067 /* Corner case, if lo is the max offset then we would be out of range
9068 once we have added the additional 1 below, so bump the msb into the
9069 pre-loading insn(s). */
9073 hi
= ((((offset
- lo
) & (HOST_WIDE_INT
) 0xffffffff)
9074 ^ (HOST_WIDE_INT
) 0x80000000)
9075 - (HOST_WIDE_INT
) 0x80000000);
9077 gcc_assert (hi
+ lo
== offset
);
9081 rtx base_plus
= gen_rtx_REG (SImode
, REGNO (operands
[2]) + 1);
9083 /* Be careful not to destroy OUTVAL. */
9084 if (reg_overlap_mentioned_p (base_plus
, outval
))
9086 /* Updating base_plus might destroy outval, see if we
9087 can swap the scratch and base_plus. */
9088 if (!reg_overlap_mentioned_p (scratch
, outval
))
9091 scratch
= base_plus
;
9096 rtx scratch_hi
= gen_rtx_REG (HImode
, REGNO (operands
[2]));
9098 /* Be conservative and copy outval into scratch now,
9099 this should only be necessary if outval is a
9100 subreg of something larger than a word. */
9101 /* XXX Might this clobber base? I can't see how it
9102 can, since scratch is known to overlap with
9104 emit_insn (gen_movhi (scratch_hi
, outval
));
9105 outval
= scratch_hi
;
9109 /* Get the base address; addsi3 knows how to handle constants
9110 that require more than one insn. */
9111 emit_insn (gen_addsi3 (base_plus
, base
, GEN_INT (hi
)));
9117 if (BYTES_BIG_ENDIAN
)
9119 emit_insn (gen_movqi (gen_rtx_MEM (QImode
,
9120 plus_constant (base
, offset
+ 1)),
9121 gen_lowpart (QImode
, outval
)));
9122 emit_insn (gen_lshrsi3 (scratch
,
9123 gen_rtx_SUBREG (SImode
, outval
, 0),
9125 emit_insn (gen_movqi (gen_rtx_MEM (QImode
, plus_constant (base
, offset
)),
9126 gen_lowpart (QImode
, scratch
)));
9130 emit_insn (gen_movqi (gen_rtx_MEM (QImode
, plus_constant (base
, offset
)),
9131 gen_lowpart (QImode
, outval
)));
9132 emit_insn (gen_lshrsi3 (scratch
,
9133 gen_rtx_SUBREG (SImode
, outval
, 0),
9135 emit_insn (gen_movqi (gen_rtx_MEM (QImode
,
9136 plus_constant (base
, offset
+ 1)),
9137 gen_lowpart (QImode
, scratch
)));
9141 /* Return true if a type must be passed in memory. For AAPCS, small aggregates
9142 (padded to the size of a word) should be passed in a register. */
9145 arm_must_pass_in_stack (enum machine_mode mode
, tree type
)
9147 if (TARGET_AAPCS_BASED
)
9148 return must_pass_in_stack_var_size (mode
, type
);
9150 return must_pass_in_stack_var_size_or_pad (mode
, type
);
9154 /* For use by FUNCTION_ARG_PADDING (MODE, TYPE).
9155 Return true if an argument passed on the stack should be padded upwards,
9156 i.e. if the least-significant byte has useful data.
9157 For legacy APCS ABIs we use the default. For AAPCS based ABIs small
9158 aggregate types are placed in the lowest memory address. */
9161 arm_pad_arg_upward (enum machine_mode mode
, tree type
)
9163 if (!TARGET_AAPCS_BASED
)
9164 return DEFAULT_FUNCTION_ARG_PADDING(mode
, type
) == upward
;
9166 if (type
&& BYTES_BIG_ENDIAN
&& INTEGRAL_TYPE_P (type
))
9173 /* Similarly, for use by BLOCK_REG_PADDING (MODE, TYPE, FIRST).
9174 For non-AAPCS, return !BYTES_BIG_ENDIAN if the least significant
9175 byte of the register has useful data, and return the opposite if the
9176 most significant byte does.
9177 For AAPCS, small aggregates and small complex types are always padded
9181 arm_pad_reg_upward (enum machine_mode mode ATTRIBUTE_UNUSED
,
9182 tree type
, int first ATTRIBUTE_UNUSED
)
9184 if (TARGET_AAPCS_BASED
9186 && (AGGREGATE_TYPE_P (type
) || TREE_CODE (type
) == COMPLEX_TYPE
)
9187 && int_size_in_bytes (type
) <= 4)
9190 /* Otherwise, use default padding. */
9191 return !BYTES_BIG_ENDIAN
;
9195 /* Print a symbolic form of X to the debug file, F. */
9197 arm_print_value (FILE *f
, rtx x
)
9199 switch (GET_CODE (x
))
9202 fprintf (f
, HOST_WIDE_INT_PRINT_HEX
, INTVAL (x
));
9206 fprintf (f
, "<0x%lx,0x%lx>", (long)XWINT (x
, 2), (long)XWINT (x
, 3));
9214 for (i
= 0; i
< CONST_VECTOR_NUNITS (x
); i
++)
9216 fprintf (f
, HOST_WIDE_INT_PRINT_HEX
, INTVAL (CONST_VECTOR_ELT (x
, i
)));
9217 if (i
< (CONST_VECTOR_NUNITS (x
) - 1))
9225 fprintf (f
, "\"%s\"", XSTR (x
, 0));
9229 fprintf (f
, "`%s'", XSTR (x
, 0));
9233 fprintf (f
, "L%d", INSN_UID (XEXP (x
, 0)));
9237 arm_print_value (f
, XEXP (x
, 0));
9241 arm_print_value (f
, XEXP (x
, 0));
9243 arm_print_value (f
, XEXP (x
, 1));
9251 fprintf (f
, "????");
9256 /* Routines for manipulation of the constant pool. */
9258 /* Arm instructions cannot load a large constant directly into a
9259 register; they have to come from a pc relative load. The constant
9260 must therefore be placed in the addressable range of the pc
9261 relative load. Depending on the precise pc relative load
9262 instruction the range is somewhere between 256 bytes and 4k. This
9263 means that we often have to dump a constant inside a function, and
9264 generate code to branch around it.
9266 It is important to minimize this, since the branches will slow
9267 things down and make the code larger.
9269 Normally we can hide the table after an existing unconditional
9270 branch so that there is no interruption of the flow, but in the
9271 worst case the code looks like this:
9289 We fix this by performing a scan after scheduling, which notices
9290 which instructions need to have their operands fetched from the
9291 constant table and builds the table.
9293 The algorithm starts by building a table of all the constants that
9294 need fixing up and all the natural barriers in the function (places
9295 where a constant table can be dropped without breaking the flow).
9296 For each fixup we note how far the pc-relative replacement will be
9297 able to reach and the offset of the instruction into the function.
9299 Having built the table we then group the fixes together to form
9300 tables that are as large as possible (subject to addressing
9301 constraints) and emit each table of constants after the last
9302 barrier that is within range of all the instructions in the group.
9303 If a group does not contain a barrier, then we forcibly create one
9304 by inserting a jump instruction into the flow. Once the table has
9305 been inserted, the insns are then modified to reference the
9306 relevant entry in the pool.
9308 Possible enhancements to the algorithm (not implemented) are:
9310 1) For some processors and object formats, there may be benefit in
9311 aligning the pools to the start of cache lines; this alignment
9312 would need to be taken into account when calculating addressability
9315 /* These typedefs are located at the start of this file, so that
9316 they can be used in the prototypes there. This comment is to
9317 remind readers of that fact so that the following structures
9318 can be understood more easily.
9320 typedef struct minipool_node Mnode;
9321 typedef struct minipool_fixup Mfix; */
9323 struct minipool_node
9325 /* Doubly linked chain of entries. */
9328 /* The maximum offset into the code that this entry can be placed. While
9329 pushing fixes for forward references, all entries are sorted in order
9330 of increasing max_address. */
9331 HOST_WIDE_INT max_address
;
9332 /* Similarly for an entry inserted for a backwards ref. */
9333 HOST_WIDE_INT min_address
;
9334 /* The number of fixes referencing this entry. This can become zero
9335 if we "unpush" an entry. In this case we ignore the entry when we
9336 come to emit the code. */
9338 /* The offset from the start of the minipool. */
9339 HOST_WIDE_INT offset
;
9340 /* The value in table. */
9342 /* The mode of value. */
9343 enum machine_mode mode
;
9344 /* The size of the value. With iWMMXt enabled
9345 sizes > 4 also imply an alignment of 8-bytes. */
9349 struct minipool_fixup
9353 HOST_WIDE_INT address
;
9355 enum machine_mode mode
;
9359 HOST_WIDE_INT forwards
;
9360 HOST_WIDE_INT backwards
;
9363 /* Fixes less than a word need padding out to a word boundary. */
9364 #define MINIPOOL_FIX_SIZE(mode) \
9365 (GET_MODE_SIZE ((mode)) >= 4 ? GET_MODE_SIZE ((mode)) : 4)
9367 /* APPLE LOCAL begin ARM 4790140 compact switch tables */
9368 /* The miniLisp in attributes doesn't seem to be up to extracting
9369 a numeric datum from the argument; do it in code. */
9371 arm_adjust_insn_length (rtx insn
, int *length
)
9373 rtx body
= PATTERN (insn
);
9374 /* APPLE LOCAL begin v7 support. Merge from mainline */
9376 /* Add two bytes to the length of conditionally executed Thumb-2
9377 instructions for the IT instruction. */
9378 if (TARGET_THUMB2
&& GET_CODE (PATTERN (insn
)) == COND_EXEC
)
9384 /* APPLE LOCAL end v7 support. Merge from mainline */
9385 if (GET_CODE (body
) == UNSPEC_VOLATILE
9386 /* APPLE LOCAL 7083296 Build without warnings. */
9387 && XINT (body
, 1) == VUNSPEC_POOL_STRING
)
9389 int len
= TREE_STRING_LENGTH (SYMBOL_REF_DECL
9390 (XVECEXP (body
, 0, 0)));
9391 len
= (len
+ 3) & ~3;
9394 if (!TARGET_THUMB2
&& GET_CODE (body
) == ADDR_DIFF_VEC
)
9396 /* The obvious sizeof(elt)*nelts, plus sizeof(elt) for the
9398 int len
= (XVECLEN (body
, 1) + 1) * GET_MODE_SIZE (GET_MODE (body
));
9399 int insn_size
= (TARGET_THUMB
) ? 2 : 4;
9401 /* 32-bit thumb tables can have one halfword of padding.
9402 If we knew the alignment + offset now, we could be correct
9403 about this calculation. Instead, we have to be
9406 && GET_MODE_SIZE (GET_MODE (body
)) == 4)
9409 /* Round up to a multiple of instruction size. */
9410 len
= ((len
+ insn_size
- 1) / insn_size
) * insn_size
;
9414 /* APPLE LOCAL 6279481 */
9416 && GET_CODE (body
) == UNSPEC_VOLATILE
9417 /* APPLE LOCAL 7083296 Build without warnings. */
9418 && XINT (body
, 1) == VUNSPEC_EPILOGUE
)
9420 *length
= handle_thumb_unexpanded_epilogue (false);
9422 /* APPLE LOCAL begin v7 support. Merge from mainline */
9423 if (INSN_CODE (insn
) == CODE_FOR_adjustable_thumb1_zero_extendhisi2
9424 || INSN_CODE (insn
) == CODE_FOR_adjustable_thumb1_zero_extendhisi2_v6
)
9425 /* APPLE LOCAL end v7 support. Merge from mainline */
9427 rtx mem
= XEXP (XEXP (body
, 1), 0);
9428 if (GET_CODE (mem
) == REG
|| GET_CODE (mem
) == SUBREG
)
9432 gcc_assert (GET_CODE (mem
) == MEM
);
9433 mem
= XEXP (mem
, 0);
9434 if (GET_CODE (mem
) == CONST
)
9435 mem
= XEXP (mem
, 0);
9436 if (GET_CODE (mem
) == PLUS
9437 && GET_CODE (XEXP (mem
, 0)) == REG
9438 && REGNO (XEXP (mem
, 0)) == SP_REGNUM
)
9444 /* APPLE LOCAL begin v7 support. Merge from mainline */
9445 if (INSN_CODE (insn
) == CODE_FOR_thumb1_extendhisi2
9446 || INSN_CODE (insn
) == CODE_FOR_adjustable_thumb1_extendhisi2_insn_v6
)
9447 /* APPLE LOCAL end v7 support. Merge from mainline */
9449 rtx mem
= XEXP (XEXP (XVECEXP (body
, 0, 0), 1), 0);
9450 if (GET_CODE (mem
) == REG
|| GET_CODE (mem
) == SUBREG
)
9454 gcc_assert (GET_CODE (mem
) == MEM
);
9455 mem
= XEXP (mem
, 0);
9456 if (GET_CODE (mem
) == CONST
)
9457 mem
= XEXP (mem
, 0);
9459 if (GET_CODE (mem
) == LABEL_REF
)
9461 if (GET_CODE (mem
) == PLUS
)
9463 if (GET_CODE (XEXP (mem
, 0)) == LABEL_REF
9464 && GET_CODE (XEXP (mem
, 1)) == CONST_INT
)
9466 if (GET_CODE (XEXP (mem
, 1)) == REG
)
9471 /* APPLE LOCAL v7 support. Merge from mainline */
9472 if (INSN_CODE (insn
) == CODE_FOR_adjustable_thumb1_extendqisi2
)
9474 rtx mem
= XEXP (XEXP (body
, 1), 0);
9475 if (GET_CODE (mem
) == REG
|| GET_CODE (mem
) == SUBREG
)
9479 gcc_assert (GET_CODE (mem
) == MEM
);
9480 mem
= XEXP (mem
, 0);
9481 if (GET_CODE (mem
) == CONST
)
9482 mem
= XEXP (mem
, 0);
9483 if (GET_CODE (mem
) == LABEL_REF
)
9485 else if (GET_CODE (mem
) == PLUS
9486 && GET_CODE (XEXP (mem
, 0)) == LABEL_REF
)
9488 /* The "operand matches V constraint" case is not handled explicitly;
9489 this can only generate valid code if the address is REG + REG,
9490 so assume this is the case and let the code below handle it. */
9491 else if (GET_CODE (mem
) == PLUS
)
9493 if (GET_CODE (XEXP (mem
, 0)) == REG
)
9495 if (GET_CODE (XEXP (mem
, 1)) == REG
)
9497 else if (REGNO (XEXP (mem
, 0)) == REGNO (XEXP (body
, 0)))
9504 gcc_assert (GET_CODE (XEXP (mem
, 1)) == REG
);
9505 if (REGNO (XEXP (mem
, 1)) == REGNO (XEXP (body
, 0)))
9511 else if (GET_CODE (mem
) == REG
&& REGNO (XEXP (body
, 0)) == REGNO (mem
))
9517 /* APPLE LOCAL v7 support. Merge from mainline */
9518 if (INSN_CODE (insn
) == CODE_FOR_adjustable_thumb1_extendqisi2_v6
)
9520 rtx mem
= XEXP (XEXP (body
, 1), 0);
9521 if (GET_CODE (mem
) == REG
|| GET_CODE (mem
) == SUBREG
)
9525 gcc_assert (GET_CODE (mem
) == MEM
);
9526 mem
= XEXP (mem
, 0);
9527 if (GET_CODE (mem
) == CONST
)
9528 mem
= XEXP (mem
, 0);
9529 if (GET_CODE (mem
) == LABEL_REF
)
9531 else if (GET_CODE (mem
) == PLUS
9532 && GET_CODE (XEXP (mem
, 0)) == LABEL_REF
)
9534 /* The "operand matches V constraint" case is not handled explicitly;
9535 this can only generate valid code if the address is REG + REG,
9536 so assume this is the case and let the code below handle it. */
9537 else if (GET_CODE (mem
) == PLUS
)
9539 if (GET_CODE (XEXP (mem
, 0)) == REG
)
9541 if (GET_CODE (XEXP (mem
, 1)) == REG
)
9543 else if (REGNO (XEXP (mem
, 0)) == REGNO (XEXP (body
, 0)))
9550 gcc_assert (GET_CODE (XEXP (mem
, 1)) == REG
);
9551 if (REGNO (XEXP (mem
, 1)) == REGNO (XEXP (body
, 0)))
9557 else if (GET_CODE (mem
) == REG
&& REGNO (XEXP (body
, 0)) == REGNO (mem
))
9563 /* APPLE LOCAL v7 support. Merge from mainline */
9564 if (INSN_CODE (insn
) == CODE_FOR_adjustable_thumb1_movhi_insn
)
9566 rtx mem
= XEXP (body
, 1);
9567 if (GET_CODE (mem
) != MEM
)
9569 else if (GET_CODE (XEXP (mem
, 0)) == PLUS
9570 && GET_CODE (XEXP (XEXP (mem
, 0), 0)) == REG
9571 && REGNO (XEXP (XEXP (mem
, 0), 0)) == SP_REGNUM
)
9576 /* APPLE LOCAL v7 support. Merge from mainline */
9577 if (INSN_CODE (insn
) == CODE_FOR_adjustable_thumb1_movdi_insn
)
9579 rtx op0
= XEXP (body
, 0);
9580 rtx op1
= XEXP (body
, 1);
9583 if (GET_CODE (op0
) == MEM
&&
9584 (GET_CODE (XEXP (op0
, 0)) == PRE_INC
9585 || GET_CODE (XEXP (op0
, 0)) == POST_INC
))
9588 else if (GET_CODE (op1
) == MEM
&&
9589 (GET_CODE (XEXP (op1
, 0)) == PRE_INC
9590 || GET_CODE (XEXP (op1
, 0)) == POST_INC
))
9593 else if (GET_CODE (op1
) == CONST_INT
9594 && !const_ok_for_arm (INTVAL (op1
))
9595 && INTVAL (op1
) >= -4095
9596 && INTVAL (op1
) <= 4095
9597 && thumb_low_register_operand (op0
, GET_MODE (op0
)))
9599 /* case 0, 1, 6, 7 */
9600 else if (GET_CODE (op1
) != MEM
)
9605 rtx addr
= XEXP (op1
, 0);
9606 if (GET_CODE (addr
) == REG
)
9608 else if (GET_CODE (addr
) == CONST
)
9610 else if (GET_CODE (addr
) == PLUS
)
9612 rtx base
= XEXP (addr
, 0);
9613 rtx offset
= XEXP (addr
, 1);
9614 if (CONSTANT_P (base
))
9620 if (GET_CODE (offset
) == REG
)
9625 else if (GET_CODE (addr
) == LABEL_REF
)
9632 /* APPLE LOCAL end ARM 4790140 compact switch tables */
9637 static Mnode
* minipool_vector_head
;
9638 static Mnode
* minipool_vector_tail
;
9639 static rtx minipool_vector_label
;
9640 static int minipool_pad
;
9642 /* The linked list of all minipool fixes required for this function. */
9643 Mfix
* minipool_fix_head
;
9644 Mfix
* minipool_fix_tail
;
9645 /* The fix entry for the current minipool, once it has been placed. */
9646 Mfix
* minipool_barrier
;
9648 /* Determines if INSN is the start of a jump table. Returns the end
9649 of the TABLE or NULL_RTX. */
9651 is_jump_table (rtx insn
)
9655 if (GET_CODE (insn
) == JUMP_INSN
9656 && JUMP_LABEL (insn
) != NULL
9657 && ((table
= next_real_insn (JUMP_LABEL (insn
)))
9658 == next_real_insn (insn
))
9660 && GET_CODE (table
) == JUMP_INSN
9661 && (GET_CODE (PATTERN (table
)) == ADDR_VEC
9662 || GET_CODE (PATTERN (table
)) == ADDR_DIFF_VEC
))
9668 #ifndef JUMP_TABLES_IN_TEXT_SECTION
9669 #define JUMP_TABLES_IN_TEXT_SECTION 0
9672 static HOST_WIDE_INT
9673 get_jump_table_size (rtx insn
)
9675 /* ADDR_VECs only take room if read-only data does into the text
9677 if (JUMP_TABLES_IN_TEXT_SECTION
|| readonly_data_section
== text_section
)
9679 rtx body
= PATTERN (insn
);
9680 int elt
= GET_CODE (body
) == ADDR_DIFF_VEC
? 1 : 0;
9681 /* APPLE LOCAL begin v7 support. Merge from mainline */
9683 HOST_WIDE_INT modesize
;
9685 modesize
= GET_MODE_SIZE (GET_MODE (body
));
9686 size
= modesize
* XVECLEN (body
, elt
);
9690 /* Round up size of TBB table to a hafword boundary. */
9691 size
= (size
+ 1) & ~(HOST_WIDE_INT
)1;
9694 /* No padding neccessary for TBH. */
9697 /* Add two bytes for alignment on Thumb. */
9705 /* APPLE LOCAL end v7 support. Merge from mainline */
9711 /* Move a minipool fix MP from its current location to before MAX_MP.
9712 If MAX_MP is NULL, then MP doesn't need moving, but the addressing
9713 constraints may need updating. */
9715 move_minipool_fix_forward_ref (Mnode
*mp
, Mnode
*max_mp
,
9716 HOST_WIDE_INT max_address
)
9718 /* The code below assumes these are different. */
9719 gcc_assert (mp
!= max_mp
);
9723 if (max_address
< mp
->max_address
)
9724 mp
->max_address
= max_address
;
9728 if (max_address
> max_mp
->max_address
- mp
->fix_size
)
9729 mp
->max_address
= max_mp
->max_address
- mp
->fix_size
;
9731 mp
->max_address
= max_address
;
9733 /* Unlink MP from its current position. Since max_mp is non-null,
9734 mp->prev must be non-null. */
9735 mp
->prev
->next
= mp
->next
;
9736 if (mp
->next
!= NULL
)
9737 mp
->next
->prev
= mp
->prev
;
9739 minipool_vector_tail
= mp
->prev
;
9741 /* Re-insert it before MAX_MP. */
9743 mp
->prev
= max_mp
->prev
;
9746 if (mp
->prev
!= NULL
)
9747 mp
->prev
->next
= mp
;
9749 minipool_vector_head
= mp
;
9752 /* Save the new entry. */
9755 /* Scan over the preceding entries and adjust their addresses as
9757 while (mp
->prev
!= NULL
9758 && mp
->prev
->max_address
> mp
->max_address
- mp
->prev
->fix_size
)
9760 mp
->prev
->max_address
= mp
->max_address
- mp
->prev
->fix_size
;
9767 /* Add a constant to the minipool for a forward reference. Returns the
9768 node added or NULL if the constant will not fit in this pool. */
9770 add_minipool_forward_ref (Mfix
*fix
)
9772 /* If set, max_mp is the first pool_entry that has a lower
9773 constraint than the one we are trying to add. */
9774 Mnode
* max_mp
= NULL
;
9775 HOST_WIDE_INT max_address
= fix
->address
+ fix
->forwards
- minipool_pad
;
9778 /* If the minipool starts before the end of FIX->INSN then this FIX
9779 can not be placed into the current pool. Furthermore, adding the
9780 new constant pool entry may cause the pool to start FIX_SIZE bytes
9782 if (minipool_vector_head
&&
9783 (fix
->address
+ get_attr_length (fix
->insn
)
9784 >= minipool_vector_head
->max_address
- fix
->fix_size
))
9787 /* Scan the pool to see if a constant with the same value has
9788 already been added. While we are doing this, also note the
9789 location where we must insert the constant if it doesn't already
9791 for (mp
= minipool_vector_head
; mp
!= NULL
; mp
= mp
->next
)
9793 if (GET_CODE (fix
->value
) == GET_CODE (mp
->value
)
9794 && fix
->mode
== mp
->mode
9795 && (GET_CODE (fix
->value
) != CODE_LABEL
9796 || (CODE_LABEL_NUMBER (fix
->value
)
9797 == CODE_LABEL_NUMBER (mp
->value
)))
9798 && rtx_equal_p (fix
->value
, mp
->value
))
9800 /* More than one fix references this entry. */
9802 return move_minipool_fix_forward_ref (mp
, max_mp
, max_address
);
9805 /* Note the insertion point if necessary. */
9807 && mp
->max_address
> max_address
)
9810 /* If we are inserting an 8-bytes aligned quantity and
9811 we have not already found an insertion point, then
9812 make sure that all such 8-byte aligned quantities are
9813 placed at the start of the pool. */
9814 if (ARM_DOUBLEWORD_ALIGN
9816 && fix
->fix_size
== 8
9817 && mp
->fix_size
!= 8)
9820 max_address
= mp
->max_address
;
9824 /* The value is not currently in the minipool, so we need to create
9825 a new entry for it. If MAX_MP is NULL, the entry will be put on
9826 the end of the list since the placement is less constrained than
9827 any existing entry. Otherwise, we insert the new fix before
9828 MAX_MP and, if necessary, adjust the constraints on the other
9831 mp
->fix_size
= fix
->fix_size
;
9832 mp
->mode
= fix
->mode
;
9833 mp
->value
= fix
->value
;
9835 /* Not yet required for a backwards ref. */
9836 mp
->min_address
= -65536;
9840 mp
->max_address
= max_address
;
9842 mp
->prev
= minipool_vector_tail
;
9844 if (mp
->prev
== NULL
)
9846 minipool_vector_head
= mp
;
9847 minipool_vector_label
= gen_label_rtx ();
9850 mp
->prev
->next
= mp
;
9852 minipool_vector_tail
= mp
;
9856 if (max_address
> max_mp
->max_address
- mp
->fix_size
)
9857 mp
->max_address
= max_mp
->max_address
- mp
->fix_size
;
9859 mp
->max_address
= max_address
;
9862 mp
->prev
= max_mp
->prev
;
9864 if (mp
->prev
!= NULL
)
9865 mp
->prev
->next
= mp
;
9867 minipool_vector_head
= mp
;
9870 /* Save the new entry. */
9873 /* Scan over the preceding entries and adjust their addresses as
9875 while (mp
->prev
!= NULL
9876 && mp
->prev
->max_address
> mp
->max_address
- mp
->prev
->fix_size
)
9878 mp
->prev
->max_address
= mp
->max_address
- mp
->prev
->fix_size
;
9886 move_minipool_fix_backward_ref (Mnode
*mp
, Mnode
*min_mp
,
9887 HOST_WIDE_INT min_address
)
9889 HOST_WIDE_INT offset
;
9891 /* The code below assumes these are different. */
9892 gcc_assert (mp
!= min_mp
);
9896 if (min_address
> mp
->min_address
)
9897 mp
->min_address
= min_address
;
9901 /* We will adjust this below if it is too loose. */
9902 mp
->min_address
= min_address
;
9904 /* Unlink MP from its current position. Since min_mp is non-null,
9905 mp->next must be non-null. */
9906 mp
->next
->prev
= mp
->prev
;
9907 if (mp
->prev
!= NULL
)
9908 mp
->prev
->next
= mp
->next
;
9910 minipool_vector_head
= mp
->next
;
9912 /* Reinsert it after MIN_MP. */
9914 mp
->next
= min_mp
->next
;
9916 if (mp
->next
!= NULL
)
9917 mp
->next
->prev
= mp
;
9919 minipool_vector_tail
= mp
;
9925 for (mp
= minipool_vector_head
; mp
!= NULL
; mp
= mp
->next
)
9927 mp
->offset
= offset
;
9928 if (mp
->refcount
> 0)
9929 offset
+= mp
->fix_size
;
9931 if (mp
->next
&& mp
->next
->min_address
< mp
->min_address
+ mp
->fix_size
)
9932 mp
->next
->min_address
= mp
->min_address
+ mp
->fix_size
;
9938 /* Add a constant to the minipool for a backward reference. Returns the
9939 node added or NULL if the constant will not fit in this pool.
9941 Note that the code for insertion for a backwards reference can be
9942 somewhat confusing because the calculated offsets for each fix do
9943 not take into account the size of the pool (which is still under
9946 add_minipool_backward_ref (Mfix
*fix
)
9948 /* If set, min_mp is the last pool_entry that has a lower constraint
9949 than the one we are trying to add. */
9950 Mnode
*min_mp
= NULL
;
9951 /* This can be negative, since it is only a constraint. */
9952 HOST_WIDE_INT min_address
= fix
->address
- fix
->backwards
;
9955 /* If we can't reach the current pool from this insn, or if we can't
9956 insert this entry at the end of the pool without pushing other
9957 fixes out of range, then we don't try. This ensures that we
9958 can't fail later on. */
9959 if (min_address
>= minipool_barrier
->address
9960 || (minipool_vector_tail
->min_address
+ fix
->fix_size
9961 >= minipool_barrier
->address
))
9964 /* Scan the pool to see if a constant with the same value has
9965 already been added. While we are doing this, also note the
9966 location where we must insert the constant if it doesn't already
9968 for (mp
= minipool_vector_tail
; mp
!= NULL
; mp
= mp
->prev
)
9970 if (GET_CODE (fix
->value
) == GET_CODE (mp
->value
)
9971 && fix
->mode
== mp
->mode
9972 && (GET_CODE (fix
->value
) != CODE_LABEL
9973 || (CODE_LABEL_NUMBER (fix
->value
)
9974 == CODE_LABEL_NUMBER (mp
->value
)))
9975 && rtx_equal_p (fix
->value
, mp
->value
)
9976 /* Check that there is enough slack to move this entry to the
9977 end of the table (this is conservative). */
9979 > (minipool_barrier
->address
9980 + minipool_vector_tail
->offset
9981 + minipool_vector_tail
->fix_size
)))
9984 return move_minipool_fix_backward_ref (mp
, min_mp
, min_address
);
9988 mp
->min_address
+= fix
->fix_size
;
9991 /* Note the insertion point if necessary. */
9992 if (mp
->min_address
< min_address
)
9994 /* For now, we do not allow the insertion of 8-byte alignment
9995 requiring nodes anywhere but at the start of the pool. */
9996 if (ARM_DOUBLEWORD_ALIGN
9997 && fix
->fix_size
== 8 && mp
->fix_size
!= 8)
10002 else if (mp
->max_address
10003 < minipool_barrier
->address
+ mp
->offset
+ fix
->fix_size
)
10005 /* Inserting before this entry would push the fix beyond
10006 its maximum address (which can happen if we have
10007 re-located a forwards fix); force the new fix to come
10010 min_address
= mp
->min_address
+ fix
->fix_size
;
10012 /* If we are inserting an 8-bytes aligned quantity and
10013 we have not already found an insertion point, then
10014 make sure that all such 8-byte aligned quantities are
10015 placed at the start of the pool. */
10016 else if (ARM_DOUBLEWORD_ALIGN
10018 && fix
->fix_size
== 8
10019 && mp
->fix_size
< 8)
10022 min_address
= mp
->min_address
+ fix
->fix_size
;
10027 /* We need to create a new entry. */
10029 mp
->fix_size
= fix
->fix_size
;
10030 mp
->mode
= fix
->mode
;
10031 mp
->value
= fix
->value
;
10033 mp
->max_address
= minipool_barrier
->address
+ 65536;
10035 mp
->min_address
= min_address
;
10037 if (min_mp
== NULL
)
10040 mp
->next
= minipool_vector_head
;
10042 if (mp
->next
== NULL
)
10044 minipool_vector_tail
= mp
;
10045 minipool_vector_label
= gen_label_rtx ();
10048 mp
->next
->prev
= mp
;
10050 minipool_vector_head
= mp
;
10054 mp
->next
= min_mp
->next
;
10058 if (mp
->next
!= NULL
)
10059 mp
->next
->prev
= mp
;
10061 minipool_vector_tail
= mp
;
10064 /* Save the new entry. */
10072 /* Scan over the following entries and adjust their offsets. */
10073 while (mp
->next
!= NULL
)
10075 if (mp
->next
->min_address
< mp
->min_address
+ mp
->fix_size
)
10076 mp
->next
->min_address
= mp
->min_address
+ mp
->fix_size
;
10079 mp
->next
->offset
= mp
->offset
+ mp
->fix_size
;
10081 mp
->next
->offset
= mp
->offset
;
10090 assign_minipool_offsets (Mfix
*barrier
)
10092 HOST_WIDE_INT offset
= 0;
10095 minipool_barrier
= barrier
;
10097 for (mp
= minipool_vector_head
; mp
!= NULL
; mp
= mp
->next
)
10099 mp
->offset
= offset
;
10101 if (mp
->refcount
> 0)
10102 offset
+= mp
->fix_size
;
10106 /* Output the literal table */
10108 dump_minipool (rtx scan
)
10114 if (ARM_DOUBLEWORD_ALIGN
)
10115 for (mp
= minipool_vector_head
; mp
!= NULL
; mp
= mp
->next
)
10116 if (mp
->refcount
> 0 && mp
->fix_size
== 8)
10123 fprintf (dump_file
,
10124 ";; Emitting minipool after insn %u; address %ld; align %d (bytes)\n",
10125 INSN_UID (scan
), (unsigned long) minipool_barrier
->address
, align64
? 8 : 4);
10127 scan
= emit_label_after (gen_label_rtx (), scan
);
10128 scan
= emit_insn_after (align64
? gen_align_8 () : gen_align_4 (), scan
);
10129 scan
= emit_label_after (minipool_vector_label
, scan
);
10131 for (mp
= minipool_vector_head
; mp
!= NULL
; mp
= nmp
)
10133 if (mp
->refcount
> 0)
10137 fprintf (dump_file
,
10138 ";; Offset %u, min %ld, max %ld ",
10139 (unsigned) mp
->offset
, (unsigned long) mp
->min_address
,
10140 (unsigned long) mp
->max_address
);
10141 arm_print_value (dump_file
, mp
->value
);
10142 fputc ('\n', dump_file
);
10145 switch (mp
->fix_size
)
10147 #ifdef HAVE_consttable_1
10149 scan
= emit_insn_after (gen_consttable_1 (mp
->value
), scan
);
10153 #ifdef HAVE_consttable_2
10155 scan
= emit_insn_after (gen_consttable_2 (mp
->value
), scan
);
10159 #ifdef HAVE_consttable_4
10161 scan
= emit_insn_after (gen_consttable_4 (mp
->value
), scan
);
10165 #ifdef HAVE_consttable_8
10167 scan
= emit_insn_after (gen_consttable_8 (mp
->value
), scan
);
10171 /* APPLE LOCAL begin v7 support. Merge from mainline */
10172 #ifdef HAVE_consttable_16
10174 scan
= emit_insn_after (gen_consttable_16 (mp
->value
), scan
);
10178 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
10180 gcc_unreachable ();
10188 minipool_vector_head
= minipool_vector_tail
= NULL
;
10189 scan
= emit_insn_after (gen_consttable_end (), scan
);
10190 scan
= emit_barrier_after (scan
);
10193 /* Return the cost of forcibly inserting a barrier after INSN. */
10195 arm_barrier_cost (rtx insn
)
10197 /* Basing the location of the pool on the loop depth is preferable,
10198 but at the moment, the basic block information seems to be
10199 corrupt by this stage of the compilation. */
10200 int base_cost
= 50;
10201 rtx next
= next_nonnote_insn (insn
);
10203 if (next
!= NULL
&& GET_CODE (next
) == CODE_LABEL
)
10206 switch (GET_CODE (insn
))
10209 /* It will always be better to place the table before the label, rather
10218 return base_cost
- 10;
10221 return base_cost
+ 10;
10225 /* Find the best place in the insn stream in the range
10226 (FIX->address,MAX_ADDRESS) to forcibly insert a minipool barrier.
10227 Create the barrier by inserting a jump and add a new fix entry for
10230 create_fix_barrier (Mfix
*fix
, HOST_WIDE_INT max_address
)
10232 HOST_WIDE_INT count
= 0;
10234 rtx from
= fix
->insn
;
10235 /* The instruction after which we will insert the jump. */
10236 rtx selected
= NULL
;
10238 /* The address at which the jump instruction will be placed. */
10239 HOST_WIDE_INT selected_address
;
10241 HOST_WIDE_INT max_count
= max_address
- fix
->address
;
10242 rtx label
= gen_label_rtx ();
10244 selected_cost
= arm_barrier_cost (from
);
10245 selected_address
= fix
->address
;
10247 while (from
&& count
< max_count
)
10252 /* This code shouldn't have been called if there was a natural barrier
10254 gcc_assert (GET_CODE (from
) != BARRIER
);
10256 /* Count the length of this insn. */
10257 count
+= get_attr_length (from
);
10259 /* APPLE LOCAL begin ARM 6008578 */
10260 if (LABEL_P (from
))
10261 count
+= get_label_pad (from
, fix
->address
+ count
);
10262 /* APPLE LOCAL end ARM 6008578 */
10264 /* If there is a jump table, add its length. */
10265 tmp
= is_jump_table (from
);
10268 count
+= get_jump_table_size (tmp
);
10270 /* Jump tables aren't in a basic block, so base the cost on
10271 the dispatch insn. If we select this location, we will
10272 still put the pool after the table. */
10273 new_cost
= arm_barrier_cost (from
);
10275 if (count
< max_count
10276 && (!selected
|| new_cost
<= selected_cost
))
10279 selected_cost
= new_cost
;
10280 selected_address
= fix
->address
+ count
;
10283 /* Continue after the dispatch table. */
10284 from
= NEXT_INSN (tmp
);
10288 new_cost
= arm_barrier_cost (from
);
10290 if (count
< max_count
10291 && (!selected
|| new_cost
<= selected_cost
))
10294 selected_cost
= new_cost
;
10295 selected_address
= fix
->address
+ count
;
10298 from
= NEXT_INSN (from
);
10301 /* Make sure that we found a place to insert the jump. */
10302 gcc_assert (selected
);
10304 /* Create a new JUMP_INSN that branches around a barrier. */
10305 from
= emit_jump_insn_after (gen_jump (label
), selected
);
10306 JUMP_LABEL (from
) = label
;
10307 barrier
= emit_barrier_after (from
);
10308 emit_label_after (label
, barrier
);
10310 /* Create a minipool barrier entry for the new barrier. */
10311 new_fix
= (Mfix
*) obstack_alloc (&minipool_obstack
, sizeof (* new_fix
));
10312 new_fix
->insn
= barrier
;
10313 new_fix
->address
= selected_address
;
10314 new_fix
->next
= fix
->next
;
10315 fix
->next
= new_fix
;
10320 /* Record that there is a natural barrier in the insn stream at
10323 push_minipool_barrier (rtx insn
, HOST_WIDE_INT address
)
10325 Mfix
* fix
= (Mfix
*) obstack_alloc (&minipool_obstack
, sizeof (* fix
));
10328 fix
->address
= address
;
10331 if (minipool_fix_head
!= NULL
)
10332 minipool_fix_tail
->next
= fix
;
10334 minipool_fix_head
= fix
;
10336 minipool_fix_tail
= fix
;
10339 /* Record INSN, which will need fixing up to load a value from the
10340 minipool. ADDRESS is the offset of the insn since the start of the
10341 function; LOC is a pointer to the part of the insn which requires
10342 fixing; VALUE is the constant that must be loaded, which is of type
10345 push_minipool_fix (rtx insn
, HOST_WIDE_INT address
, rtx
*loc
,
10346 enum machine_mode mode
, rtx value
)
10348 Mfix
* fix
= (Mfix
*) obstack_alloc (&minipool_obstack
, sizeof (* fix
));
10350 #ifdef AOF_ASSEMBLER
10351 /* PIC symbol references need to be converted into offsets into the
10353 /* XXX This shouldn't be done here. */
10354 if (flag_pic
&& GET_CODE (value
) == SYMBOL_REF
)
10355 value
= aof_pic_entry (value
);
10356 #endif /* AOF_ASSEMBLER */
10359 fix
->address
= address
;
10362 fix
->fix_size
= MINIPOOL_FIX_SIZE (mode
);
10363 fix
->value
= value
;
10364 fix
->forwards
= get_attr_pool_range (insn
);
10365 fix
->backwards
= get_attr_neg_pool_range (insn
);
10366 fix
->minipool
= NULL
;
10368 /* If an insn doesn't have a range defined for it, then it isn't
10369 expecting to be reworked by this code. Better to stop now than
10370 to generate duff assembly code. */
10371 gcc_assert (fix
->forwards
|| fix
->backwards
);
10373 /* If an entry requires 8-byte alignment then assume all constant pools
10374 require 4 bytes of padding. Trying to do this later on a per-pool
10375 basis is awkward because existing pool entries have to be modified. */
10376 if (ARM_DOUBLEWORD_ALIGN
&& fix
->fix_size
== 8)
10381 fprintf (dump_file
,
10382 ";; %smode fixup for i%d; addr %lu, range (%ld,%ld): ",
10383 GET_MODE_NAME (mode
),
10384 INSN_UID (insn
), (unsigned long) address
,
10385 -1 * (long)fix
->backwards
, (long)fix
->forwards
);
10386 arm_print_value (dump_file
, fix
->value
);
10387 fprintf (dump_file
, "\n");
10390 /* Add it to the chain of fixes. */
10393 if (minipool_fix_head
!= NULL
)
10394 minipool_fix_tail
->next
= fix
;
10396 minipool_fix_head
= fix
;
10398 minipool_fix_tail
= fix
;
10404 /* Return the cost of synthesizing a 64-bit constant VAL inline.
10405 Returns the number of insns needed, or 99 if we don't know how to
10408 arm_const_double_inline_cost (rtx val
)
10410 rtx lowpart
, highpart
;
10411 enum machine_mode mode
;
10413 mode
= GET_MODE (val
);
10415 if (mode
== VOIDmode
)
10418 gcc_assert (GET_MODE_SIZE (mode
) == 8);
10420 lowpart
= gen_lowpart (SImode
, val
);
10421 highpart
= gen_highpart_mode (SImode
, mode
, val
);
10423 gcc_assert (GET_CODE (lowpart
) == CONST_INT
);
10424 gcc_assert (GET_CODE (highpart
) == CONST_INT
);
10426 return (arm_gen_constant (SET
, SImode
, NULL_RTX
, INTVAL (lowpart
),
10427 NULL_RTX
, NULL_RTX
, 0, 0)
10428 + arm_gen_constant (SET
, SImode
, NULL_RTX
, INTVAL (highpart
),
10429 NULL_RTX
, NULL_RTX
, 0, 0));
10432 /* APPLE LOCAL begin 5831562 long long constants */
10433 /* Return true if a 64-bit constant consists of two 32-bit halves,
10434 each of which is a valid immediate data-processing operand.
10435 (This differs from other 64-bit evaluations in that ~const is
10440 const64_ok_for_arm_immediate (rtx val
)
10442 rtx lowpart
, highpart
;
10443 enum machine_mode mode
;
10448 mode
= GET_MODE (val
);
10450 if (mode
== VOIDmode
)
10453 gcc_assert (GET_MODE_SIZE (mode
) == 8);
10455 lowpart
= gen_lowpart (SImode
, val
);
10456 highpart
= gen_highpart_mode (SImode
, mode
, val
);
10458 gcc_assert (GET_CODE (lowpart
) == CONST_INT
);
10459 gcc_assert (GET_CODE (highpart
) == CONST_INT
);
10461 return (const_ok_for_arm (INTVAL (lowpart
))
10462 && const_ok_for_arm (INTVAL (highpart
)));
10465 /* As above, but allow for constants whose negative value
10466 fits as well. Both halves must match either as themselves
10469 const64_ok_for_arm_add (rtx val
)
10471 rtx lowpart
, highpart
, lowpart_neg
, highpart_neg
, val_neg
;
10472 enum machine_mode mode
;
10477 mode
= GET_MODE (val
);
10479 if (mode
== VOIDmode
)
10482 gcc_assert (GET_MODE_SIZE (mode
) == 8);
10484 lowpart
= gen_lowpart (SImode
, val
);
10485 highpart
= gen_highpart_mode (SImode
, mode
, val
);
10487 val_neg
= negate_rtx (mode
, val
);
10488 lowpart_neg
= gen_lowpart (SImode
, val_neg
);
10489 highpart_neg
= gen_highpart_mode (SImode
, mode
, val_neg
);
10491 gcc_assert (GET_CODE (lowpart
) == CONST_INT
);
10492 gcc_assert (GET_CODE (highpart
) == CONST_INT
);
10494 return ((const_ok_for_arm (INTVAL (lowpart
))
10495 && const_ok_for_arm (INTVAL (highpart
)))
10496 || (const_ok_for_arm (INTVAL (lowpart_neg
))
10497 && const_ok_for_arm (INTVAL (highpart_neg
))));
10499 /* APPLE LOCAL end 5831562 long long constants */
10501 /* Return true if it is worthwhile to split a 64-bit constant into two
10502 32-bit operations. This is the case if optimizing for size, or
10503 if we have load delay slots, or if one 32-bit part can be done with
10504 a single data operation. */
10506 arm_const_double_by_parts (rtx val
)
10508 enum machine_mode mode
= GET_MODE (val
);
10511 if (optimize_size
|| arm_ld_sched
)
10514 if (mode
== VOIDmode
)
10517 part
= gen_highpart_mode (SImode
, mode
, val
);
10519 gcc_assert (GET_CODE (part
) == CONST_INT
);
10521 if (const_ok_for_arm (INTVAL (part
))
10522 || const_ok_for_arm (~INTVAL (part
)))
10525 part
= gen_lowpart (SImode
, val
);
10527 gcc_assert (GET_CODE (part
) == CONST_INT
);
10529 if (const_ok_for_arm (INTVAL (part
))
10530 || const_ok_for_arm (~INTVAL (part
)))
10537 #ifndef ENABLE_LLVM
10539 /* Scan INSN and note any of its operands that need fixing.
10540 If DO_PUSHES is false we do not actually push any of the fixups
10541 needed. The function returns TRUE if any fixups were needed/pushed.
10542 This is used by arm_memory_load_p() which needs to know about loads
10543 of constants that will be converted into minipool loads. */
10545 note_invalid_constants (rtx insn
, HOST_WIDE_INT address
, int do_pushes
)
10547 bool result
= false;
10550 extract_insn (insn
);
10552 if (!constrain_operands (1))
10553 fatal_insn_not_found (insn
);
10555 if (recog_data
.n_alternatives
== 0)
10558 /* Fill in recog_op_alt with information about the constraints of
10560 preprocess_constraints ();
10562 for (opno
= 0; opno
< recog_data
.n_operands
; opno
++)
10564 /* Things we need to fix can only occur in inputs. */
10565 if (recog_data
.operand_type
[opno
] != OP_IN
)
10568 /* If this alternative is a memory reference, then any mention
10569 of constants in this alternative is really to fool reload
10570 into allowing us to accept one there. We need to fix them up
10571 now so that we output the right code. */
10572 if (recog_op_alt
[opno
][which_alternative
].memory_ok
)
10574 rtx op
= recog_data
.operand
[opno
];
10576 if (CONSTANT_P (op
))
10579 push_minipool_fix (insn
, address
, recog_data
.operand_loc
[opno
],
10580 recog_data
.operand_mode
[opno
], op
);
10583 else if (GET_CODE (op
) == MEM
10584 && GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
10585 && CONSTANT_POOL_ADDRESS_P (XEXP (op
, 0)))
10589 rtx cop
= avoid_constant_pool_reference (op
);
10591 /* Casting the address of something to a mode narrower
10592 than a word can cause avoid_constant_pool_reference()
10593 to return the pool reference itself. That's no good to
10594 us here. Lets just hope that we can use the
10595 constant pool value directly. */
10597 cop
= get_pool_constant (XEXP (op
, 0));
10599 push_minipool_fix (insn
, address
,
10600 recog_data
.operand_loc
[opno
],
10601 recog_data
.operand_mode
[opno
], cop
);
10612 /* APPLE LOCAL begin ARM 6008578 */
10613 /* Return the bytes of padding that will be inserted to align
10614 the label INSN given the current pc ADDRESS. */
10615 static HOST_WIDE_INT
get_label_pad (rtx insn
, HOST_WIDE_INT address
)
10617 int label_align
, max_skip
;
10618 unsigned HOST_WIDE_INT align_mask
;
10621 gcc_assert (LABEL_P (insn
));
10623 label_align
= LABEL_ALIGN_LOG (insn
);
10624 max_skip
= LABEL_MAX_SKIP (insn
);
10625 align_mask
= ((unsigned int) 1 << label_align
) - 1;
10627 /* Already aligned. */
10628 if ((address
& align_mask
) == 0)
10631 pad_needed
= ((address
| align_mask
) + 1) - address
;
10633 /* We would have to insert more than max_skip bytes to
10634 align this label. */
10635 if (max_skip
&& (pad_needed
> max_skip
))
10640 /* APPLE LOCAL end ARM 6008578 */
10645 /* Gcc puts the pool in the wrong place for ARM, since we can only
10646 load addresses a limited distance around the pc. We do some
10647 special munging to move the constant pool values to the correct
10648 point in the code. */
10653 #ifndef ENABLE_LLVM
10655 HOST_WIDE_INT address
= 0;
10658 minipool_fix_head
= minipool_fix_tail
= NULL
;
10660 /* APPLE LOCAL begin ARM compact switch tables */
10661 /* This is actually lurking bug I think, alignment matters. */
10663 address
= count_thumb_unexpanded_prologue ();
10664 /* APPLE LOCAL end ARM compact switch tables */
10666 /* The first insn must always be a note, or the code below won't
10667 scan it properly. */
10668 insn
= get_insns ();
10669 gcc_assert (GET_CODE (insn
) == NOTE
);
10672 /* Scan all the insns and record the operands that will need fixing. */
10673 for (insn
= next_nonnote_insn (insn
); insn
; insn
= next_nonnote_insn (insn
))
10675 if (TARGET_CIRRUS_FIX_INVALID_INSNS
10676 && (arm_cirrus_insn_p (insn
)
10677 || GET_CODE (insn
) == JUMP_INSN
10678 || arm_memory_load_p (insn
)))
10679 cirrus_reorg (insn
);
10681 if (GET_CODE (insn
) == BARRIER
)
10682 push_minipool_barrier (insn
, address
);
10683 /* APPLE LOCAL begin ARM 6008578 */
10684 else if (LABEL_P (insn
))
10685 address
+= get_label_pad (insn
, address
);
10686 /* APPLE LOCAL end ARM 6008578 */
10687 else if (INSN_P (insn
))
10691 note_invalid_constants (insn
, address
, true);
10692 address
+= get_attr_length (insn
);
10694 /* If the insn is a vector jump, add the size of the table
10695 and skip the table. */
10696 if ((table
= is_jump_table (insn
)) != NULL
)
10698 address
+= get_jump_table_size (table
);
10704 fix
= minipool_fix_head
;
10706 /* Now scan the fixups and perform the required changes. */
10711 Mfix
* last_added_fix
;
10712 Mfix
* last_barrier
= NULL
;
10715 /* Skip any further barriers before the next fix. */
10716 while (fix
&& GET_CODE (fix
->insn
) == BARRIER
)
10719 /* No more fixes. */
10723 last_added_fix
= NULL
;
10725 for (ftmp
= fix
; ftmp
; ftmp
= ftmp
->next
)
10727 if (GET_CODE (ftmp
->insn
) == BARRIER
)
10729 if (ftmp
->address
>= minipool_vector_head
->max_address
)
10732 last_barrier
= ftmp
;
10734 else if ((ftmp
->minipool
= add_minipool_forward_ref (ftmp
)) == NULL
)
10737 last_added_fix
= ftmp
; /* Keep track of the last fix added. */
10740 /* If we found a barrier, drop back to that; any fixes that we
10741 could have reached but come after the barrier will now go in
10742 the next mini-pool. */
10743 if (last_barrier
!= NULL
)
10745 /* Reduce the refcount for those fixes that won't go into this
10747 for (fdel
= last_barrier
->next
;
10748 fdel
&& fdel
!= ftmp
;
10751 fdel
->minipool
->refcount
--;
10752 fdel
->minipool
= NULL
;
10755 ftmp
= last_barrier
;
10759 /* ftmp is first fix that we can't fit into this pool and
10760 there no natural barriers that we could use. Insert a
10761 new barrier in the code somewhere between the previous
10762 fix and this one, and arrange to jump around it. */
10763 HOST_WIDE_INT max_address
;
10765 /* The last item on the list of fixes must be a barrier, so
10766 we can never run off the end of the list of fixes without
10767 last_barrier being set. */
10770 max_address
= minipool_vector_head
->max_address
;
10771 /* Check that there isn't another fix that is in range that
10772 we couldn't fit into this pool because the pool was
10773 already too large: we need to put the pool before such an
10774 instruction. The pool itself may come just after the
10775 fix because create_fix_barrier also allows space for a
10776 jump instruction. */
10777 if (ftmp
->address
< max_address
)
10778 max_address
= ftmp
->address
+ 1;
10780 last_barrier
= create_fix_barrier (last_added_fix
, max_address
);
10783 assign_minipool_offsets (last_barrier
);
10787 if (GET_CODE (ftmp
->insn
) != BARRIER
10788 && ((ftmp
->minipool
= add_minipool_backward_ref (ftmp
))
10795 /* Scan over the fixes we have identified for this pool, fixing them
10796 up and adding the constants to the pool itself. */
10797 for (this_fix
= fix
; this_fix
&& ftmp
!= this_fix
;
10798 this_fix
= this_fix
->next
)
10799 if (GET_CODE (this_fix
->insn
) != BARRIER
)
10802 = plus_constant (gen_rtx_LABEL_REF (VOIDmode
,
10803 minipool_vector_label
),
10804 this_fix
->minipool
->offset
);
10805 *this_fix
->loc
= gen_rtx_MEM (this_fix
->mode
, addr
);
10808 dump_minipool (last_barrier
->insn
);
10812 /* From now on we must synthesize any constants that we can't handle
10813 directly. This can happen if the RTL gets split during final
10814 instruction generation. */
10815 after_arm_reorg
= 1;
10817 /* Free the minipool memory. */
10818 obstack_free (&minipool_obstack
, minipool_startobj
);
10823 /* Routines to output assembly language. */
10825 /* If the rtx is the correct value then return the string of the number.
10826 In this way we can ensure that valid double constants are generated even
10827 when cross compiling. */
10829 fp_immediate_constant (rtx x
)
10834 if (!fp_consts_inited
)
10837 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
10838 for (i
= 0; i
< 8; i
++)
10839 if (REAL_VALUES_EQUAL (r
, values_fp
[i
]))
10840 return strings_fp
[i
];
10842 gcc_unreachable ();
10845 /* As for fp_immediate_constant, but value is passed directly, not in rtx. */
10846 static const char *
10847 fp_const_from_val (REAL_VALUE_TYPE
*r
)
10851 if (!fp_consts_inited
)
10854 for (i
= 0; i
< 8; i
++)
10855 if (REAL_VALUES_EQUAL (*r
, values_fp
[i
]))
10856 return strings_fp
[i
];
10858 gcc_unreachable ();
10861 /* Output the operands of a LDM/STM instruction to STREAM.
10862 MASK is the ARM register set mask of which only bits 0-15 are important.
10863 REG is the base register, either the frame pointer or the stack pointer,
10864 INSTR is the possibly suffixed load or store instruction. */
10867 print_multi_reg (FILE *stream
, const char *instr
, unsigned reg
,
10868 unsigned long mask
)
10871 bool not_first
= FALSE
;
10873 fputc ('\t', stream
);
10874 asm_fprintf (stream
, instr
, reg
);
10875 /* APPLE LOCAL v7 support. Merge from mainline */
10876 fputc ('{', stream
);
10878 for (i
= 0; i
<= LAST_ARM_REGNUM
; i
++)
10879 if (mask
& (1 << i
))
10881 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
10883 fprintf (stream
, ", ");
10885 asm_fprintf (stream
, "%r", i
);
10887 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
10890 fprintf (stream
, "}\n");
10894 /* APPLE LOCAL begin v7 support. Merge from mainline */
10895 /* Output a FLDMD instruction to STREAM.
10896 BASE if the register containing the address.
10897 REG and COUNT specify the register range.
10898 Extra registers may be added to avoid hardware bugs.
10900 We output FLDMD even for ARMv5 VFP implementations. Although
10901 FLDMD is technically not supported until ARMv6, it is believed
10902 that all VFP implementations support its use in this context. */
10905 vfp_output_fldmd (FILE * stream
, unsigned int base
, int reg
, int count
)
10906 /* APPLE LOCAL end v7 support. Merge from mainline */
10910 /* Workaround ARM10 VFPr1 bug. */
10911 if (count
== 2 && !arm_arch6
)
10918 /* APPLE LOCAL begin v7 support. Merge from mainline */
10919 /* FLDMD may not load more than 16 doubleword registers at a time. Split the
10920 load into multiple parts if we have to handle more than 16 registers. */
10923 vfp_output_fldmd (stream
, base
, reg
, 16);
10924 vfp_output_fldmd (stream
, base
, reg
+ 16, count
- 16);
10928 fputc ('\t', stream
);
10929 asm_fprintf (stream
, "fldmfdd\t%r!, {", base
);
10930 /* APPLE LOCAL end v7 support. Merge from mainline */
10932 for (i
= reg
; i
< reg
+ count
; i
++)
10935 fputs (", ", stream
);
10936 asm_fprintf (stream
, "d%d", i
);
10938 fputs ("}\n", stream
);
10943 /* Output the assembly for a store multiple. */
10946 /* APPLE LOCAL v7 support. Merge from mainline */
10947 vfp_output_fstmd (rtx
* operands
)
10954 /* APPLE LOCAL v7 support. Merge from mainline */
10955 strcpy (pattern
, "fstmfdd\t%m0!, {%P1");
10956 p
= strlen (pattern
);
10958 gcc_assert (GET_CODE (operands
[1]) == REG
);
10960 base
= (REGNO (operands
[1]) - FIRST_VFP_REGNUM
) / 2;
10961 for (i
= 1; i
< XVECLEN (operands
[2], 0); i
++)
10963 p
+= sprintf (&pattern
[p
], ", d%d", base
+ i
);
10965 strcpy (&pattern
[p
], "}");
10967 output_asm_insn (pattern
, operands
);
10972 /* Emit RTL to save block of VFP register pairs to the stack. Returns the
10973 number of bytes pushed. */
10976 /* APPLE LOCAL v7 support. Merge from mainline */
10977 vfp_emit_fstmd (int base_reg
, int count
)
10984 /* Workaround ARM10 VFPr1 bug. Data corruption can occur when exactly two
10985 register pairs are stored by a store multiple insn. We avoid this
10986 by pushing an extra pair. */
10987 if (count
== 2 && !arm_arch6
)
10989 if (base_reg
== LAST_VFP_REGNUM
- 3)
10994 /* APPLE LOCAL begin v7 support. Merge from mainline */
10995 /* FSTMD may not store more than 16 doubleword registers at once. Split
10996 larger stores into multiple parts (up to a maximum of two, in
11001 /* NOTE: base_reg is an internal register number, so each D register
11003 saved
= vfp_emit_fstmd (base_reg
+ 32, count
- 16);
11004 saved
+= vfp_emit_fstmd (base_reg
, 16);
11008 /* APPLE LOCAL end v7 support. Merge from mainline */
11009 par
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (count
));
11010 dwarf
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (count
+ 1));
11012 reg
= gen_rtx_REG (DFmode
, base_reg
);
11015 XVECEXP (par
, 0, 0)
11016 = gen_rtx_SET (VOIDmode
,
11017 gen_frame_mem (BLKmode
,
11018 gen_rtx_PRE_DEC (BLKmode
,
11019 stack_pointer_rtx
)),
11020 gen_rtx_UNSPEC (BLKmode
,
11021 gen_rtvec (1, reg
),
11022 UNSPEC_PUSH_MULT
));
11024 tmp
= gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
11025 /* APPLE LOCAL v7 support. Merge from mainline */
11026 plus_constant (stack_pointer_rtx
, -(count
* 8)));
11027 RTX_FRAME_RELATED_P (tmp
) = 1;
11028 XVECEXP (dwarf
, 0, 0) = tmp
;
11030 tmp
= gen_rtx_SET (VOIDmode
,
11031 gen_frame_mem (DFmode
, stack_pointer_rtx
),
11033 RTX_FRAME_RELATED_P (tmp
) = 1;
11034 XVECEXP (dwarf
, 0, 1) = tmp
;
11036 for (i
= 1; i
< count
; i
++)
11038 reg
= gen_rtx_REG (DFmode
, base_reg
);
11040 XVECEXP (par
, 0, i
) = gen_rtx_USE (VOIDmode
, reg
);
11042 tmp
= gen_rtx_SET (VOIDmode
,
11043 gen_frame_mem (DFmode
,
11044 plus_constant (stack_pointer_rtx
,
11047 RTX_FRAME_RELATED_P (tmp
) = 1;
11048 XVECEXP (dwarf
, 0, i
+ 1) = tmp
;
11051 par
= emit_insn (par
);
11052 REG_NOTES (par
) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR
, dwarf
,
11054 RTX_FRAME_RELATED_P (par
) = 1;
11056 /* APPLE LOCAL v7 support. Merge from mainline */
11061 /* Output a 'call' insn. */
11063 output_call (rtx
*operands
)
11065 gcc_assert (!arm_arch5
); /* Patterns should call blx <reg> directly. */
11067 /* Handle calls to lr using ip (which may be clobbered in subr anyway). */
11068 if (REGNO (operands
[0]) == LR_REGNUM
)
11070 operands
[0] = gen_rtx_REG (SImode
, IP_REGNUM
);
11071 output_asm_insn ("mov%?\t%0, %|lr", operands
);
11074 output_asm_insn ("mov%?\t%|lr, %|pc", operands
);
11076 if (TARGET_INTERWORK
|| arm_arch4t
)
11077 output_asm_insn ("bx%?\t%0", operands
);
11079 output_asm_insn ("mov%?\t%|pc, %0", operands
);
11084 /* Output a 'call' insn that is a reference in memory. */
11086 output_call_mem (rtx
*operands
)
11088 if (TARGET_INTERWORK
&& !arm_arch5
)
11090 output_asm_insn ("ldr%?\t%|ip, %0", operands
);
11091 output_asm_insn ("mov%?\t%|lr, %|pc", operands
);
11092 output_asm_insn ("bx%?\t%|ip", operands
);
11094 else if (regno_use_in (LR_REGNUM
, operands
[0]))
11096 /* LR is used in the memory address. We load the address in the
11097 first instruction. It's safe to use IP as the target of the
11098 load since the call will kill it anyway. */
11099 output_asm_insn ("ldr%?\t%|ip, %0", operands
);
11101 output_asm_insn ("blx%?\t%|ip", operands
);
11104 output_asm_insn ("mov%?\t%|lr, %|pc", operands
);
11106 output_asm_insn ("bx%?\t%|ip", operands
);
11108 output_asm_insn ("mov%?\t%|pc, %|ip", operands
);
11113 output_asm_insn ("mov%?\t%|lr, %|pc", operands
);
11114 output_asm_insn ("ldr%?\t%|pc, %0", operands
);
11121 /* Output a move from arm registers to an fpa registers.
11122 OPERANDS[0] is an fpa register.
11123 OPERANDS[1] is the first registers of an arm register pair. */
11125 output_mov_long_double_fpa_from_arm (rtx
*operands
)
11127 int arm_reg0
= REGNO (operands
[1]);
11130 gcc_assert (arm_reg0
!= IP_REGNUM
);
11132 ops
[0] = gen_rtx_REG (SImode
, arm_reg0
);
11133 ops
[1] = gen_rtx_REG (SImode
, 1 + arm_reg0
);
11134 ops
[2] = gen_rtx_REG (SImode
, 2 + arm_reg0
);
11136 /* APPLE LOCAL v7 support. Merge from mainline */
11137 output_asm_insn ("stm%(fd%)\t%|sp!, {%0, %1, %2}", ops
);
11138 output_asm_insn ("ldf%?e\t%0, [%|sp], #12", operands
);
11143 /* Output a move from an fpa register to arm registers.
11144 OPERANDS[0] is the first registers of an arm register pair.
11145 OPERANDS[1] is an fpa register. */
11147 output_mov_long_double_arm_from_fpa (rtx
*operands
)
11149 int arm_reg0
= REGNO (operands
[0]);
11152 gcc_assert (arm_reg0
!= IP_REGNUM
);
11154 ops
[0] = gen_rtx_REG (SImode
, arm_reg0
);
11155 ops
[1] = gen_rtx_REG (SImode
, 1 + arm_reg0
);
11156 ops
[2] = gen_rtx_REG (SImode
, 2 + arm_reg0
);
11158 output_asm_insn ("stf%?e\t%1, [%|sp, #-12]!", operands
);
11159 /* APPLE LOCAL v7 support. Merge from mainline */
11160 output_asm_insn ("ldm%(fd%)\t%|sp!, {%0, %1, %2}", ops
);
11164 /* Output a move from arm registers to arm registers of a long double
11165 OPERANDS[0] is the destination.
11166 OPERANDS[1] is the source. */
11168 output_mov_long_double_arm_from_arm (rtx
*operands
)
11170 /* We have to be careful here because the two might overlap. */
11171 int dest_start
= REGNO (operands
[0]);
11172 int src_start
= REGNO (operands
[1]);
11176 if (dest_start
< src_start
)
11178 for (i
= 0; i
< 3; i
++)
11180 ops
[0] = gen_rtx_REG (SImode
, dest_start
+ i
);
11181 ops
[1] = gen_rtx_REG (SImode
, src_start
+ i
);
11182 output_asm_insn ("mov%?\t%0, %1", ops
);
11187 for (i
= 2; i
>= 0; i
--)
11189 ops
[0] = gen_rtx_REG (SImode
, dest_start
+ i
);
11190 ops
[1] = gen_rtx_REG (SImode
, src_start
+ i
);
11191 output_asm_insn ("mov%?\t%0, %1", ops
);
11199 /* Output a move from arm registers to an fpa registers.
11200 OPERANDS[0] is an fpa register.
11201 OPERANDS[1] is the first registers of an arm register pair. */
11203 output_mov_double_fpa_from_arm (rtx
*operands
)
11205 int arm_reg0
= REGNO (operands
[1]);
11208 gcc_assert (arm_reg0
!= IP_REGNUM
);
11210 ops
[0] = gen_rtx_REG (SImode
, arm_reg0
);
11211 ops
[1] = gen_rtx_REG (SImode
, 1 + arm_reg0
);
11212 /* APPLE LOCAL v7 support. Merge from mainline */
11213 output_asm_insn ("stm%(fd%)\t%|sp!, {%0, %1}", ops
);
11214 output_asm_insn ("ldf%?d\t%0, [%|sp], #8", operands
);
11218 /* Output a move from an fpa register to arm registers.
11219 OPERANDS[0] is the first registers of an arm register pair.
11220 OPERANDS[1] is an fpa register. */
11222 output_mov_double_arm_from_fpa (rtx
*operands
)
11224 int arm_reg0
= REGNO (operands
[0]);
11227 gcc_assert (arm_reg0
!= IP_REGNUM
);
11229 ops
[0] = gen_rtx_REG (SImode
, arm_reg0
);
11230 ops
[1] = gen_rtx_REG (SImode
, 1 + arm_reg0
);
11231 output_asm_insn ("stf%?d\t%1, [%|sp, #-8]!", operands
);
11232 /* APPLE LOCAL v7 support. Merge from mainline */
11233 output_asm_insn ("ldm%(fd%)\t%|sp!, {%0, %1}", ops
);
11237 /* Output a move between double words.
11238 It must be REG<-REG, REG<-CONST_DOUBLE, REG<-CONST_INT, REG<-MEM
11239 or MEM<-REG and all MEMs must be offsettable addresses. */
11241 output_move_double (rtx
*operands
)
11243 enum rtx_code code0
= GET_CODE (operands
[0]);
11244 enum rtx_code code1
= GET_CODE (operands
[1]);
11249 int reg0
= REGNO (operands
[0]);
11251 otherops
[0] = gen_rtx_REG (SImode
, 1 + reg0
);
11253 gcc_assert (code1
== MEM
); /* Constraints should ensure this. */
11255 switch (GET_CODE (XEXP (operands
[1], 0)))
11258 /* APPLE LOCAL v7 support. Merge from mainline */
11259 output_asm_insn ("ldm%(ia%)\t%m1, %M0", operands
);
11263 gcc_assert (TARGET_LDRD
);
11264 /* APPLE LOCAL v7 support. Merge from mainline */
11265 output_asm_insn ("ldr%(d%)\t%0, [%m1, #8]!", operands
);
11269 /* APPLE LOCAL begin v7 support. Merge from mainline */
11271 output_asm_insn ("ldr%(d%)\t%0, [%m1, #-8]!", operands
);
11273 output_asm_insn ("ldm%(db%)\t%m1!, %M0", operands
);
11274 /* APPLE LOCAL end v7 support. Merge from mainline */
11278 /* APPLE LOCAL v7 support. Merge from mainline */
11279 output_asm_insn ("ldm%(ia%)\t%m1!, %M0", operands
);
11283 gcc_assert (TARGET_LDRD
);
11284 /* APPLE LOCAL v7 support. Merge from mainline */
11285 output_asm_insn ("ldr%(d%)\t%0, [%m1], #-8", operands
);
11290 otherops
[0] = operands
[0];
11291 otherops
[1] = XEXP (XEXP (XEXP (operands
[1], 0), 1), 0);
11292 otherops
[2] = XEXP (XEXP (XEXP (operands
[1], 0), 1), 1);
11294 /* APPLE LOCAL begin v7 support. Merge from mainline */
11295 if (GET_CODE (XEXP (operands
[1], 0)) == PRE_MODIFY
)
11297 if (reg_overlap_mentioned_p (otherops
[0], otherops
[2]))
11299 /* Registers overlap so split out the increment. */
11300 output_asm_insn ("add%?\t%1, %1, %2", otherops
);
11301 output_asm_insn ("ldr%(d%)\t%0, [%1] @split", otherops
);
11305 /* IWMMXT allows offsets larger than ARM ldrd can handle,
11306 fix these up with a pair of ldr. */
11307 if (TARGET_ARM
&& GET_CODE (otherops
[2]) == CONST_INT
11308 && (INTVAL(otherops
[2]) <= -256
11309 || INTVAL(otherops
[2]) >= 256))
11311 output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops
);
11312 otherops
[0] = gen_rtx_REG (SImode
, 1 + reg0
);
11313 output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops
);
11316 output_asm_insn ("ldr%(d%)\t%0, [%1, %2]!", otherops
);
11321 /* IWMMXT allows offsets larger than ARM ldrd can handle,
11322 fix these up with a pair of ldr. */
11323 if (TARGET_ARM
&& GET_CODE (otherops
[2]) == CONST_INT
11324 && (INTVAL(otherops
[2]) <= -256
11325 || INTVAL(otherops
[2]) >= 256))
11327 otherops
[0] = gen_rtx_REG (SImode
, 1 + reg0
);
11328 output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops
);
11329 otherops
[0] = operands
[0];
11330 output_asm_insn ("ldr%?\t%0, [%1], %2", otherops
);
11333 /* We only allow constant increments, so this is safe. */
11334 output_asm_insn ("ldr%(d%)\t%0, [%1], %2", otherops
);
11336 /* APPLE LOCAL end v7 support. Merge from mainline */
11341 output_asm_insn ("adr%?\t%0, %1", operands
);
11342 /* APPLE LOCAL v7 support. Merge from mainline */
11343 output_asm_insn ("ldm%(ia%)\t%0, %M0", operands
);
11346 /* APPLE LOCAL v7 support. Merge from mainline */
11347 /* ??? This needs checking for thumb2. */
11349 if (arm_add_operand (XEXP (XEXP (operands
[1], 0), 1),
11350 GET_MODE (XEXP (XEXP (operands
[1], 0), 1))))
11352 otherops
[0] = operands
[0];
11353 otherops
[1] = XEXP (XEXP (operands
[1], 0), 0);
11354 otherops
[2] = XEXP (XEXP (operands
[1], 0), 1);
11356 if (GET_CODE (XEXP (operands
[1], 0)) == PLUS
)
11358 if (GET_CODE (otherops
[2]) == CONST_INT
)
11360 /* APPLE LOCAL begin v7 support. Merge from mainline */
11361 switch ((int) INTVAL (otherops
[2]))
11364 output_asm_insn ("ldm%(db%)\t%1, %M0", otherops
);
11369 output_asm_insn ("ldm%(da%)\t%1, %M0", otherops
);
11374 output_asm_insn ("ldm%(ib%)\t%1, %M0", otherops
);
11377 /* APPLE LOCAL end v7 support. Merge from mainline */
11380 && (GET_CODE (otherops
[2]) == REG
11381 || (GET_CODE (otherops
[2]) == CONST_INT
11382 && INTVAL (otherops
[2]) > -256
11383 && INTVAL (otherops
[2]) < 256)))
11385 if (reg_overlap_mentioned_p (otherops
[0],
11388 /* Swap base and index registers over to
11389 avoid a conflict. */
11390 otherops
[1] = XEXP (XEXP (operands
[1], 0), 1);
11391 otherops
[2] = XEXP (XEXP (operands
[1], 0), 0);
11393 /* If both registers conflict, it will usually
11394 have been fixed by a splitter. */
11395 if (reg_overlap_mentioned_p (otherops
[0], otherops
[2]))
11397 output_asm_insn ("add%?\t%1, %1, %2", otherops
);
11398 /* APPLE LOCAL v7 support. Merge from mainline */
11399 output_asm_insn ("ldr%(d%)\t%0, [%1]",
11403 /* APPLE LOCAL v7 support. Merge from mainline */
11404 output_asm_insn ("ldr%(d%)\t%0, [%1, %2]", otherops
);
11408 if (GET_CODE (otherops
[2]) == CONST_INT
)
11410 if (!(const_ok_for_arm (INTVAL (otherops
[2]))))
11411 output_asm_insn ("sub%?\t%0, %1, #%n2", otherops
);
11413 output_asm_insn ("add%?\t%0, %1, %2", otherops
);
11416 output_asm_insn ("add%?\t%0, %1, %2", otherops
);
11419 output_asm_insn ("sub%?\t%0, %1, %2", otherops
);
11421 /* APPLE LOCAL v7 support. Merge from mainline */
11422 return "ldm%(ia%)\t%0, %M0";
11426 otherops
[1] = adjust_address (operands
[1], SImode
, 4);
11427 /* Take care of overlapping base/data reg. */
11428 if (reg_mentioned_p (operands
[0], operands
[1]))
11430 output_asm_insn ("ldr%?\t%0, %1", otherops
);
11431 output_asm_insn ("ldr%?\t%0, %1", operands
);
11435 output_asm_insn ("ldr%?\t%0, %1", operands
);
11436 output_asm_insn ("ldr%?\t%0, %1", otherops
);
11443 /* Constraints should ensure this. */
11444 gcc_assert (code0
== MEM
&& code1
== REG
);
11445 gcc_assert (REGNO (operands
[1]) != IP_REGNUM
);
11447 switch (GET_CODE (XEXP (operands
[0], 0)))
11450 /* APPLE LOCAL v7 support. Merge from mainline */
11451 output_asm_insn ("stm%(ia%)\t%m0, %M1", operands
);
11455 gcc_assert (TARGET_LDRD
);
11456 /* APPLE LOCAL v7 support. Merge from mainline */
11457 output_asm_insn ("str%(d%)\t%1, [%m0, #8]!", operands
);
11461 /* APPLE LOCAL begin v7 support. Merge from mainline */
11463 output_asm_insn ("str%(d%)\t%1, [%m0, #-8]!", operands
);
11465 output_asm_insn ("stm%(db%)\t%m0!, %M1", operands
);
11466 /* APPLE LOCAL end v7 support. Merge from mainline */
11470 /* APPLE LOCAL v7 support. Merge from mainline */
11471 output_asm_insn ("stm%(ia%)\t%m0!, %M1", operands
);
11475 gcc_assert (TARGET_LDRD
);
11476 /* APPLE LOCAL v7 support. Merge from mainline */
11477 output_asm_insn ("str%(d%)\t%1, [%m0], #-8", operands
);
11482 otherops
[0] = operands
[1];
11483 otherops
[1] = XEXP (XEXP (XEXP (operands
[0], 0), 1), 0);
11484 otherops
[2] = XEXP (XEXP (XEXP (operands
[0], 0), 1), 1);
11486 /* APPLE LOCAL begin v7 support. Merge from mainline */
11487 /* IWMMXT allows offsets larger than ARM ldrd can handle,
11488 fix these up with a pair of ldr. */
11489 if (TARGET_ARM
&& GET_CODE (otherops
[2]) == CONST_INT
11490 /* APPLE LOCAL end v7 support. Merge from mainline */
11491 && (INTVAL(otherops
[2]) <= -256
11492 || INTVAL(otherops
[2]) >= 256))
11495 reg1
= gen_rtx_REG (SImode
, 1 + REGNO (operands
[1]));
11496 if (GET_CODE (XEXP (operands
[0], 0)) == PRE_MODIFY
)
11498 output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops
);
11499 otherops
[0] = reg1
;
11500 output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops
);
11504 otherops
[0] = reg1
;
11505 output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops
);
11506 otherops
[0] = operands
[1];
11507 output_asm_insn ("ldr%?\t%0, [%1], %2", otherops
);
11510 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_MODIFY
)
11511 /* APPLE LOCAL v7 support. Merge from mainline */
11512 output_asm_insn ("str%(d%)\t%0, [%1, %2]!", otherops
);
11514 /* APPLE LOCAL v7 support. Merge from mainline */
11515 output_asm_insn ("str%(d%)\t%0, [%1], %2", otherops
);
11519 otherops
[2] = XEXP (XEXP (operands
[0], 0), 1);
11520 if (GET_CODE (otherops
[2]) == CONST_INT
)
11522 /* APPLE LOCAL begin v7 support. Merge from mainline */
11523 switch ((int) INTVAL (XEXP (XEXP (operands
[0], 0), 1)))
11526 output_asm_insn ("stm%(db%)\t%m0, %M1", operands
);
11532 output_asm_insn ("stm%(da%)\t%m0, %M1", operands
);
11538 output_asm_insn ("stm%(ib%)\t%m0, %M1", operands
);
11541 /* APPLE LOCAL end v7 support. Merge from mainline */
11544 && (GET_CODE (otherops
[2]) == REG
11545 || (GET_CODE (otherops
[2]) == CONST_INT
11546 && INTVAL (otherops
[2]) > -256
11547 && INTVAL (otherops
[2]) < 256)))
11549 otherops
[0] = operands
[1];
11550 otherops
[1] = XEXP (XEXP (operands
[0], 0), 0);
11551 /* APPLE LOCAL v7 support. Merge from mainline */
11552 output_asm_insn ("str%(d%)\t%0, [%1, %2]", otherops
);
11558 otherops
[0] = adjust_address (operands
[0], SImode
, 4);
11559 otherops
[1] = gen_rtx_REG (SImode
, 1 + REGNO (operands
[1]));
11560 output_asm_insn ("str%?\t%1, %0", operands
);
11561 output_asm_insn ("str%?\t%1, %0", otherops
);
11568 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
11569 /* Output a move, load or store for quad-word vectors in ARM registers. Only
11570 handles MEMs accepted by neon_vector_mem_operand with CORE=true. */
11573 output_move_quad (rtx
*operands
)
11575 if (REG_P (operands
[0]))
11577 /* Load, or reg->reg move. */
11579 if (MEM_P (operands
[1]))
11581 switch (GET_CODE (XEXP (operands
[1], 0)))
11584 output_asm_insn ("ldm%(ia%)\t%m1, %M0", operands
);
11589 output_asm_insn ("adr%?\t%0, %1", operands
);
11590 output_asm_insn ("ldm%(ia%)\t%0, %M0", operands
);
11594 gcc_unreachable ();
11602 gcc_assert (REG_P (operands
[1]));
11604 dest
= REGNO (operands
[0]);
11605 src
= REGNO (operands
[1]);
11607 /* This seems pretty dumb, but hopefully GCC won't try to do it
11610 for (i
= 0; i
< 4; i
++)
11612 ops
[0] = gen_rtx_REG (SImode
, dest
+ i
);
11613 ops
[1] = gen_rtx_REG (SImode
, src
+ i
);
11614 output_asm_insn ("mov%?\t%0, %1", ops
);
11617 for (i
= 3; i
>= 0; i
--)
11619 ops
[0] = gen_rtx_REG (SImode
, dest
+ i
);
11620 ops
[1] = gen_rtx_REG (SImode
, src
+ i
);
11621 output_asm_insn ("mov%?\t%0, %1", ops
);
11627 gcc_assert (MEM_P (operands
[0]));
11628 gcc_assert (REG_P (operands
[1]));
11629 gcc_assert (!reg_overlap_mentioned_p (operands
[1], operands
[0]));
11631 switch (GET_CODE (XEXP (operands
[0], 0)))
11634 output_asm_insn ("stm%(ia%)\t%m0, %M1", operands
);
11638 gcc_unreachable ();
11645 /* Output a VFP load or store instruction. */
11648 output_move_vfp (rtx
*operands
)
11650 rtx reg
, mem
, addr
, ops
[2];
11651 int load
= REG_P (operands
[0]);
11652 int dp
= GET_MODE_SIZE (GET_MODE (operands
[0])) == 8;
11653 int integer_p
= GET_MODE_CLASS (GET_MODE (operands
[0])) == MODE_INT
;
11654 const char *template;
11656 enum machine_mode mode
;
11658 reg
= operands
[!load
];
11659 mem
= operands
[load
];
11661 mode
= GET_MODE (reg
);
11663 gcc_assert (REG_P (reg
));
11664 gcc_assert (IS_VFP_REGNUM (REGNO (reg
)));
11665 gcc_assert (mode
== SFmode
11669 || (TARGET_NEON
&& VALID_NEON_DREG_MODE (mode
)));
11670 gcc_assert (MEM_P (mem
));
11672 addr
= XEXP (mem
, 0);
11674 switch (GET_CODE (addr
))
11677 template = "f%smdb%c%%?\t%%0!, {%%%s1}%s";
11678 ops
[0] = XEXP (addr
, 0);
11683 template = "f%smia%c%%?\t%%0!, {%%%s1}%s";
11684 ops
[0] = XEXP (addr
, 0);
11689 template = "f%s%c%%?\t%%%s0, %%1%s";
11695 sprintf (buff
, template,
11696 load
? "ld" : "st",
11699 integer_p
? "\t%@ int" : "");
11700 output_asm_insn (buff
, ops
);
11705 /* Output a Neon quad-word load or store, or a load or store for
11706 larger structure modes. We could also support post-modify
11707 forms using VLD1/VST1, but we don't do that yet.
11708 WARNING, FIXME: The ordering of elements in memory is going to be weird in
11709 big-endian mode at present, because we use VSTM instead of VST1, to make
11710 it easy to make vector stores via ARM registers write values in the same
11711 order as stores direct from Neon registers. For example, the byte ordering
11712 of a quadword vector with 16-byte elements like this:
11714 [e7:e6:e5:e4:e3:e2:e1:e0] (highest-numbered element first)
11716 will be (with lowest address first, h = most-significant byte,
11717 l = least-significant byte of element):
11719 [e3h, e3l, e2h, e2l, e1h, e1l, e0h, e0l,
11720 e7h, e7l, e6h, e6l, e5h, e5l, e4h, e4l]
11722 When necessary, quadword registers (dN, dN+1) are moved to ARM registers from
11725 dN -> (rN+1, rN), dN+1 -> (rN+3, rN+2)
11727 So that STM/LDM can be used on vectors in ARM registers, and the same memory
11728 layout will result as if VSTM/VLDM were used.
11730 This memory format (in BE mode) is very likely to change in the future. */
11733 output_move_neon (rtx
*operands
)
11735 rtx reg
, mem
, addr
, ops
[2];
11736 int regno
, load
= REG_P (operands
[0]);
11737 const char *template;
11739 enum machine_mode mode
;
11741 reg
= operands
[!load
];
11742 mem
= operands
[load
];
11744 mode
= GET_MODE (reg
);
11746 gcc_assert (REG_P (reg
));
11747 regno
= REGNO (reg
);
11748 gcc_assert (VFP_REGNO_OK_FOR_DOUBLE (regno
)
11749 || NEON_REGNO_OK_FOR_QUAD (regno
));
11750 gcc_assert (VALID_NEON_DREG_MODE (mode
)
11751 || VALID_NEON_QREG_MODE (mode
)
11752 || VALID_NEON_STRUCT_MODE (mode
));
11753 gcc_assert (MEM_P (mem
));
11755 addr
= XEXP (mem
, 0);
11757 /* Strip off const from addresses like (const (plus (...))). */
11758 if (GET_CODE (addr
) == CONST
&& GET_CODE (XEXP (addr
, 0)) == PLUS
)
11759 addr
= XEXP (addr
, 0);
11761 switch (GET_CODE (addr
))
11764 /* FIXME: We should be using vld1/vst1 here in BE mode? */
11765 template = "v%smia%%?\t%%0!, %%h1";
11766 ops
[0] = XEXP (addr
, 0);
11771 /* FIXME: Not currently enabled in neon_vector_mem_operand. */
11772 gcc_unreachable ();
11777 int nregs
= HARD_REGNO_NREGS (REGNO (reg
), mode
) / 2;
11780 for (i
= 0; i
< nregs
; i
++)
11782 /* We're only using DImode here because it's a convenient size.
11783 FIXME: This will need updating if the memory format of vectors
11785 ops
[0] = gen_rtx_REG (DImode
, REGNO (reg
) + 2 * i
);
11786 ops
[1] = adjust_address (mem
, SImode
, 8 * i
);
11787 if (reg_overlap_mentioned_p (ops
[0], mem
))
11789 gcc_assert (overlap
== -1);
11794 sprintf (buff
, "v%sr%%?\t%%P0, %%1", load
? "ld" : "st");
11795 output_asm_insn (buff
, ops
);
11800 ops
[0] = gen_rtx_REG (DImode
, REGNO (reg
) + 2 * overlap
);
11801 ops
[1] = adjust_address (mem
, SImode
, 8 * overlap
);
11802 sprintf (buff
, "v%sr%%?\t%%P0, %%1", load
? "ld" : "st");
11803 output_asm_insn (buff
, ops
);
11810 /* FIXME: See POST_INC. */
11811 template = "v%smia%%?\t%%m0, %%h1";
11816 sprintf (buff
, template, load
? "ld" : "st");
11817 output_asm_insn (buff
, ops
);
11822 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
11823 /* Output an ADD r, s, #n where n may be too big for one instruction.
11824 If adding zero to one register, output nothing. */
11826 output_add_immediate (rtx
*operands
)
11828 HOST_WIDE_INT n
= INTVAL (operands
[2]);
11830 if (n
!= 0 || REGNO (operands
[0]) != REGNO (operands
[1]))
11833 output_multi_immediate (operands
,
11834 "sub%?\t%0, %1, %2", "sub%?\t%0, %0, %2", 2,
11837 output_multi_immediate (operands
,
11838 "add%?\t%0, %1, %2", "add%?\t%0, %0, %2", 2,
11845 /* Output a multiple immediate operation.
11846 OPERANDS is the vector of operands referred to in the output patterns.
11847 INSTR1 is the output pattern to use for the first constant.
11848 INSTR2 is the output pattern to use for subsequent constants.
11849 IMMED_OP is the index of the constant slot in OPERANDS.
11850 N is the constant value. */
11851 static const char *
11852 output_multi_immediate (rtx
*operands
, const char *instr1
, const char *instr2
,
11853 int immed_op
, HOST_WIDE_INT n
)
11855 #if HOST_BITS_PER_WIDE_INT > 32
11861 /* Quick and easy output. */
11862 operands
[immed_op
] = const0_rtx
;
11863 output_asm_insn (instr1
, operands
);
11868 const char * instr
= instr1
;
11870 /* Note that n is never zero here (which would give no output). */
11871 for (i
= 0; i
< 32; i
+= 2)
11875 operands
[immed_op
] = GEN_INT (n
& (255 << i
));
11876 output_asm_insn (instr
, operands
);
11886 /* APPLE LOCAL begin v7 support. Merge from mainline */
11887 /* Return the name of a shifter operation. */
11888 static const char *
11889 arm_shift_nmem(enum rtx_code code
)
11894 return ARM_LSL_NAME
;
11910 /* APPLE LOCAL end v7 support. Merge from mainline */
11911 /* Return the appropriate ARM instruction for the operation code.
11912 The returned result should not be overwritten. OP is the rtx of the
11913 operation. SHIFT_FIRST_ARG is TRUE if the first argument of the operator
11916 arithmetic_instr (rtx op
, int shift_first_arg
)
11918 switch (GET_CODE (op
))
11924 return shift_first_arg
? "rsb" : "sub";
11935 /* APPLE LOCAL begin v7 support. Merge from mainline */
11940 return arm_shift_nmem(GET_CODE(op
));
11941 /* APPLE LOCAL end v7 support. Merge from mainline */
11944 gcc_unreachable ();
11948 /* Ensure valid constant shifts and return the appropriate shift mnemonic
11949 for the operation code. The returned result should not be overwritten.
11950 OP is the rtx code of the shift.
11951 On exit, *AMOUNTP will be -1 if the shift is by a register, or a constant
11953 static const char *
11954 shift_op (rtx op
, HOST_WIDE_INT
*amountp
)
11957 enum rtx_code code
= GET_CODE (op
);
11959 switch (GET_CODE (XEXP (op
, 1)))
11967 *amountp
= INTVAL (XEXP (op
, 1));
11971 gcc_unreachable ();
11974 /* APPLE LOCAL begin v7 support. Merge from mainline */
11978 gcc_assert (*amountp
!= -1);
11979 *amountp
= 32 - *amountp
;
11982 /* Fall through. */
11988 mnem
= arm_shift_nmem(code
);
11992 /* We never have to worry about the amount being other than a
11993 power of 2, since this case can never be reloaded from a reg. */
11994 gcc_assert (*amountp
!= -1);
11995 *amountp
= int_log2 (*amountp
);
11996 return ARM_LSL_NAME
;
11999 gcc_unreachable ();
12002 if (*amountp
!= -1)
12004 /* This is not 100% correct, but follows from the desire to merge
12005 multiplication by a power of 2 with the recognizer for a
12006 shift. >=32 is not a valid shift for "lsl", so we must try and
12007 output a shift that produces the correct arithmetical result.
12008 Using lsr #32 is identical except for the fact that the carry bit
12009 is not set correctly if we set the flags; but we never use the
12010 carry bit from such an operation, so we can ignore that. */
12011 if (code
== ROTATERT
)
12012 /* Rotate is just modulo 32. */
12014 else if (*amountp
!= (*amountp
& 31))
12016 if (code
== ASHIFT
)
12021 /* Shifts of 0 are no-ops. */
12025 /* APPLE LOCAL end v7 support. Merge from mainline */
12030 /* Obtain the shift from the POWER of two. */
12032 static HOST_WIDE_INT
12033 int_log2 (HOST_WIDE_INT power
)
12035 HOST_WIDE_INT shift
= 0;
12037 while ((((HOST_WIDE_INT
) 1 << shift
) & power
) == 0)
12039 gcc_assert (shift
<= 31);
12046 /* Output a .ascii pseudo-op, keeping track of lengths. This is
12047 because /bin/as is horribly restrictive. The judgement about
12048 whether or not each character is 'printable' (and can be output as
12049 is) or not (and must be printed with an octal escape) must be made
12050 with reference to the *host* character set -- the situation is
12051 similar to that discussed in the comments above pp_c_char in
12052 c-pretty-print.c. */
12054 #define MAX_ASCII_LEN 51
12057 output_ascii_pseudo_op (FILE *stream
, const unsigned char *p
, int len
)
12060 int len_so_far
= 0;
12062 fputs ("\t.ascii\t\"", stream
);
12064 for (i
= 0; i
< len
; i
++)
12068 if (len_so_far
>= MAX_ASCII_LEN
)
12070 fputs ("\"\n\t.ascii\t\"", stream
);
12076 if (c
== '\\' || c
== '\"')
12078 putc ('\\', stream
);
12086 fprintf (stream
, "\\%03o", c
);
12091 fputs ("\"\n", stream
);
12094 /* Compute the register save mask for registers 0 through 12
12095 inclusive. This code is used by arm_compute_save_reg_mask. */
12097 static unsigned long
12098 arm_compute_save_reg0_reg12_mask (void)
12100 unsigned long func_type
= arm_current_func_type ();
12101 unsigned long save_reg_mask
= 0;
12104 if (IS_INTERRUPT (func_type
))
12106 unsigned int max_reg
;
12107 /* Interrupt functions must not corrupt any registers,
12108 even call clobbered ones. If this is a leaf function
12109 we can just examine the registers used by the RTL, but
12110 otherwise we have to assume that whatever function is
12111 called might clobber anything, and so we have to save
12112 all the call-clobbered registers as well. */
12113 if (ARM_FUNC_TYPE (func_type
) == ARM_FT_FIQ
)
12114 /* FIQ handlers have registers r8 - r12 banked, so
12115 we only need to check r0 - r7, Normal ISRs only
12116 bank r14 and r15, so we must check up to r12.
12117 r13 is the stack pointer which is always preserved,
12118 so we do not need to consider it here. */
12123 for (reg
= 0; reg
<= max_reg
; reg
++)
12124 if (regs_ever_live
[reg
]
12125 || (! current_function_is_leaf
&& call_used_regs
[reg
]))
12126 save_reg_mask
|= (1 << reg
);
12128 /* Also save the pic base register if necessary. */
12130 && !TARGET_SINGLE_PIC_BASE
12131 && arm_pic_register
!= INVALID_REGNUM
12132 && current_function_uses_pic_offset_table
)
12133 save_reg_mask
|= 1 << PIC_OFFSET_TABLE_REGNUM
;
12137 /* APPLE LOCAL begin ARM custom frame layout */
12138 /* In the normal case we only need to save those registers
12139 which are call saved and which are used by this function. */
12140 for (reg
= 0; reg
<= 11; reg
++)
12141 if (regs_ever_live
[reg
] && ! call_used_regs
[reg
])
12142 save_reg_mask
|= (1 << reg
);
12144 /* Handle the frame pointer as a special case. */
12145 if (frame_pointer_needed
)
12146 save_reg_mask
|= 1 << HARD_FRAME_POINTER_REGNUM
;
12147 /* APPLE LOCAL end ARM use custom frame layout */
12149 /* If we aren't loading the PIC register,
12150 don't stack it even though it may be live. */
12152 && !TARGET_SINGLE_PIC_BASE
12153 && arm_pic_register
!= INVALID_REGNUM
12154 && (regs_ever_live
[PIC_OFFSET_TABLE_REGNUM
]
12155 || current_function_uses_pic_offset_table
))
12156 save_reg_mask
|= 1 << PIC_OFFSET_TABLE_REGNUM
;
12158 /* APPLE LOCAL begin v7 support. Merge from mainline */
12159 /* The prologue will copy SP into R0, so save it. */
12160 if (IS_STACKALIGN (func_type
))
12161 save_reg_mask
|= 1;
12162 /* APPLE LOCAL end v7 support. Merge from mainline */
12165 /* Save registers so the exception handler can modify them. */
12166 if (current_function_calls_eh_return
)
12172 reg
= EH_RETURN_DATA_REGNO (i
);
12173 if (reg
== INVALID_REGNUM
)
12175 save_reg_mask
|= 1 << reg
;
12179 return save_reg_mask
;
12182 /* Compute a bit mask of which registers need to be
12183 saved on the stack for the current function. */
12185 static unsigned long
12186 arm_compute_save_reg_mask (void)
12188 unsigned int save_reg_mask
= 0;
12189 unsigned long func_type
= arm_current_func_type ();
12190 /* APPLE LOCAL v7 support. Merge from mainline */
12193 if (IS_NAKED (func_type
))
12194 /* This should never really happen. */
12197 /* APPLE LOCAL begin ARM use custom frame layout */
12198 /* Volatile functions do not return, so there
12199 is no need to save any other registers. */
12200 if (!IS_VOLATILE (func_type
))
12201 save_reg_mask
|= arm_compute_save_reg0_reg12_mask ();
12202 /* APPLE LOCAL end ARM use custom frame layout */
12204 /* Decide if we need to save the link register.
12205 Interrupt routines have their own banked link register,
12206 so they never need to save it.
12207 Otherwise if we do not use the link register we do not need to save
12208 it. If we are pushing other registers onto the stack however, we
12209 can save an instruction in the epilogue by pushing the link register
12210 now and then popping it back into the PC. This incurs extra memory
12211 accesses though, so we only do it when optimizing for size, and only
12212 if we know that we will not need a fancy return sequence. */
12213 if (regs_ever_live
[LR_REGNUM
]
12216 && ARM_FUNC_TYPE (func_type
) == ARM_FT_NORMAL
12217 && !current_function_calls_eh_return
))
12218 save_reg_mask
|= 1 << LR_REGNUM
;
12220 if (cfun
->machine
->lr_save_eliminated
)
12221 save_reg_mask
&= ~ (1 << LR_REGNUM
);
12223 /* APPLE LOCAL begin ARM custom frame layout */
12224 if (frame_pointer_needed
)
12225 save_reg_mask
|= (1 << LR_REGNUM
| 1 << HARD_FRAME_POINTER_REGNUM
);
12226 /* APPLE LOCAL end ARM custom frame layout */
12228 if (TARGET_REALLY_IWMMXT
12229 /* APPLE LOCAL ARM custom frame layout */
12230 && (!IS_VOLATILE (func_type
))
12231 && ((bit_count (save_reg_mask
)
12232 + ARM_NUM_INTS (current_function_pretend_args_size
)) % 2) != 0)
12234 /* APPLE LOCAL v7 support. Merge from mainline */
12235 /* moved definition of 'reg' to function level scope */
12236 /* The total number of registers that are going to be pushed
12237 onto the stack is odd. We need to ensure that the stack
12238 is 64-bit aligned before we start to save iWMMXt registers,
12239 and also before we start to create locals. (A local variable
12240 might be a double or long long which we will load/store using
12241 an iWMMXt instruction). Therefore we need to push another
12242 ARM register, so that the stack will be 64-bit aligned. We
12243 try to avoid using the arg registers (r0 -r3) as they might be
12244 used to pass values in a tail call. */
12245 for (reg
= 4; reg
<= 12; reg
++)
12246 if ((save_reg_mask
& (1 << reg
)) == 0)
12250 save_reg_mask
|= (1 << reg
);
12253 cfun
->machine
->sibcall_blocked
= 1;
12254 save_reg_mask
|= (1 << 3);
12258 /* APPLE LOCAL begin v7 support. Merge from mainline */
12259 /* We may need to push an additional register for use initializing the
12260 PIC base register. */
12261 if (TARGET_THUMB2
&& IS_NESTED (func_type
) && flag_pic
12262 && (save_reg_mask
& THUMB2_WORK_REGS
) == 0)
12264 reg
= thumb_find_work_register (1 << 4);
12265 if (!call_used_regs
[reg
])
12266 save_reg_mask
|= (1 << reg
);
12269 /* APPLE LOCAL end v7 support. Merge from mainline */
12270 return save_reg_mask
;
12274 /* Compute a bit mask of which registers need to be
12275 saved on the stack for the current function. */
12276 static unsigned long
12277 /* APPLE LOCAL v7 support. Merge from mainline */
12278 thumb1_compute_save_reg_mask (void)
12280 unsigned long mask
;
12284 for (reg
= 0; reg
< 12; reg
++)
12285 if (regs_ever_live
[reg
] && !call_used_regs
[reg
])
12288 /* APPLE LOCAL begin ARM thumb requires FP */
12289 if (frame_pointer_needed
)
12290 mask
|= 1 << THUMB_HARD_FRAME_POINTER_REGNUM
;
12291 /* APPLE LOCAL end ARM thumb requires FP */
12294 && !TARGET_SINGLE_PIC_BASE
12295 && arm_pic_register
!= INVALID_REGNUM
12296 && current_function_uses_pic_offset_table
)
12297 mask
|= 1 << PIC_OFFSET_TABLE_REGNUM
;
12299 /* See if we might need r11 for calls to _interwork_r11_call_via_rN(). */
12300 if (!frame_pointer_needed
&& CALLER_INTERWORKING_SLOT_SIZE
> 0)
12301 mask
|= 1 << ARM_HARD_FRAME_POINTER_REGNUM
;
12303 /* LR will also be pushed if any lo regs are pushed. */
12304 if (mask
& 0xff || thumb_force_lr_save ())
12305 mask
|= (1 << LR_REGNUM
);
12307 /* Make sure we have a low work register if we need one.
12308 We will need one if we are going to push a high register,
12309 but we are not currently intending to push a low register. */
12310 if ((mask
& 0xff) == 0
12311 && ((mask
& 0x0f00) || TARGET_BACKTRACE
))
12313 /* Use thumb_find_work_register to choose which register
12314 we will use. If the register is live then we will
12315 have to push it. Use LAST_LO_REGNUM as our fallback
12316 choice for the register to select. */
12317 /* APPLE LOCAL ARM thumb requires FP */
12318 reg
= thumb_find_work_register (1 << (LAST_LO_REGNUM
- 1));
12320 if (! call_used_regs
[reg
])
12324 /* APPLE LOCAL begin ARM custom frame layout */
12325 /* Also need a scratch register in the case where the frame size is
12326 too big for the subtract instruction. This is not exactly the right
12327 computation for frame size, there's a circular dependency on which
12328 registers get saved, but it should catch most of the problem cases
12329 and there is (very inefficient) code to handle the rare case where
12330 we didn't allocate a scratch reg and need one. */
12331 if (frame_pointer_needed
&& ((mask
& 0x70) == 0)
12332 && (ROUND_UP_WORD (get_frame_size ())
12333 + current_function_outgoing_args_size
) >= 512)
12334 mask
|= 1 << (LAST_LO_REGNUM
- 1);
12335 /* APPLE LOCAL end ARM custom frame layout */
12341 /* Return the number of bytes required to save VFP registers. */
12343 arm_get_vfp_saved_size (void)
12345 unsigned int regno
;
12350 /* Space for saved VFP registers. */
12351 if (TARGET_HARD_FLOAT
&& TARGET_VFP
)
12354 for (regno
= FIRST_VFP_REGNUM
;
12355 regno
< LAST_VFP_REGNUM
;
12358 if ((!regs_ever_live
[regno
] || call_used_regs
[regno
])
12359 && (!regs_ever_live
[regno
+ 1] || call_used_regs
[regno
+ 1]))
12363 /* Workaround ARM10 VFPr1 bug. */
12364 if (count
== 2 && !arm_arch6
)
12366 /* APPLE LOCAL v7 support. Merge from mainline */
12367 saved
+= count
* 8;
12376 if (count
== 2 && !arm_arch6
)
12378 /* APPLE LOCAL v7 support. Merge from mainline */
12379 saved
+= count
* 8;
12386 /* Generate a function exit sequence. If REALLY_RETURN is false, then do
12387 everything bar the final return instruction. */
12389 output_return_instruction (rtx operand
, int really_return
, int reverse
)
12391 char conditional
[10];
12394 unsigned long live_regs_mask
;
12395 unsigned long func_type
;
12396 arm_stack_offsets
*offsets
;
12398 func_type
= arm_current_func_type ();
12400 if (IS_NAKED (func_type
))
12403 if (IS_VOLATILE (func_type
) && TARGET_ABORT_NORETURN
)
12405 /* If this function was declared non-returning, and we have
12406 found a tail call, then we have to trust that the called
12407 function won't return. */
12412 /* Otherwise, trap an attempted return by aborting. */
12414 ops
[1] = gen_rtx_SYMBOL_REF (Pmode
, NEED_PLT_RELOC
? "abort(PLT)"
12416 assemble_external_libcall (ops
[1]);
12417 output_asm_insn (reverse
? "bl%D0\t%a1" : "bl%d0\t%a1", ops
);
12423 gcc_assert (!current_function_calls_alloca
|| really_return
);
12425 sprintf (conditional
, "%%?%%%c0", reverse
? 'D' : 'd');
12427 return_used_this_function
= 1;
12429 live_regs_mask
= arm_compute_save_reg_mask ();
12431 if (live_regs_mask
)
12433 const char * return_reg
;
12435 /* If we do not have any special requirements for function exit
12436 (e.g. interworking, or ISR) then we can load the return address
12437 directly into the PC. Otherwise we must load it into LR. */
12439 /* APPLE LOCAL ARM interworking */
12440 && (! TARGET_INTERWORK
|| arm_arch5
))
12441 return_reg
= reg_names
[PC_REGNUM
];
12443 return_reg
= reg_names
[LR_REGNUM
];
12445 if ((live_regs_mask
& (1 << IP_REGNUM
)) == (1 << IP_REGNUM
))
12447 /* There are three possible reasons for the IP register
12448 being saved. 1) a stack frame was created, in which case
12449 IP contains the old stack pointer, or 2) an ISR routine
12450 corrupted it, or 3) it was saved to align the stack on
12451 iWMMXt. In case 1, restore IP into SP, otherwise just
12453 if (frame_pointer_needed
)
12455 live_regs_mask
&= ~ (1 << IP_REGNUM
);
12456 live_regs_mask
|= (1 << SP_REGNUM
);
12459 gcc_assert (IS_INTERRUPT (func_type
) || TARGET_REALLY_IWMMXT
);
12462 /* On some ARM architectures it is faster to use LDR rather than
12463 LDM to load a single register. On other architectures, the
12464 cost is the same. In 26 bit mode, or for exception handlers,
12465 we have to use LDM to load the PC so that the CPSR is also
12467 for (reg
= 0; reg
<= LAST_ARM_REGNUM
; reg
++)
12468 if (live_regs_mask
== (1U << reg
))
12471 if (reg
<= LAST_ARM_REGNUM
12472 && (reg
!= LR_REGNUM
12474 || ! IS_INTERRUPT (func_type
)))
12476 sprintf (instr
, "ldr%s\t%%|%s, [%%|sp], #4", conditional
,
12477 (reg
== LR_REGNUM
) ? return_reg
: reg_names
[reg
]);
12484 /* Generate the load multiple instruction to restore the
12485 registers. Note we can get here, even if
12486 frame_pointer_needed is true, but only if sp already
12487 points to the base of the saved core registers. */
12488 if (live_regs_mask
& (1 << SP_REGNUM
))
12490 unsigned HOST_WIDE_INT stack_adjust
;
12492 offsets
= arm_get_frame_offsets ();
12493 stack_adjust
= offsets
->outgoing_args
- offsets
->saved_regs
;
12494 gcc_assert (stack_adjust
== 0 || stack_adjust
== 4);
12496 /* APPLE LOCAL v7 support. Merge from mainline */
12497 if (stack_adjust
&& arm_arch5
&& TARGET_ARM
)
12498 sprintf (instr
, "ldm%sib\t%%|sp, {", conditional
);
12501 /* If we can't use ldmib (SA110 bug),
12502 then try to pop r3 instead. */
12504 live_regs_mask
|= 1 << 3;
12505 sprintf (instr
, "ldm%sfd\t%%|sp, {", conditional
);
12509 sprintf (instr
, "ldm%sfd\t%%|sp!, {", conditional
);
12511 p
= instr
+ strlen (instr
);
12513 for (reg
= 0; reg
<= SP_REGNUM
; reg
++)
12514 if (live_regs_mask
& (1 << reg
))
12516 int l
= strlen (reg_names
[reg
]);
12522 memcpy (p
, ", ", 2);
12526 memcpy (p
, "%|", 2);
12527 memcpy (p
+ 2, reg_names
[reg
], l
);
12531 if (live_regs_mask
& (1 << LR_REGNUM
))
12533 sprintf (p
, "%s%%|%s}", first
? "" : ", ", return_reg
);
12534 /* If returning from an interrupt, restore the CPSR. */
12535 if (IS_INTERRUPT (func_type
))
12542 output_asm_insn (instr
, & operand
);
12544 /* See if we need to generate an extra instruction to
12545 perform the actual function return. */
12547 && func_type
!= ARM_FT_INTERWORKED
12548 && (live_regs_mask
& (1 << LR_REGNUM
)) != 0)
12550 /* The return has already been handled
12551 by loading the LR into the PC. */
12558 switch ((int) ARM_FUNC_TYPE (func_type
))
12562 /* APPLE LOCAL v7 support. Merge from mainline */
12563 /* ??? This is wrong for unified assembly syntax. */
12564 sprintf (instr
, "sub%ss\t%%|pc, %%|lr, #4", conditional
);
12567 case ARM_FT_INTERWORKED
:
12568 sprintf (instr
, "bx%s\t%%|lr", conditional
);
12571 case ARM_FT_EXCEPTION
:
12572 /* APPLE LOCAL v7 support. Merge from mainline */
12573 /* ??? This is wrong for unified assembly syntax. */
12574 sprintf (instr
, "mov%ss\t%%|pc, %%|lr", conditional
);
12578 /* Use bx if it's available. */
12579 if (arm_arch5
|| arm_arch4t
)
12580 sprintf (instr
, "bx%s\t%%|lr", conditional
);
12582 sprintf (instr
, "mov%s\t%%|pc, %%|lr", conditional
);
12586 output_asm_insn (instr
, & operand
);
12592 /* Write the function name into the code section, directly preceding
12593 the function prologue.
12595 Code will be output similar to this:
12597 .ascii "arm_poke_function_name", 0
12600 .word 0xff000000 + (t1 - t0)
12601 arm_poke_function_name
12603 stmfd sp!, {fp, ip, lr, pc}
12606 When performing a stack backtrace, code can inspect the value
12607 of 'pc' stored at 'fp' + 0. If the trace function then looks
12608 at location pc - 12 and the top 8 bits are set, then we know
12609 that there is a function name embedded immediately preceding this
12610 location and has length ((pc[-3]) & 0xff000000).
12612 We assume that pc is declared as a pointer to an unsigned long.
12614 It is of no benefit to output the function name if we are assembling
12615 a leaf function. These function types will not contain a stack
12616 backtrace structure, therefore it is not possible to determine the
12619 arm_poke_function_name (FILE *stream
, const char *name
)
12621 unsigned long alignlength
;
12622 unsigned long length
;
12625 length
= strlen (name
) + 1;
12626 alignlength
= ROUND_UP_WORD (length
);
12628 ASM_OUTPUT_ASCII (stream
, name
, length
);
12629 ASM_OUTPUT_ALIGN (stream
, 2);
12630 x
= GEN_INT ((unsigned HOST_WIDE_INT
) 0xff000000 + alignlength
);
12631 assemble_aligned_integer (UNITS_PER_WORD
, x
);
12634 /* Place some comments into the assembler stream
12635 describing the current function. */
12637 arm_output_function_prologue (FILE *f
, HOST_WIDE_INT frame_size
)
12639 unsigned long func_type
;
12641 /* APPLE LOCAL begin v7 support. Merge from mainline */
12644 thumb1_output_function_prologue (f
, frame_size
);
12647 /* APPLE LOCAL end v7 support. Merge from mainline */
12649 /* Sanity check. */
12650 gcc_assert (!arm_ccfsm_state
&& !arm_target_insn
);
12652 func_type
= arm_current_func_type ();
12654 switch ((int) ARM_FUNC_TYPE (func_type
))
12657 case ARM_FT_NORMAL
:
12659 case ARM_FT_INTERWORKED
:
12660 asm_fprintf (f
, "\t%@ Function supports interworking.\n");
12663 asm_fprintf (f
, "\t%@ Interrupt Service Routine.\n");
12666 asm_fprintf (f
, "\t%@ Fast Interrupt Service Routine.\n");
12668 case ARM_FT_EXCEPTION
:
12669 asm_fprintf (f
, "\t%@ ARM Exception Handler.\n");
12673 if (IS_NAKED (func_type
))
12674 asm_fprintf (f
, "\t%@ Naked Function: prologue and epilogue provided by programmer.\n");
12676 if (IS_VOLATILE (func_type
))
12677 asm_fprintf (f
, "\t%@ Volatile: function does not return.\n");
12679 if (IS_NESTED (func_type
))
12680 asm_fprintf (f
, "\t%@ Nested: function declared inside another function.\n");
12681 /* APPLE LOCAL begin v7 support. Merge from mainline */
12682 if (IS_STACKALIGN (func_type
))
12683 asm_fprintf (f
, "\t%@ Stack Align: May be called with mis-aligned SP.\n");
12684 /* APPLE LOCAL end v7 support. Merge from mainline */
12686 asm_fprintf (f
, "\t%@ args = %d, pretend = %d, frame = %wd\n",
12687 current_function_args_size
,
12688 current_function_pretend_args_size
, frame_size
);
12690 asm_fprintf (f
, "\t%@ frame_needed = %d, uses_anonymous_args = %d\n",
12691 frame_pointer_needed
,
12692 cfun
->machine
->uses_anonymous_args
);
12694 if (cfun
->machine
->lr_save_eliminated
)
12695 asm_fprintf (f
, "\t%@ link register save eliminated.\n");
12697 if (current_function_calls_eh_return
)
12698 asm_fprintf (f
, "\t@ Calls __builtin_eh_return.\n");
12700 #ifdef AOF_ASSEMBLER
12702 asm_fprintf (f
, "\tmov\t%r, %r\n", IP_REGNUM
, PIC_OFFSET_TABLE_REGNUM
);
12705 return_used_this_function
= 0;
12708 /* APPLE LOCAL begin 6902937 out of order VFP restore */
12710 arm_output_epilogue_vfp_restore (void)
12712 int reg
, start_reg
;
12713 FILE * f
= asm_out_file
;
12714 start_reg
= LAST_VFP_REGNUM
- 1;
12715 for (reg
= LAST_VFP_REGNUM
- 1 ; reg
>= FIRST_VFP_REGNUM
; reg
-= 2)
12717 if ((!regs_ever_live
[reg
] || call_used_regs
[reg
])
12718 && (!regs_ever_live
[reg
+ 1] || call_used_regs
[reg
+ 1]))
12720 if (start_reg
!= reg
)
12721 vfp_output_fldmd (f
, SP_REGNUM
,
12722 (reg
- FIRST_VFP_REGNUM
) / 2 + 1,
12723 (start_reg
- reg
) / 2);
12724 start_reg
= reg
- 2;
12727 if (start_reg
!= reg
)
12728 vfp_output_fldmd (f
, SP_REGNUM
,
12729 (reg
- FIRST_VFP_REGNUM
+ 2) / 2 + 1,
12730 (start_reg
- reg
) / 2);
12732 /* APPLE LOCAL end 6902937 out of order VFP restore */
12735 arm_output_epilogue (rtx sibling
)
12738 unsigned long saved_regs_mask
;
12739 unsigned long func_type
;
12740 /* Floats_offset is the offset from the "virtual" frame. In an APCS
12741 frame that is $fp + 4 for a non-variadic function. */
12742 int floats_offset
= 0;
12744 FILE * f
= asm_out_file
;
12745 unsigned int lrm_count
= 0;
12746 int really_return
= (sibling
== NULL
);
12748 arm_stack_offsets
*offsets
;
12749 /* APPLE LOCAL 6196857 use pop for thumb-2 epilogue */
12750 const char *pop_insn
;
12752 /* If we have already generated the return instruction
12753 then it is futile to generate anything else. */
12754 if (use_return_insn (FALSE
, sibling
) && return_used_this_function
)
12757 func_type
= arm_current_func_type ();
12759 if (IS_NAKED (func_type
))
12760 /* Naked functions don't have epilogues. */
12763 if (IS_VOLATILE (func_type
) && TARGET_ABORT_NORETURN
)
12767 /* A volatile function should never return. Call abort. */
12768 op
= gen_rtx_SYMBOL_REF (Pmode
, NEED_PLT_RELOC
? "abort(PLT)" : "abort");
12769 assemble_external_libcall (op
);
12770 output_asm_insn ("bl\t%a0", &op
);
12775 /* If we are throwing an exception, then we really must be doing a
12776 return, so we can't tail-call. */
12777 gcc_assert (!current_function_calls_eh_return
|| really_return
);
12779 offsets
= arm_get_frame_offsets ();
12780 saved_regs_mask
= arm_compute_save_reg_mask ();
12783 lrm_count
= bit_count (saved_regs_mask
);
12785 floats_offset
= offsets
->saved_args
;
12786 /* Compute how far away the floats will be. */
12787 for (reg
= 0; reg
<= LAST_ARM_REGNUM
; reg
++)
12788 if (saved_regs_mask
& (1 << reg
))
12789 floats_offset
+= 4;
12791 /* APPLE LOCAL v7 support. Merge from mainline */
12792 if (frame_pointer_needed
&& TARGET_32BIT
)
12794 /* This variable is for the Virtual Frame Pointer, not VFP regs. */
12795 int vfp_offset
= offsets
->frame
;
12796 /* APPLE LOCAL begin ARM custom frame layout */
12797 unsigned long regs_above_fp
=
12798 inclusive_bitmask (ARM_HARD_FRAME_POINTER_REGNUM
+ 1, 11);
12799 /* APPLE LOCAL end ARM custom frame layout */
12801 if (arm_fpu_arch
== FPUTYPE_FPA_EMU2
)
12803 for (reg
= LAST_FPA_REGNUM
; reg
>= FIRST_FPA_REGNUM
; reg
--)
12804 if (regs_ever_live
[reg
] && !call_used_regs
[reg
])
12806 floats_offset
+= 12;
12807 asm_fprintf (f
, "\tldfe\t%r, [%r, #-%d]\n",
12808 reg
, FP_REGNUM
, floats_offset
- vfp_offset
);
12813 start_reg
= LAST_FPA_REGNUM
;
12815 for (reg
= LAST_FPA_REGNUM
; reg
>= FIRST_FPA_REGNUM
; reg
--)
12817 if (regs_ever_live
[reg
] && !call_used_regs
[reg
])
12819 floats_offset
+= 12;
12821 /* We can't unstack more than four registers at once. */
12822 if (start_reg
- reg
== 3)
12824 asm_fprintf (f
, "\tlfm\t%r, 4, [%r, #-%d]\n",
12825 reg
, FP_REGNUM
, floats_offset
- vfp_offset
);
12826 start_reg
= reg
- 1;
12831 if (reg
!= start_reg
)
12832 asm_fprintf (f
, "\tlfm\t%r, %d, [%r, #-%d]\n",
12833 reg
+ 1, start_reg
- reg
,
12834 FP_REGNUM
, floats_offset
- vfp_offset
);
12835 start_reg
= reg
- 1;
12839 /* Just in case the last register checked also needs unstacking. */
12840 if (reg
!= start_reg
)
12841 asm_fprintf (f
, "\tlfm\t%r, %d, [%r, #-%d]\n",
12842 reg
+ 1, start_reg
- reg
,
12843 FP_REGNUM
, floats_offset
- vfp_offset
);
12846 if (TARGET_HARD_FLOAT
&& TARGET_VFP
)
12850 /* APPLE LOCAL begin 4809156 */
12851 /* APPLE LOCAL begin v7 support. Merge from mainline */
12852 /* The fldmd insns do not have base+offset addressing modes,
12853 so we use SP to hold the address. (IP might have a
12854 live value in it for indirect sibcalls, can't use that.) */
12855 /* APPLE LOCAL end v7 support. Merge from mainline */
12856 saved_size
= arm_get_vfp_saved_size ();
12858 if (saved_size
> 0)
12860 floats_offset
+= saved_size
;
12861 asm_fprintf (f
, "\tsub\t%r, %r, #%d\n", SP_REGNUM
,
12862 FP_REGNUM
, floats_offset
- vfp_offset
);
12864 /* APPLE LOCAL 6902937 out of order VFP restore */
12865 arm_output_epilogue_vfp_restore ();
12866 /* APPLE LOCAL end 4809156 */
12871 /* The frame pointer is guaranteed to be non-double-word aligned.
12872 This is because it is set to (old_stack_pointer - 4) and the
12873 old_stack_pointer was double word aligned. Thus the offset to
12874 the iWMMXt registers to be loaded must also be non-double-word
12875 sized, so that the resultant address *is* double-word aligned.
12876 We can ignore floats_offset since that was already included in
12877 the live_regs_mask. */
12878 lrm_count
+= (lrm_count
% 2 ? 2 : 1);
12880 for (reg
= LAST_IWMMXT_REGNUM
; reg
>= FIRST_IWMMXT_REGNUM
; reg
--)
12881 if (regs_ever_live
[reg
] && !call_used_regs
[reg
])
12883 asm_fprintf (f
, "\twldrd\t%r, [%r, #-%d]\n",
12884 reg
, FP_REGNUM
, lrm_count
* 4);
12889 /* APPLE LOCAL ARM custom frame layout */
12890 /* Removed lines. */
12892 /* APPLE LOCAL begin ARM indirect sibcalls */
12893 /* If we have an indirect sibcall that uses a reg saved across calls, that reg will
12894 be clobbered when we pop the old value off the stack. Copy the value to IP
12895 before doing the pop. */
12899 int regno
= indirect_sibreturn_reg (sibling
, &is_value
);
12900 if (regno
> 3 && regno
!= 12)
12903 XEXP (XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 1), 0), 0)
12904 = gen_rtx_REG (SImode
, IP_REGNUM
);
12906 XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 0), 0)
12907 = gen_rtx_REG (SImode
, IP_REGNUM
);
12908 asm_fprintf (f
, "\tmov\t%r, %r\n", IP_REGNUM
, regno
);
12912 rtx stack_reg
, offset
;
12913 offset
= indirect_sibreturn_mem (sibling
, &stack_reg
, &is_value
);
12917 XEXP (XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 1), 0), 0)
12918 = gen_rtx_REG (SImode
, IP_REGNUM
);
12920 XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 0), 0)
12921 = gen_rtx_REG (SImode
, IP_REGNUM
);
12922 asm_fprintf (f
, "\tldr\t%r, [%r, #%wd]\n", IP_REGNUM
,
12923 REGNO (stack_reg
), INTVAL (offset
));
12927 /* APPLE LOCAL end ARM indirect sibcalls */
12929 /* We must use SP as the base register, because SP is one of the
12930 registers being restored. If an interrupt or page fault
12931 happens in the ldm instruction, the SP might or might not
12932 have been restored. That would be bad, as then SP will no
12933 longer indicate the safe area of stack, and we can get stack
12934 corruption. Using SP as the base register means that it will
12935 be reset correctly to the original value, should an interrupt
12936 occur. If the stack pointer already points at the right
12937 place, then omit the subtraction. */
12939 /* APPLE LOCAL begin ARM custom frame layout */
12940 if ((offsets
->outgoing_args
- offsets
->saved_args
12941 != (signed) bit_count (saved_regs_mask
) * 4)
12942 || ! current_function_sp_is_unchanging
)
12943 /* FP points 8 bytes into the frame. */
12944 asm_fprintf (f
, "\tsub\t%r, %r, #%d\n", SP_REGNUM
, FP_REGNUM
,
12945 (bit_count (saved_regs_mask
) - 2) * 4);
12947 /* If we can, restore the LR into the PC. */
12948 if (ARM_FUNC_TYPE (func_type
) == ARM_FT_NORMAL
12950 && current_function_pretend_args_size
== 0
12951 && saved_regs_mask
& (1 << LR_REGNUM
)
12952 && !current_function_calls_eh_return
)
12954 saved_regs_mask
&= ~ (1 << LR_REGNUM
);
12955 saved_regs_mask
|= (1 << PC_REGNUM
);
12958 /* We mustn't be trying to restore SP from the stack. */
12959 gcc_assert (! (saved_regs_mask
& (1 << SP_REGNUM
)));
12961 /* APPLE LOCAL 6196857 begin use pop for thumb-2 epilogue */
12963 pop_insn
= "ldmfd\t%r!, ";
12964 else /* (TARGET_THUMB2) */
12965 pop_insn
= "pop\t";
12967 /* APPLE LOCAL begin v7 support. Merge from mainline */
12968 if (saved_regs_mask
& regs_above_fp
)
12970 print_multi_reg (f
, pop_insn
, SP_REGNUM
,
12971 saved_regs_mask
& regs_above_fp
);
12972 print_multi_reg (f
, pop_insn
, SP_REGNUM
,
12973 saved_regs_mask
& ~regs_above_fp
);
12976 print_multi_reg (f
, pop_insn
, SP_REGNUM
, saved_regs_mask
);
12977 /* APPLE LOCAL end v7 support. Merge from mainline */
12978 /* APPLE LOCAL 6196857 begin use pop for thumb-2 epilogue */
12980 if (current_function_pretend_args_size
)
12982 /* Unwind the pre-pushed regs. */
12983 operands
[0] = operands
[1] = stack_pointer_rtx
;
12984 operands
[2] = GEN_INT (current_function_pretend_args_size
);
12985 output_add_immediate (operands
);
12987 /* APPLE LOCAL end ARM custom frame layout */
12989 if (IS_INTERRUPT (func_type
))
12990 /* Interrupt handlers will have pushed the
12991 IP onto the stack, so restore it now. */
12992 /* APPLE LOCAL v7 support. Merge from mainline */
12993 print_multi_reg (f
, "ldmfd\t%r!, ", SP_REGNUM
, 1 << IP_REGNUM
);
12997 /* APPLE LOCAL begin ARM indirect sibcalls */
13000 /* If we have an indirect sibcall that uses a reg saved across calls, that reg will
13001 be clobbered when we pop the old value off the stack. Copy the value to IP
13002 before doing the pop. */
13006 int regno
= indirect_sibreturn_reg (sibling
, &is_value
);
13007 if (regno
> 3 && regno
!= 12)
13011 XEXP (XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 1), 0), 0)
13012 = gen_rtx_REG (SImode
, IP_REGNUM
);
13014 XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 0), 0)
13015 = gen_rtx_REG (SImode
, IP_REGNUM
);
13016 asm_fprintf (f
, "\tmov\t%r, %r\n", IP_REGNUM
, regno
);
13020 rtx stack_reg
, offset
;
13021 offset
= indirect_sibreturn_mem (sibling
, &stack_reg
, &is_value
);
13026 XEXP (XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 1), 0), 0)
13027 = gen_rtx_REG (SImode
, IP_REGNUM
);
13029 XEXP (XEXP (XVECEXP (PATTERN (sibling
), 0, 0), 0), 0)
13030 = gen_rtx_REG (SImode
, IP_REGNUM
);
13031 asm_fprintf (f
, "\tldr\t%r, [%r, #%wd]\n", IP_REGNUM
,
13032 REGNO (stack_reg
), INTVAL (offset
));
13037 /* APPLE LOCAL begin ARM combine stack pop and register pop */
13038 /* Code here is probably making overly specific assumptions about modes. */
13039 /* Restore stack pointer if necessary. */
13040 if (offsets
->outgoing_args
!= offsets
->saved_regs
)
13042 int delta
= offsets
->outgoing_args
- offsets
->saved_regs
;
13044 tree rettype
= TREE_TYPE (TREE_TYPE (current_function_decl
));
13045 /* We can use R0 through R3 for this purpose, but not any regs that
13046 contain (part of) the return value. */
13047 if (TYPE_MODE (rettype
) == VOIDmode
)
13049 else if (TYPE_MODE (rettype
) == DFmode
13050 || TYPE_MODE (rettype
) == DImode
)
13054 /* We can also use R12 provided it was not used for the sibcall hack above,
13055 and we are not saving any regs in the range R4...R11. In the latter case
13056 they are stored on the stack below the "empty" spot used for R12 and
13057 the saved values would get clobbered. */
13058 if (saved_regs_mask
13059 & ((1<<4) | (1<<5) | (1<<6) | (1<<7) | (1<<8) | (1<<9) | (1<<10) | (1<<11)))
13064 && delta
<= maxpopsize
&& delta
% 4 == 0
13067 && TARGET_SOFT_FLOAT
13068 && arm_fpu_arch
== FPUTYPE_NONE
13070 && !frame_pointer_needed
)
13072 int reg
= ip_ok
? 12 : 3;
13075 saved_regs_mask
|= (1 << reg
);
13076 reg
= (reg
== 12) ? 3 : reg
- 1;
13082 operands
[0] = operands
[1] = stack_pointer_rtx
;
13083 operands
[2] = GEN_INT (offsets
->outgoing_args
- offsets
->saved_regs
);
13084 output_add_immediate (operands
);
13087 /* APPLE LOCAL end ARM combine stack pop and register pop */
13088 /* APPLE LOCAL end ARM indirect sibcalls */
13090 if (arm_fpu_arch
== FPUTYPE_FPA_EMU2
)
13092 for (reg
= FIRST_FPA_REGNUM
; reg
<= LAST_FPA_REGNUM
; reg
++)
13093 if (regs_ever_live
[reg
] && !call_used_regs
[reg
])
13094 asm_fprintf (f
, "\tldfe\t%r, [%r], #12\n",
13099 start_reg
= FIRST_FPA_REGNUM
;
13101 for (reg
= FIRST_FPA_REGNUM
; reg
<= LAST_FPA_REGNUM
; reg
++)
13103 if (regs_ever_live
[reg
] && !call_used_regs
[reg
])
13105 if (reg
- start_reg
== 3)
13107 asm_fprintf (f
, "\tlfmfd\t%r, 4, [%r]!\n",
13108 start_reg
, SP_REGNUM
);
13109 start_reg
= reg
+ 1;
13114 if (reg
!= start_reg
)
13115 asm_fprintf (f
, "\tlfmfd\t%r, %d, [%r]!\n",
13116 start_reg
, reg
- start_reg
,
13119 start_reg
= reg
+ 1;
13123 /* Just in case the last register checked also needs unstacking. */
13124 if (reg
!= start_reg
)
13125 asm_fprintf (f
, "\tlfmfd\t%r, %d, [%r]!\n",
13126 start_reg
, reg
- start_reg
, SP_REGNUM
);
13129 if (TARGET_HARD_FLOAT
&& TARGET_VFP
)
13131 /* APPLE LOCAL 6902937 out of order VFP restore */
13132 arm_output_epilogue_vfp_restore ();
13135 for (reg
= FIRST_IWMMXT_REGNUM
; reg
<= LAST_IWMMXT_REGNUM
; reg
++)
13136 if (regs_ever_live
[reg
] && !call_used_regs
[reg
])
13137 asm_fprintf (f
, "\twldrd\t%r, [%r], #8\n", reg
, SP_REGNUM
);
13139 /* If we can, restore the LR into the PC. */
13140 if (ARM_FUNC_TYPE (func_type
) == ARM_FT_NORMAL
13141 /* APPLE LOCAL v7 support. Merge from mainline */
13142 && !IS_STACKALIGN (func_type
)
13144 && current_function_pretend_args_size
== 0
13145 && saved_regs_mask
& (1 << LR_REGNUM
)
13146 && !current_function_calls_eh_return
)
13148 saved_regs_mask
&= ~ (1 << LR_REGNUM
);
13149 saved_regs_mask
|= (1 << PC_REGNUM
);
13152 /* APPLE LOCAL begin v7 support. Merge from mainline */
13153 /* Load the registers off the stack. If we only have one register
13154 to load use the LDR instruction - it is faster. For Thumb-2
13155 always use pop and the assembler will pick the best instruction.*/
13156 if (TARGET_ARM
&& saved_regs_mask
== (1 << LR_REGNUM
))
13158 asm_fprintf (f
, "\tldr\t%r, [%r], #4\n", LR_REGNUM
, SP_REGNUM
);
13160 else if (saved_regs_mask
)
13162 if (saved_regs_mask
& (1 << SP_REGNUM
))
13163 /* Note - write back to the stack register is not enabled
13164 (i.e. "ldmfd sp!..."). We know that the stack pointer is
13165 in the list of registers and if we add writeback the
13166 instruction becomes UNPREDICTABLE. */
13167 print_multi_reg (f
, "ldmfd\t%r, ", SP_REGNUM
, saved_regs_mask
);
13168 else if (TARGET_ARM
)
13169 print_multi_reg (f
, "ldmfd\t%r!, ", SP_REGNUM
, saved_regs_mask
);
13171 print_multi_reg (f
, "pop\t", SP_REGNUM
, saved_regs_mask
);
13173 /* APPLE LOCAL end v7 support. Merge from mainline */
13175 if (current_function_pretend_args_size
)
13177 /* Unwind the pre-pushed regs. */
13178 operands
[0] = operands
[1] = stack_pointer_rtx
;
13179 operands
[2] = GEN_INT (current_function_pretend_args_size
);
13180 output_add_immediate (operands
);
13184 /* We may have already restored PC directly from the stack. */
13185 if (!really_return
|| saved_regs_mask
& (1 << PC_REGNUM
))
13188 /* Stack adjustment for exception handler. */
13189 if (current_function_calls_eh_return
)
13190 asm_fprintf (f
, "\tadd\t%r, %r, %r\n", SP_REGNUM
, SP_REGNUM
,
13191 ARM_EH_STACKADJ_REGNUM
);
13193 /* Generate the return instruction. */
13194 switch ((int) ARM_FUNC_TYPE (func_type
))
13198 asm_fprintf (f
, "\tsubs\t%r, %r, #4\n", PC_REGNUM
, LR_REGNUM
);
13201 case ARM_FT_EXCEPTION
:
13202 asm_fprintf (f
, "\tmovs\t%r, %r\n", PC_REGNUM
, LR_REGNUM
);
13205 case ARM_FT_INTERWORKED
:
13206 asm_fprintf (f
, "\tbx\t%r\n", LR_REGNUM
);
13210 /* APPLE LOCAL begin v7 support. Merge from mainline */
13211 if (IS_STACKALIGN (func_type
))
13213 /* See comment in arm_expand_prologue. */
13214 asm_fprintf (f
, "\tmov\t%r, %r\n", SP_REGNUM
, 0);
13216 /* APPLE LOCAL end v7 support. Merge from mainline */
13217 if (arm_arch5
|| arm_arch4t
)
13218 asm_fprintf (f
, "\tbx\t%r\n", LR_REGNUM
);
13220 asm_fprintf (f
, "\tmov\t%r, %r\n", PC_REGNUM
, LR_REGNUM
);
13228 arm_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED
,
13229 HOST_WIDE_INT frame_size ATTRIBUTE_UNUSED
)
13231 arm_stack_offsets
*offsets
;
13233 /* APPLE LOCAL v7 support. Merge from mainline */
13238 /* Emit any call-via-reg trampolines that are needed for v4t support
13239 of call_reg and call_value_reg type insns. */
13240 for (regno
= 0; regno
< LR_REGNUM
; regno
++)
13242 rtx label
= cfun
->machine
->call_via
[regno
];
13246 switch_to_section (function_section (current_function_decl
));
13247 targetm
.asm_out
.internal_label (asm_out_file
, "L",
13248 CODE_LABEL_NUMBER (label
));
13249 asm_fprintf (asm_out_file
, "\tbx\t%r\n", regno
);
13253 /* ??? Probably not safe to set this here, since it assumes that a
13254 function will be emitted as assembly immediately after we generate
13255 RTL for it. This does not happen for inline functions. */
13256 return_used_this_function
= 0;
13258 /* APPLE LOCAL v7 support. Merge from mainline */
13259 else /* TARGET_32BIT */
13261 /* We need to take into account any stack-frame rounding. */
13262 offsets
= arm_get_frame_offsets ();
13264 gcc_assert (!use_return_insn (FALSE
, NULL
)
13265 || !return_used_this_function
13266 || offsets
->saved_regs
== offsets
->outgoing_args
13267 || frame_pointer_needed
);
13269 /* Reset the ARM-specific per-function variables. */
13270 after_arm_reorg
= 0;
13273 /* APPLE LOCAL begin ARM label addresses */
13275 /* Mach-O doesn't support labels at the end of objects, so if
13276 it looks like we might want one, insert a NOP. */
13278 rtx insn
= get_last_insn ();
13281 && NOTE_LINE_NUMBER (insn
) != NOTE_INSN_DELETED_LABEL
)
13282 insn
= PREV_INSN (insn
);
13286 && NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED_LABEL
)))
13287 fputs ("\tnop\n", file
);
13290 /* APPLE LOCAL end ARM label addresses */
13293 /* Generate and emit an insn that we will recognize as a push_multi.
13294 Unfortunately, since this insn does not reflect very well the actual
13295 semantics of the operation, we need to annotate the insn for the benefit
13296 of DWARF2 frame unwind information. */
13298 emit_multi_reg_push (unsigned long mask
)
13301 int num_dwarf_regs
;
13305 int dwarf_par_index
;
13308 for (i
= 0; i
<= LAST_ARM_REGNUM
; i
++)
13309 if (mask
& (1 << i
))
13312 gcc_assert (num_regs
&& num_regs
<= 16);
13314 /* We don't record the PC in the dwarf frame information. */
13315 num_dwarf_regs
= num_regs
;
13316 if (mask
& (1 << PC_REGNUM
))
13319 /* For the body of the insn we are going to generate an UNSPEC in
13320 parallel with several USEs. This allows the insn to be recognized
13321 by the push_multi pattern in the arm.md file. The insn looks
13322 something like this:
13325 (set (mem:BLK (pre_dec:BLK (reg:SI sp)))
13326 (unspec:BLK [(reg:SI r4)] UNSPEC_PUSH_MULT))
13327 (use (reg:SI 11 fp))
13328 (use (reg:SI 12 ip))
13329 (use (reg:SI 14 lr))
13330 (use (reg:SI 15 pc))
13333 For the frame note however, we try to be more explicit and actually
13334 show each register being stored into the stack frame, plus a (single)
13335 decrement of the stack pointer. We do it this way in order to be
13336 friendly to the stack unwinding code, which only wants to see a single
13337 stack decrement per instruction. The RTL we generate for the note looks
13338 something like this:
13341 (set (reg:SI sp) (plus:SI (reg:SI sp) (const_int -20)))
13342 (set (mem:SI (reg:SI sp)) (reg:SI r4))
13343 (set (mem:SI (plus:SI (reg:SI sp) (const_int 4))) (reg:SI fp))
13344 (set (mem:SI (plus:SI (reg:SI sp) (const_int 8))) (reg:SI ip))
13345 (set (mem:SI (plus:SI (reg:SI sp) (const_int 12))) (reg:SI lr))
13348 This sequence is used both by the code to support stack unwinding for
13349 exceptions handlers and the code to generate dwarf2 frame debugging. */
13351 par
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (num_regs
));
13352 dwarf
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (num_dwarf_regs
+ 1));
13353 dwarf_par_index
= 1;
13355 for (i
= 0; i
<= LAST_ARM_REGNUM
; i
++)
13357 if (mask
& (1 << i
))
13359 reg
= gen_rtx_REG (SImode
, i
);
13361 XVECEXP (par
, 0, 0)
13362 = gen_rtx_SET (VOIDmode
,
13363 gen_frame_mem (BLKmode
,
13364 gen_rtx_PRE_DEC (BLKmode
,
13365 stack_pointer_rtx
)),
13366 gen_rtx_UNSPEC (BLKmode
,
13367 gen_rtvec (1, reg
),
13368 UNSPEC_PUSH_MULT
));
13370 if (i
!= PC_REGNUM
)
13372 tmp
= gen_rtx_SET (VOIDmode
,
13373 gen_frame_mem (SImode
, stack_pointer_rtx
),
13375 RTX_FRAME_RELATED_P (tmp
) = 1;
13376 XVECEXP (dwarf
, 0, dwarf_par_index
) = tmp
;
13384 for (j
= 1, i
++; j
< num_regs
; i
++)
13386 if (mask
& (1 << i
))
13388 reg
= gen_rtx_REG (SImode
, i
);
13390 XVECEXP (par
, 0, j
) = gen_rtx_USE (VOIDmode
, reg
);
13392 if (i
!= PC_REGNUM
)
13395 = gen_rtx_SET (VOIDmode
,
13396 gen_frame_mem (SImode
,
13397 plus_constant (stack_pointer_rtx
,
13400 RTX_FRAME_RELATED_P (tmp
) = 1;
13401 XVECEXP (dwarf
, 0, dwarf_par_index
++) = tmp
;
13408 par
= emit_insn (par
);
13410 tmp
= gen_rtx_SET (VOIDmode
,
13412 plus_constant (stack_pointer_rtx
, -4 * num_regs
));
13413 RTX_FRAME_RELATED_P (tmp
) = 1;
13414 XVECEXP (dwarf
, 0, 0) = tmp
;
13416 REG_NOTES (par
) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR
, dwarf
,
13421 /* Calculate the size of the return value that is passed in registers. */
13423 arm_size_return_regs (void)
13425 enum machine_mode mode
;
13427 if (current_function_return_rtx
!= 0)
13428 mode
= GET_MODE (current_function_return_rtx
);
13430 mode
= DECL_MODE (DECL_RESULT (current_function_decl
));
13432 return GET_MODE_SIZE (mode
);
13436 emit_sfm (int base_reg
, int count
)
13443 par
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (count
));
13444 dwarf
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (count
+ 1));
13446 reg
= gen_rtx_REG (XFmode
, base_reg
++);
13448 XVECEXP (par
, 0, 0)
13449 = gen_rtx_SET (VOIDmode
,
13450 gen_frame_mem (BLKmode
,
13451 gen_rtx_PRE_DEC (BLKmode
,
13452 stack_pointer_rtx
)),
13453 gen_rtx_UNSPEC (BLKmode
,
13454 gen_rtvec (1, reg
),
13455 UNSPEC_PUSH_MULT
));
13456 tmp
= gen_rtx_SET (VOIDmode
,
13457 gen_frame_mem (XFmode
, stack_pointer_rtx
), reg
);
13458 RTX_FRAME_RELATED_P (tmp
) = 1;
13459 XVECEXP (dwarf
, 0, 1) = tmp
;
13461 for (i
= 1; i
< count
; i
++)
13463 reg
= gen_rtx_REG (XFmode
, base_reg
++);
13464 XVECEXP (par
, 0, i
) = gen_rtx_USE (VOIDmode
, reg
);
13466 tmp
= gen_rtx_SET (VOIDmode
,
13467 gen_frame_mem (XFmode
,
13468 plus_constant (stack_pointer_rtx
,
13471 RTX_FRAME_RELATED_P (tmp
) = 1;
13472 XVECEXP (dwarf
, 0, i
+ 1) = tmp
;
13475 tmp
= gen_rtx_SET (VOIDmode
,
13477 plus_constant (stack_pointer_rtx
, -12 * count
));
13479 RTX_FRAME_RELATED_P (tmp
) = 1;
13480 XVECEXP (dwarf
, 0, 0) = tmp
;
13482 par
= emit_insn (par
);
13483 REG_NOTES (par
) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR
, dwarf
,
13489 /* Return true if the current function needs to save/restore LR. */
13492 thumb_force_lr_save (void)
13494 return !cfun
->machine
->lr_save_eliminated
13495 && (!leaf_function_p ()
13496 || thumb_far_jump_used_p ()
13497 || regs_ever_live
[LR_REGNUM
]);
13501 /* Compute the distance from register FROM to register TO.
13502 These can be the arg pointer (26), the soft frame pointer (25),
13503 the stack pointer (13) or the hard frame pointer (11).
13504 In thumb mode r7 is used as the soft frame pointer, if needed.
13505 Typical stack layout looks like this:
13507 old stack pointer -> | |
13510 | | saved arguments for
13511 | | vararg functions
13514 hard FP & arg pointer -> | | \
13522 soft frame pointer -> | | /
13527 locals base pointer -> | | /
13532 current stack pointer -> | | /
13535 For a given function some or all of these stack components
13536 may not be needed, giving rise to the possibility of
13537 eliminating some of the registers.
13539 The values returned by this function must reflect the behavior
13540 of arm_expand_prologue() and arm_compute_save_reg_mask().
13542 The sign of the number returned reflects the direction of stack
13543 growth, so the values are positive for all eliminations except
13544 from the soft frame pointer to the hard frame pointer.
13546 SFP may point just inside the local variables block to ensure correct
13550 /* Calculate stack offsets. These are used to calculate register elimination
13551 offsets and in prologue/epilogue code. */
13553 static arm_stack_offsets
*
13554 arm_get_frame_offsets (void)
13556 struct arm_stack_offsets
*offsets
;
13557 unsigned long func_type
;
13560 HOST_WIDE_INT frame_size
;
13562 offsets
= &cfun
->machine
->stack_offsets
;
13564 /* We need to know if we are a leaf function. Unfortunately, it
13565 is possible to be called after start_sequence has been called,
13566 which causes get_insns to return the insns for the sequence,
13567 not the function, which will cause leaf_function_p to return
13568 the incorrect result.
13570 to know about leaf functions once reload has completed, and the
13571 frame size cannot be changed after that time, so we can safely
13572 use the cached value. */
13574 if (reload_completed
)
13577 /* Initially this is the size of the local variables. It will translated
13578 into an offset once we have determined the size of preceding data. */
13579 frame_size
= ROUND_UP_WORD (get_frame_size ());
13581 leaf
= leaf_function_p ();
13583 /* Space for variadic functions. */
13584 offsets
->saved_args
= current_function_pretend_args_size
;
13586 /* APPLE LOCAL ARM custom frame layout */
13587 offsets
->frame
= offsets
->saved_args
+ (frame_pointer_needed
? 8 : 0);
13589 /* APPLE LOCAL v7 support. Merge from mainline */
13592 unsigned int regno
;
13594 saved
= bit_count (arm_compute_save_reg_mask ()) * 4;
13596 /* We know that SP will be doubleword aligned on entry, and we must
13597 preserve that condition at any subroutine call. We also require the
13598 soft frame pointer to be doubleword aligned. */
13600 if (TARGET_REALLY_IWMMXT
)
13602 /* Check for the call-saved iWMMXt registers. */
13603 for (regno
= FIRST_IWMMXT_REGNUM
;
13604 regno
<= LAST_IWMMXT_REGNUM
;
13606 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
13610 func_type
= arm_current_func_type ();
13611 if (! IS_VOLATILE (func_type
))
13613 /* Space for saved FPA registers. */
13614 for (regno
= FIRST_FPA_REGNUM
; regno
<= LAST_FPA_REGNUM
; regno
++)
13615 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
13618 /* Space for saved VFP registers. */
13619 if (TARGET_HARD_FLOAT
&& TARGET_VFP
)
13620 saved
+= arm_get_vfp_saved_size ();
13623 /* APPLE LOCAL v7 support. Merge from mainline */
13624 else /* TARGET_THUMB1 */
13626 /* APPLE LOCAL v7 support. Merge from mainline */
13627 saved
= bit_count (thumb1_compute_save_reg_mask ()) * 4;
13628 if (TARGET_BACKTRACE
)
13630 /* APPLE LOCAL begin 6465387 exception handling interworking VFP save */
13631 /* Saved VFP registers in thumb mode aren't accounted for by
13632 thumb1_compute_save_reg_mask() */
13633 if (current_function_has_nonlocal_label
&& arm_arch6
)
13635 /* APPLE LOCAL end 6465387 exception handling interworking VFP save */
13638 /* Saved registers include the stack frame. */
13639 offsets
->saved_regs
= offsets
->saved_args
+ saved
;
13640 offsets
->soft_frame
= offsets
->saved_regs
+ CALLER_INTERWORKING_SLOT_SIZE
;
13641 /* A leaf function does not need any stack alignment if it has nothing
13643 if (leaf
&& frame_size
== 0)
13645 offsets
->outgoing_args
= offsets
->soft_frame
;
13646 offsets
->locals_base
= offsets
->soft_frame
;
13650 /* Ensure SFP has the correct alignment. */
13651 if (ARM_DOUBLEWORD_ALIGN
13652 && (offsets
->soft_frame
& 7))
13653 offsets
->soft_frame
+= 4;
13655 offsets
->locals_base
= offsets
->soft_frame
+ frame_size
;
13656 offsets
->outgoing_args
= (offsets
->locals_base
13657 + current_function_outgoing_args_size
);
13659 if (ARM_DOUBLEWORD_ALIGN
)
13661 /* Ensure SP remains doubleword aligned. */
13662 if (offsets
->outgoing_args
& 7)
13663 offsets
->outgoing_args
+= 4;
13664 gcc_assert (!(offsets
->outgoing_args
& 7));
13671 /* Calculate the relative offsets for the different stack pointers. Positive
13672 offsets are in the direction of stack growth. */
13675 arm_compute_initial_elimination_offset (unsigned int from
, unsigned int to
)
13677 arm_stack_offsets
*offsets
;
13679 offsets
= arm_get_frame_offsets ();
13681 /* OK, now we have enough information to compute the distances.
13682 There must be an entry in these switch tables for each pair
13683 of registers in ELIMINABLE_REGS, even if some of the entries
13684 seem to be redundant or useless. */
13687 case ARG_POINTER_REGNUM
:
13690 /* APPLE LOCAL ARM custom frame layout */
13691 /* Removed lines. */
13693 case FRAME_POINTER_REGNUM
:
13694 /* This is the reverse of the soft frame pointer
13695 to hard frame pointer elimination below. */
13696 return offsets
->soft_frame
- offsets
->saved_args
;
13698 /* APPLE LOCAL begin ARM custom frame layout */
13699 case HARD_FRAME_POINTER_REGNUM
:
13700 return offsets
->frame
- (offsets
->saved_args
+ 4);
13701 /* APPLE LOCAL end ARM custom frame layout */
13703 case STACK_POINTER_REGNUM
:
13704 /* If nothing has been pushed on the stack at all
13705 then this will return -4. This *is* correct! */
13706 return offsets
->outgoing_args
- (offsets
->saved_args
+ 4);
13709 gcc_unreachable ();
13711 gcc_unreachable ();
13713 case FRAME_POINTER_REGNUM
:
13716 /* APPLE LOCAL begin ARM custom frame layout */
13717 case HARD_FRAME_POINTER_REGNUM
:
13718 /* APPLE LOCAL end ARM custom frame layout */
13719 /* The hard frame pointer points to the top entry in the
13720 stack frame. The soft frame pointer to the bottom entry
13721 in the stack frame. If there is no stack frame at all,
13722 then they are identical. */
13724 return offsets
->frame
- offsets
->soft_frame
;
13726 case STACK_POINTER_REGNUM
:
13727 return offsets
->outgoing_args
- offsets
->soft_frame
;
13730 gcc_unreachable ();
13732 gcc_unreachable ();
13735 /* You cannot eliminate from the stack pointer.
13736 In theory you could eliminate from the hard frame
13737 pointer to the stack pointer, but this will never
13738 happen, since if a stack frame is not needed the
13739 hard frame pointer will never be used. */
13740 gcc_unreachable ();
13745 /* APPLE LOCAL begin v7 support. Merge from mainline */
13746 /* Emit RTL to save coprocessor registers on funciton entry. Returns the
13747 number of bytes pushed. */
13750 arm_save_coproc_regs(void)
13752 int saved_size
= 0;
13754 unsigned start_reg
;
13757 for (reg
= LAST_IWMMXT_REGNUM
; reg
>= FIRST_IWMMXT_REGNUM
; reg
--)
13758 if (regs_ever_live
[reg
] && ! call_used_regs
[reg
])
13760 insn
= gen_rtx_PRE_DEC (V2SImode
, stack_pointer_rtx
);
13761 insn
= gen_rtx_MEM (V2SImode
, insn
);
13762 insn
= emit_set_insn (insn
, gen_rtx_REG (V2SImode
, reg
));
13763 RTX_FRAME_RELATED_P (insn
) = 1;
13767 /* Save any floating point call-saved registers used by this
13769 if (arm_fpu_arch
== FPUTYPE_FPA_EMU2
)
13771 for (reg
= LAST_FPA_REGNUM
; reg
>= FIRST_FPA_REGNUM
; reg
--)
13772 if (regs_ever_live
[reg
] && !call_used_regs
[reg
])
13774 insn
= gen_rtx_PRE_DEC (XFmode
, stack_pointer_rtx
);
13775 insn
= gen_rtx_MEM (XFmode
, insn
);
13776 insn
= emit_set_insn (insn
, gen_rtx_REG (XFmode
, reg
));
13777 RTX_FRAME_RELATED_P (insn
) = 1;
13783 start_reg
= LAST_FPA_REGNUM
;
13785 for (reg
= LAST_FPA_REGNUM
; reg
>= FIRST_FPA_REGNUM
; reg
--)
13787 if (regs_ever_live
[reg
] && !call_used_regs
[reg
])
13789 if (start_reg
- reg
== 3)
13791 insn
= emit_sfm (reg
, 4);
13792 RTX_FRAME_RELATED_P (insn
) = 1;
13794 start_reg
= reg
- 1;
13799 if (start_reg
!= reg
)
13801 insn
= emit_sfm (reg
+ 1, start_reg
- reg
);
13802 RTX_FRAME_RELATED_P (insn
) = 1;
13803 saved_size
+= (start_reg
- reg
) * 12;
13805 start_reg
= reg
- 1;
13809 if (start_reg
!= reg
)
13811 insn
= emit_sfm (reg
+ 1, start_reg
- reg
);
13812 saved_size
+= (start_reg
- reg
) * 12;
13813 RTX_FRAME_RELATED_P (insn
) = 1;
13816 if (TARGET_HARD_FLOAT
&& TARGET_VFP
)
13818 start_reg
= FIRST_VFP_REGNUM
;
13820 for (reg
= FIRST_VFP_REGNUM
; reg
< LAST_VFP_REGNUM
; reg
+= 2)
13822 if ((!regs_ever_live
[reg
] || call_used_regs
[reg
])
13823 && (!regs_ever_live
[reg
+ 1] || call_used_regs
[reg
+ 1]))
13825 if (start_reg
!= reg
)
13826 saved_size
+= vfp_emit_fstmd (start_reg
,
13827 (reg
- start_reg
) / 2);
13828 start_reg
= reg
+ 2;
13831 if (start_reg
!= reg
)
13832 saved_size
+= vfp_emit_fstmd (start_reg
,
13833 (reg
- start_reg
) / 2);
13839 /* Set the Thumb frame pointer from the stack pointer. */
13842 thumb_set_frame_pointer (arm_stack_offsets
*offsets
)
13844 HOST_WIDE_INT amount
;
13847 amount
= offsets
->outgoing_args
- offsets
->locals_base
;
13849 insn
= emit_insn (gen_addsi3 (hard_frame_pointer_rtx
,
13850 stack_pointer_rtx
, GEN_INT (amount
)));
13853 emit_insn (gen_movsi (hard_frame_pointer_rtx
, GEN_INT (amount
)));
13854 insn
= emit_insn (gen_addsi3 (hard_frame_pointer_rtx
,
13855 hard_frame_pointer_rtx
,
13856 stack_pointer_rtx
));
13857 dwarf
= gen_rtx_SET (VOIDmode
, hard_frame_pointer_rtx
,
13858 plus_constant (stack_pointer_rtx
, amount
));
13859 RTX_FRAME_RELATED_P (dwarf
) = 1;
13860 REG_NOTES (insn
) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR
, dwarf
,
13864 RTX_FRAME_RELATED_P (insn
) = 1;
13867 /* Generate the prologue instructions for entry into an ARM or Thumb-2
13869 /* APPLE LOCAL end v7 support. Merge from mainline */
13871 arm_expand_prologue (void)
13873 /* APPLE LOCAL v7 support. Merge from mainline */
13874 /* Remove 'reg' variable */
13878 unsigned long live_regs_mask
;
13879 unsigned long func_type
;
13880 /* APPLE LOCAL ARM custom frame layout */
13881 /* Remove unused variable definitions. */
13882 int saved_regs
= 0;
13883 unsigned HOST_WIDE_INT args_to_push
;
13884 arm_stack_offsets
*offsets
;
13886 func_type
= arm_current_func_type ();
13888 /* Naked functions don't have prologues. */
13889 if (IS_NAKED (func_type
))
13892 /* Make a copy of c_f_p_a_s as we may need to modify it locally. */
13893 args_to_push
= current_function_pretend_args_size
;
13895 /* Compute which register we will have to save onto the stack. */
13896 live_regs_mask
= arm_compute_save_reg_mask ();
13898 ip_rtx
= gen_rtx_REG (SImode
, IP_REGNUM
);
13900 /* APPLE LOCAL begin v7 support. Merge from mainline */
13901 if (IS_STACKALIGN (func_type
))
13906 /* Handle a word-aligned stack pointer. We generate the following:
13911 <save and restore r0 in normal prologue/epilogue>
13915 The unwinder doesn't need to know about the stack realignment.
13916 Just tell it we saved SP in r0. */
13917 gcc_assert (TARGET_THUMB2
&& !arm_arch_notm
&& args_to_push
== 0);
13919 r0
= gen_rtx_REG (SImode
, 0);
13920 r1
= gen_rtx_REG (SImode
, 1);
13921 dwarf
= gen_rtx_UNSPEC (SImode
, NULL_RTVEC
, UNSPEC_STACK_ALIGN
);
13922 dwarf
= gen_rtx_SET (VOIDmode
, r0
, dwarf
);
13923 insn
= gen_movsi (r0
, stack_pointer_rtx
);
13924 RTX_FRAME_RELATED_P (insn
) = 1;
13925 REG_NOTES (insn
) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR
,
13926 dwarf
, REG_NOTES (insn
));
13928 emit_insn (gen_andsi3 (r1
, r0
, GEN_INT (~(HOST_WIDE_INT
)7)));
13929 emit_insn (gen_movsi (stack_pointer_rtx
, r1
));
13932 if (frame_pointer_needed
&& TARGET_ARM
)
13934 /* APPLE LOCAL end v7 support. Merge from mainline */
13935 if (IS_INTERRUPT (func_type
))
13937 /* Interrupt functions must not corrupt any registers.
13938 Creating a frame pointer however, corrupts the IP
13939 register, so we must push it first. */
13940 insn
= emit_multi_reg_push (1 << IP_REGNUM
);
13942 /* Do not set RTX_FRAME_RELATED_P on this insn.
13943 The dwarf stack unwinding code only wants to see one
13944 stack decrement per function, and this is not it. If
13945 this instruction is labeled as being part of the frame
13946 creation sequence then dwarf2out_frame_debug_expr will
13947 die when it encounters the assignment of IP to FP
13948 later on, since the use of SP here establishes SP as
13949 the CFA register and not IP.
13951 Anyway this instruction is not really part of the stack
13952 frame creation although it is part of the prologue. */
13954 /* APPLE LOCAL begin ARM custom frame layout */
13955 else if (IS_NESTED (func_type
))
13957 /* Our prologue doesn't corrupt IP, so no need to save it. */
13959 /* APPLE LOCAL end ARM custom frame layout */
13964 /* Push the argument registers, or reserve space for them. */
13965 if (cfun
->machine
->uses_anonymous_args
)
13966 insn
= emit_multi_reg_push
13967 ((0xf0 >> (args_to_push
/ 4)) & 0xf);
13970 (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
13971 GEN_INT (- args_to_push
)));
13972 RTX_FRAME_RELATED_P (insn
) = 1;
13975 /* If this is an interrupt service routine, and the link register
13976 is going to be pushed, and we are not creating a stack frame,
13977 (which would involve an extra push of IP and a pop in the epilogue)
13978 subtracting four from LR now will mean that the function return
13979 can be done with a single instruction. */
13980 if ((func_type
== ARM_FT_ISR
|| func_type
== ARM_FT_FIQ
)
13981 && (live_regs_mask
& (1 << LR_REGNUM
)) != 0
13982 && ! frame_pointer_needed
)
13984 rtx lr
= gen_rtx_REG (SImode
, LR_REGNUM
);
13986 emit_set_insn (lr
, plus_constant (lr
, -4));
13989 /* APPLE LOCAL begin ARM peephole combine reg store and stack push */
13990 offsets
= arm_get_frame_offsets ();
13992 if (live_regs_mask
)
13994 saved_regs
+= bit_count (live_regs_mask
) * 4;
13996 /* Space optimization: if we need a small amount of stack space, and
13997 we're going to do a push, push some extra registers rather than
13998 doing a separate subtract. We can safely push R0 thru R3. We can
13999 also use R12 provided no regs in the range R4..R11 are being saved.
14000 (Their saved values would be below the value of R12 on the stack,
14001 and would get clobbered.) */
14002 /* The conditions here are probably overly restrictive. */
14005 && !frame_pointer_needed
14006 && arm_fpu_arch
== FPUTYPE_NONE
14007 && TARGET_SOFT_FLOAT
14011 int delta
= offsets
->outgoing_args
- offsets
->saved_args
- saved_regs
;
14015 & ((1<<4) | (1<<5) | (1<<6) | (1<<7) | (1<<8) | (1<<9) | (1<<10) | (1<<11)))
14017 if (delta
<= (ip_ok
? 20 : 16) && delta
% 4 == 0)
14019 int reg
= (ip_ok
? 12 : 3);
14023 live_regs_mask
|= (1<<reg
);
14024 reg
= (reg
== 12) ? 3 : reg
- 1;
14030 /* APPLE LOCAL begin ARM custom frame layout */
14031 if (frame_pointer_needed
)
14033 unsigned long regs_above_fp
=
14034 inclusive_bitmask (ARM_HARD_FRAME_POINTER_REGNUM
+ 1, 11);
14035 unsigned long initial_push_regs
= live_regs_mask
14037 unsigned long second_push_regs
= live_regs_mask
14040 /* Save everything up to the FP, and the LR */
14041 insn
= emit_multi_reg_push (initial_push_regs
);
14042 /* rdar://6148015 */
14043 RTX_FRAME_RELATED_P (insn
) = 1;
14045 /* Configure FP to point to the saved FP. */
14047 gen_addsi3 (hard_frame_pointer_rtx
, stack_pointer_rtx
,
14048 GEN_INT ((bit_count (initial_push_regs
) - 2)
14050 RTX_FRAME_RELATED_P (insn
) = 1;
14052 /* Prevent attempts to optimize away the frame pointer. */
14053 emit_insn (gen_rtx_USE (VOIDmode
, hard_frame_pointer_rtx
));
14055 /* Push remaining regs. */
14056 if (second_push_regs
)
14058 insn
= emit_multi_reg_push (second_push_regs
);
14059 /* rdar://6148015 */
14060 RTX_FRAME_RELATED_P (insn
) = 1;
14065 insn
= emit_multi_reg_push (live_regs_mask
);
14066 RTX_FRAME_RELATED_P (insn
) = 1;
14068 /* APPLE LOCAL end ARM custom frame layout */
14070 /* APPLE LOCAL end ARM peephole combine reg store and stack push */
14072 /* APPLE LOCAL begin v7 support. Merge from mainline */
14073 if (! IS_VOLATILE (func_type
))
14074 saved_regs
+= arm_save_coproc_regs ();
14075 /* APPLE LOCAL end v7 support. Merge from mainline */
14077 /* APPLE LOCAL ARM custom frame layout */
14078 /* Removed lines. */
14080 /* APPLE LOCAL ARM peephole combine reg store and stack push */
14081 /* Remove call to arm_get_frame_offsets. */
14082 if (offsets
->outgoing_args
!= offsets
->saved_args
+ saved_regs
)
14084 /* This add can produce multiple insns for a large constant, so we
14085 need to get tricky. */
14086 rtx last
= get_last_insn ();
14088 amount
= GEN_INT (offsets
->saved_args
+ saved_regs
14089 - offsets
->outgoing_args
);
14091 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
14095 last
= last
? NEXT_INSN (last
) : get_insns ();
14096 RTX_FRAME_RELATED_P (last
) = 1;
14098 while (last
!= insn
);
14100 /* If the frame pointer is needed, emit a special barrier that
14101 will prevent the scheduler from moving stores to the frame
14102 before the stack adjustment. */
14103 if (frame_pointer_needed
)
14104 insn
= emit_insn (gen_stack_tie (stack_pointer_rtx
,
14105 hard_frame_pointer_rtx
));
14109 /* APPLE LOCAL begin v7 support. Merge from mainline */
14110 /* APPLE LOCAL add !live_regs_mask. that's handled above by apple code */
14111 if (frame_pointer_needed
&& TARGET_THUMB2
&& !live_regs_mask
)
14112 thumb_set_frame_pointer (offsets
);
14114 if (flag_pic
&& arm_pic_register
!= INVALID_REGNUM
)
14116 unsigned long mask
;
14118 mask
= live_regs_mask
;
14119 mask
&= THUMB2_WORK_REGS
;
14120 if (!IS_NESTED (func_type
))
14121 mask
|= (1 << IP_REGNUM
);
14122 arm_load_pic_register (mask
);
14125 /* APPLE LOCAL end v7 support. Merge from mainline */
14126 /* If we are profiling, make sure no instructions are scheduled before
14127 the call to mcount. Similarly if the user has requested no
14128 scheduling in the prolog. Similarly if we want non-call exceptions
14129 using the EABI unwinder, to prevent faulting instructions from being
14130 swapped with a stack adjustment. */
14131 if (current_function_profile
|| !TARGET_SCHED_PROLOG
14132 || (ARM_EABI_UNWIND_TABLES
&& flag_non_call_exceptions
))
14133 emit_insn (gen_blockage ());
14135 /* If the link register is being kept alive, with the return address in it,
14136 then make sure that it does not get reused by the ce2 pass. */
14137 if ((live_regs_mask
& (1 << LR_REGNUM
)) == 0)
14139 emit_insn (gen_prologue_use (gen_rtx_REG (SImode
, LR_REGNUM
)));
14140 cfun
->machine
->lr_save_eliminated
= 1;
14144 /* APPLE LOCAL begin v7 support. Merge from mainline */
14145 /* Print condition code to STREAM. Helper function for arm_print_operand. */
14147 arm_print_condition (FILE *stream
)
14149 if (arm_ccfsm_state
== 3 || arm_ccfsm_state
== 4)
14151 /* Branch conversion is not implemented for Thumb-2. */
14154 output_operand_lossage ("predicated Thumb instruction");
14157 if (current_insn_predicate
!= NULL
)
14159 output_operand_lossage
14160 ("predicated instruction in conditional sequence");
14164 fputs (arm_condition_codes
[arm_current_cc
], stream
);
14166 else if (current_insn_predicate
)
14168 enum arm_cond_code code
;
14172 output_operand_lossage ("predicated Thumb instruction");
14176 code
= get_arm_condition_code (current_insn_predicate
);
14177 fputs (arm_condition_codes
[code
], stream
);
14182 /* APPLE LOCAL end v7 support. Merge from mainline */
14183 /* If CODE is 'd', then the X is a condition operand and the instruction
14184 should only be executed if the condition is true.
14185 if CODE is 'D', then the X is a condition operand and the instruction
14186 should only be executed if the condition is false: however, if the mode
14187 of the comparison is CCFPEmode, then always execute the instruction -- we
14188 do this because in these circumstances !GE does not necessarily imply LT;
14189 in these cases the instruction pattern will take care to make sure that
14190 an instruction containing %d will follow, thereby undoing the effects of
14191 doing this instruction unconditionally.
14192 If CODE is 'N' then X is a floating point operand that must be negated
14194 If CODE is 'B' then output a bitwise inverted value of X (a const int).
14195 If X is a REG and CODE is `M', output a ldm/stm style multi-reg. */
14197 arm_print_operand (FILE *stream
, rtx x
, int code
)
14201 /* APPLE LOCAL begin ARM MACH assembler */
14202 /* APPLE LOCAL change appple '.' code to '~' for v7 to avoid conflict */
14204 #ifdef LOCAL_LABEL_PREFIX
14205 fputs (LOCAL_LABEL_PREFIX
, stream
);
14208 /* APPLE LOCAL end ARM MACH assembler */
14211 fputs (ASM_COMMENT_START
, stream
);
14215 fputs (user_label_prefix
, stream
);
14219 fputs (REGISTER_PREFIX
, stream
);
14222 /* APPLE LOCAL begin v7 support. Merge from mainline */
14224 arm_print_condition (stream
);
14228 /* Nothing in unified syntax, otherwise the current condition code. */
14229 if (!TARGET_UNIFIED_ASM
)
14230 arm_print_condition (stream
);
14234 /* The current condition code in unified syntax, otherwise nothing. */
14235 if (TARGET_UNIFIED_ASM
)
14236 arm_print_condition (stream
);
14240 /* The current condition code for a condition code setting instruction.
14241 Preceeded by 's' in unified syntax, otherwise followed by 's'. */
14242 if (TARGET_UNIFIED_ASM
)
14244 fputc('s', stream
);
14245 arm_print_condition (stream
);
14249 arm_print_condition (stream
);
14250 fputc('s', stream
);
14255 /* If the instruction is conditionally executed then print
14256 the current condition code, otherwise print 's'. */
14257 gcc_assert (TARGET_THUMB2
&& TARGET_UNIFIED_ASM
);
14258 if (current_insn_predicate
)
14259 arm_print_condition (stream
);
14261 fputc('s', stream
);
14264 /* APPLE LOCAL end v7 support. Merge from mainline */
14265 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
14266 /* %# is a "break" sequence. It doesn't output anything, but is used to
14267 seperate e.g. operand numbers from following text, if that text consists
14268 of further digits which we don't want to be part of the operand
14272 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
14277 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
14278 r
= REAL_VALUE_NEGATE (r
);
14279 fprintf (stream
, "%s", fp_const_from_val (&r
));
14283 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
14284 /* An integer without a preceding # sign. */
14286 gcc_assert (GET_CODE (x
) == CONST_INT
);
14287 fprintf (stream
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
));
14290 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
14292 if (GET_CODE (x
) == CONST_INT
)
14295 val
= ARM_SIGN_EXTEND (~INTVAL (x
));
14296 fprintf (stream
, HOST_WIDE_INT_PRINT_DEC
, val
);
14300 putc ('~', stream
);
14301 output_addr_const (stream
, x
);
14305 /* APPLE LOCAL begin v7 support. Merge from mainline */
14307 /* The low 16 bits of an immediate constant. */
14308 fprintf (stream
, HOST_WIDE_INT_PRINT_DEC
, INTVAL(x
) & 0xffff);
14311 /* APPLE LOCAL end v7 support. Merge from mainline */
14313 fprintf (stream
, "%s", arithmetic_instr (x
, 1));
14316 /* Truncate Cirrus shift counts. */
14318 if (GET_CODE (x
) == CONST_INT
)
14320 fprintf (stream
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
) & 0x3f);
14323 arm_print_operand (stream
, x
, 0);
14327 fprintf (stream
, "%s", arithmetic_instr (x
, 0));
14335 if (!shift_operator (x
, SImode
))
14337 output_operand_lossage ("invalid shift operand");
14341 shift
= shift_op (x
, &val
);
14345 fprintf (stream
, ", %s ", shift
);
14347 arm_print_operand (stream
, XEXP (x
, 1), 0);
14349 fprintf (stream
, "#" HOST_WIDE_INT_PRINT_DEC
, val
);
14354 /* An explanation of the 'Q', 'R' and 'H' register operands:
14356 In a pair of registers containing a DI or DF value the 'Q'
14357 operand returns the register number of the register containing
14358 the least significant part of the value. The 'R' operand returns
14359 the register number of the register containing the most
14360 significant part of the value.
14362 The 'H' operand returns the higher of the two register numbers.
14363 On a run where WORDS_BIG_ENDIAN is true the 'H' operand is the
14364 same as the 'Q' operand, since the most significant part of the
14365 value is held in the lower number register. The reverse is true
14366 on systems where WORDS_BIG_ENDIAN is false.
14368 The purpose of these operands is to distinguish between cases
14369 where the endian-ness of the values is important (for example
14370 when they are added together), and cases where the endian-ness
14371 is irrelevant, but the order of register operations is important.
14372 For example when loading a value from memory into a register
14373 pair, the endian-ness does not matter. Provided that the value
14374 from the lower memory address is put into the lower numbered
14375 register, and the value from the higher address is put into the
14376 higher numbered register, the load will work regardless of whether
14377 the value being loaded is big-wordian or little-wordian. The
14378 order of the two register loads can matter however, if the address
14379 of the memory location is actually held in one of the registers
14380 being overwritten by the load. */
14382 if (GET_CODE (x
) != REG
|| REGNO (x
) > LAST_ARM_REGNUM
)
14384 output_operand_lossage ("invalid operand for code '%c'", code
);
14388 asm_fprintf (stream
, "%r", REGNO (x
) + (WORDS_BIG_ENDIAN
? 1 : 0));
14392 if (GET_CODE (x
) != REG
|| REGNO (x
) > LAST_ARM_REGNUM
)
14394 output_operand_lossage ("invalid operand for code '%c'", code
);
14398 asm_fprintf (stream
, "%r", REGNO (x
) + (WORDS_BIG_ENDIAN
? 0 : 1));
14402 if (GET_CODE (x
) != REG
|| REGNO (x
) > LAST_ARM_REGNUM
)
14404 output_operand_lossage ("invalid operand for code '%c'", code
);
14408 asm_fprintf (stream
, "%r", REGNO (x
) + 1);
14411 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
14413 if (GET_CODE (x
) != REG
|| REGNO (x
) > LAST_ARM_REGNUM
)
14415 output_operand_lossage ("invalid operand for code '%c'", code
);
14419 asm_fprintf (stream
, "%r", REGNO (x
) + (WORDS_BIG_ENDIAN
? 3 : 2));
14423 if (GET_CODE (x
) != REG
|| REGNO (x
) > LAST_ARM_REGNUM
)
14425 output_operand_lossage ("invalid operand for code '%c'", code
);
14429 asm_fprintf (stream
, "%r", REGNO (x
) + (WORDS_BIG_ENDIAN
? 2 : 3));
14432 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
14434 asm_fprintf (stream
, "%r",
14435 GET_CODE (XEXP (x
, 0)) == REG
14436 ? REGNO (XEXP (x
, 0)) : REGNO (XEXP (XEXP (x
, 0), 0)));
14440 asm_fprintf (stream
, "{%r-%r}",
14442 REGNO (x
) + ARM_NUM_REGS (GET_MODE (x
)) - 1);
14445 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
14446 /* Like 'M', but writing doubleword vector registers, for use by Neon
14450 int regno
= (REGNO (x
) - FIRST_VFP_REGNUM
) / 2;
14451 int numregs
= ARM_NUM_REGS (GET_MODE (x
)) / 2;
14453 asm_fprintf (stream
, "{d%d}", regno
);
14455 asm_fprintf (stream
, "{d%d-d%d}", regno
, regno
+ numregs
- 1);
14459 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
14461 /* CONST_TRUE_RTX means always -- that's the default. */
14462 if (x
== const_true_rtx
)
14465 if (!COMPARISON_P (x
))
14467 output_operand_lossage ("invalid operand for code '%c'", code
);
14471 fputs (arm_condition_codes
[get_arm_condition_code (x
)],
14476 /* CONST_TRUE_RTX means not always -- i.e. never. We shouldn't ever
14477 want to do that. */
14478 if (x
== const_true_rtx
)
14480 output_operand_lossage ("instruction never exectued");
14483 if (!COMPARISON_P (x
))
14485 output_operand_lossage ("invalid operand for code '%c'", code
);
14489 fputs (arm_condition_codes
[ARM_INVERSE_CONDITION_CODE
14490 (get_arm_condition_code (x
))],
14494 /* Cirrus registers can be accessed in a variety of ways:
14495 single floating point (f)
14496 double floating point (d)
14498 64bit integer (dx). */
14499 case 'W': /* Cirrus register in F mode. */
14500 case 'X': /* Cirrus register in D mode. */
14501 case 'Y': /* Cirrus register in FX mode. */
14502 case 'Z': /* Cirrus register in DX mode. */
14503 gcc_assert (GET_CODE (x
) == REG
14504 && REGNO_REG_CLASS (REGNO (x
)) == CIRRUS_REGS
);
14506 fprintf (stream
, "mv%s%s",
14508 : code
== 'X' ? "d"
14509 : code
== 'Y' ? "fx" : "dx", reg_names
[REGNO (x
)] + 2);
14513 /* Print cirrus register in the mode specified by the register's mode. */
14516 int mode
= GET_MODE (x
);
14518 if (GET_CODE (x
) != REG
|| REGNO_REG_CLASS (REGNO (x
)) != CIRRUS_REGS
)
14520 output_operand_lossage ("invalid operand for code '%c'", code
);
14524 fprintf (stream
, "mv%s%s",
14525 mode
== DFmode
? "d"
14526 : mode
== SImode
? "fx"
14527 : mode
== DImode
? "dx"
14528 : "f", reg_names
[REGNO (x
)] + 2);
14534 if (GET_CODE (x
) != REG
14535 || REGNO (x
) < FIRST_IWMMXT_GR_REGNUM
14536 || REGNO (x
) > LAST_IWMMXT_GR_REGNUM
)
14537 /* Bad value for wCG register number. */
14539 output_operand_lossage ("invalid operand for code '%c'", code
);
14544 fprintf (stream
, "%d", REGNO (x
) - FIRST_IWMMXT_GR_REGNUM
);
14547 /* Print an iWMMXt control register name. */
14549 if (GET_CODE (x
) != CONST_INT
14551 || INTVAL (x
) >= 16)
14552 /* Bad value for wC register number. */
14554 output_operand_lossage ("invalid operand for code '%c'", code
);
14560 static const char * wc_reg_names
[16] =
14562 "wCID", "wCon", "wCSSF", "wCASF",
14563 "wC4", "wC5", "wC6", "wC7",
14564 "wCGR0", "wCGR1", "wCGR2", "wCGR3",
14565 "wC12", "wC13", "wC14", "wC15"
14568 /* APPLE LOCAL default to Wformat-security 5764921 */
14569 fprintf (stream
, "%s", wc_reg_names
[INTVAL (x
)]);
14573 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
14574 /* Print a VFP/Neon double precision or quad precision register name. */
14578 int mode
= GET_MODE (x
);
14579 int is_quad
= (code
== 'q');
14582 if (GET_MODE_SIZE (mode
) != (is_quad
? 16 : 8))
14584 output_operand_lossage ("invalid operand for code '%c'", code
);
14588 if (GET_CODE (x
) != REG
14589 || !IS_VFP_REGNUM (REGNO (x
)))
14591 output_operand_lossage ("invalid operand for code '%c'", code
);
14596 if ((is_quad
&& !NEON_REGNO_OK_FOR_QUAD (regno
))
14597 || (!is_quad
&& !VFP_REGNO_OK_FOR_DOUBLE (regno
)))
14599 output_operand_lossage ("invalid operand for code '%c'", code
);
14603 fprintf (stream
, "%c%d", is_quad
? 'q' : 'd',
14604 (regno
- FIRST_VFP_REGNUM
) >> (is_quad
? 2 : 1));
14608 /* APPLE LOCAL 6150859 begin use NEON instructions for SF math */
14609 /* This code prints the double precision register name starting at
14610 register number of the indicated single precision register. */
14613 int mode
= GET_MODE (x
);
14616 if (GET_CODE (x
) != REG
|| !IS_VFP_REGNUM (REGNO (x
))
14617 || GET_MODE_SIZE (mode
) != 4)
14619 output_operand_lossage ("invalid operand for code '%c'", code
);
14624 if (((regno
- FIRST_VFP_REGNUM
) & 0x1) != 0)
14626 output_operand_lossage ("invalid operand for code '%c'", code
);
14630 fprintf (stream
, "d%d", (regno
- FIRST_VFP_REGNUM
) >> 1);
14633 /* APPLE LOCAL 6150859 end use NEON instructions for SF math */
14635 /* These two codes print the low/high doubleword register of a Neon quad
14636 register, respectively. For pair-structure types, can also print
14637 low/high quadword registers. */
14641 int mode
= GET_MODE (x
);
14644 if ((GET_MODE_SIZE (mode
) != 16
14645 && GET_MODE_SIZE (mode
) != 32) || GET_CODE (x
) != REG
)
14647 output_operand_lossage ("invalid operand for code '%c'", code
);
14652 if (!NEON_REGNO_OK_FOR_QUAD (regno
))
14654 output_operand_lossage ("invalid operand for code '%c'", code
);
14658 if (GET_MODE_SIZE (mode
) == 16)
14659 fprintf (stream
, "d%d", ((regno
- FIRST_VFP_REGNUM
) >> 1)
14660 + (code
== 'f' ? 1 : 0));
14662 fprintf (stream
, "q%d", ((regno
- FIRST_VFP_REGNUM
) >> 2)
14663 + (code
== 'f' ? 1 : 0));
14667 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
14668 /* APPLE LOCAL begin v7 support. Merge from mainline */
14669 /* Print a VFPv3 floating-point constant, represented as an integer
14673 int index
= vfp3_const_double_index (x
);
14674 gcc_assert (index
!= -1);
14675 fprintf (stream
, "%d", index
);
14679 /* APPLE LOCAL end v7 support. Merge from mainline */
14680 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
14681 /* Print bits representing opcode features for Neon.
14683 Bit 0 is 1 for signed, 0 for unsigned. Floats count as signed
14684 and polynomials as unsigned.
14686 Bit 1 is 1 for rounding functions, 0 otherwise.
14688 Bit 2 is 1 for floats and polynomials, 0 for ordinary integers. */
14690 /* Identify the type as 's', 'u', 'p' or 'f'. */
14693 HOST_WIDE_INT bits
= INTVAL (x
);
14694 fputc ((bits
& 1) != 0
14695 ? ((bits
& 4) != 0 ? 'f' : 's')
14696 : ((bits
& 4) != 0 ? 'p' : 'u'),
14701 /* Likewise, but signed and unsigned integers are both 'i'. */
14704 HOST_WIDE_INT bits
= INTVAL (x
);
14705 fputc ((bits
& 4) != 0
14706 ? ((bits
& 1) != 0 ? 'f' : 'p')
14712 /* As for 'T', but emit 'u' instead of 'p'. */
14715 HOST_WIDE_INT bits
= INTVAL (x
);
14716 fputc ((bits
& 1) != 0
14717 ? ((bits
& 4) != 0 ? 'f' : 's')
14723 /* Bit 1: rounding (vs none). */
14726 HOST_WIDE_INT bits
= INTVAL (x
);
14727 fputs ((bits
& 2) != 0 ? "r" : "", stream
);
14731 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
14735 output_operand_lossage ("missing operand");
14739 switch (GET_CODE (x
))
14742 asm_fprintf (stream
, "%r", REGNO (x
));
14746 output_memory_reference_mode
= GET_MODE (x
);
14747 output_address (XEXP (x
, 0));
14751 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
14755 real_to_decimal (fpstr
, CONST_DOUBLE_REAL_VALUE (x
),
14756 sizeof (fpstr
), 0, 1);
14757 fprintf (stream
, "#%s", fpstr
);
14760 fprintf (stream
, "#%s", fp_immediate_constant (x
));
14761 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
14765 gcc_assert (GET_CODE (x
) != NEG
);
14766 fputc ('#', stream
);
14767 output_addr_const (stream
, x
);
14773 #ifndef AOF_ASSEMBLER
14774 /* Target hook for assembling integer objects. The ARM version needs to
14775 handle word-sized values specially. */
14777 arm_assemble_integer (rtx x
, unsigned int size
, int aligned_p
)
14779 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
14780 enum machine_mode mode
;
14782 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
14783 /* APPLE LOCAL begin ARM MACH assembler */
14784 /* We can always handle unaligned data with the normal pseudoops. */
14787 /* APPLE LOCAL end ARM MACH assembler */
14789 if (size
== UNITS_PER_WORD
&& aligned_p
)
14791 /* APPLE LOCAL ARM MACH assembler */
14792 fputs ("\t" DOT_WORD
"\t", asm_out_file
);
14793 output_addr_const (asm_out_file
, x
);
14795 /* Mark symbols as position independent. We only do this in the
14796 .text segment, not in the .data segment. */
14797 if (NEED_GOT_RELOC
&& flag_pic
&& making_const_table
&&
14798 (GET_CODE (x
) == SYMBOL_REF
|| GET_CODE (x
) == LABEL_REF
))
14800 if (GET_CODE (x
) == SYMBOL_REF
14801 && (CONSTANT_POOL_ADDRESS_P (x
)
14802 || SYMBOL_REF_LOCAL_P (x
)))
14803 fputs ("(GOTOFF)", asm_out_file
);
14804 else if (GET_CODE (x
) == LABEL_REF
)
14805 fputs ("(GOTOFF)", asm_out_file
);
14807 fputs ("(GOT)", asm_out_file
);
14809 fputc ('\n', asm_out_file
);
14813 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
14814 mode
= GET_MODE (x
);
14816 if (arm_vector_mode_supported_p (mode
))
14819 unsigned int invmask
= 0, parts_per_word
;
14821 gcc_assert (GET_CODE (x
) == CONST_VECTOR
);
14823 units
= CONST_VECTOR_NUNITS (x
);
14824 size
= GET_MODE_SIZE (GET_MODE_INNER (mode
));
14826 /* For big-endian Neon vectors, we must permute the vector to the form
14827 which, when loaded by a VLDR or VLDM instruction, will give a vector
14828 with the elements in the right order. */
14829 if (TARGET_NEON
&& WORDS_BIG_ENDIAN
)
14831 parts_per_word
= UNITS_PER_WORD
/ size
;
14832 /* FIXME: This might be wrong for 64-bit vector elements, but we don't
14833 support those anywhere yet. */
14834 invmask
= (parts_per_word
== 0) ? 0 : (1 << (parts_per_word
- 1)) - 1;
14837 if (GET_MODE_CLASS (mode
) == MODE_VECTOR_INT
)
14838 for (i
= 0; i
< units
; i
++)
14840 rtx elt
= CONST_VECTOR_ELT (x
, i
^ invmask
);
14842 (elt
, size
, i
== 0 ? BIGGEST_ALIGNMENT
: size
* BITS_PER_UNIT
, 1);
14845 for (i
= 0; i
< units
; i
++)
14847 rtx elt
= CONST_VECTOR_ELT (x
, i
);
14848 REAL_VALUE_TYPE rval
;
14850 REAL_VALUE_FROM_CONST_DOUBLE (rval
, elt
);
14853 (rval
, GET_MODE_INNER (mode
),
14854 i
== 0 ? BIGGEST_ALIGNMENT
: size
* BITS_PER_UNIT
);
14859 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
14861 return default_assemble_integer (x
, size
, aligned_p
);
14865 /* APPLE LOCAL ARM macho file format */
14866 #ifdef OBJECT_FORMAT_ELF
14867 /* Add a function to the list of static constructors. */
14870 arm_elf_asm_constructor (rtx symbol
, int priority ATTRIBUTE_UNUSED
)
14872 if (!TARGET_AAPCS_BASED
)
14874 default_named_section_asm_out_constructor (symbol
, priority
);
14878 /* Put these in the .init_array section, using a special relocation. */
14879 switch_to_section (ctors_section
);
14880 assemble_align (POINTER_SIZE
);
14881 fputs ("\t.word\t", asm_out_file
);
14882 output_addr_const (asm_out_file
, symbol
);
14883 fputs ("(target1)\n", asm_out_file
);
14885 /* APPLE LOCAL ARM macho file format */
14889 /* A finite state machine takes care of noticing whether or not instructions
14890 can be conditionally executed, and thus decrease execution time and code
14891 size by deleting branch instructions. The fsm is controlled by
14892 final_prescan_insn, and controls the actions of ASM_OUTPUT_OPCODE. */
14894 /* The state of the fsm controlling condition codes are:
14895 0: normal, do nothing special
14896 1: make ASM_OUTPUT_OPCODE not output this instruction
14897 2: make ASM_OUTPUT_OPCODE not output this instruction
14898 3: make instructions conditional
14899 4: make instructions conditional
14901 State transitions (state->state by whom under condition):
14902 0 -> 1 final_prescan_insn if the `target' is a label
14903 0 -> 2 final_prescan_insn if the `target' is an unconditional branch
14904 1 -> 3 ASM_OUTPUT_OPCODE after not having output the conditional branch
14905 2 -> 4 ASM_OUTPUT_OPCODE after not having output the conditional branch
14906 3 -> 0 (*targetm.asm_out.internal_label) if the `target' label is reached
14907 (the target label has CODE_LABEL_NUMBER equal to arm_target_label).
14908 4 -> 0 final_prescan_insn if the `target' unconditional branch is reached
14909 (the target insn is arm_target_insn).
14911 If the jump clobbers the conditions then we use states 2 and 4.
14913 A similar thing can be done with conditional return insns.
14915 XXX In case the `target' is an unconditional branch, this conditionalising
14916 of the instructions always reduces code size, but not always execution
14917 time. But then, I want to reduce the code size to somewhere near what
14918 /bin/cc produces. */
14920 /* APPLE LOCAL begin v7 support. Merge from mainline */
14921 /* In addition to this, state is maintained for Thumb-2 COND_EXEC
14922 instructions. When a COND_EXEC instruction is seen the subsequent
14923 instructions are scanned so that multiple conditional instructions can be
14924 combined into a single IT block. arm_condexec_count and arm_condexec_mask
14925 specify the length and true/false mask for the IT block. These will be
14926 decremented/zeroed by arm_asm_output_opcode as the insns are output. */
14928 /* APPLE LOCAL end v7 support. Merge from mainline */
14929 /* Returns the index of the ARM condition code string in
14930 `arm_condition_codes'. COMPARISON should be an rtx like
14931 `(eq (...) (...))'. */
14932 static enum arm_cond_code
14933 get_arm_condition_code (rtx comparison
)
14935 enum machine_mode mode
= GET_MODE (XEXP (comparison
, 0));
14937 enum rtx_code comp_code
= GET_CODE (comparison
);
14939 if (GET_MODE_CLASS (mode
) != MODE_CC
)
14940 mode
= SELECT_CC_MODE (comp_code
, XEXP (comparison
, 0),
14941 XEXP (comparison
, 1));
14945 case CC_DNEmode
: code
= ARM_NE
; goto dominance
;
14946 case CC_DEQmode
: code
= ARM_EQ
; goto dominance
;
14947 case CC_DGEmode
: code
= ARM_GE
; goto dominance
;
14948 case CC_DGTmode
: code
= ARM_GT
; goto dominance
;
14949 case CC_DLEmode
: code
= ARM_LE
; goto dominance
;
14950 case CC_DLTmode
: code
= ARM_LT
; goto dominance
;
14951 case CC_DGEUmode
: code
= ARM_CS
; goto dominance
;
14952 case CC_DGTUmode
: code
= ARM_HI
; goto dominance
;
14953 case CC_DLEUmode
: code
= ARM_LS
; goto dominance
;
14954 case CC_DLTUmode
: code
= ARM_CC
;
14957 gcc_assert (comp_code
== EQ
|| comp_code
== NE
);
14959 if (comp_code
== EQ
)
14960 return ARM_INVERSE_CONDITION_CODE (code
);
14966 case NE
: return ARM_NE
;
14967 case EQ
: return ARM_EQ
;
14968 case GE
: return ARM_PL
;
14969 case LT
: return ARM_MI
;
14970 default: gcc_unreachable ();
14976 case NE
: return ARM_NE
;
14977 case EQ
: return ARM_EQ
;
14978 default: gcc_unreachable ();
14984 case NE
: return ARM_MI
;
14985 case EQ
: return ARM_PL
;
14986 default: gcc_unreachable ();
14991 /* These encodings assume that AC=1 in the FPA system control
14992 byte. This allows us to handle all cases except UNEQ and
14996 case GE
: return ARM_GE
;
14997 case GT
: return ARM_GT
;
14998 case LE
: return ARM_LS
;
14999 case LT
: return ARM_MI
;
15000 case NE
: return ARM_NE
;
15001 case EQ
: return ARM_EQ
;
15002 case ORDERED
: return ARM_VC
;
15003 case UNORDERED
: return ARM_VS
;
15004 case UNLT
: return ARM_LT
;
15005 case UNLE
: return ARM_LE
;
15006 case UNGT
: return ARM_HI
;
15007 case UNGE
: return ARM_PL
;
15008 /* UNEQ and LTGT do not have a representation. */
15009 case UNEQ
: /* Fall through. */
15010 case LTGT
: /* Fall through. */
15011 default: gcc_unreachable ();
15017 case NE
: return ARM_NE
;
15018 case EQ
: return ARM_EQ
;
15019 case GE
: return ARM_LE
;
15020 case GT
: return ARM_LT
;
15021 case LE
: return ARM_GE
;
15022 case LT
: return ARM_GT
;
15023 case GEU
: return ARM_LS
;
15024 case GTU
: return ARM_CC
;
15025 case LEU
: return ARM_CS
;
15026 case LTU
: return ARM_HI
;
15027 default: gcc_unreachable ();
15033 case LTU
: return ARM_CS
;
15034 case GEU
: return ARM_CC
;
15035 default: gcc_unreachable ();
15041 case NE
: return ARM_NE
;
15042 case EQ
: return ARM_EQ
;
15043 case GE
: return ARM_GE
;
15044 case GT
: return ARM_GT
;
15045 case LE
: return ARM_LE
;
15046 case LT
: return ARM_LT
;
15047 case GEU
: return ARM_CS
;
15048 case GTU
: return ARM_HI
;
15049 case LEU
: return ARM_LS
;
15050 case LTU
: return ARM_CC
;
15051 default: gcc_unreachable ();
15054 default: gcc_unreachable ();
15058 /* APPLE LOCAL begin v7 support. Merge from mainline */
15059 /* Tell arm_asm_ouput_opcode to output IT blocks for conditionally executed
15062 thumb2_final_prescan_insn (rtx insn
)
15064 rtx first_insn
= insn
;
15065 rtx body
= PATTERN (insn
);
15067 enum arm_cond_code code
;
15071 /* Remove the previous insn from the count of insns to be output. */
15072 if (arm_condexec_count
)
15073 arm_condexec_count
--;
15075 /* Nothing to do if we are already inside a conditional block. */
15076 if (arm_condexec_count
)
15079 if (GET_CODE (body
) != COND_EXEC
)
15082 /* Conditional jumps are implemented directly. */
15083 if (GET_CODE (insn
) == JUMP_INSN
)
15086 predicate
= COND_EXEC_TEST (body
);
15087 arm_current_cc
= get_arm_condition_code (predicate
);
15089 n
= get_attr_ce_count (insn
);
15090 arm_condexec_count
= 1;
15091 arm_condexec_mask
= (1 << n
) - 1;
15092 arm_condexec_masklen
= n
;
15093 /* See if subsequent instructions can be combined into the same block. */
15096 insn
= next_nonnote_insn (insn
);
15098 /* Jumping into the middle of an IT block is illegal, so a label or
15099 barrier terminates the block. */
15100 if (GET_CODE (insn
) != INSN
&& GET_CODE(insn
) != JUMP_INSN
)
15103 body
= PATTERN (insn
);
15104 /* USE and CLOBBER aren't really insns, so just skip them. */
15105 if (GET_CODE (body
) == USE
15106 || GET_CODE (body
) == CLOBBER
)
15109 /* ??? Recognise conditional jumps, and combine them with IT blocks. */
15110 if (GET_CODE (body
) != COND_EXEC
)
15112 /* Allow up to 4 conditionally executed instructions in a block. */
15113 n
= get_attr_ce_count (insn
);
15114 if (arm_condexec_masklen
+ n
> 4)
15117 predicate
= COND_EXEC_TEST (body
);
15118 code
= get_arm_condition_code (predicate
);
15119 mask
= (1 << n
) - 1;
15120 if (arm_current_cc
== code
)
15121 arm_condexec_mask
|= (mask
<< arm_condexec_masklen
);
15122 else if (arm_current_cc
!= ARM_INVERSE_CONDITION_CODE(code
))
15125 arm_condexec_count
++;
15126 arm_condexec_masklen
+= n
;
15128 /* A jump must be the last instruction in a conditional block. */
15129 if (GET_CODE(insn
) == JUMP_INSN
)
15132 /* Restore recog_data (getting the attributes of other insns can
15133 destroy this array, but final.c assumes that it remains intact
15134 across this call). */
15135 extract_constrain_insn_cached (first_insn
);
15138 /* APPLE LOCAL end v7 support. Merge from mainline */
15140 arm_final_prescan_insn (rtx insn
)
15142 /* LLVM LOCAL begin */
15147 /* LLVM LOCAL end */
15148 /* BODY will hold the body of INSN. */
15149 rtx body
= PATTERN (insn
);
15151 /* This will be 1 if trying to repeat the trick, and things need to be
15152 reversed if it appears to fail. */
15155 /* JUMP_CLOBBERS will be one implies that the conditions if a branch is
15156 taken are clobbered, even if the rtl suggests otherwise. It also
15157 means that we have to grub around within the jump expression to find
15158 out what the conditions are when the jump isn't taken. */
15159 int jump_clobbers
= 0;
15161 /* If we start with a return insn, we only succeed if we find another one. */
15162 int seeking_return
= 0;
15164 /* START_INSN will hold the insn from where we start looking. This is the
15165 first insn after the following code_label if REVERSE is true. */
15166 rtx start_insn
= insn
;
15168 /* If in state 4, check if the target branch is reached, in order to
15169 change back to state 0. */
15170 if (arm_ccfsm_state
== 4)
15172 if (insn
== arm_target_insn
)
15174 arm_target_insn
= NULL
;
15175 arm_ccfsm_state
= 0;
15180 /* If in state 3, it is possible to repeat the trick, if this insn is an
15181 unconditional branch to a label, and immediately following this branch
15182 is the previous target label which is only used once, and the label this
15183 branch jumps to is not too far off. */
15184 if (arm_ccfsm_state
== 3)
15186 if (simplejump_p (insn
))
15188 start_insn
= next_nonnote_insn (start_insn
);
15189 if (GET_CODE (start_insn
) == BARRIER
)
15191 /* XXX Isn't this always a barrier? */
15192 start_insn
= next_nonnote_insn (start_insn
);
15194 if (GET_CODE (start_insn
) == CODE_LABEL
15195 && CODE_LABEL_NUMBER (start_insn
) == arm_target_label
15196 && LABEL_NUSES (start_insn
) == 1)
15201 else if (GET_CODE (body
) == RETURN
)
15203 start_insn
= next_nonnote_insn (start_insn
);
15204 if (GET_CODE (start_insn
) == BARRIER
)
15205 start_insn
= next_nonnote_insn (start_insn
);
15206 if (GET_CODE (start_insn
) == CODE_LABEL
15207 && CODE_LABEL_NUMBER (start_insn
) == arm_target_label
15208 && LABEL_NUSES (start_insn
) == 1)
15211 seeking_return
= 1;
15220 gcc_assert (!arm_ccfsm_state
|| reverse
);
15221 if (GET_CODE (insn
) != JUMP_INSN
)
15224 /* This jump might be paralleled with a clobber of the condition codes
15225 the jump should always come first */
15226 if (GET_CODE (body
) == PARALLEL
&& XVECLEN (body
, 0) > 0)
15227 body
= XVECEXP (body
, 0, 0);
15230 || (GET_CODE (body
) == SET
&& GET_CODE (SET_DEST (body
)) == PC
15231 && GET_CODE (SET_SRC (body
)) == IF_THEN_ELSE
))
15234 int fail
= FALSE
, succeed
= FALSE
;
15235 /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
15236 int then_not_else
= TRUE
;
15237 rtx this_insn
= start_insn
, label
= 0;
15239 /* If the jump cannot be done with one instruction, we cannot
15240 conditionally execute the instruction in the inverse case. */
15241 if (get_attr_conds (insn
) == CONDS_JUMP_CLOB
)
15247 /* Register the insn jumped to. */
15250 if (!seeking_return
)
15251 label
= XEXP (SET_SRC (body
), 0);
15253 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == LABEL_REF
)
15254 label
= XEXP (XEXP (SET_SRC (body
), 1), 0);
15255 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == LABEL_REF
)
15257 label
= XEXP (XEXP (SET_SRC (body
), 2), 0);
15258 then_not_else
= FALSE
;
15260 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == RETURN
)
15261 seeking_return
= 1;
15262 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == RETURN
)
15264 seeking_return
= 1;
15265 then_not_else
= FALSE
;
15268 gcc_unreachable ();
15270 /* See how many insns this branch skips, and what kind of insns. If all
15271 insns are okay, and the label or unconditional branch to the same
15272 label is not too far away, succeed. */
15273 for (insns_skipped
= 0;
15274 !fail
&& !succeed
&& insns_skipped
++ < max_insns_skipped
;)
15278 this_insn
= next_nonnote_insn (this_insn
);
15282 switch (GET_CODE (this_insn
))
15285 /* Succeed if it is the target label, otherwise fail since
15286 control falls in from somewhere else. */
15287 if (this_insn
== label
)
15291 arm_ccfsm_state
= 2;
15292 this_insn
= next_nonnote_insn (this_insn
);
15295 arm_ccfsm_state
= 1;
15303 /* Succeed if the following insn is the target label.
15305 If return insns are used then the last insn in a function
15306 will be a barrier. */
15307 this_insn
= next_nonnote_insn (this_insn
);
15308 if (this_insn
&& this_insn
== label
)
15312 arm_ccfsm_state
= 2;
15313 this_insn
= next_nonnote_insn (this_insn
);
15316 arm_ccfsm_state
= 1;
15324 /* The AAPCS says that conditional calls should not be
15325 used since they make interworking inefficient (the
15326 linker can't transform BL<cond> into BLX). That's
15327 only a problem if the machine has BLX. */
15334 /* Succeed if the following insn is the target label, or
15335 if the following two insns are a barrier and the
15337 this_insn
= next_nonnote_insn (this_insn
);
15338 if (this_insn
&& GET_CODE (this_insn
) == BARRIER
)
15339 this_insn
= next_nonnote_insn (this_insn
);
15341 if (this_insn
&& this_insn
== label
15342 && insns_skipped
< max_insns_skipped
)
15346 arm_ccfsm_state
= 2;
15347 this_insn
= next_nonnote_insn (this_insn
);
15350 arm_ccfsm_state
= 1;
15358 /* If this is an unconditional branch to the same label, succeed.
15359 If it is to another label, do nothing. If it is conditional,
15361 /* XXX Probably, the tests for SET and the PC are
15364 scanbody
= PATTERN (this_insn
);
15365 if (GET_CODE (scanbody
) == SET
15366 && GET_CODE (SET_DEST (scanbody
)) == PC
)
15368 if (GET_CODE (SET_SRC (scanbody
)) == LABEL_REF
15369 && XEXP (SET_SRC (scanbody
), 0) == label
&& !reverse
)
15371 arm_ccfsm_state
= 2;
15374 else if (GET_CODE (SET_SRC (scanbody
)) == IF_THEN_ELSE
)
15377 /* Fail if a conditional return is undesirable (e.g. on a
15378 StrongARM), but still allow this if optimizing for size. */
15379 else if (GET_CODE (scanbody
) == RETURN
15380 && !use_return_insn (TRUE
, NULL
)
15383 else if (GET_CODE (scanbody
) == RETURN
15386 arm_ccfsm_state
= 2;
15389 else if (GET_CODE (scanbody
) == PARALLEL
)
15391 switch (get_attr_conds (this_insn
))
15401 fail
= TRUE
; /* Unrecognized jump (e.g. epilogue). */
15406 /* Instructions using or affecting the condition codes make it
15408 scanbody
= PATTERN (this_insn
);
15409 if (!(GET_CODE (scanbody
) == SET
15410 || GET_CODE (scanbody
) == PARALLEL
)
15411 || get_attr_conds (this_insn
) != CONDS_NOCOND
)
15414 /* A conditional cirrus instruction must be followed by
15415 a non Cirrus instruction. However, since we
15416 conditionalize instructions in this function and by
15417 the time we get here we can't add instructions
15418 (nops), because shorten_branches() has already been
15419 called, we will disable conditionalizing Cirrus
15420 instructions to be safe. */
15421 if (GET_CODE (scanbody
) != USE
15422 && GET_CODE (scanbody
) != CLOBBER
15423 && get_attr_cirrus (this_insn
) != CIRRUS_NOT
)
15426 /* APPLE LOCAL begin 6280380 */
15427 /* While most ARM instructions are predicable, a few
15428 like NEON instructions aren't... */
15429 if (GET_CODE (scanbody
) != USE
15430 && GET_CODE (scanbody
) != CLOBBER
15431 && get_attr_predicable (this_insn
) == PREDICABLE_NO
)
15433 /* APPLE LOCAL end 6280380 */
15442 if ((!seeking_return
) && (arm_ccfsm_state
== 1 || reverse
))
15443 arm_target_label
= CODE_LABEL_NUMBER (label
);
15446 gcc_assert (seeking_return
|| arm_ccfsm_state
== 2);
15448 while (this_insn
&& GET_CODE (PATTERN (this_insn
)) == USE
)
15450 this_insn
= next_nonnote_insn (this_insn
);
15451 gcc_assert (!this_insn
15452 || (GET_CODE (this_insn
) != BARRIER
15453 && GET_CODE (this_insn
) != CODE_LABEL
));
15457 /* Oh, dear! we ran off the end.. give up. */
15458 /* APPLE LOCAL v7 support. Merge from mainline */
15459 extract_constrain_insn_cached (insn
);
15460 arm_ccfsm_state
= 0;
15461 arm_target_insn
= NULL
;
15464 arm_target_insn
= this_insn
;
15468 gcc_assert (!reverse
);
15470 get_arm_condition_code (XEXP (XEXP (XEXP (SET_SRC (body
),
15472 if (GET_CODE (XEXP (XEXP (SET_SRC (body
), 0), 0)) == AND
)
15473 arm_current_cc
= ARM_INVERSE_CONDITION_CODE (arm_current_cc
);
15474 if (GET_CODE (XEXP (SET_SRC (body
), 0)) == NE
)
15475 arm_current_cc
= ARM_INVERSE_CONDITION_CODE (arm_current_cc
);
15479 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
15482 arm_current_cc
= get_arm_condition_code (XEXP (SET_SRC (body
),
15486 if (reverse
|| then_not_else
)
15487 arm_current_cc
= ARM_INVERSE_CONDITION_CODE (arm_current_cc
);
15490 /* APPLE LOCAL begin v7 support. Merge from mainline */
15491 /* Restore recog_data (getting the attributes of other insns can
15492 destroy this array, but final.c assumes that it remains intact
15493 across this call. */
15494 extract_constrain_insn_cached (insn
);
15499 /* APPLE LOCAL end v7 support. Merge from mainline */
15501 /* APPLE LOCAL begin v7 support. Merge from mainline */
15502 /* Output IT instructions. */
15504 thumb2_asm_output_opcode (FILE * stream
)
15509 if (arm_condexec_mask
)
15511 for (n
= 0; n
< arm_condexec_masklen
; n
++)
15512 buff
[n
] = (arm_condexec_mask
& (1 << n
)) ? 't' : 'e';
15514 asm_fprintf(stream
, "i%s\t%s\n\t", buff
,
15515 arm_condition_codes
[arm_current_cc
]);
15516 arm_condexec_mask
= 0;
15519 /* APPLE LOCAL end v7 support. Merge from mainline */
15521 /* Returns true if REGNO is a valid register
15522 for holding a quantity of type MODE. */
15524 arm_hard_regno_mode_ok (unsigned int regno
, enum machine_mode mode
)
15526 if (GET_MODE_CLASS (mode
) == MODE_CC
)
15527 return (regno
== CC_REGNUM
15528 || (TARGET_HARD_FLOAT
&& TARGET_VFP
15529 && regno
== VFPCC_REGNUM
));
15531 /* APPLE LOCAL v7 support. Merge from mainline */
15533 /* For the Thumb we only allow values bigger than SImode in
15534 registers 0 - 6, so that there is always a second low
15535 register available to hold the upper part of the value.
15536 We probably we ought to ensure that the register is the
15537 start of an even numbered register pair. */
15538 return (ARM_NUM_REGS (mode
) < 2) || (regno
< LAST_LO_REGNUM
);
15540 if (TARGET_HARD_FLOAT
&& TARGET_MAVERICK
15541 && IS_CIRRUS_REGNUM (regno
))
15542 /* We have outlawed SI values in Cirrus registers because they
15543 reside in the lower 32 bits, but SF values reside in the
15544 upper 32 bits. This causes gcc all sorts of grief. We can't
15545 even split the registers into pairs because Cirrus SI values
15546 get sign extended to 64bits-- aldyh. */
15547 return (GET_MODE_CLASS (mode
) == MODE_FLOAT
) || (mode
== DImode
);
15549 if (TARGET_HARD_FLOAT
&& TARGET_VFP
15550 && IS_VFP_REGNUM (regno
))
15552 /* APPLE LOCAL begin v7 support. Merge from mainline */
15553 if (mode
== SFmode
|| mode
== SImode
)
15554 return VFP_REGNO_OK_FOR_SINGLE (regno
);
15556 if (mode
== DFmode
)
15557 return VFP_REGNO_OK_FOR_DOUBLE (regno
);
15558 /* APPLE LOCAL end v7 support. Merge from mainline */
15559 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
15562 return (VALID_NEON_DREG_MODE (mode
) && VFP_REGNO_OK_FOR_DOUBLE (regno
))
15563 || (VALID_NEON_QREG_MODE (mode
)
15564 && NEON_REGNO_OK_FOR_QUAD (regno
))
15565 || (mode
== TImode
&& NEON_REGNO_OK_FOR_NREGS (regno
, 2))
15566 || (mode
== EImode
&& NEON_REGNO_OK_FOR_NREGS (regno
, 3))
15567 || (mode
== OImode
&& NEON_REGNO_OK_FOR_NREGS (regno
, 4))
15568 || (mode
== CImode
&& NEON_REGNO_OK_FOR_NREGS (regno
, 6))
15569 || (mode
== XImode
&& NEON_REGNO_OK_FOR_NREGS (regno
, 8));
15571 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
15575 if (TARGET_REALLY_IWMMXT
)
15577 if (IS_IWMMXT_GR_REGNUM (regno
))
15578 return mode
== SImode
;
15580 if (IS_IWMMXT_REGNUM (regno
))
15581 return VALID_IWMMXT_REG_MODE (mode
);
15584 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
15585 /* We allow any value to be stored in the general registers.
15586 Restrict doubleword quantities to even register pairs so that we can
15587 use ldrd. Do not allow Neon structure opaque modes in general registers;
15588 they would use too many. */
15589 if (regno
<= LAST_ARM_REGNUM
)
15590 return !(TARGET_LDRD
&& GET_MODE_SIZE (mode
) > 4 && (regno
& 1) != 0)
15591 && !VALID_NEON_STRUCT_MODE (mode
);
15592 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
15594 if (regno
== FRAME_POINTER_REGNUM
15595 || regno
== ARG_POINTER_REGNUM
)
15596 /* We only allow integers in the fake hard registers. */
15597 return GET_MODE_CLASS (mode
) == MODE_INT
;
15599 /* The only registers left are the FPA registers
15600 which we only allow to hold FP values. */
15601 return (TARGET_HARD_FLOAT
&& TARGET_FPA
15602 && GET_MODE_CLASS (mode
) == MODE_FLOAT
15603 && regno
>= FIRST_FPA_REGNUM
15604 && regno
<= LAST_FPA_REGNUM
);
15607 /* APPLE LOCAL begin v7 support. Merge from mainline */
15608 /* For efficiency and historical reasons LO_REGS, HI_REGS and CC_REGS are
15609 not used in arm mode. */
15611 arm_regno_class (int regno
)
15615 if (regno
== STACK_POINTER_REGNUM
)
15617 if (regno
== CC_REGNUM
)
15624 if (TARGET_THUMB2
&& regno
< 8)
15627 if ( regno
<= LAST_ARM_REGNUM
15628 || regno
== FRAME_POINTER_REGNUM
15629 || regno
== ARG_POINTER_REGNUM
)
15630 return TARGET_THUMB2
? HI_REGS
: GENERAL_REGS
;
15632 if (regno
== CC_REGNUM
|| regno
== VFPCC_REGNUM
)
15633 return TARGET_THUMB2
? CC_REG
: NO_REGS
;
15635 if (IS_CIRRUS_REGNUM (regno
))
15636 return CIRRUS_REGS
;
15638 if (IS_VFP_REGNUM (regno
))
15640 if (regno
<= D7_VFP_REGNUM
)
15641 return VFP_D0_D7_REGS
;
15642 else if (regno
<= LAST_LO_VFP_REGNUM
)
15643 return VFP_LO_REGS
;
15645 return VFP_HI_REGS
;
15648 if (IS_IWMMXT_REGNUM (regno
))
15649 return IWMMXT_REGS
;
15651 if (IS_IWMMXT_GR_REGNUM (regno
))
15652 return IWMMXT_GR_REGS
;
15656 /* APPLE LOCAL end v7 support. Merge from mainline */
15658 /* Handle a special case when computing the offset
15659 of an argument from the frame pointer. */
15661 arm_debugger_arg_offset (int value
, rtx addr
)
15665 /* APPLE LOCAL begin ARM prefer SP to FP */
15666 /* If we generated a frame, but the offset is from the SP anyway, then
15667 we have to adjust the offset to be FP-relative, as that's what gdb
15668 will be expecting. */
15669 if (frame_pointer_needed
)
15671 if ((GET_CODE (addr
) == REG
) && (REGNO (addr
) == SP_REGNUM
))
15672 return arm_local_debug_offset (addr
);
15674 if (GET_CODE (addr
) == PLUS
15675 && GET_CODE (XEXP (addr
, 0)) == REG
15676 && REGNO (XEXP (addr
, 0)) == SP_REGNUM
)
15677 return arm_local_debug_offset (addr
);
15680 /* We are only interested if dbxout_parms() failed to compute the offset. */
15683 /* APPLE LOCAL end ARM prefer SP to FP */
15685 /* We can only cope with the case where the address is held in a register. */
15686 if (GET_CODE (addr
) != REG
)
15689 /* If we are using the frame pointer to point at the argument, then
15690 an offset of 0 is correct. */
15691 if (REGNO (addr
) == (unsigned) HARD_FRAME_POINTER_REGNUM
)
15694 /* If we are using the stack pointer to point at the
15695 argument, then an offset of 0 is correct. */
15696 /* APPLE LOCAL v7 support. Merge from mainline */
15697 /* ??? Check this is consistent with thumb2 frame layout. */
15698 if ((TARGET_THUMB
|| !frame_pointer_needed
)
15699 && REGNO (addr
) == SP_REGNUM
)
15702 /* Oh dear. The argument is pointed to by a register rather
15703 than being held in a register, or being stored at a known
15704 offset from the frame pointer. Since GDB only understands
15705 those two kinds of argument we must translate the address
15706 held in the register into an offset from the frame pointer.
15707 We do this by searching through the insns for the function
15708 looking to see where this register gets its value. If the
15709 register is initialized from the frame pointer plus an offset
15710 then we are in luck and we can continue, otherwise we give up.
15712 This code is exercised by producing debugging information
15713 for a function with arguments like this:
15715 double func (double a, double b, int c, double d) {return d;}
15717 Without this code the stab for parameter 'd' will be set to
15718 an offset of 0 from the frame pointer, rather than 8. */
15720 /* The if() statement says:
15722 If the insn is a normal instruction
15723 and if the insn is setting the value in a register
15724 and if the register being set is the register holding the address of the argument
15725 and if the address is computing by an addition
15726 that involves adding to a register
15727 which is the frame pointer
15732 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
15734 if ( GET_CODE (insn
) == INSN
15735 && GET_CODE (PATTERN (insn
)) == SET
15736 && REGNO (XEXP (PATTERN (insn
), 0)) == REGNO (addr
)
15737 && GET_CODE (XEXP (PATTERN (insn
), 1)) == PLUS
15738 && GET_CODE (XEXP (XEXP (PATTERN (insn
), 1), 0)) == REG
15739 && REGNO (XEXP (XEXP (PATTERN (insn
), 1), 0)) == (unsigned) HARD_FRAME_POINTER_REGNUM
15740 && GET_CODE (XEXP (XEXP (PATTERN (insn
), 1), 1)) == CONST_INT
15743 value
= INTVAL (XEXP (XEXP (PATTERN (insn
), 1), 1));
15752 warning (0, "unable to compute real location of stacked parameter");
15753 value
= 8; /* XXX magic hack */
15759 #define def_mbuiltin(MASK, NAME, TYPE, CODE) \
15762 if ((MASK) & insn_flags) \
15763 lang_hooks.builtin_function ((NAME), (TYPE), (CODE), \
15764 BUILT_IN_MD, NULL, NULL_TREE); \
15768 struct builtin_description
15770 const unsigned int mask
;
15771 const enum insn_code icode
;
15772 const char * const name
;
15773 const enum arm_builtins code
;
15774 const enum rtx_code comparison
;
15775 const unsigned int flag
;
15778 static const struct builtin_description bdesc_2arg
[] =
15780 #define IWMMXT_BUILTIN(code, string, builtin) \
15781 { FL_IWMMXT, CODE_FOR_##code, "__builtin_arm_" string, \
15782 ARM_BUILTIN_##builtin, 0, 0 },
15784 IWMMXT_BUILTIN (addv8qi3
, "waddb", WADDB
)
15785 IWMMXT_BUILTIN (addv4hi3
, "waddh", WADDH
)
15786 IWMMXT_BUILTIN (addv2si3
, "waddw", WADDW
)
15787 IWMMXT_BUILTIN (subv8qi3
, "wsubb", WSUBB
)
15788 IWMMXT_BUILTIN (subv4hi3
, "wsubh", WSUBH
)
15789 IWMMXT_BUILTIN (subv2si3
, "wsubw", WSUBW
)
15790 IWMMXT_BUILTIN (ssaddv8qi3
, "waddbss", WADDSSB
)
15791 IWMMXT_BUILTIN (ssaddv4hi3
, "waddhss", WADDSSH
)
15792 IWMMXT_BUILTIN (ssaddv2si3
, "waddwss", WADDSSW
)
15793 IWMMXT_BUILTIN (sssubv8qi3
, "wsubbss", WSUBSSB
)
15794 IWMMXT_BUILTIN (sssubv4hi3
, "wsubhss", WSUBSSH
)
15795 IWMMXT_BUILTIN (sssubv2si3
, "wsubwss", WSUBSSW
)
15796 IWMMXT_BUILTIN (usaddv8qi3
, "waddbus", WADDUSB
)
15797 IWMMXT_BUILTIN (usaddv4hi3
, "waddhus", WADDUSH
)
15798 IWMMXT_BUILTIN (usaddv2si3
, "waddwus", WADDUSW
)
15799 IWMMXT_BUILTIN (ussubv8qi3
, "wsubbus", WSUBUSB
)
15800 IWMMXT_BUILTIN (ussubv4hi3
, "wsubhus", WSUBUSH
)
15801 IWMMXT_BUILTIN (ussubv2si3
, "wsubwus", WSUBUSW
)
15802 IWMMXT_BUILTIN (mulv4hi3
, "wmulul", WMULUL
)
15803 IWMMXT_BUILTIN (smulv4hi3_highpart
, "wmulsm", WMULSM
)
15804 IWMMXT_BUILTIN (umulv4hi3_highpart
, "wmulum", WMULUM
)
15805 IWMMXT_BUILTIN (eqv8qi3
, "wcmpeqb", WCMPEQB
)
15806 IWMMXT_BUILTIN (eqv4hi3
, "wcmpeqh", WCMPEQH
)
15807 IWMMXT_BUILTIN (eqv2si3
, "wcmpeqw", WCMPEQW
)
15808 IWMMXT_BUILTIN (gtuv8qi3
, "wcmpgtub", WCMPGTUB
)
15809 IWMMXT_BUILTIN (gtuv4hi3
, "wcmpgtuh", WCMPGTUH
)
15810 IWMMXT_BUILTIN (gtuv2si3
, "wcmpgtuw", WCMPGTUW
)
15811 IWMMXT_BUILTIN (gtv8qi3
, "wcmpgtsb", WCMPGTSB
)
15812 IWMMXT_BUILTIN (gtv4hi3
, "wcmpgtsh", WCMPGTSH
)
15813 IWMMXT_BUILTIN (gtv2si3
, "wcmpgtsw", WCMPGTSW
)
15814 IWMMXT_BUILTIN (umaxv8qi3
, "wmaxub", WMAXUB
)
15815 IWMMXT_BUILTIN (smaxv8qi3
, "wmaxsb", WMAXSB
)
15816 IWMMXT_BUILTIN (umaxv4hi3
, "wmaxuh", WMAXUH
)
15817 IWMMXT_BUILTIN (smaxv4hi3
, "wmaxsh", WMAXSH
)
15818 IWMMXT_BUILTIN (umaxv2si3
, "wmaxuw", WMAXUW
)
15819 IWMMXT_BUILTIN (smaxv2si3
, "wmaxsw", WMAXSW
)
15820 IWMMXT_BUILTIN (uminv8qi3
, "wminub", WMINUB
)
15821 IWMMXT_BUILTIN (sminv8qi3
, "wminsb", WMINSB
)
15822 IWMMXT_BUILTIN (uminv4hi3
, "wminuh", WMINUH
)
15823 IWMMXT_BUILTIN (sminv4hi3
, "wminsh", WMINSH
)
15824 IWMMXT_BUILTIN (uminv2si3
, "wminuw", WMINUW
)
15825 IWMMXT_BUILTIN (sminv2si3
, "wminsw", WMINSW
)
15826 IWMMXT_BUILTIN (iwmmxt_anddi3
, "wand", WAND
)
15827 IWMMXT_BUILTIN (iwmmxt_nanddi3
, "wandn", WANDN
)
15828 IWMMXT_BUILTIN (iwmmxt_iordi3
, "wor", WOR
)
15829 IWMMXT_BUILTIN (iwmmxt_xordi3
, "wxor", WXOR
)
15830 IWMMXT_BUILTIN (iwmmxt_uavgv8qi3
, "wavg2b", WAVG2B
)
15831 IWMMXT_BUILTIN (iwmmxt_uavgv4hi3
, "wavg2h", WAVG2H
)
15832 IWMMXT_BUILTIN (iwmmxt_uavgrndv8qi3
, "wavg2br", WAVG2BR
)
15833 IWMMXT_BUILTIN (iwmmxt_uavgrndv4hi3
, "wavg2hr", WAVG2HR
)
15834 IWMMXT_BUILTIN (iwmmxt_wunpckilb
, "wunpckilb", WUNPCKILB
)
15835 IWMMXT_BUILTIN (iwmmxt_wunpckilh
, "wunpckilh", WUNPCKILH
)
15836 IWMMXT_BUILTIN (iwmmxt_wunpckilw
, "wunpckilw", WUNPCKILW
)
15837 IWMMXT_BUILTIN (iwmmxt_wunpckihb
, "wunpckihb", WUNPCKIHB
)
15838 IWMMXT_BUILTIN (iwmmxt_wunpckihh
, "wunpckihh", WUNPCKIHH
)
15839 IWMMXT_BUILTIN (iwmmxt_wunpckihw
, "wunpckihw", WUNPCKIHW
)
15840 IWMMXT_BUILTIN (iwmmxt_wmadds
, "wmadds", WMADDS
)
15841 IWMMXT_BUILTIN (iwmmxt_wmaddu
, "wmaddu", WMADDU
)
15843 #define IWMMXT_BUILTIN2(code, builtin) \
15844 { FL_IWMMXT, CODE_FOR_##code, NULL, ARM_BUILTIN_##builtin, 0, 0 },
15846 IWMMXT_BUILTIN2 (iwmmxt_wpackhss
, WPACKHSS
)
15847 IWMMXT_BUILTIN2 (iwmmxt_wpackwss
, WPACKWSS
)
15848 IWMMXT_BUILTIN2 (iwmmxt_wpackdss
, WPACKDSS
)
15849 IWMMXT_BUILTIN2 (iwmmxt_wpackhus
, WPACKHUS
)
15850 IWMMXT_BUILTIN2 (iwmmxt_wpackwus
, WPACKWUS
)
15851 IWMMXT_BUILTIN2 (iwmmxt_wpackdus
, WPACKDUS
)
15852 IWMMXT_BUILTIN2 (ashlv4hi3_di
, WSLLH
)
15853 IWMMXT_BUILTIN2 (ashlv4hi3
, WSLLHI
)
15854 IWMMXT_BUILTIN2 (ashlv2si3_di
, WSLLW
)
15855 IWMMXT_BUILTIN2 (ashlv2si3
, WSLLWI
)
15856 IWMMXT_BUILTIN2 (ashldi3_di
, WSLLD
)
15857 IWMMXT_BUILTIN2 (ashldi3_iwmmxt
, WSLLDI
)
15858 IWMMXT_BUILTIN2 (lshrv4hi3_di
, WSRLH
)
15859 IWMMXT_BUILTIN2 (lshrv4hi3
, WSRLHI
)
15860 IWMMXT_BUILTIN2 (lshrv2si3_di
, WSRLW
)
15861 IWMMXT_BUILTIN2 (lshrv2si3
, WSRLWI
)
15862 IWMMXT_BUILTIN2 (lshrdi3_di
, WSRLD
)
15863 IWMMXT_BUILTIN2 (lshrdi3_iwmmxt
, WSRLDI
)
15864 IWMMXT_BUILTIN2 (ashrv4hi3_di
, WSRAH
)
15865 IWMMXT_BUILTIN2 (ashrv4hi3
, WSRAHI
)
15866 IWMMXT_BUILTIN2 (ashrv2si3_di
, WSRAW
)
15867 IWMMXT_BUILTIN2 (ashrv2si3
, WSRAWI
)
15868 IWMMXT_BUILTIN2 (ashrdi3_di
, WSRAD
)
15869 IWMMXT_BUILTIN2 (ashrdi3_iwmmxt
, WSRADI
)
15870 IWMMXT_BUILTIN2 (rorv4hi3_di
, WRORH
)
15871 IWMMXT_BUILTIN2 (rorv4hi3
, WRORHI
)
15872 IWMMXT_BUILTIN2 (rorv2si3_di
, WRORW
)
15873 IWMMXT_BUILTIN2 (rorv2si3
, WRORWI
)
15874 IWMMXT_BUILTIN2 (rordi3_di
, WRORD
)
15875 IWMMXT_BUILTIN2 (rordi3
, WRORDI
)
15876 IWMMXT_BUILTIN2 (iwmmxt_wmacuz
, WMACUZ
)
15877 IWMMXT_BUILTIN2 (iwmmxt_wmacsz
, WMACSZ
)
15880 static const struct builtin_description bdesc_1arg
[] =
15882 IWMMXT_BUILTIN (iwmmxt_tmovmskb
, "tmovmskb", TMOVMSKB
)
15883 IWMMXT_BUILTIN (iwmmxt_tmovmskh
, "tmovmskh", TMOVMSKH
)
15884 IWMMXT_BUILTIN (iwmmxt_tmovmskw
, "tmovmskw", TMOVMSKW
)
15885 IWMMXT_BUILTIN (iwmmxt_waccb
, "waccb", WACCB
)
15886 IWMMXT_BUILTIN (iwmmxt_wacch
, "wacch", WACCH
)
15887 IWMMXT_BUILTIN (iwmmxt_waccw
, "waccw", WACCW
)
15888 IWMMXT_BUILTIN (iwmmxt_wunpckehub
, "wunpckehub", WUNPCKEHUB
)
15889 IWMMXT_BUILTIN (iwmmxt_wunpckehuh
, "wunpckehuh", WUNPCKEHUH
)
15890 IWMMXT_BUILTIN (iwmmxt_wunpckehuw
, "wunpckehuw", WUNPCKEHUW
)
15891 IWMMXT_BUILTIN (iwmmxt_wunpckehsb
, "wunpckehsb", WUNPCKEHSB
)
15892 IWMMXT_BUILTIN (iwmmxt_wunpckehsh
, "wunpckehsh", WUNPCKEHSH
)
15893 IWMMXT_BUILTIN (iwmmxt_wunpckehsw
, "wunpckehsw", WUNPCKEHSW
)
15894 IWMMXT_BUILTIN (iwmmxt_wunpckelub
, "wunpckelub", WUNPCKELUB
)
15895 IWMMXT_BUILTIN (iwmmxt_wunpckeluh
, "wunpckeluh", WUNPCKELUH
)
15896 IWMMXT_BUILTIN (iwmmxt_wunpckeluw
, "wunpckeluw", WUNPCKELUW
)
15897 IWMMXT_BUILTIN (iwmmxt_wunpckelsb
, "wunpckelsb", WUNPCKELSB
)
15898 IWMMXT_BUILTIN (iwmmxt_wunpckelsh
, "wunpckelsh", WUNPCKELSH
)
15899 IWMMXT_BUILTIN (iwmmxt_wunpckelsw
, "wunpckelsw", WUNPCKELSW
)
15902 /* Set up all the iWMMXt builtins. This is
15903 not called if TARGET_IWMMXT is zero. */
15906 arm_init_iwmmxt_builtins (void)
15908 const struct builtin_description
* d
;
15910 tree endlink
= void_list_node
;
15912 tree V2SI_type_node
= build_vector_type_for_mode (intSI_type_node
, V2SImode
);
15913 tree V4HI_type_node
= build_vector_type_for_mode (intHI_type_node
, V4HImode
);
15914 tree V8QI_type_node
= build_vector_type_for_mode (intQI_type_node
, V8QImode
);
15917 = build_function_type (integer_type_node
,
15918 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
15919 tree v8qi_ftype_v8qi_v8qi_int
15920 = build_function_type (V8QI_type_node
,
15921 tree_cons (NULL_TREE
, V8QI_type_node
,
15922 tree_cons (NULL_TREE
, V8QI_type_node
,
15923 tree_cons (NULL_TREE
,
15926 tree v4hi_ftype_v4hi_int
15927 = build_function_type (V4HI_type_node
,
15928 tree_cons (NULL_TREE
, V4HI_type_node
,
15929 tree_cons (NULL_TREE
, integer_type_node
,
15931 tree v2si_ftype_v2si_int
15932 = build_function_type (V2SI_type_node
,
15933 tree_cons (NULL_TREE
, V2SI_type_node
,
15934 tree_cons (NULL_TREE
, integer_type_node
,
15936 tree v2si_ftype_di_di
15937 = build_function_type (V2SI_type_node
,
15938 tree_cons (NULL_TREE
, long_long_integer_type_node
,
15939 tree_cons (NULL_TREE
, long_long_integer_type_node
,
15941 tree di_ftype_di_int
15942 = build_function_type (long_long_integer_type_node
,
15943 tree_cons (NULL_TREE
, long_long_integer_type_node
,
15944 tree_cons (NULL_TREE
, integer_type_node
,
15946 tree di_ftype_di_int_int
15947 = build_function_type (long_long_integer_type_node
,
15948 tree_cons (NULL_TREE
, long_long_integer_type_node
,
15949 tree_cons (NULL_TREE
, integer_type_node
,
15950 tree_cons (NULL_TREE
,
15953 tree int_ftype_v8qi
15954 = build_function_type (integer_type_node
,
15955 tree_cons (NULL_TREE
, V8QI_type_node
,
15957 tree int_ftype_v4hi
15958 = build_function_type (integer_type_node
,
15959 tree_cons (NULL_TREE
, V4HI_type_node
,
15961 tree int_ftype_v2si
15962 = build_function_type (integer_type_node
,
15963 tree_cons (NULL_TREE
, V2SI_type_node
,
15965 tree int_ftype_v8qi_int
15966 = build_function_type (integer_type_node
,
15967 tree_cons (NULL_TREE
, V8QI_type_node
,
15968 tree_cons (NULL_TREE
, integer_type_node
,
15970 tree int_ftype_v4hi_int
15971 = build_function_type (integer_type_node
,
15972 tree_cons (NULL_TREE
, V4HI_type_node
,
15973 tree_cons (NULL_TREE
, integer_type_node
,
15975 tree int_ftype_v2si_int
15976 = build_function_type (integer_type_node
,
15977 tree_cons (NULL_TREE
, V2SI_type_node
,
15978 tree_cons (NULL_TREE
, integer_type_node
,
15980 tree v8qi_ftype_v8qi_int_int
15981 = build_function_type (V8QI_type_node
,
15982 tree_cons (NULL_TREE
, V8QI_type_node
,
15983 tree_cons (NULL_TREE
, integer_type_node
,
15984 tree_cons (NULL_TREE
,
15987 tree v4hi_ftype_v4hi_int_int
15988 = build_function_type (V4HI_type_node
,
15989 tree_cons (NULL_TREE
, V4HI_type_node
,
15990 tree_cons (NULL_TREE
, integer_type_node
,
15991 tree_cons (NULL_TREE
,
15994 tree v2si_ftype_v2si_int_int
15995 = build_function_type (V2SI_type_node
,
15996 tree_cons (NULL_TREE
, V2SI_type_node
,
15997 tree_cons (NULL_TREE
, integer_type_node
,
15998 tree_cons (NULL_TREE
,
16001 /* Miscellaneous. */
16002 tree v8qi_ftype_v4hi_v4hi
16003 = build_function_type (V8QI_type_node
,
16004 tree_cons (NULL_TREE
, V4HI_type_node
,
16005 tree_cons (NULL_TREE
, V4HI_type_node
,
16007 tree v4hi_ftype_v2si_v2si
16008 = build_function_type (V4HI_type_node
,
16009 tree_cons (NULL_TREE
, V2SI_type_node
,
16010 tree_cons (NULL_TREE
, V2SI_type_node
,
16012 tree v2si_ftype_v4hi_v4hi
16013 = build_function_type (V2SI_type_node
,
16014 tree_cons (NULL_TREE
, V4HI_type_node
,
16015 tree_cons (NULL_TREE
, V4HI_type_node
,
16017 tree v2si_ftype_v8qi_v8qi
16018 = build_function_type (V2SI_type_node
,
16019 tree_cons (NULL_TREE
, V8QI_type_node
,
16020 tree_cons (NULL_TREE
, V8QI_type_node
,
16022 tree v4hi_ftype_v4hi_di
16023 = build_function_type (V4HI_type_node
,
16024 tree_cons (NULL_TREE
, V4HI_type_node
,
16025 tree_cons (NULL_TREE
,
16026 long_long_integer_type_node
,
16028 tree v2si_ftype_v2si_di
16029 = build_function_type (V2SI_type_node
,
16030 tree_cons (NULL_TREE
, V2SI_type_node
,
16031 tree_cons (NULL_TREE
,
16032 long_long_integer_type_node
,
16034 tree void_ftype_int_int
16035 = build_function_type (void_type_node
,
16036 tree_cons (NULL_TREE
, integer_type_node
,
16037 tree_cons (NULL_TREE
, integer_type_node
,
16040 = build_function_type (long_long_unsigned_type_node
, endlink
);
16042 = build_function_type (long_long_integer_type_node
,
16043 tree_cons (NULL_TREE
, V8QI_type_node
,
16046 = build_function_type (long_long_integer_type_node
,
16047 tree_cons (NULL_TREE
, V4HI_type_node
,
16050 = build_function_type (long_long_integer_type_node
,
16051 tree_cons (NULL_TREE
, V2SI_type_node
,
16053 tree v2si_ftype_v4hi
16054 = build_function_type (V2SI_type_node
,
16055 tree_cons (NULL_TREE
, V4HI_type_node
,
16057 tree v4hi_ftype_v8qi
16058 = build_function_type (V4HI_type_node
,
16059 tree_cons (NULL_TREE
, V8QI_type_node
,
16062 tree di_ftype_di_v4hi_v4hi
16063 = build_function_type (long_long_unsigned_type_node
,
16064 tree_cons (NULL_TREE
,
16065 long_long_unsigned_type_node
,
16066 tree_cons (NULL_TREE
, V4HI_type_node
,
16067 tree_cons (NULL_TREE
,
16071 tree di_ftype_v4hi_v4hi
16072 = build_function_type (long_long_unsigned_type_node
,
16073 tree_cons (NULL_TREE
, V4HI_type_node
,
16074 tree_cons (NULL_TREE
, V4HI_type_node
,
16077 /* Normal vector binops. */
16078 tree v8qi_ftype_v8qi_v8qi
16079 = build_function_type (V8QI_type_node
,
16080 tree_cons (NULL_TREE
, V8QI_type_node
,
16081 tree_cons (NULL_TREE
, V8QI_type_node
,
16083 tree v4hi_ftype_v4hi_v4hi
16084 = build_function_type (V4HI_type_node
,
16085 tree_cons (NULL_TREE
, V4HI_type_node
,
16086 tree_cons (NULL_TREE
, V4HI_type_node
,
16088 tree v2si_ftype_v2si_v2si
16089 = build_function_type (V2SI_type_node
,
16090 tree_cons (NULL_TREE
, V2SI_type_node
,
16091 tree_cons (NULL_TREE
, V2SI_type_node
,
16093 tree di_ftype_di_di
16094 = build_function_type (long_long_unsigned_type_node
,
16095 tree_cons (NULL_TREE
, long_long_unsigned_type_node
,
16096 tree_cons (NULL_TREE
,
16097 long_long_unsigned_type_node
,
16100 /* Add all builtins that are more or less simple operations on two
16102 for (i
= 0, d
= bdesc_2arg
; i
< ARRAY_SIZE (bdesc_2arg
); i
++, d
++)
16104 /* Use one of the operands; the target can have a different mode for
16105 mask-generating compares. */
16106 enum machine_mode mode
;
16112 mode
= insn_data
[d
->icode
].operand
[1].mode
;
16117 type
= v8qi_ftype_v8qi_v8qi
;
16120 type
= v4hi_ftype_v4hi_v4hi
;
16123 type
= v2si_ftype_v2si_v2si
;
16126 type
= di_ftype_di_di
;
16130 gcc_unreachable ();
16133 def_mbuiltin (d
->mask
, d
->name
, type
, d
->code
);
16136 /* Add the remaining MMX insns with somewhat more complicated types. */
16137 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wzero", di_ftype_void
, ARM_BUILTIN_WZERO
);
16138 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_setwcx", void_ftype_int_int
, ARM_BUILTIN_SETWCX
);
16139 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_getwcx", int_ftype_int
, ARM_BUILTIN_GETWCX
);
16141 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsllh", v4hi_ftype_v4hi_di
, ARM_BUILTIN_WSLLH
);
16142 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsllw", v2si_ftype_v2si_di
, ARM_BUILTIN_WSLLW
);
16143 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wslld", di_ftype_di_di
, ARM_BUILTIN_WSLLD
);
16144 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsllhi", v4hi_ftype_v4hi_int
, ARM_BUILTIN_WSLLHI
);
16145 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsllwi", v2si_ftype_v2si_int
, ARM_BUILTIN_WSLLWI
);
16146 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wslldi", di_ftype_di_int
, ARM_BUILTIN_WSLLDI
);
16148 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsrlh", v4hi_ftype_v4hi_di
, ARM_BUILTIN_WSRLH
);
16149 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsrlw", v2si_ftype_v2si_di
, ARM_BUILTIN_WSRLW
);
16150 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsrld", di_ftype_di_di
, ARM_BUILTIN_WSRLD
);
16151 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsrlhi", v4hi_ftype_v4hi_int
, ARM_BUILTIN_WSRLHI
);
16152 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsrlwi", v2si_ftype_v2si_int
, ARM_BUILTIN_WSRLWI
);
16153 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsrldi", di_ftype_di_int
, ARM_BUILTIN_WSRLDI
);
16155 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsrah", v4hi_ftype_v4hi_di
, ARM_BUILTIN_WSRAH
);
16156 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsraw", v2si_ftype_v2si_di
, ARM_BUILTIN_WSRAW
);
16157 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsrad", di_ftype_di_di
, ARM_BUILTIN_WSRAD
);
16158 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsrahi", v4hi_ftype_v4hi_int
, ARM_BUILTIN_WSRAHI
);
16159 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsrawi", v2si_ftype_v2si_int
, ARM_BUILTIN_WSRAWI
);
16160 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsradi", di_ftype_di_int
, ARM_BUILTIN_WSRADI
);
16162 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wrorh", v4hi_ftype_v4hi_di
, ARM_BUILTIN_WRORH
);
16163 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wrorw", v2si_ftype_v2si_di
, ARM_BUILTIN_WRORW
);
16164 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wrord", di_ftype_di_di
, ARM_BUILTIN_WRORD
);
16165 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wrorhi", v4hi_ftype_v4hi_int
, ARM_BUILTIN_WRORHI
);
16166 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wrorwi", v2si_ftype_v2si_int
, ARM_BUILTIN_WRORWI
);
16167 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wrordi", di_ftype_di_int
, ARM_BUILTIN_WRORDI
);
16169 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wshufh", v4hi_ftype_v4hi_int
, ARM_BUILTIN_WSHUFH
);
16171 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsadb", v2si_ftype_v8qi_v8qi
, ARM_BUILTIN_WSADB
);
16172 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsadh", v2si_ftype_v4hi_v4hi
, ARM_BUILTIN_WSADH
);
16173 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsadbz", v2si_ftype_v8qi_v8qi
, ARM_BUILTIN_WSADBZ
);
16174 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wsadhz", v2si_ftype_v4hi_v4hi
, ARM_BUILTIN_WSADHZ
);
16176 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_textrmsb", int_ftype_v8qi_int
, ARM_BUILTIN_TEXTRMSB
);
16177 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_textrmsh", int_ftype_v4hi_int
, ARM_BUILTIN_TEXTRMSH
);
16178 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_textrmsw", int_ftype_v2si_int
, ARM_BUILTIN_TEXTRMSW
);
16179 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_textrmub", int_ftype_v8qi_int
, ARM_BUILTIN_TEXTRMUB
);
16180 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_textrmuh", int_ftype_v4hi_int
, ARM_BUILTIN_TEXTRMUH
);
16181 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_textrmuw", int_ftype_v2si_int
, ARM_BUILTIN_TEXTRMUW
);
16182 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_tinsrb", v8qi_ftype_v8qi_int_int
, ARM_BUILTIN_TINSRB
);
16183 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_tinsrh", v4hi_ftype_v4hi_int_int
, ARM_BUILTIN_TINSRH
);
16184 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_tinsrw", v2si_ftype_v2si_int_int
, ARM_BUILTIN_TINSRW
);
16186 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_waccb", di_ftype_v8qi
, ARM_BUILTIN_WACCB
);
16187 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wacch", di_ftype_v4hi
, ARM_BUILTIN_WACCH
);
16188 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_waccw", di_ftype_v2si
, ARM_BUILTIN_WACCW
);
16190 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_tmovmskb", int_ftype_v8qi
, ARM_BUILTIN_TMOVMSKB
);
16191 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_tmovmskh", int_ftype_v4hi
, ARM_BUILTIN_TMOVMSKH
);
16192 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_tmovmskw", int_ftype_v2si
, ARM_BUILTIN_TMOVMSKW
);
16194 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wpackhss", v8qi_ftype_v4hi_v4hi
, ARM_BUILTIN_WPACKHSS
);
16195 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wpackhus", v8qi_ftype_v4hi_v4hi
, ARM_BUILTIN_WPACKHUS
);
16196 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wpackwus", v4hi_ftype_v2si_v2si
, ARM_BUILTIN_WPACKWUS
);
16197 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wpackwss", v4hi_ftype_v2si_v2si
, ARM_BUILTIN_WPACKWSS
);
16198 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wpackdus", v2si_ftype_di_di
, ARM_BUILTIN_WPACKDUS
);
16199 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wpackdss", v2si_ftype_di_di
, ARM_BUILTIN_WPACKDSS
);
16201 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wunpckehub", v4hi_ftype_v8qi
, ARM_BUILTIN_WUNPCKEHUB
);
16202 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wunpckehuh", v2si_ftype_v4hi
, ARM_BUILTIN_WUNPCKEHUH
);
16203 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wunpckehuw", di_ftype_v2si
, ARM_BUILTIN_WUNPCKEHUW
);
16204 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wunpckehsb", v4hi_ftype_v8qi
, ARM_BUILTIN_WUNPCKEHSB
);
16205 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wunpckehsh", v2si_ftype_v4hi
, ARM_BUILTIN_WUNPCKEHSH
);
16206 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wunpckehsw", di_ftype_v2si
, ARM_BUILTIN_WUNPCKEHSW
);
16207 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wunpckelub", v4hi_ftype_v8qi
, ARM_BUILTIN_WUNPCKELUB
);
16208 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wunpckeluh", v2si_ftype_v4hi
, ARM_BUILTIN_WUNPCKELUH
);
16209 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wunpckeluw", di_ftype_v2si
, ARM_BUILTIN_WUNPCKELUW
);
16210 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wunpckelsb", v4hi_ftype_v8qi
, ARM_BUILTIN_WUNPCKELSB
);
16211 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wunpckelsh", v2si_ftype_v4hi
, ARM_BUILTIN_WUNPCKELSH
);
16212 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wunpckelsw", di_ftype_v2si
, ARM_BUILTIN_WUNPCKELSW
);
16214 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wmacs", di_ftype_di_v4hi_v4hi
, ARM_BUILTIN_WMACS
);
16215 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wmacsz", di_ftype_v4hi_v4hi
, ARM_BUILTIN_WMACSZ
);
16216 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wmacu", di_ftype_di_v4hi_v4hi
, ARM_BUILTIN_WMACU
);
16217 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_wmacuz", di_ftype_v4hi_v4hi
, ARM_BUILTIN_WMACUZ
);
16219 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_walign", v8qi_ftype_v8qi_v8qi_int
, ARM_BUILTIN_WALIGN
);
16220 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_tmia", di_ftype_di_int_int
, ARM_BUILTIN_TMIA
);
16221 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_tmiaph", di_ftype_di_int_int
, ARM_BUILTIN_TMIAPH
);
16222 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_tmiabb", di_ftype_di_int_int
, ARM_BUILTIN_TMIABB
);
16223 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_tmiabt", di_ftype_di_int_int
, ARM_BUILTIN_TMIABT
);
16224 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_tmiatb", di_ftype_di_int_int
, ARM_BUILTIN_TMIATB
);
16225 def_mbuiltin (FL_IWMMXT
, "__builtin_arm_tmiatt", di_ftype_di_int_int
, ARM_BUILTIN_TMIATT
);
16229 arm_init_tls_builtins (void)
16232 tree nothrow
= tree_cons (get_identifier ("nothrow"), NULL
, NULL
);
16233 tree const_nothrow
= tree_cons (get_identifier ("const"), NULL
, nothrow
);
16235 ftype
= build_function_type (ptr_type_node
, void_list_node
);
16236 lang_hooks
.builtin_function ("__builtin_thread_pointer", ftype
,
16237 ARM_BUILTIN_THREAD_POINTER
, BUILT_IN_MD
,
16238 NULL
, const_nothrow
);
16241 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
16247 /* LLVM LOCAL begin */
16249 /* LLVM LOCAL end */
16258 } neon_builtin_type_bits
;
16260 #define v8qi_UP T_V8QI
16261 #define v4hi_UP T_V4HI
16262 #define v2si_UP T_V2SI
16263 #define v2sf_UP T_V2SF
16264 /* LLVM LOCAL begin */
16265 #define v1di_UP T_V1DI
16266 /* LLVM LOCAL end */
16267 #define v16qi_UP T_V16QI
16268 #define v8hi_UP T_V8HI
16269 #define v4si_UP T_V4SI
16270 #define v4sf_UP T_V4SF
16271 #define v2di_UP T_V2DI
16276 #define UP(X) X##_UP
16280 /* FIXME: Add other types of insn (loads & stores, etc.). */
16312 NEON_LOADSTRUCTLANE
,
16314 NEON_STORESTRUCTLANE
,
16323 const neon_itype itype
;
16324 const neon_builtin_type_bits bits
;
16325 const enum insn_code codes
[T_MAX
];
16326 const unsigned int num_vars
;
16327 unsigned int base_fcode
;
16328 /* LLVM LOCAL begin */
16329 /* Map each entry to the corresponding neon_builtins enum value.
16330 GCC does not make it easy to identify NEON builtins, but LLVM
16331 needs to translate them to intrinsics. */
16332 enum neon_builtins neon_code
;
16333 /* LLVM LOCAL end */
16334 } neon_builtin_datum
;
16336 #define CF(N,X) CODE_FOR_neon_##N##X
16338 /* LLVM LOCAL begin Add initializers for neon_code field. */
16339 #define VAR1(T, N, A) \
16340 #N, NEON_##T, UP (A), { CF (N, A) }, 1, 0, \
16342 #define VAR2(T, N, A, B) \
16343 #N, NEON_##T, UP (A) | UP (B), { CF (N, A), CF (N, B) }, 2, 0, \
16345 #define VAR3(T, N, A, B, C) \
16346 #N, NEON_##T, UP (A) | UP (B) | UP (C), \
16347 { CF (N, A), CF (N, B), CF (N, C) }, 3, 0, \
16349 #define VAR4(T, N, A, B, C, D) \
16350 #N, NEON_##T, UP (A) | UP (B) | UP (C) | UP (D), \
16351 { CF (N, A), CF (N, B), CF (N, C), CF (N, D) }, 4, 0, \
16353 #define VAR5(T, N, A, B, C, D, E) \
16354 #N, NEON_##T, UP (A) | UP (B) | UP (C) | UP (D) | UP (E), \
16355 { CF (N, A), CF (N, B), CF (N, C), CF (N, D), CF (N, E) }, 5, 0, \
16357 #define VAR6(T, N, A, B, C, D, E, F) \
16358 #N, NEON_##T, UP (A) | UP (B) | UP (C) | UP (D) | UP (E) | UP (F), \
16359 { CF (N, A), CF (N, B), CF (N, C), CF (N, D), CF (N, E), CF (N, F) }, 6, 0, \
16361 #define VAR7(T, N, A, B, C, D, E, F, G) \
16362 #N, NEON_##T, UP (A) | UP (B) | UP (C) | UP (D) | UP (E) | UP (F) | UP (G), \
16363 { CF (N, A), CF (N, B), CF (N, C), CF (N, D), CF (N, E), CF (N, F), \
16364 CF (N, G) }, 7, 0, \
16366 #define VAR8(T, N, A, B, C, D, E, F, G, H) \
16367 #N, NEON_##T, UP (A) | UP (B) | UP (C) | UP (D) | UP (E) | UP (F) | UP (G) \
16369 { CF (N, A), CF (N, B), CF (N, C), CF (N, D), CF (N, E), CF (N, F), \
16370 CF (N, G), CF (N, H) }, 8, 0, \
16372 #define VAR9(T, N, A, B, C, D, E, F, G, H, I) \
16373 #N, NEON_##T, UP (A) | UP (B) | UP (C) | UP (D) | UP (E) | UP (F) | UP (G) \
16374 | UP (H) | UP (I), \
16375 { CF (N, A), CF (N, B), CF (N, C), CF (N, D), CF (N, E), CF (N, F), \
16376 CF (N, G), CF (N, H), CF (N, I) }, 9, 0, \
16378 #define VAR10(T, N, A, B, C, D, E, F, G, H, I, J) \
16379 #N, NEON_##T, UP (A) | UP (B) | UP (C) | UP (D) | UP (E) | UP (F) | UP (G) \
16380 | UP (H) | UP (I) | UP (J), \
16381 { CF (N, A), CF (N, B), CF (N, C), CF (N, D), CF (N, E), CF (N, F), \
16382 CF (N, G), CF (N, H), CF (N, I), CF (N, J) }, 10, 0, \
16384 /* LLVM LOCAL end Add initializers for neon_code field. */
16386 /* The mode entries in the following table correspond to the "key" type of the
16387 instruction variant, i.e. equivalent to that which would be specified after
16388 the assembler mnemonic, which usually refers to the last vector operand.
16389 (Signed/unsigned/polynomial types are not differentiated between though, and
16390 are all mapped onto the same mode for a given element size.) The modes
16391 listed per instruction should be the same as those defined for that
16392 instruction's pattern in neon.md.
16393 WARNING: Variants should be listed in the same increasing order as
16394 neon_builtin_type_bits. */
16396 /* LLVM LOCAL begin */
16397 static neon_builtin_datum neon_builtin_data
[] =
16399 { VAR10 (BINOP
, vadd
,
16400 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16401 { VAR3 (BINOP
, vaddl
, v8qi
, v4hi
, v2si
) },
16402 { VAR3 (BINOP
, vaddw
, v8qi
, v4hi
, v2si
) },
16403 { VAR6 (BINOP
, vhadd
, v8qi
, v4hi
, v2si
, v16qi
, v8hi
, v4si
) },
16404 { VAR8 (BINOP
, vqadd
, v8qi
, v4hi
, v2si
, v1di
, v16qi
, v8hi
, v4si
, v2di
) },
16405 { VAR3 (BINOP
, vaddhn
, v8hi
, v4si
, v2di
) },
16406 { VAR8 (BINOP
, vmul
, v8qi
, v4hi
, v2si
, v2sf
, v16qi
, v8hi
, v4si
, v4sf
) },
16407 { VAR8 (TERNOP
, vmla
, v8qi
, v4hi
, v2si
, v2sf
, v16qi
, v8hi
, v4si
, v4sf
) },
16408 { VAR3 (TERNOP
, vmlal
, v8qi
, v4hi
, v2si
) },
16409 { VAR8 (TERNOP
, vmls
, v8qi
, v4hi
, v2si
, v2sf
, v16qi
, v8hi
, v4si
, v4sf
) },
16410 { VAR3 (TERNOP
, vmlsl
, v8qi
, v4hi
, v2si
) },
16411 { VAR4 (BINOP
, vqdmulh
, v4hi
, v2si
, v8hi
, v4si
) },
16412 { VAR2 (TERNOP
, vqdmlal
, v4hi
, v2si
) },
16413 { VAR2 (TERNOP
, vqdmlsl
, v4hi
, v2si
) },
16414 { VAR3 (BINOP
, vmull
, v8qi
, v4hi
, v2si
) },
16415 { VAR2 (SCALARMULL
, vmull_n
, v4hi
, v2si
) },
16416 { VAR2 (LANEMULL
, vmull_lane
, v4hi
, v2si
) },
16417 { VAR2 (SCALARMULL
, vqdmull_n
, v4hi
, v2si
) },
16418 { VAR2 (LANEMULL
, vqdmull_lane
, v4hi
, v2si
) },
16419 { VAR4 (SCALARMULH
, vqdmulh_n
, v4hi
, v2si
, v8hi
, v4si
) },
16420 { VAR4 (LANEMULH
, vqdmulh_lane
, v4hi
, v2si
, v8hi
, v4si
) },
16421 { VAR2 (BINOP
, vqdmull
, v4hi
, v2si
) },
16422 { VAR8 (BINOP
, vshl
, v8qi
, v4hi
, v2si
, v1di
, v16qi
, v8hi
, v4si
, v2di
) },
16423 { VAR8 (BINOP
, vqshl
, v8qi
, v4hi
, v2si
, v1di
, v16qi
, v8hi
, v4si
, v2di
) },
16424 { VAR8 (SHIFTIMM
, vshr_n
, v8qi
, v4hi
, v2si
, v1di
, v16qi
, v8hi
, v4si
, v2di
) },
16425 { VAR3 (SHIFTIMM
, vshrn_n
, v8hi
, v4si
, v2di
) },
16426 { VAR3 (SHIFTIMM
, vqshrn_n
, v8hi
, v4si
, v2di
) },
16427 { VAR3 (SHIFTIMM
, vqshrun_n
, v8hi
, v4si
, v2di
) },
16428 { VAR8 (SHIFTIMM
, vshl_n
, v8qi
, v4hi
, v2si
, v1di
, v16qi
, v8hi
, v4si
, v2di
) },
16429 { VAR8 (SHIFTIMM
, vqshl_n
, v8qi
, v4hi
, v2si
, v1di
, v16qi
, v8hi
, v4si
, v2di
) },
16430 { VAR8 (SHIFTIMM
, vqshlu_n
, v8qi
, v4hi
, v2si
, v1di
, v16qi
, v8hi
, v4si
, v2di
) },
16431 { VAR3 (SHIFTIMM
, vshll_n
, v8qi
, v4hi
, v2si
) },
16432 { VAR8 (SHIFTACC
, vsra_n
, v8qi
, v4hi
, v2si
, v1di
, v16qi
, v8hi
, v4si
, v2di
) },
16433 { VAR10 (BINOP
, vsub
,
16434 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16435 { VAR3 (BINOP
, vsubl
, v8qi
, v4hi
, v2si
) },
16436 { VAR3 (BINOP
, vsubw
, v8qi
, v4hi
, v2si
) },
16437 { VAR8 (BINOP
, vqsub
, v8qi
, v4hi
, v2si
, v1di
, v16qi
, v8hi
, v4si
, v2di
) },
16438 { VAR6 (BINOP
, vhsub
, v8qi
, v4hi
, v2si
, v16qi
, v8hi
, v4si
) },
16439 { VAR3 (BINOP
, vsubhn
, v8hi
, v4si
, v2di
) },
16440 { VAR8 (BINOP
, vceq
, v8qi
, v4hi
, v2si
, v2sf
, v16qi
, v8hi
, v4si
, v4sf
) },
16441 { VAR8 (BINOP
, vcge
, v8qi
, v4hi
, v2si
, v2sf
, v16qi
, v8hi
, v4si
, v4sf
) },
16442 { VAR8 (BINOP
, vcgt
, v8qi
, v4hi
, v2si
, v2sf
, v16qi
, v8hi
, v4si
, v4sf
) },
16443 { VAR2 (BINOP
, vcage
, v2sf
, v4sf
) },
16444 { VAR2 (BINOP
, vcagt
, v2sf
, v4sf
) },
16445 { VAR6 (BINOP
, vtst
, v8qi
, v4hi
, v2si
, v16qi
, v8hi
, v4si
) },
16446 { VAR8 (BINOP
, vabd
, v8qi
, v4hi
, v2si
, v2sf
, v16qi
, v8hi
, v4si
, v4sf
) },
16447 { VAR3 (BINOP
, vabdl
, v8qi
, v4hi
, v2si
) },
16448 { VAR6 (TERNOP
, vaba
, v8qi
, v4hi
, v2si
, v16qi
, v8hi
, v4si
) },
16449 { VAR3 (TERNOP
, vabal
, v8qi
, v4hi
, v2si
) },
16450 { VAR8 (BINOP
, vmax
, v8qi
, v4hi
, v2si
, v2sf
, v16qi
, v8hi
, v4si
, v4sf
) },
16451 { VAR8 (BINOP
, vmin
, v8qi
, v4hi
, v2si
, v2sf
, v16qi
, v8hi
, v4si
, v4sf
) },
16452 { VAR4 (BINOP
, vpadd
, v8qi
, v4hi
, v2si
, v2sf
) },
16453 { VAR6 (UNOP
, vpaddl
, v8qi
, v4hi
, v2si
, v16qi
, v8hi
, v4si
) },
16454 { VAR6 (BINOP
, vpadal
, v8qi
, v4hi
, v2si
, v16qi
, v8hi
, v4si
) },
16455 { VAR4 (BINOP
, vpmax
, v8qi
, v4hi
, v2si
, v2sf
) },
16456 { VAR4 (BINOP
, vpmin
, v8qi
, v4hi
, v2si
, v2sf
) },
16457 { VAR2 (BINOP
, vrecps
, v2sf
, v4sf
) },
16458 { VAR2 (BINOP
, vrsqrts
, v2sf
, v4sf
) },
16459 { VAR8 (SHIFTINSERT
, vsri_n
, v8qi
, v4hi
, v2si
, v1di
, v16qi
, v8hi
, v4si
, v2di
) },
16460 { VAR8 (SHIFTINSERT
, vsli_n
, v8qi
, v4hi
, v2si
, v1di
, v16qi
, v8hi
, v4si
, v2di
) },
16461 { VAR8 (UNOP
, vabs
, v8qi
, v4hi
, v2si
, v2sf
, v16qi
, v8hi
, v4si
, v4sf
) },
16462 { VAR6 (UNOP
, vqabs
, v8qi
, v4hi
, v2si
, v16qi
, v8hi
, v4si
) },
16463 { VAR8 (UNOP
, vneg
, v8qi
, v4hi
, v2si
, v2sf
, v16qi
, v8hi
, v4si
, v4sf
) },
16464 { VAR6 (UNOP
, vqneg
, v8qi
, v4hi
, v2si
, v16qi
, v8hi
, v4si
) },
16465 { VAR6 (UNOP
, vcls
, v8qi
, v4hi
, v2si
, v16qi
, v8hi
, v4si
) },
16466 { VAR6 (UNOP
, vclz
, v8qi
, v4hi
, v2si
, v16qi
, v8hi
, v4si
) },
16467 { VAR2 (UNOP
, vcnt
, v8qi
, v16qi
) },
16468 { VAR4 (UNOP
, vrecpe
, v2si
, v2sf
, v4si
, v4sf
) },
16469 { VAR4 (UNOP
, vrsqrte
, v2si
, v2sf
, v4si
, v4sf
) },
16470 { VAR6 (UNOP
, vmvn
, v8qi
, v4hi
, v2si
, v16qi
, v8hi
, v4si
) },
16471 /* FIXME: vget_lane supports more variants than this! */
16472 { VAR10 (GETLANE
, vget_lane
,
16473 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16474 { VAR10 (SETLANE
, vset_lane
,
16475 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16476 { VAR5 (CREATE
, vcreate
, v8qi
, v4hi
, v2si
, v2sf
, v1di
) },
16477 { VAR10 (DUP
, vdup_n
,
16478 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16479 { VAR10 (DUPLANE
, vdup_lane
,
16480 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16481 { VAR5 (COMBINE
, vcombine
, v8qi
, v4hi
, v2si
, v2sf
, v1di
) },
16482 { VAR5 (SPLIT
, vget_high
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16483 { VAR5 (SPLIT
, vget_low
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16484 { VAR3 (UNOP
, vmovn
, v8hi
, v4si
, v2di
) },
16485 { VAR3 (UNOP
, vqmovn
, v8hi
, v4si
, v2di
) },
16486 { VAR3 (UNOP
, vqmovun
, v8hi
, v4si
, v2di
) },
16487 { VAR3 (UNOP
, vmovl
, v8qi
, v4hi
, v2si
) },
16488 { VAR6 (LANEMUL
, vmul_lane
, v4hi
, v2si
, v2sf
, v8hi
, v4si
, v4sf
) },
16489 { VAR6 (LANEMAC
, vmla_lane
, v4hi
, v2si
, v2sf
, v8hi
, v4si
, v4sf
) },
16490 { VAR2 (LANEMAC
, vmlal_lane
, v4hi
, v2si
) },
16491 { VAR2 (LANEMAC
, vqdmlal_lane
, v4hi
, v2si
) },
16492 { VAR6 (LANEMAC
, vmls_lane
, v4hi
, v2si
, v2sf
, v8hi
, v4si
, v4sf
) },
16493 { VAR2 (LANEMAC
, vmlsl_lane
, v4hi
, v2si
) },
16494 { VAR2 (LANEMAC
, vqdmlsl_lane
, v4hi
, v2si
) },
16495 { VAR6 (SCALARMUL
, vmul_n
, v4hi
, v2si
, v2sf
, v8hi
, v4si
, v4sf
) },
16496 { VAR6 (SCALARMAC
, vmla_n
, v4hi
, v2si
, v2sf
, v8hi
, v4si
, v4sf
) },
16497 { VAR2 (SCALARMAC
, vmlal_n
, v4hi
, v2si
) },
16498 { VAR2 (SCALARMAC
, vqdmlal_n
, v4hi
, v2si
) },
16499 { VAR6 (SCALARMAC
, vmls_n
, v4hi
, v2si
, v2sf
, v8hi
, v4si
, v4sf
) },
16500 { VAR2 (SCALARMAC
, vmlsl_n
, v4hi
, v2si
) },
16501 { VAR2 (SCALARMAC
, vqdmlsl_n
, v4hi
, v2si
) },
16502 { VAR10 (BINOP
, vext
,
16503 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16504 { VAR8 (UNOP
, vrev64
, v8qi
, v4hi
, v2si
, v2sf
, v16qi
, v8hi
, v4si
, v4sf
) },
16505 { VAR4 (UNOP
, vrev32
, v8qi
, v4hi
, v16qi
, v8hi
) },
16506 { VAR2 (UNOP
, vrev16
, v8qi
, v16qi
) },
16507 { VAR4 (CONVERT
, vcvt
, v2si
, v2sf
, v4si
, v4sf
) },
16508 { VAR4 (FIXCONV
, vcvt_n
, v2si
, v2sf
, v4si
, v4sf
) },
16509 { VAR10 (SELECT
, vbsl
,
16510 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16511 { VAR1 (VTBL
, vtbl1
, v8qi
) },
16512 { VAR1 (VTBL
, vtbl2
, v8qi
) },
16513 { VAR1 (VTBL
, vtbl3
, v8qi
) },
16514 { VAR1 (VTBL
, vtbl4
, v8qi
) },
16515 { VAR1 (VTBX
, vtbx1
, v8qi
) },
16516 { VAR1 (VTBX
, vtbx2
, v8qi
) },
16517 { VAR1 (VTBX
, vtbx3
, v8qi
) },
16518 { VAR1 (VTBX
, vtbx4
, v8qi
) },
16519 { VAR8 (RESULTPAIR
, vtrn
, v8qi
, v4hi
, v2si
, v2sf
, v16qi
, v8hi
, v4si
, v4sf
) },
16520 { VAR8 (RESULTPAIR
, vzip
, v8qi
, v4hi
, v2si
, v2sf
, v16qi
, v8hi
, v4si
, v4sf
) },
16521 { VAR8 (RESULTPAIR
, vuzp
, v8qi
, v4hi
, v2si
, v2sf
, v16qi
, v8hi
, v4si
, v4sf
) },
16522 { VAR5 (REINTERP
, vreinterpretv8qi
, v8qi
, v4hi
, v2si
, v2sf
, v1di
) },
16523 { VAR5 (REINTERP
, vreinterpretv4hi
, v8qi
, v4hi
, v2si
, v2sf
, v1di
) },
16524 { VAR5 (REINTERP
, vreinterpretv2si
, v8qi
, v4hi
, v2si
, v2sf
, v1di
) },
16525 { VAR5 (REINTERP
, vreinterpretv2sf
, v8qi
, v4hi
, v2si
, v2sf
, v1di
) },
16526 { VAR5 (REINTERP
, vreinterpretv1di
, v8qi
, v4hi
, v2si
, v2sf
, v1di
) },
16527 { VAR5 (REINTERP
, vreinterpretv16qi
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16528 { VAR5 (REINTERP
, vreinterpretv8hi
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16529 { VAR5 (REINTERP
, vreinterpretv4si
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16530 { VAR5 (REINTERP
, vreinterpretv4sf
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16531 { VAR5 (REINTERP
, vreinterpretv2di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16532 { VAR10 (LOAD1
, vld1
,
16533 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16534 { VAR10 (LOAD1LANE
, vld1_lane
,
16535 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16536 { VAR10 (LOAD1
, vld1_dup
,
16537 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16538 { VAR10 (STORE1
, vst1
,
16539 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16540 { VAR10 (STORE1LANE
, vst1_lane
,
16541 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16542 { VAR9 (LOADSTRUCT
,
16543 vld2
, v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
) },
16544 { VAR7 (LOADSTRUCTLANE
, vld2_lane
,
16545 v8qi
, v4hi
, v2si
, v2sf
, v8hi
, v4si
, v4sf
) },
16546 { VAR5 (LOADSTRUCT
, vld2_dup
, v8qi
, v4hi
, v2si
, v2sf
, v1di
) },
16547 { VAR9 (STORESTRUCT
, vst2
,
16548 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
) },
16549 { VAR7 (STORESTRUCTLANE
, vst2_lane
,
16550 v8qi
, v4hi
, v2si
, v2sf
, v8hi
, v4si
, v4sf
) },
16551 { VAR9 (LOADSTRUCT
,
16552 vld3
, v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
) },
16553 { VAR7 (LOADSTRUCTLANE
, vld3_lane
,
16554 v8qi
, v4hi
, v2si
, v2sf
, v8hi
, v4si
, v4sf
) },
16555 { VAR5 (LOADSTRUCT
, vld3_dup
, v8qi
, v4hi
, v2si
, v2sf
, v1di
) },
16556 { VAR9 (STORESTRUCT
, vst3
,
16557 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
) },
16558 { VAR7 (STORESTRUCTLANE
, vst3_lane
,
16559 v8qi
, v4hi
, v2si
, v2sf
, v8hi
, v4si
, v4sf
) },
16560 { VAR9 (LOADSTRUCT
, vld4
,
16561 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
) },
16562 { VAR7 (LOADSTRUCTLANE
, vld4_lane
,
16563 v8qi
, v4hi
, v2si
, v2sf
, v8hi
, v4si
, v4sf
) },
16564 { VAR5 (LOADSTRUCT
, vld4_dup
, v8qi
, v4hi
, v2si
, v2sf
, v1di
) },
16565 { VAR9 (STORESTRUCT
, vst4
,
16566 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
) },
16567 { VAR7 (STORESTRUCTLANE
, vst4_lane
,
16568 v8qi
, v4hi
, v2si
, v2sf
, v8hi
, v4si
, v4sf
) },
16569 { VAR10 (LOGICBINOP
, vand
,
16570 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16571 { VAR10 (LOGICBINOP
, vorr
,
16572 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16573 { VAR10 (BINOP
, veor
,
16574 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16575 { VAR10 (LOGICBINOP
, vbic
,
16576 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) },
16577 { VAR10 (LOGICBINOP
, vorn
,
16578 v8qi
, v4hi
, v2si
, v2sf
, v1di
, v16qi
, v8hi
, v4si
, v4sf
, v2di
) }
16580 /* LLVM LOCAL end */
16595 valid_neon_mode (enum machine_mode mode
)
16597 return VALID_NEON_DREG_MODE (mode
) || VALID_NEON_QREG_MODE (mode
);
16600 /* APPLE LOCAL begin 7083296 Build without warnings. */
16602 make_neon_float_type (void)
16604 tree neon_float_type_node
= make_node (REAL_TYPE
);
16605 TYPE_PRECISION (neon_float_type_node
) = FLOAT_TYPE_SIZE
;
16606 layout_type (neon_float_type_node
);
16607 return neon_float_type_node
;
16609 /* APPLE LOCAL end 7083296 Build without warnings. */
16611 /* LLVM LOCAL begin multi-vector types */
16613 /* Create a new builtin struct type containing NUMVECS fields (where NUMVECS
16614 is in the range from 1 to 4) of type VECTYPE. */
16616 build_multivec_type (tree vectype
, unsigned numvecs
, const char *tag
)
16618 tree record
, name
, fields
, fld
;
16622 record
= (*lang_hooks
.types
.make_type
) (RECORD_TYPE
);
16623 name
= build_decl (TYPE_DECL
, get_identifier (tag
), record
);
16624 TYPE_NAME (record
) = name
;
16626 gcc_assert (numvecs
>= 1 && numvecs
<= 4);
16628 for (n
= 0; n
< numvecs
; ++n
)
16630 /* The fields are created in reverse order because it is easier to
16631 chain them together that way. Number them accordingly. */
16632 sprintf (fldname
, "val%u", numvecs
- n
- 1);
16633 fld
= build_decl (FIELD_DECL
, get_identifier (fldname
), vectype
);
16634 DECL_FIELD_CONTEXT (fld
) = record
;
16635 TREE_CHAIN (fld
) = fields
;
16639 TYPE_FIELDS (record
) = fields
;
16640 layout_type (record
);
16643 #endif /* ENABLE_LLVM */
16644 /* LLVM LOCAL end multi-vector types */
16647 arm_init_neon_builtins (void)
16649 #define qi_TN neon_intQI_type_node
16650 #define hi_TN neon_intHI_type_node
16651 #define pqi_TN neon_polyQI_type_node
16652 #define qhi_TN neon_polyHI_type_node
16653 #define si_TN neon_intSI_type_node
16654 #define di_TN neon_intDI_type_node
16655 /* LLVM LOCAL begin multi-vector types */
16657 #define ti_TN V8QI2_type_node
16658 #define ei_TN V8QI3_type_node
16659 #define oi_TN V8QI4_type_node
16661 #define ti_TN intTI_type_node
16662 #define ei_TN intEI_type_node
16663 #define oi_TN intOI_type_node
16664 #define ci_TN intCI_type_node
16665 #define xi_TN intXI_type_node
16667 /* LLVM LOCAL end multi-vector types */
16669 #define sf_TN neon_float_type_node
16671 #define v8qi_TN V8QI_type_node
16672 #define v4hi_TN V4HI_type_node
16673 #define v2si_TN V2SI_type_node
16674 #define v2sf_TN V2SF_type_node
16676 #define v16qi_TN V16QI_type_node
16677 #define v8hi_TN V8HI_type_node
16678 #define v4si_TN V4SI_type_node
16679 #define v4sf_TN V4SF_type_node
16680 /* LLVM LOCAL begin */
16681 #define v1di_TN V1DI_type_node
16682 /* LLVM LOCAL end */
16683 #define v2di_TN V2DI_type_node
16685 /* LLVM LOCAL begin multi-vector types */
16687 #define pv8qi_TN V8QI2_type_node
16688 #define pv4hi_TN V4HI2_type_node
16689 #define pv2si_TN V2SI2_type_node
16690 #define pv2sf_TN V2SF2_type_node
16692 #define pv16qi_TN V16QI2_type_node
16693 #define pv8hi_TN V8HI2_type_node
16694 #define pv4si_TN V4SI2_type_node
16695 #define pv4sf_TN V4SF2_type_node
16696 #define pv2di_TN V2DI2_type_node
16697 #define pv1di_TN V1DI2_type_node
16698 #else /* !ENABLE_LLVM */
16699 #define pv8qi_TN V8QI_pointer_node
16700 #define pv4hi_TN V4HI_pointer_node
16701 #define pv2si_TN V2SI_pointer_node
16702 #define pv2sf_TN V2SF_pointer_node
16703 #define pv1di_TN V1DI_pointer_node
16705 #define pv16qi_TN V16QI_pointer_node
16706 #define pv8hi_TN V8HI_pointer_node
16707 #define pv4si_TN V4SI_pointer_node
16708 #define pv4sf_TN V4SF_pointer_node
16709 #define pv2di_TN V2DI_pointer_node
16710 #endif /* !ENABLE_LLVM */
16711 /* LLVM LOCAL end multi-vector types */
16713 #define void_TN void_type_node
16715 #define TYPE2(A,B) \
16716 tree A##_##ftype##_##B = build_function_type_list (A##_TN, B##_TN, NULL)
16717 #define TYPE3(A,B,C) \
16718 tree A##_##ftype##_##B##_##C = build_function_type_list (A##_TN, B##_TN, \
16720 #define TYPE4(A,B,C,D) \
16721 tree A##_##ftype##_##B##_##C##_##D = build_function_type_list (A##_TN, \
16722 B##_TN, C##_TN, D##_TN, NULL)
16723 /* LLVM LOCAL begin multi-vector types */
16725 #define TYPE4_RESULTPAIR(A,B,C,D) \
16726 tree A##_##ftype##_##B##_##C##_##D = build_function_type_list (B##_TN, \
16727 C##_TN, D##_TN, NULL)
16729 #define TYPE4_RESULTPAIR(A,B,C,D) TYPE4(A,B,C,D)
16731 /* LLVM LOCAL end multi-vector types */
16732 #define TYPE5(A,B,C,D,E) \
16733 tree A##_##ftype##_##B##_##C##_##D##_##E = build_function_type_list (A##_TN, \
16734 B##_TN, C##_TN, D##_TN, E##_TN, NULL)
16735 #define TYPE6(A,B,C,D,E,F) \
16736 tree A##_##ftype##_##B##_##C##_##D##_##E##_##F = build_function_type_list \
16737 (A##_TN, B##_TN, C##_TN, D##_TN, E##_TN, F##_TN, NULL)
16739 unsigned int i
, fcode
= ARM_BUILTIN_NEON_BASE
;
16741 /* Create distinguished type nodes for NEON vector element types,
16742 and pointers to values of such types, so we can detect them later. */
16743 tree neon_intQI_type_node
= make_signed_type (GET_MODE_PRECISION (QImode
));
16744 tree neon_intHI_type_node
= make_signed_type (GET_MODE_PRECISION (HImode
));
16745 tree neon_polyQI_type_node
= make_signed_type (GET_MODE_PRECISION (QImode
));
16746 tree neon_polyHI_type_node
= make_signed_type (GET_MODE_PRECISION (HImode
));
16747 tree neon_intSI_type_node
= make_signed_type (GET_MODE_PRECISION (SImode
));
16748 tree neon_intDI_type_node
= make_signed_type (GET_MODE_PRECISION (DImode
));
16749 /* APPLE LOCAL begin 7083296 Build without warnings. */
16750 tree neon_float_type_node
= make_neon_float_type ();
16752 /* APPLE LOCAL end 7083296 Build without warnings. */
16753 tree intQI_pointer_node
= build_pointer_type (neon_intQI_type_node
);
16754 tree intHI_pointer_node
= build_pointer_type (neon_intHI_type_node
);
16755 tree intSI_pointer_node
= build_pointer_type (neon_intSI_type_node
);
16756 tree intDI_pointer_node
= build_pointer_type (neon_intDI_type_node
);
16757 tree float_pointer_node
= build_pointer_type (neon_float_type_node
);
16759 /* Next create constant-qualified versions of the above types. */
16760 tree const_intQI_node
= build_qualified_type (neon_intQI_type_node
,
16762 tree const_intHI_node
= build_qualified_type (neon_intHI_type_node
,
16764 tree const_intSI_node
= build_qualified_type (neon_intSI_type_node
,
16766 tree const_intDI_node
= build_qualified_type (neon_intDI_type_node
,
16768 tree const_float_node
= build_qualified_type (neon_float_type_node
,
16771 tree const_intQI_pointer_node
= build_pointer_type (const_intQI_node
);
16772 tree const_intHI_pointer_node
= build_pointer_type (const_intHI_node
);
16773 tree const_intSI_pointer_node
= build_pointer_type (const_intSI_node
);
16774 tree const_intDI_pointer_node
= build_pointer_type (const_intDI_node
);
16775 tree const_float_pointer_node
= build_pointer_type (const_float_node
);
16777 /* Now create vector types based on our NEON element types. */
16778 /* 64-bit vectors. */
16779 tree V8QI_type_node
=
16780 build_vector_type_for_mode (neon_intQI_type_node
, V8QImode
);
16781 tree V4HI_type_node
=
16782 build_vector_type_for_mode (neon_intHI_type_node
, V4HImode
);
16783 tree V2SI_type_node
=
16784 build_vector_type_for_mode (neon_intSI_type_node
, V2SImode
);
16785 tree V2SF_type_node
=
16786 build_vector_type_for_mode (neon_float_type_node
, V2SFmode
);
16787 /* LLVM LOCAL begin */
16788 tree V1DI_type_node
=
16789 build_vector_type_for_mode (neon_intDI_type_node
, V1DImode
);
16790 /* LLVM LOCAL end */
16792 /* 128-bit vectors. */
16793 tree V16QI_type_node
=
16794 build_vector_type_for_mode (neon_intQI_type_node
, V16QImode
);
16795 tree V8HI_type_node
=
16796 build_vector_type_for_mode (neon_intHI_type_node
, V8HImode
);
16797 tree V4SI_type_node
=
16798 build_vector_type_for_mode (neon_intSI_type_node
, V4SImode
);
16799 tree V4SF_type_node
=
16800 build_vector_type_for_mode (neon_float_type_node
, V4SFmode
);
16801 tree V2DI_type_node
=
16802 build_vector_type_for_mode (neon_intDI_type_node
, V2DImode
);
16804 /* Unsigned integer types for various mode sizes. */
16805 tree intUQI_type_node
= make_unsigned_type (GET_MODE_PRECISION (QImode
));
16806 tree intUHI_type_node
= make_unsigned_type (GET_MODE_PRECISION (HImode
));
16807 tree intUSI_type_node
= make_unsigned_type (GET_MODE_PRECISION (SImode
));
16808 tree intUDI_type_node
= make_unsigned_type (GET_MODE_PRECISION (DImode
));
16810 /* LLVM LOCAL begin multi-vector types */
16812 tree V8QI2_type_node
= build_multivec_type (V8QI_type_node
, 2,
16813 "__builtin_neon_v8qi2");
16814 tree V4HI2_type_node
= build_multivec_type (V4HI_type_node
, 2,
16815 "__builtin_neon_v4hi2");
16816 tree V2SI2_type_node
= build_multivec_type (V2SI_type_node
, 2,
16817 "__builtin_neon_v2si2");
16818 tree V1DI2_type_node
= build_multivec_type (V1DI_type_node
, 2,
16819 "__builtin_neon_v1di2");
16820 tree V2SF2_type_node
= build_multivec_type (V2SF_type_node
, 2,
16821 "__builtin_neon_v2sf2");
16822 tree V8QI3_type_node
= build_multivec_type (V8QI_type_node
, 3,
16823 "__builtin_neon_v8qi3");
16824 tree V4HI3_type_node
= build_multivec_type (V4HI_type_node
, 3,
16825 "__builtin_neon_v4hi3");
16826 tree V2SI3_type_node
= build_multivec_type (V2SI_type_node
, 3,
16827 "__builtin_neon_v2si3");
16828 tree V1DI3_type_node
= build_multivec_type (V1DI_type_node
, 3,
16829 "__builtin_neon_v1di2");
16830 tree V2SF3_type_node
= build_multivec_type (V2SF_type_node
, 3,
16831 "__builtin_neon_v2sf3");
16832 tree V8QI4_type_node
= build_multivec_type (V8QI_type_node
, 4,
16833 "__builtin_neon_v8qi4");
16834 tree V4HI4_type_node
= build_multivec_type (V4HI_type_node
, 4,
16835 "__builtin_neon_v4hi4");
16836 tree V2SI4_type_node
= build_multivec_type (V2SI_type_node
, 4,
16837 "__builtin_neon_v2si4");
16838 tree V1DI4_type_node
= build_multivec_type (V1DI_type_node
, 4,
16839 "__builtin_neon_v1di2");
16840 tree V2SF4_type_node
= build_multivec_type (V2SF_type_node
, 4,
16841 "__builtin_neon_v2sf4");
16842 tree V16QI2_type_node
= build_multivec_type (V16QI_type_node
, 2,
16843 "__builtin_neon_v16qi2");
16844 tree V8HI2_type_node
= build_multivec_type (V8HI_type_node
, 2,
16845 "__builtin_neon_v8hi2");
16846 tree V4SI2_type_node
= build_multivec_type (V4SI_type_node
, 2,
16847 "__builtin_neon_v4si2");
16848 tree V4SF2_type_node
= build_multivec_type (V4SF_type_node
, 2,
16849 "__builtin_neon_v4sf2");
16850 tree V2DI2_type_node
= build_multivec_type (V2DI_type_node
, 2,
16851 "__builtin_neon_v2di2");
16852 tree V16QI3_type_node
= build_multivec_type (V16QI_type_node
, 3,
16853 "__builtin_neon_v16qi3");
16854 tree V8HI3_type_node
= build_multivec_type (V8HI_type_node
, 3,
16855 "__builtin_neon_v8hi3");
16856 tree V4SI3_type_node
= build_multivec_type (V4SI_type_node
, 3,
16857 "__builtin_neon_v4si3");
16858 tree V4SF3_type_node
= build_multivec_type (V4SF_type_node
, 3,
16859 "__builtin_neon_v4sf3");
16860 tree V16QI4_type_node
= build_multivec_type (V16QI_type_node
, 4,
16861 "__builtin_neon_v16qi4");
16862 tree V8HI4_type_node
= build_multivec_type (V8HI_type_node
, 4,
16863 "__builtin_neon_v8hi4");
16864 tree V4SI4_type_node
= build_multivec_type (V4SI_type_node
, 4,
16865 "__builtin_neon_v4si4");
16866 tree V4SF4_type_node
= build_multivec_type (V4SF_type_node
, 4,
16867 "__builtin_neon_v4sf4");
16868 #else /* ENABLE_LLVM */
16869 /* Opaque integer types for structures of vectors. */
16870 tree intEI_type_node
= make_signed_type (GET_MODE_PRECISION (EImode
));
16871 tree intOI_type_node
= make_signed_type (GET_MODE_PRECISION (OImode
));
16872 tree intCI_type_node
= make_signed_type (GET_MODE_PRECISION (CImode
));
16873 tree intXI_type_node
= make_signed_type (GET_MODE_PRECISION (XImode
));
16875 tree V8QI2_type_node
= intTI_type_node
;
16876 tree V4HI2_type_node
= intTI_type_node
;
16877 tree V2SI2_type_node
= intTI_type_node
;
16878 tree V1DI2_type_node
= intTI_type_node
;
16879 tree V2SF2_type_node
= intTI_type_node
;
16880 tree V8QI3_type_node
= intEI_type_node
;
16881 tree V4HI3_type_node
= intEI_type_node
;
16882 tree V2SI3_type_node
= intEI_type_node
;
16883 tree V1DI3_type_node
= intEI_type_node
;
16884 tree V2SF3_type_node
= intEI_type_node
;
16885 tree V8QI4_type_node
= intOI_type_node
;
16886 tree V4HI4_type_node
= intOI_type_node
;
16887 tree V2SI4_type_node
= intOI_type_node
;
16888 tree V1DI4_type_node
= intOI_type_node
;
16889 tree V2SF4_type_node
= intOI_type_node
;
16890 tree V16QI2_type_node
= intOI_type_node
;
16891 tree V8HI2_type_node
= intOI_type_node
;
16892 tree V4SI2_type_node
= intOI_type_node
;
16893 tree V4SF2_type_node
= intOI_type_node
;
16894 tree V16QI3_type_node
= intCI_type_node
;
16895 tree V8HI3_type_node
= intCI_type_node
;
16896 tree V4SI3_type_node
= intCI_type_node
;
16897 tree V4SF3_type_node
= intCI_type_node
;
16898 tree V16QI4_type_node
= intXI_type_node
;
16899 tree V8HI4_type_node
= intXI_type_node
;
16900 tree V4SI4_type_node
= intXI_type_node
;
16901 tree V4SF4_type_node
= intXI_type_node
;
16903 /* Pointers to vector types. */
16904 tree V8QI_pointer_node
= build_pointer_type (V8QI_type_node
);
16905 tree V4HI_pointer_node
= build_pointer_type (V4HI_type_node
);
16906 tree V2SI_pointer_node
= build_pointer_type (V2SI_type_node
);
16907 tree V2SF_pointer_node
= build_pointer_type (V2SF_type_node
);
16908 tree V16QI_pointer_node
= build_pointer_type (V16QI_type_node
);
16909 tree V8HI_pointer_node
= build_pointer_type (V8HI_type_node
);
16910 tree V4SI_pointer_node
= build_pointer_type (V4SI_type_node
);
16911 tree V4SF_pointer_node
= build_pointer_type (V4SF_type_node
);
16912 tree V2DI_pointer_node
= build_pointer_type (V2DI_type_node
);
16913 #endif /* ENABLE_LLVM */
16914 /* LLVM LOCAL end multi-vector types */
16916 /* LLVM LOCAL begin */
16917 /* Binops, all-doubleword arithmetic. */
16918 TYPE4 (v8qi
, v8qi
, v8qi
, si
);
16919 TYPE4 (v4hi
, v4hi
, v4hi
, si
);
16920 TYPE4 (v2si
, v2si
, v2si
, si
);
16921 TYPE4 (v2sf
, v2sf
, v2sf
, si
);
16922 TYPE4 (v1di
, v1di
, v1di
, si
);
16924 /* Binops, all-quadword arithmetic. */
16925 TYPE4 (v16qi
, v16qi
, v16qi
, si
);
16926 TYPE4 (v8hi
, v8hi
, v8hi
, si
);
16927 TYPE4 (v4si
, v4si
, v4si
, si
);
16928 TYPE4 (v4sf
, v4sf
, v4sf
, si
);
16929 TYPE4 (v2di
, v2di
, v2di
, si
);
16931 /* Binops, "long" operations (dest wider than operands). */
16932 TYPE4 (v8hi
, v8qi
, v8qi
, si
);
16933 TYPE4 (v4si
, v4hi
, v4hi
, si
);
16934 TYPE4 (v2di
, v2si
, v2si
, si
);
16936 /* Binops, "wide" operations (dest and first operand wider than second
16938 TYPE4 (v8hi
, v8hi
, v8qi
, si
);
16939 TYPE4 (v4si
, v4si
, v4hi
, si
);
16940 TYPE4 (v2di
, v2di
, v2si
, si
);
16942 /* Binops, "narrow" operations (dest narrower than operands). */
16943 TYPE4 (v8qi
, v8hi
, v8hi
, si
);
16944 TYPE4 (v4hi
, v4si
, v4si
, si
);
16945 TYPE4 (v2si
, v2di
, v2di
, si
);
16947 /* Binops, comparisons (return type always an integer vector). */
16948 TYPE4 (v2si
, v2sf
, v2sf
, si
);
16949 TYPE4 (v4si
, v4sf
, v4sf
, si
);
16951 /* Binops, dest and first operand elements wider (vpadal). */
16952 TYPE4 (v4hi
, v4hi
, v8qi
, si
);
16953 TYPE4 (v2si
, v2si
, v4hi
, si
);
16954 TYPE4 (v1di
, v1di
, v2si
, si
);
16955 TYPE4 (v8hi
, v8hi
, v16qi
, si
);
16956 TYPE4 (v4si
, v4si
, v8hi
, si
);
16957 TYPE4 (v2di
, v2di
, v4si
, si
);
16959 /* Ternary operations, all-doubleword arithmetic. */
16960 TYPE5 (v8qi
, v8qi
, v8qi
, v8qi
, si
);
16961 TYPE5 (v4hi
, v4hi
, v4hi
, v4hi
, si
);
16962 TYPE5 (v2si
, v2si
, v2si
, v2si
, si
);
16963 TYPE5 (v2sf
, v2sf
, v2sf
, v2sf
, si
);
16965 /* Ternary operations, all-quadword arithmetic. */
16966 TYPE5 (v16qi
, v16qi
, v16qi
, v16qi
, si
);
16967 TYPE5 (v8hi
, v8hi
, v8hi
, v8hi
, si
);
16968 TYPE5 (v4si
, v4si
, v4si
, v4si
, si
);
16969 TYPE5 (v4sf
, v4sf
, v4sf
, v4sf
, si
);
16971 /* Ternary operations, "long" operations (dest and first operand
16972 wider than second and third operands). */
16973 TYPE5 (v8hi
, v8hi
, v8qi
, v8qi
, si
);
16974 TYPE5 (v4si
, v4si
, v4hi
, v4hi
, si
);
16975 TYPE5 (v2di
, v2di
, v2si
, v2si
, si
);
16977 /* Unops, all-doubleword arithmetic. */
16978 TYPE3 (v8qi
, v8qi
, si
);
16979 TYPE3 (v4hi
, v4hi
, si
);
16980 TYPE3 (v2si
, v2si
, si
);
16981 TYPE3 (v2sf
, v2sf
, si
);
16982 TYPE3 (v1di
, v1di
, si
);
16984 /* Unops, all-quadword arithmetic. */
16985 TYPE3 (v16qi
, v16qi
, si
);
16986 TYPE3 (v8hi
, v8hi
, si
);
16987 TYPE3 (v4si
, v4si
, si
);
16988 TYPE3 (v4sf
, v4sf
, si
);
16989 TYPE3 (v2di
, v2di
, si
);
16991 /* Unops, narrowing. */
16992 TYPE3 (v8qi
, v8hi
, si
);
16993 TYPE3 (v4hi
, v4si
, si
);
16994 TYPE3 (v2si
, v2di
, si
);
16996 /* Unops, widening. */
16997 TYPE3 (v8hi
, v8qi
, si
);
16998 TYPE3 (v4si
, v4hi
, si
);
16999 TYPE3 (v2di
, v2si
, si
);
17001 /* Unops, dest elements wider (vpaddl). */
17002 TYPE3 (v4hi
, v8qi
, si
);
17003 TYPE3 (v2si
, v4hi
, si
);
17004 TYPE3 (v1di
, v2si
, si
);
17005 TYPE3 (v8hi
, v16qi
, si
);
17006 TYPE3 (v4si
, v8hi
, si
);
17007 TYPE3 (v2di
, v4si
, si
);
17009 /* Get-lane from doubleword insns (single-element result). */
17010 TYPE4 (qi
, v8qi
, si
, si
);
17011 TYPE4 (hi
, v4hi
, si
, si
);
17012 TYPE4 (si
, v2si
, si
, si
);
17013 TYPE4 (sf
, v2sf
, si
, si
);
17014 TYPE4 (di
, v1di
, si
, si
);
17016 /* Get-lane from quadword insns. */
17017 TYPE4 (qi
, v16qi
, si
, si
);
17018 TYPE4 (hi
, v8hi
, si
, si
);
17019 TYPE4 (si
, v4si
, si
, si
);
17020 TYPE4 (sf
, v4sf
, si
, si
);
17021 TYPE4 (di
, v2di
, si
, si
);
17023 /* Set lane in doubleword insns (single-element result). */
17024 TYPE4 (v8qi
, qi
, v8qi
, si
);
17025 TYPE4 (v4hi
, hi
, v4hi
, si
);
17026 TYPE4 (v2si
, si
, v2si
, si
);
17027 TYPE4 (v2sf
, sf
, v2sf
, si
);
17028 TYPE4 (v1di
, di
, v1di
, si
);
17030 /* Set lane in quadword insns. */
17031 TYPE4 (v16qi
, qi
, v16qi
, si
);
17032 TYPE4 (v8hi
, hi
, v8hi
, si
);
17033 TYPE4 (v4si
, si
, v4si
, si
);
17034 TYPE4 (v4sf
, sf
, v4sf
, si
);
17035 TYPE4 (v2di
, di
, v2di
, si
);
17037 /* Create vector from bit pattern. */
17044 /* Duplicate an ARM register into lanes of a vector. */
17056 /* Duplicate a lane of a vector to all lanes of another vector. */
17057 TYPE3 (v16qi
, v8qi
, si
);
17058 TYPE3 (v8hi
, v4hi
, si
);
17059 TYPE3 (v4si
, v2si
, si
);
17060 TYPE3 (v4sf
, v2sf
, si
);
17061 TYPE3 (v2di
, v1di
, si
);
17063 /* Combine doubleword vectors into quadword vectors. */
17064 TYPE3 (v16qi
, v8qi
, v8qi
);
17065 TYPE3 (v8hi
, v4hi
, v4hi
);
17066 TYPE3 (v4si
, v2si
, v2si
);
17067 TYPE3 (v4sf
, v2sf
, v2sf
);
17068 TYPE3 (v2di
, v1di
, v1di
);
17070 /* Split quadword vectors into high or low parts. */
17071 TYPE2 (v8qi
, v16qi
);
17072 TYPE2 (v4hi
, v8hi
);
17073 TYPE2 (v2si
, v4si
);
17074 TYPE2 (v2sf
, v4sf
);
17075 TYPE2 (v1di
, v2di
);
17077 /* Conversions, int<->float. */
17078 TYPE3 (v2si
, v2sf
, si
);
17079 TYPE3 (v2sf
, v2si
, si
);
17080 TYPE3 (v4si
, v4sf
, si
);
17081 TYPE3 (v4sf
, v4si
, si
);
17083 /* Conversions, fixed point<->float. */
17084 TYPE4 (v2si
, v2sf
, si
, si
);
17085 TYPE4 (v2sf
, v2si
, si
, si
);
17086 TYPE4 (v4si
, v4sf
, si
, si
);
17087 TYPE4 (v4sf
, v4si
, si
, si
);
17089 /* Multiply by scalar (lane). */
17090 TYPE5 (v4hi
, v4hi
, v4hi
, si
, si
);
17091 TYPE5 (v2si
, v2si
, v2si
, si
, si
);
17092 TYPE5 (v2sf
, v2sf
, v2sf
, si
, si
);
17093 TYPE5 (v8hi
, v8hi
, v4hi
, si
, si
);
17094 TYPE5 (v4si
, v4si
, v2si
, si
, si
);
17095 TYPE5 (v4sf
, v4sf
, v2sf
, si
, si
);
17097 /* Long multiply by scalar (lane). */
17098 TYPE5 (v4si
, v4hi
, v4hi
, si
, si
);
17099 TYPE5 (v2di
, v2si
, v2si
, si
, si
);
17101 /* Multiply-accumulate etc. by scalar (lane). */
17102 TYPE6 (v4hi
, v4hi
, v4hi
, v4hi
, si
, si
);
17103 TYPE6 (v2si
, v2si
, v2si
, v2si
, si
, si
);
17104 TYPE6 (v2sf
, v2sf
, v2sf
, v2sf
, si
, si
);
17105 TYPE6 (v8hi
, v8hi
, v8hi
, v4hi
, si
, si
);
17106 TYPE6 (v4si
, v4si
, v4si
, v2si
, si
, si
);
17107 TYPE6 (v4sf
, v4sf
, v4sf
, v2sf
, si
, si
);
17109 /* Multiply-accumulate, etc. by scalar (lane), widening. */
17110 TYPE6 (v4si
, v4si
, v4hi
, v4hi
, si
, si
);
17111 TYPE6 (v2di
, v2di
, v2si
, v2si
, si
, si
);
17113 /* Multiply by scalar. */
17114 TYPE4 (v4hi
, v4hi
, hi
, si
);
17115 TYPE4 (v2si
, v2si
, si
, si
);
17116 TYPE4 (v2sf
, v2sf
, sf
, si
);
17118 TYPE4 (v8hi
, v8hi
, hi
, si
);
17119 TYPE4 (v4si
, v4si
, si
, si
);
17120 TYPE4 (v4sf
, v4sf
, sf
, si
);
17122 /* Long multiply by scalar. */
17123 TYPE4 (v4si
, v4hi
, hi
, si
);
17125 /* Multiply-accumulate etc. by scalar. */
17126 TYPE5 (v4hi
, v4hi
, v4hi
, hi
, si
);
17127 /* TYPE5 (v2si, v2si, v2si, si, si);*/
17128 TYPE5 (v2sf
, v2sf
, v2sf
, sf
, si
);
17129 TYPE5 (v8hi
, v8hi
, v8hi
, hi
, si
);
17130 TYPE5 (v4si
, v4si
, v4si
, si
, si
);
17131 TYPE5 (v4sf
, v4sf
, v4sf
, sf
, si
);
17133 /* Multiply-accumulate by scalar, widening. */
17134 TYPE5 (v4si
, v4si
, v4hi
, hi
, si
);
17135 TYPE5 (v2di
, v2di
, v2si
, si
, si
);
17137 /* Bit select operations. */
17138 TYPE4 (v8qi
, v8qi
, v8qi
, v8qi
);
17139 TYPE4 (v4hi
, v4hi
, v4hi
, v4hi
);
17140 TYPE4 (v2si
, v2si
, v2si
, v2si
);
17141 TYPE4 (v2sf
, v2si
, v2sf
, v2sf
);
17142 TYPE4 (v1di
, v1di
, v1di
, v1di
);
17144 TYPE4 (v16qi
, v16qi
, v16qi
, v16qi
);
17145 TYPE4 (v8hi
, v8hi
, v8hi
, v8hi
);
17146 TYPE4 (v4si
, v4si
, v4si
, v4si
);
17147 TYPE4 (v4sf
, v4si
, v4sf
, v4sf
);
17148 TYPE4 (v2di
, v2di
, v2di
, v2di
);
17150 /* Shift immediate operations. */
17151 TYPE4 (v8qi
, v8qi
, si
, si
);
17152 TYPE4 (v4hi
, v4hi
, si
, si
);
17153 TYPE4 (v1di
, v1di
, si
, si
);
17155 TYPE4 (v16qi
, v16qi
, si
, si
);
17156 TYPE4 (v8hi
, v8hi
, si
, si
);
17157 TYPE4 (v2di
, v2di
, si
, si
);
17159 /* Shift immediate, long operations. */
17160 TYPE4 (v8hi
, v8qi
, si
, si
);
17161 TYPE4 (v4si
, v4hi
, si
, si
);
17162 TYPE4 (v2di
, v2si
, si
, si
);
17164 /* Shift immediate, narrowing operations. */
17165 TYPE4 (v8qi
, v8hi
, si
, si
);
17166 TYPE4 (v4hi
, v4si
, si
, si
);
17167 TYPE4 (v2si
, v2di
, si
, si
);
17169 /* Shift + accumulate operations. */
17170 TYPE5 (v8qi
, v8qi
, v8qi
, si
, si
);
17171 TYPE5 (v1di
, v1di
, v1di
, si
, si
);
17173 TYPE5 (v16qi
, v16qi
, v16qi
, si
, si
);
17174 TYPE5 (v8hi
, v8hi
, v8hi
, si
, si
);
17175 TYPE5 (v4sf
, v4sf
, v4sf
, si
, si
);
17176 TYPE5 (v2di
, v2di
, v2di
, si
, si
);
17177 /* LLVM LOCAL end */
17179 /* Operations which return results as pairs. */
17180 /* LLVM LOCAL begin multi-vector types */
17181 TYPE4_RESULTPAIR (void, pv8qi
, v8qi
, v8qi
);
17182 TYPE4_RESULTPAIR (void, pv4hi
, v4hi
, v4hi
);
17183 TYPE4_RESULTPAIR (void, pv2si
, v2si
, v2si
);
17184 TYPE4_RESULTPAIR (void, pv2sf
, v2sf
, v2sf
);
17185 TYPE4_RESULTPAIR (void, pv1di
, v1di
, v1di
);
17187 TYPE4_RESULTPAIR (void, pv16qi
, v16qi
, v16qi
);
17188 TYPE4_RESULTPAIR (void, pv8hi
, v8hi
, v8hi
);
17189 TYPE4_RESULTPAIR (void, pv4si
, v4si
, v4si
);
17190 TYPE4_RESULTPAIR (void, pv4sf
, v4sf
, v4sf
);
17191 TYPE4_RESULTPAIR (void, pv2di
, v2di
, v2di
);
17192 /* LLVM LOCAL end multi-vector types */
17194 /* Table look-up. */
17195 TYPE3 (v8qi
, v8qi
, v8qi
);
17196 TYPE3 (v8qi
, ti
, v8qi
);
17197 TYPE3 (v8qi
, ei
, v8qi
);
17198 TYPE3 (v8qi
, oi
, v8qi
);
17200 /* Extended table look-up. */
17201 /*TYPE4 (v8qi, v8qi, v8qi, v8qi);*/
17202 TYPE4 (v8qi
, v8qi
, ti
, v8qi
);
17203 TYPE4 (v8qi
, v8qi
, ei
, v8qi
);
17204 TYPE4 (v8qi
, v8qi
, oi
, v8qi
);
17206 /* Load operations, double-word. */
17207 tree v8qi_ftype_const_qi_pointer
=
17208 build_function_type_list (V8QI_type_node
, const_intQI_pointer_node
, NULL
);
17209 tree v4hi_ftype_const_hi_pointer
=
17210 build_function_type_list (V4HI_type_node
, const_intHI_pointer_node
, NULL
);
17211 tree v2si_ftype_const_si_pointer
=
17212 build_function_type_list (V2SI_type_node
, const_intSI_pointer_node
, NULL
);
17213 /* LLVM LOCAL begin */
17214 tree v1di_ftype_const_di_pointer
=
17215 build_function_type_list (V1DI_type_node
, const_intDI_pointer_node
, NULL
);
17216 /* LLVM LOCAL end */
17217 tree v2sf_ftype_const_sf_pointer
=
17218 build_function_type_list (V2SF_type_node
, const_float_pointer_node
, NULL
);
17220 /* Load operations, quad-word. */
17221 tree v16qi_ftype_const_qi_pointer
=
17222 build_function_type_list (V16QI_type_node
, const_intQI_pointer_node
, NULL
);
17223 tree v8hi_ftype_const_hi_pointer
=
17224 build_function_type_list (V8HI_type_node
, const_intHI_pointer_node
, NULL
);
17225 tree v4si_ftype_const_si_pointer
=
17226 build_function_type_list (V4SI_type_node
, const_intSI_pointer_node
, NULL
);
17227 tree v2di_ftype_const_di_pointer
=
17228 build_function_type_list (V2DI_type_node
, const_intDI_pointer_node
, NULL
);
17229 tree v4sf_ftype_const_sf_pointer
=
17230 build_function_type_list (V4SF_type_node
, const_float_pointer_node
, NULL
);
17232 /* Load lane operations, double-word. */
17233 tree v8qi_ftype_const_qi_pointer_v8qi_si
=
17234 build_function_type_list (V8QI_type_node
, const_intQI_pointer_node
,
17235 V8QI_type_node
, intSI_type_node
, NULL
);
17236 tree v4hi_ftype_const_hi_pointer_v4hi_si
=
17237 build_function_type_list (V4HI_type_node
, const_intHI_pointer_node
,
17238 V4HI_type_node
, intSI_type_node
, NULL
);
17239 tree v2si_ftype_const_si_pointer_v2si_si
=
17240 build_function_type_list (V2SI_type_node
, const_intSI_pointer_node
,
17241 V2SI_type_node
, intSI_type_node
, NULL
);
17242 /* LLVM LOCAL begin */
17243 tree v1di_ftype_const_di_pointer_v1di_si
=
17244 build_function_type_list (V1DI_type_node
, const_intDI_pointer_node
,
17245 V1DI_type_node
, intSI_type_node
, NULL
);
17246 /* LLVM LOCAL end */
17247 tree v2sf_ftype_const_sf_pointer_v2sf_si
=
17248 build_function_type_list (V2SF_type_node
, const_float_pointer_node
,
17249 V2SF_type_node
, intSI_type_node
, NULL
);
17251 /* Load lane operations, quad-word. */
17252 tree v16qi_ftype_const_qi_pointer_v16qi_si
=
17253 build_function_type_list (V16QI_type_node
, const_intQI_pointer_node
,
17254 V16QI_type_node
, intSI_type_node
, NULL
);
17255 tree v8hi_ftype_const_hi_pointer_v8hi_si
=
17256 build_function_type_list (V8HI_type_node
, const_intHI_pointer_node
,
17257 V8HI_type_node
, intSI_type_node
, NULL
);
17258 tree v4si_ftype_const_si_pointer_v4si_si
=
17259 build_function_type_list (V4SI_type_node
, const_intSI_pointer_node
,
17260 V4SI_type_node
, intSI_type_node
, NULL
);
17261 tree v2di_ftype_const_di_pointer_v2di_si
=
17262 build_function_type_list (V2DI_type_node
, const_intDI_pointer_node
,
17263 V2DI_type_node
, intSI_type_node
, NULL
);
17264 tree v4sf_ftype_const_sf_pointer_v4sf_si
=
17265 build_function_type_list (V4SF_type_node
, const_float_pointer_node
,
17266 V4SF_type_node
, intSI_type_node
, NULL
);
17268 /* Store operations, double-word. */
17269 tree void_ftype_qi_pointer_v8qi
=
17270 build_function_type_list (void_type_node
, intQI_pointer_node
,
17271 V8QI_type_node
, NULL
);
17272 tree void_ftype_hi_pointer_v4hi
=
17273 build_function_type_list (void_type_node
, intHI_pointer_node
,
17274 V4HI_type_node
, NULL
);
17275 tree void_ftype_si_pointer_v2si
=
17276 build_function_type_list (void_type_node
, intSI_pointer_node
,
17277 V2SI_type_node
, NULL
);
17278 /* LLVM LOCAL begin */
17279 tree void_ftype_di_pointer_v1di
=
17280 build_function_type_list (void_type_node
, intDI_pointer_node
,
17281 V1DI_type_node
, NULL
);
17282 /* LLVM LOCAL end */
17283 tree void_ftype_sf_pointer_v2sf
=
17284 build_function_type_list (void_type_node
, float_pointer_node
,
17285 V2SF_type_node
, NULL
);
17287 /* Store operations, quad-word. */
17288 tree void_ftype_qi_pointer_v16qi
=
17289 build_function_type_list (void_type_node
, intQI_pointer_node
,
17290 V16QI_type_node
, NULL
);
17291 tree void_ftype_hi_pointer_v8hi
=
17292 build_function_type_list (void_type_node
, intHI_pointer_node
,
17293 V8HI_type_node
, NULL
);
17294 tree void_ftype_si_pointer_v4si
=
17295 build_function_type_list (void_type_node
, intSI_pointer_node
,
17296 V4SI_type_node
, NULL
);
17297 tree void_ftype_di_pointer_v2di
=
17298 build_function_type_list (void_type_node
, intDI_pointer_node
,
17299 V2DI_type_node
, NULL
);
17300 tree void_ftype_sf_pointer_v4sf
=
17301 build_function_type_list (void_type_node
, float_pointer_node
,
17302 V4SF_type_node
, NULL
);
17304 /* Store lane operations, double-word. */
17305 tree void_ftype_qi_pointer_v8qi_si
=
17306 build_function_type_list (void_type_node
, intQI_pointer_node
,
17307 V8QI_type_node
, intSI_type_node
, NULL
);
17308 tree void_ftype_hi_pointer_v4hi_si
=
17309 build_function_type_list (void_type_node
, intHI_pointer_node
,
17310 V4HI_type_node
, intSI_type_node
, NULL
);
17311 tree void_ftype_si_pointer_v2si_si
=
17312 build_function_type_list (void_type_node
, intSI_pointer_node
,
17313 V2SI_type_node
, intSI_type_node
, NULL
);
17314 /* LLVM LOCAL begin */
17315 tree void_ftype_di_pointer_v1di_si
=
17316 build_function_type_list (void_type_node
, intDI_pointer_node
,
17317 V1DI_type_node
, intSI_type_node
, NULL
);
17318 /* LLVM LOCAL end */
17319 tree void_ftype_sf_pointer_v2sf_si
=
17320 build_function_type_list (void_type_node
, float_pointer_node
,
17321 V2SF_type_node
, intSI_type_node
, NULL
);
17323 /* Store lane operations, quad-word. */
17324 tree void_ftype_qi_pointer_v16qi_si
=
17325 build_function_type_list (void_type_node
, intQI_pointer_node
,
17326 V16QI_type_node
, intSI_type_node
, NULL
);
17327 tree void_ftype_hi_pointer_v8hi_si
=
17328 build_function_type_list (void_type_node
, intHI_pointer_node
,
17329 V8HI_type_node
, intSI_type_node
, NULL
);
17330 tree void_ftype_si_pointer_v4si_si
=
17331 build_function_type_list (void_type_node
, intSI_pointer_node
,
17332 V4SI_type_node
, intSI_type_node
, NULL
);
17333 tree void_ftype_di_pointer_v2di_si
=
17334 build_function_type_list (void_type_node
, intDI_pointer_node
,
17335 V2DI_type_node
, intSI_type_node
, NULL
);
17336 tree void_ftype_sf_pointer_v4sf_si
=
17337 build_function_type_list (void_type_node
, float_pointer_node
,
17338 V4SF_type_node
, intSI_type_node
, NULL
);
17340 /* Load size-2 structure operations, double-word. */
17341 /* LLVM LOCAL begin multi-vector types */
17342 /* LLVM: To minimize changes to the GCC source, the original wide-integer
17343 mode abbrevations (ti, ei, oi, ci, and xi) have not been replaced by
17344 vector-type-specific names (e.g., v8qi2, etc.) in the following
17345 types. OI-mode values, however, are type-ambiguous: they can be
17346 structs of 4 double-register vectors or 2 quad-register vectors. In
17347 places where this ambiguity exists, "d" and "q" suffixes are added to
17348 the "oi" name, i.e., "oid" and "oiq", to distinguish the double- and
17349 quad-register types. */
17350 tree ti_ftype_const_qi_pointer
=
17351 build_function_type_list (V8QI2_type_node
, const_intQI_pointer_node
, NULL
);
17352 tree ti_ftype_const_hi_pointer
=
17353 build_function_type_list (V4HI2_type_node
, const_intHI_pointer_node
, NULL
);
17354 tree ti_ftype_const_si_pointer
=
17355 build_function_type_list (V2SI2_type_node
, const_intSI_pointer_node
, NULL
);
17356 tree ti_ftype_const_di_pointer
=
17357 build_function_type_list (V1DI2_type_node
, const_intDI_pointer_node
, NULL
);
17358 tree ti_ftype_const_sf_pointer
=
17359 build_function_type_list (V2SF2_type_node
, const_float_pointer_node
, NULL
);
17361 /* Load size-2 structure operations, quad-word; also load size-4,
17363 tree oiq_ftype_const_qi_pointer
=
17364 build_function_type_list (V16QI2_type_node
, const_intQI_pointer_node
, NULL
);
17365 tree oiq_ftype_const_hi_pointer
=
17366 build_function_type_list (V8HI2_type_node
, const_intHI_pointer_node
, NULL
);
17367 tree oiq_ftype_const_si_pointer
=
17368 build_function_type_list (V4SI2_type_node
, const_intSI_pointer_node
, NULL
);
17369 tree oiq_ftype_const_sf_pointer
=
17370 build_function_type_list (V4SF2_type_node
, const_float_pointer_node
, NULL
);
17372 tree oid_ftype_const_qi_pointer
=
17373 build_function_type_list (V8QI4_type_node
, const_intQI_pointer_node
, NULL
);
17374 tree oid_ftype_const_hi_pointer
=
17375 build_function_type_list (V4HI4_type_node
, const_intHI_pointer_node
, NULL
);
17376 tree oid_ftype_const_si_pointer
=
17377 build_function_type_list (V2SI4_type_node
, const_intSI_pointer_node
, NULL
);
17378 tree oid_ftype_const_sf_pointer
=
17379 build_function_type_list (V2SF4_type_node
, const_float_pointer_node
, NULL
);
17381 /* Load lane size-2 structure operations, double-word. */
17382 tree ti_ftype_const_qi_pointer_ti_si
=
17383 build_function_type_list (V8QI2_type_node
, const_intQI_pointer_node
,
17384 V8QI2_type_node
, intSI_type_node
, NULL
);
17385 tree ti_ftype_const_hi_pointer_ti_si
=
17386 build_function_type_list (V4HI2_type_node
, const_intHI_pointer_node
,
17387 V4HI2_type_node
, intSI_type_node
, NULL
);
17388 tree ti_ftype_const_si_pointer_ti_si
=
17389 build_function_type_list (V2SI2_type_node
, const_intSI_pointer_node
,
17390 V2SI2_type_node
, intSI_type_node
, NULL
);
17391 tree ti_ftype_const_sf_pointer_ti_si
=
17392 build_function_type_list (V2SF2_type_node
, const_float_pointer_node
,
17393 V2SF2_type_node
, intSI_type_node
, NULL
);
17395 /* Load lane size-2 structure operations, quad-word; also load lane size-4,
17397 tree oiq_ftype_const_hi_pointer_oiq_si
=
17398 build_function_type_list (V8HI2_type_node
, const_intHI_pointer_node
,
17399 V8HI2_type_node
, intSI_type_node
, NULL
);
17400 tree oiq_ftype_const_si_pointer_oiq_si
=
17401 build_function_type_list (V4SI2_type_node
, const_intSI_pointer_node
,
17402 V4SI2_type_node
, intSI_type_node
, NULL
);
17403 tree oiq_ftype_const_sf_pointer_oiq_si
=
17404 build_function_type_list (V4SF2_type_node
, const_float_pointer_node
,
17405 V4SF2_type_node
, intSI_type_node
, NULL
);
17407 tree oid_ftype_const_hi_pointer_oid_si
=
17408 build_function_type_list (V4HI4_type_node
, const_intHI_pointer_node
,
17409 V4HI4_type_node
, intSI_type_node
, NULL
);
17410 tree oid_ftype_const_si_pointer_oid_si
=
17411 build_function_type_list (V2SI4_type_node
, const_intSI_pointer_node
,
17412 V2SI4_type_node
, intSI_type_node
, NULL
);
17413 tree oid_ftype_const_sf_pointer_oid_si
=
17414 build_function_type_list (V2SF4_type_node
, const_float_pointer_node
,
17415 V2SF4_type_node
, intSI_type_node
, NULL
);
17417 /* Store size-2 structure operations, double-word. */
17418 tree void_ftype_qi_pointer_ti
=
17419 build_function_type_list (void_type_node
, intQI_pointer_node
,
17420 V8QI2_type_node
, NULL
);
17421 tree void_ftype_hi_pointer_ti
=
17422 build_function_type_list (void_type_node
, intHI_pointer_node
,
17423 V4HI2_type_node
, NULL
);
17424 tree void_ftype_si_pointer_ti
=
17425 build_function_type_list (void_type_node
, intSI_pointer_node
,
17426 V2SI2_type_node
, NULL
);
17427 tree void_ftype_di_pointer_ti
=
17428 build_function_type_list (void_type_node
, intDI_pointer_node
,
17429 V1DI2_type_node
, NULL
);
17430 tree void_ftype_sf_pointer_ti
=
17431 build_function_type_list (void_type_node
, float_pointer_node
,
17432 V2SF2_type_node
, NULL
);
17434 /* Store size-2 structure operations, quad-word; also store size-4,
17436 tree void_ftype_qi_pointer_oiq
=
17437 build_function_type_list (void_type_node
, intQI_pointer_node
,
17438 V16QI2_type_node
, NULL
);
17439 tree void_ftype_hi_pointer_oiq
=
17440 build_function_type_list (void_type_node
, intHI_pointer_node
,
17441 V8HI2_type_node
, NULL
);
17442 tree void_ftype_si_pointer_oiq
=
17443 build_function_type_list (void_type_node
, intSI_pointer_node
,
17444 V4SI2_type_node
, NULL
);
17445 tree void_ftype_sf_pointer_oiq
=
17446 build_function_type_list (void_type_node
, float_pointer_node
,
17447 V4SF2_type_node
, NULL
);
17449 tree void_ftype_qi_pointer_oid
=
17450 build_function_type_list (void_type_node
, intQI_pointer_node
,
17451 V8QI4_type_node
, NULL
);
17452 tree void_ftype_hi_pointer_oid
=
17453 build_function_type_list (void_type_node
, intHI_pointer_node
,
17454 V4HI4_type_node
, NULL
);
17455 tree void_ftype_si_pointer_oid
=
17456 build_function_type_list (void_type_node
, intSI_pointer_node
,
17457 V2SI4_type_node
, NULL
);
17458 tree void_ftype_sf_pointer_oid
=
17459 build_function_type_list (void_type_node
, float_pointer_node
,
17460 V2SF4_type_node
, NULL
);
17462 /* Store lane size-2 structure operations, double-word. */
17463 tree void_ftype_qi_pointer_ti_si
=
17464 build_function_type_list (void_type_node
, intQI_pointer_node
,
17465 V8QI2_type_node
, intSI_type_node
, NULL
);
17466 tree void_ftype_hi_pointer_ti_si
=
17467 build_function_type_list (void_type_node
, intHI_pointer_node
,
17468 V4HI2_type_node
, intSI_type_node
, NULL
);
17469 tree void_ftype_si_pointer_ti_si
=
17470 build_function_type_list (void_type_node
, intSI_pointer_node
,
17471 V2SI2_type_node
, intSI_type_node
, NULL
);
17472 tree void_ftype_sf_pointer_ti_si
=
17473 build_function_type_list (void_type_node
, float_pointer_node
,
17474 V2SF2_type_node
, intSI_type_node
, NULL
);
17476 /* Store lane size-2 structure operations, quad-word; also store
17477 lane size-4, double-word. */
17478 tree void_ftype_hi_pointer_oiq_si
=
17479 build_function_type_list (void_type_node
, intHI_pointer_node
,
17480 V8HI2_type_node
, intSI_type_node
, NULL
);
17481 tree void_ftype_si_pointer_oiq_si
=
17482 build_function_type_list (void_type_node
, intSI_pointer_node
,
17483 V4SI2_type_node
, intSI_type_node
, NULL
);
17484 tree void_ftype_sf_pointer_oiq_si
=
17485 build_function_type_list (void_type_node
, float_pointer_node
,
17486 V4SF2_type_node
, intSI_type_node
, NULL
);
17488 tree void_ftype_hi_pointer_oid_si
=
17489 build_function_type_list (void_type_node
, intHI_pointer_node
,
17490 V4HI4_type_node
, intSI_type_node
, NULL
);
17491 tree void_ftype_si_pointer_oid_si
=
17492 build_function_type_list (void_type_node
, intSI_pointer_node
,
17493 V2SI4_type_node
, intSI_type_node
, NULL
);
17494 tree void_ftype_sf_pointer_oid_si
=
17495 build_function_type_list (void_type_node
, float_pointer_node
,
17496 V2SF4_type_node
, intSI_type_node
, NULL
);
17498 /* Load size-3 structure operations, double-word. */
17499 tree ei_ftype_const_qi_pointer
=
17500 build_function_type_list (V8QI3_type_node
, const_intQI_pointer_node
, NULL
);
17501 tree ei_ftype_const_hi_pointer
=
17502 build_function_type_list (V4HI3_type_node
, const_intHI_pointer_node
, NULL
);
17503 tree ei_ftype_const_si_pointer
=
17504 build_function_type_list (V2SI3_type_node
, const_intSI_pointer_node
, NULL
);
17505 tree ei_ftype_const_di_pointer
=
17506 build_function_type_list (V1DI3_type_node
, const_intDI_pointer_node
, NULL
);
17507 tree ei_ftype_const_sf_pointer
=
17508 build_function_type_list (V2SF3_type_node
, const_float_pointer_node
, NULL
);
17510 /* Load size-3 structure operations, quad-word. */
17511 tree ci_ftype_const_qi_pointer
=
17512 build_function_type_list (V16QI3_type_node
, const_intQI_pointer_node
, NULL
);
17513 tree ci_ftype_const_hi_pointer
=
17514 build_function_type_list (V8HI3_type_node
, const_intHI_pointer_node
, NULL
);
17515 tree ci_ftype_const_si_pointer
=
17516 build_function_type_list (V4SI3_type_node
, const_intSI_pointer_node
, NULL
);
17517 tree ci_ftype_const_sf_pointer
=
17518 build_function_type_list (V4SF3_type_node
, const_float_pointer_node
, NULL
);
17520 /* Load lane size-3 structure operations, double-word. */
17521 tree ei_ftype_const_qi_pointer_ei_si
=
17522 build_function_type_list (V8QI3_type_node
, const_intQI_pointer_node
,
17523 V8QI3_type_node
, intSI_type_node
, NULL
);
17524 tree ei_ftype_const_hi_pointer_ei_si
=
17525 build_function_type_list (V4HI3_type_node
, const_intHI_pointer_node
,
17526 V4HI3_type_node
, intSI_type_node
, NULL
);
17527 tree ei_ftype_const_si_pointer_ei_si
=
17528 build_function_type_list (V2SI3_type_node
, const_intSI_pointer_node
,
17529 V2SI3_type_node
, intSI_type_node
, NULL
);
17530 tree ei_ftype_const_sf_pointer_ei_si
=
17531 build_function_type_list (V2SF3_type_node
, const_float_pointer_node
,
17532 V2SF3_type_node
, intSI_type_node
, NULL
);
17534 /* Load lane size-3 structure operations, quad-word. */
17535 tree ci_ftype_const_hi_pointer_ci_si
=
17536 build_function_type_list (V8HI3_type_node
, const_intHI_pointer_node
,
17537 V8HI3_type_node
, intSI_type_node
, NULL
);
17538 tree ci_ftype_const_si_pointer_ci_si
=
17539 build_function_type_list (V4SI3_type_node
, const_intSI_pointer_node
,
17540 V4SI3_type_node
, intSI_type_node
, NULL
);
17541 tree ci_ftype_const_sf_pointer_ci_si
=
17542 build_function_type_list (V4SF3_type_node
, const_float_pointer_node
,
17543 V4SF3_type_node
, intSI_type_node
, NULL
);
17545 /* Store size-3 structure operations, double-word. */
17546 tree void_ftype_qi_pointer_ei
=
17547 build_function_type_list (void_type_node
, intQI_pointer_node
,
17548 V8QI3_type_node
, NULL
);
17549 tree void_ftype_hi_pointer_ei
=
17550 build_function_type_list (void_type_node
, intHI_pointer_node
,
17551 V4HI3_type_node
, NULL
);
17552 tree void_ftype_si_pointer_ei
=
17553 build_function_type_list (void_type_node
, intSI_pointer_node
,
17554 V2SI3_type_node
, NULL
);
17555 tree void_ftype_di_pointer_ei
=
17556 build_function_type_list (void_type_node
, intDI_pointer_node
,
17557 V1DI3_type_node
, NULL
);
17558 tree void_ftype_sf_pointer_ei
=
17559 build_function_type_list (void_type_node
, float_pointer_node
,
17560 V2SF3_type_node
, NULL
);
17562 /* Store size-3 structure operations, quad-word. */
17563 tree void_ftype_qi_pointer_ci
=
17564 build_function_type_list (void_type_node
, intQI_pointer_node
,
17565 V16QI3_type_node
, NULL
);
17566 tree void_ftype_hi_pointer_ci
=
17567 build_function_type_list (void_type_node
, intHI_pointer_node
,
17568 V8HI3_type_node
, NULL
);
17569 tree void_ftype_si_pointer_ci
=
17570 build_function_type_list (void_type_node
, intSI_pointer_node
,
17571 V4SI3_type_node
, NULL
);
17572 tree void_ftype_sf_pointer_ci
=
17573 build_function_type_list (void_type_node
, float_pointer_node
,
17574 V4SF3_type_node
, NULL
);
17576 /* Store lane size-3 structure operations, double-word. */
17577 tree void_ftype_qi_pointer_ei_si
=
17578 build_function_type_list (void_type_node
, intQI_pointer_node
,
17579 V8QI3_type_node
, intSI_type_node
, NULL
);
17580 tree void_ftype_hi_pointer_ei_si
=
17581 build_function_type_list (void_type_node
, intHI_pointer_node
,
17582 V4HI3_type_node
, intSI_type_node
, NULL
);
17583 tree void_ftype_si_pointer_ei_si
=
17584 build_function_type_list (void_type_node
, intSI_pointer_node
,
17585 V2SI3_type_node
, intSI_type_node
, NULL
);
17586 tree void_ftype_sf_pointer_ei_si
=
17587 build_function_type_list (void_type_node
, float_pointer_node
,
17588 V2SF3_type_node
, intSI_type_node
, NULL
);
17590 /* Store lane size-3 structure operations, quad-word. */
17591 tree void_ftype_hi_pointer_ci_si
=
17592 build_function_type_list (void_type_node
, intHI_pointer_node
,
17593 V8HI3_type_node
, intSI_type_node
, NULL
);
17594 tree void_ftype_si_pointer_ci_si
=
17595 build_function_type_list (void_type_node
, intSI_pointer_node
,
17596 V4SI3_type_node
, intSI_type_node
, NULL
);
17597 tree void_ftype_sf_pointer_ci_si
=
17598 build_function_type_list (void_type_node
, float_pointer_node
,
17599 V4SF3_type_node
, intSI_type_node
, NULL
);
17601 /* Load size-4 structure operations, double-word. */
17602 tree oi_ftype_const_di_pointer
=
17603 build_function_type_list (V1DI4_type_node
, const_intDI_pointer_node
, NULL
);
17605 /* Load size-4 structure operations, quad-word. */
17606 tree xi_ftype_const_qi_pointer
=
17607 build_function_type_list (V16QI4_type_node
, const_intQI_pointer_node
, NULL
);
17608 tree xi_ftype_const_hi_pointer
=
17609 build_function_type_list (V8HI4_type_node
, const_intHI_pointer_node
, NULL
);
17610 tree xi_ftype_const_si_pointer
=
17611 build_function_type_list (V4SI4_type_node
, const_intSI_pointer_node
, NULL
);
17612 tree xi_ftype_const_sf_pointer
=
17613 build_function_type_list (V4SF4_type_node
, const_float_pointer_node
, NULL
);
17615 /* Load lane size-4 structure operations, double-word. */
17616 tree oi_ftype_const_qi_pointer_oi_si
=
17617 build_function_type_list (V8QI4_type_node
, const_intQI_pointer_node
,
17618 V8QI4_type_node
, intSI_type_node
, NULL
);
17620 /* Load lane size-4 structure operations, quad-word. */
17621 tree xi_ftype_const_hi_pointer_xi_si
=
17622 build_function_type_list (V8HI4_type_node
, const_intHI_pointer_node
,
17623 V8HI4_type_node
, intSI_type_node
, NULL
);
17624 tree xi_ftype_const_si_pointer_xi_si
=
17625 build_function_type_list (V4SI4_type_node
, const_intSI_pointer_node
,
17626 V4SI4_type_node
, intSI_type_node
, NULL
);
17627 tree xi_ftype_const_sf_pointer_xi_si
=
17628 build_function_type_list (V4SF4_type_node
, const_float_pointer_node
,
17629 V4SF4_type_node
, intSI_type_node
, NULL
);
17631 /* Store size-4 structure operations, double-word. */
17632 tree void_ftype_di_pointer_oi
=
17633 build_function_type_list (void_type_node
, intDI_pointer_node
,
17634 V1DI4_type_node
, NULL
);
17636 /* Store size-4 structure operations, quad-word. */
17637 tree void_ftype_qi_pointer_xi
=
17638 build_function_type_list (void_type_node
, intQI_pointer_node
,
17639 V16QI4_type_node
, NULL
);
17640 tree void_ftype_hi_pointer_xi
=
17641 build_function_type_list (void_type_node
, intHI_pointer_node
,
17642 V8HI4_type_node
, NULL
);
17643 tree void_ftype_si_pointer_xi
=
17644 build_function_type_list (void_type_node
, intSI_pointer_node
,
17645 V4SI4_type_node
, NULL
);
17646 tree void_ftype_sf_pointer_xi
=
17647 build_function_type_list (void_type_node
, float_pointer_node
,
17648 V4SF4_type_node
, NULL
);
17650 /* Store lane size-4 structure operations, double-word. */
17651 tree void_ftype_qi_pointer_oi_si
=
17652 build_function_type_list (void_type_node
, intQI_pointer_node
,
17653 V8QI4_type_node
, intSI_type_node
, NULL
);
17655 /* Store lane size-4 structure operations, quad-word. */
17656 tree void_ftype_hi_pointer_xi_si
=
17657 build_function_type_list (void_type_node
, intHI_pointer_node
,
17658 V8HI4_type_node
, intSI_type_node
, NULL
);
17659 tree void_ftype_si_pointer_xi_si
=
17660 build_function_type_list (void_type_node
, intSI_pointer_node
,
17661 V4SI4_type_node
, intSI_type_node
, NULL
);
17662 tree void_ftype_sf_pointer_xi_si
=
17663 build_function_type_list (void_type_node
, float_pointer_node
,
17664 V4SF4_type_node
, intSI_type_node
, NULL
);
17665 /* LLVM LOCAL end multi-vector types */
17667 tree reinterp_ftype_dreg
[5][5];
17668 tree reinterp_ftype_qreg
[5][5];
17669 tree dreg_types
[5], qreg_types
[5];
17671 /* APPLE LOCAL begin 7083296 Build without warnings. */
17672 /* Define typedefs which exactly correspond to the modes we are basing vector
17673 types on. If you change these names you'll need to change
17674 the table used by arm_mangle_type too. */
17675 (*lang_hooks
.types
.register_builtin_type
) (neon_intQI_type_node
,
17676 "__builtin_neon_qi");
17677 (*lang_hooks
.types
.register_builtin_type
) (neon_intHI_type_node
,
17678 "__builtin_neon_hi");
17679 (*lang_hooks
.types
.register_builtin_type
) (neon_intSI_type_node
,
17680 "__builtin_neon_si");
17681 (*lang_hooks
.types
.register_builtin_type
) (neon_float_type_node
,
17682 "__builtin_neon_sf");
17683 (*lang_hooks
.types
.register_builtin_type
) (neon_intDI_type_node
,
17684 "__builtin_neon_di");
17686 (*lang_hooks
.types
.register_builtin_type
) (neon_polyQI_type_node
,
17687 "__builtin_neon_poly8");
17688 (*lang_hooks
.types
.register_builtin_type
) (neon_polyHI_type_node
,
17689 "__builtin_neon_poly16");
17691 (*lang_hooks
.types
.register_builtin_type
) (intUQI_type_node
,
17692 "__builtin_neon_uqi");
17693 (*lang_hooks
.types
.register_builtin_type
) (intUHI_type_node
,
17694 "__builtin_neon_uhi");
17695 (*lang_hooks
.types
.register_builtin_type
) (intUSI_type_node
,
17696 "__builtin_neon_usi");
17697 (*lang_hooks
.types
.register_builtin_type
) (intUDI_type_node
,
17698 "__builtin_neon_udi");
17700 /* LLVM LOCAL begin multi-vector types */
17701 (*lang_hooks
.types
.register_builtin_type
) (V8QI2_type_node
,
17702 "__builtin_neon_v8qi2");
17703 (*lang_hooks
.types
.register_builtin_type
) (V4HI2_type_node
,
17704 "__builtin_neon_v4hi2");
17705 (*lang_hooks
.types
.register_builtin_type
) (V2SI2_type_node
,
17706 "__builtin_neon_v2si2");
17707 (*lang_hooks
.types
.register_builtin_type
) (V2SF2_type_node
,
17708 "__builtin_neon_v2sf2");
17709 (*lang_hooks
.types
.register_builtin_type
) (V1DI2_type_node
,
17710 "__builtin_neon_v1di2");
17711 (*lang_hooks
.types
.register_builtin_type
) (V8QI3_type_node
,
17712 "__builtin_neon_v8qi3");
17713 (*lang_hooks
.types
.register_builtin_type
) (V4HI3_type_node
,
17714 "__builtin_neon_v4hi3");
17715 (*lang_hooks
.types
.register_builtin_type
) (V2SI3_type_node
,
17716 "__builtin_neon_v2si3");
17717 (*lang_hooks
.types
.register_builtin_type
) (V2SF3_type_node
,
17718 "__builtin_neon_v2sf3");
17719 (*lang_hooks
.types
.register_builtin_type
) (V1DI3_type_node
,
17720 "__builtin_neon_v1di3");
17721 (*lang_hooks
.types
.register_builtin_type
) (V8QI4_type_node
,
17722 "__builtin_neon_v8qi4");
17723 (*lang_hooks
.types
.register_builtin_type
) (V4HI4_type_node
,
17724 "__builtin_neon_v4hi4");
17725 (*lang_hooks
.types
.register_builtin_type
) (V2SI4_type_node
,
17726 "__builtin_neon_v2si4");
17727 (*lang_hooks
.types
.register_builtin_type
) (V2SF4_type_node
,
17728 "__builtin_neon_v2sf4");
17729 (*lang_hooks
.types
.register_builtin_type
) (V1DI4_type_node
,
17730 "__builtin_neon_v1di4");
17731 (*lang_hooks
.types
.register_builtin_type
) (V16QI2_type_node
,
17732 "__builtin_neon_v16qi2");
17733 (*lang_hooks
.types
.register_builtin_type
) (V8HI2_type_node
,
17734 "__builtin_neon_v8hi2");
17735 (*lang_hooks
.types
.register_builtin_type
) (V4SI2_type_node
,
17736 "__builtin_neon_v4si2");
17737 (*lang_hooks
.types
.register_builtin_type
) (V4SF2_type_node
,
17738 "__builtin_neon_v4sf2");
17739 (*lang_hooks
.types
.register_builtin_type
) (V16QI3_type_node
,
17740 "__builtin_neon_v16qi3");
17741 (*lang_hooks
.types
.register_builtin_type
) (V8HI3_type_node
,
17742 "__builtin_neon_v8hi3");
17743 (*lang_hooks
.types
.register_builtin_type
) (V4SI3_type_node
,
17744 "__builtin_neon_v4si3");
17745 (*lang_hooks
.types
.register_builtin_type
) (V4SF3_type_node
,
17746 "__builtin_neon_v4sf3");
17747 (*lang_hooks
.types
.register_builtin_type
) (V16QI4_type_node
,
17748 "__builtin_neon_v16qi4");
17749 (*lang_hooks
.types
.register_builtin_type
) (V8HI4_type_node
,
17750 "__builtin_neon_v8hi4");
17751 (*lang_hooks
.types
.register_builtin_type
) (V4SI4_type_node
,
17752 "__builtin_neon_v4si4");
17753 (*lang_hooks
.types
.register_builtin_type
) (V4SF4_type_node
,
17754 "__builtin_neon_v4sf4");
17755 /* LLVM LOCAL end multi-vector types */
17756 /* APPLE LOCAL end 7083296 Build without warnings. */
17758 dreg_types
[0] = V8QI_type_node
;
17759 dreg_types
[1] = V4HI_type_node
;
17760 dreg_types
[2] = V2SI_type_node
;
17761 dreg_types
[3] = V2SF_type_node
;
17762 /* LLVM LOCAL begin */
17763 dreg_types
[4] = V1DI_type_node
;
17764 /* LLVM LOCAL end */
17766 qreg_types
[0] = V16QI_type_node
;
17767 qreg_types
[1] = V8HI_type_node
;
17768 qreg_types
[2] = V4SI_type_node
;
17769 qreg_types
[3] = V4SF_type_node
;
17770 qreg_types
[4] = V2DI_type_node
;
17772 for (i
= 0; i
< 5; i
++)
17775 for (j
= 0; j
< 5; j
++)
17777 reinterp_ftype_dreg
[i
][j
]
17778 = build_function_type_list (dreg_types
[i
], dreg_types
[j
], NULL
);
17779 reinterp_ftype_qreg
[i
][j
]
17780 = build_function_type_list (qreg_types
[i
], qreg_types
[j
], NULL
);
17784 for (i
= 0; i
< ARRAY_SIZE (neon_builtin_data
); i
++)
17786 neon_builtin_datum
*d
= &neon_builtin_data
[i
];
17787 unsigned int j
, codeidx
= 0;
17789 d
->base_fcode
= fcode
;
17791 for (j
= 0; j
< T_MAX
; j
++)
17793 /* LLVM LOCAL begin */
17794 const char* const modenames
[] = {
17795 "v8qi", "v4hi", "v2si", "v2sf", "v1di",
17796 "v16qi", "v8hi", "v4si", "v4sf", "v2di"
17798 /* LLVM LOCAL end */
17801 enum insn_code icode
;
17802 enum machine_mode tmode
, mode0
, mode1
, mode2
, mode3
;
17804 if ((d
->bits
& (1 << j
)) == 0)
17807 icode
= d
->codes
[codeidx
++];
17809 tmode
= insn_data
[icode
].operand
[0].mode
;
17810 mode0
= insn_data
[icode
].operand
[1].mode
;
17811 mode1
= insn_data
[icode
].operand
[2].mode
;
17812 mode2
= insn_data
[icode
].operand
[3].mode
;
17813 mode3
= insn_data
[icode
].operand
[4].mode
;
17818 /* A unary operation with one vector operand and a vector
17819 destination, plus an extra information word. */
17820 gcc_assert (valid_neon_mode (tmode
) && valid_neon_mode (mode0
)
17821 && mode1
== SImode
);
17825 if (mode0
== V8QImode
)
17826 ftype
= v8qi_ftype_v8qi_si
;
17827 else if (mode0
== V8HImode
)
17828 ftype
= v8qi_ftype_v8hi_si
;
17832 if (mode0
== V4HImode
)
17833 ftype
= v4hi_ftype_v4hi_si
;
17834 else if (mode0
== V4SImode
)
17835 ftype
= v4hi_ftype_v4si_si
;
17836 else if (mode0
== V8QImode
)
17837 ftype
= v4hi_ftype_v8qi_si
;
17841 if (mode0
== V2SImode
)
17842 ftype
= v2si_ftype_v2si_si
;
17843 else if (mode0
== V2DImode
)
17844 ftype
= v2si_ftype_v2di_si
;
17845 else if (mode0
== V4HImode
)
17846 ftype
= v2si_ftype_v4hi_si
;
17850 if (mode0
== V2SFmode
)
17851 ftype
= v2sf_ftype_v2sf_si
;
17854 /* LLVM LOCAL begin */
17856 if (mode0
== V1DImode
)
17857 ftype
= v1di_ftype_v1di_si
;
17858 else if (mode0
== V2SImode
)
17859 ftype
= v1di_ftype_v2si_si
;
17861 /* LLVM LOCAL end */
17864 if (mode0
== V16QImode
)
17865 ftype
= v16qi_ftype_v16qi_si
;
17869 if (mode0
== V8HImode
)
17870 ftype
= v8hi_ftype_v8hi_si
;
17871 else if (mode0
== V8QImode
)
17872 ftype
= v8hi_ftype_v8qi_si
;
17873 else if (mode0
== V16QImode
)
17874 ftype
= v8hi_ftype_v16qi_si
;
17878 if (mode0
== V4SImode
)
17879 ftype
= v4si_ftype_v4si_si
;
17880 else if (mode0
== V4HImode
)
17881 ftype
= v4si_ftype_v4hi_si
;
17882 else if (mode0
== V8HImode
)
17883 ftype
= v4si_ftype_v8hi_si
;
17887 if (mode0
== V4SFmode
)
17888 ftype
= v4sf_ftype_v4sf_si
;
17892 if (mode0
== V2DImode
)
17893 ftype
= v2di_ftype_v2di_si
;
17894 else if (mode0
== V2SImode
)
17895 ftype
= v2di_ftype_v2si_si
;
17896 else if (mode0
== V4SImode
)
17897 ftype
= v2di_ftype_v4si_si
;
17901 gcc_unreachable ();
17906 case NEON_LOGICBINOP
:
17907 case NEON_SHIFTINSERT
:
17908 /* A binary operation with two vector operands and a vector
17909 destination, plus an extra information word. */
17910 gcc_assert (valid_neon_mode (tmode
) && valid_neon_mode (mode0
)
17911 && valid_neon_mode (mode1
) && mode2
== SImode
);
17915 if (mode0
== V8QImode
&& mode1
== V8QImode
)
17916 ftype
= v8qi_ftype_v8qi_v8qi_si
;
17917 else if (mode0
== V8HImode
&& mode1
== V8HImode
)
17918 ftype
= v8qi_ftype_v8hi_v8hi_si
;
17922 if (mode0
== V4HImode
&& mode1
== V4HImode
)
17923 ftype
= v4hi_ftype_v4hi_v4hi_si
;
17924 else if (mode0
== V4SImode
&& mode1
== V4SImode
)
17925 ftype
= v4hi_ftype_v4si_v4si_si
;
17926 else if (mode0
== V4HImode
&& mode1
== V8QImode
)
17927 ftype
= v4hi_ftype_v4hi_v8qi_si
;
17931 if (mode0
== V2SImode
&& mode1
== V2SImode
)
17932 ftype
= v2si_ftype_v2si_v2si_si
;
17933 else if (mode0
== V2DImode
&& mode1
== V2DImode
)
17934 ftype
= v2si_ftype_v2di_v2di_si
;
17935 else if (mode0
== V2SFmode
&& mode1
== V2SFmode
)
17936 ftype
= v2si_ftype_v2sf_v2sf_si
;
17937 else if (mode0
== V2SImode
&& mode1
== V4HImode
)
17938 ftype
= v2si_ftype_v2si_v4hi_si
;
17942 if (mode0
== V2SFmode
&& mode1
== V2SFmode
)
17943 ftype
= v2sf_ftype_v2sf_v2sf_si
;
17946 /* LLVM LOCAL begin */
17948 if (mode0
== V1DImode
&& mode1
== V1DImode
)
17949 ftype
= v1di_ftype_v1di_v1di_si
;
17950 else if (mode0
== V1DImode
&& mode1
== V2SImode
)
17951 ftype
= v1di_ftype_v1di_v2si_si
;
17953 /* LLVM LOCAL end */
17956 if (mode0
== V16QImode
&& mode1
== V16QImode
)
17957 ftype
= v16qi_ftype_v16qi_v16qi_si
;
17961 if (mode0
== V8HImode
&& mode1
== V8HImode
)
17962 ftype
= v8hi_ftype_v8hi_v8hi_si
;
17963 else if (mode0
== V8QImode
&& mode1
== V8QImode
)
17964 ftype
= v8hi_ftype_v8qi_v8qi_si
;
17965 else if (mode0
== V8HImode
&& mode1
== V8QImode
)
17966 ftype
= v8hi_ftype_v8hi_v8qi_si
;
17967 else if (mode0
== V8HImode
&& mode1
== V16QImode
)
17968 ftype
= v8hi_ftype_v8hi_v16qi_si
;
17972 if (mode0
== V4SImode
&& mode1
== V4SImode
)
17973 ftype
= v4si_ftype_v4si_v4si_si
;
17974 else if (mode0
== V4HImode
&& mode1
== V4HImode
)
17975 ftype
= v4si_ftype_v4hi_v4hi_si
;
17976 else if (mode0
== V4SImode
&& mode1
== V4HImode
)
17977 ftype
= v4si_ftype_v4si_v4hi_si
;
17978 else if (mode0
== V4SFmode
&& mode1
== V4SFmode
)
17979 ftype
= v4si_ftype_v4sf_v4sf_si
;
17980 else if (mode0
== V4SImode
&& mode1
== V8HImode
)
17981 ftype
= v4si_ftype_v4si_v8hi_si
;
17985 if (mode0
== V4SFmode
&& mode1
== V4SFmode
)
17986 ftype
= v4sf_ftype_v4sf_v4sf_si
;
17990 if (mode0
== V2DImode
&& mode1
== V2DImode
)
17991 ftype
= v2di_ftype_v2di_v2di_si
;
17992 else if (mode0
== V2SImode
&& mode1
== V2SImode
)
17993 ftype
= v2di_ftype_v2si_v2si_si
;
17994 else if (mode0
== V2DImode
&& mode1
== V2SImode
)
17995 ftype
= v2di_ftype_v2di_v2si_si
;
17996 else if (mode0
== V2DImode
&& mode1
== V4SImode
)
17997 ftype
= v2di_ftype_v2di_v4si_si
;
18001 gcc_unreachable ();
18006 /* A ternary operation with three vector operands and a
18007 vector destination, plus an extra information
18009 gcc_assert (valid_neon_mode (tmode
) && valid_neon_mode (mode0
)
18010 && valid_neon_mode (mode1
)
18011 && valid_neon_mode (mode2
)
18012 && mode3
== SImode
);
18016 if (mode0
== V8QImode
&& mode1
== V8QImode
18017 && mode2
== V8QImode
)
18018 ftype
= v8qi_ftype_v8qi_v8qi_v8qi_si
;
18022 if (mode0
== V4HImode
&& mode1
== V4HImode
18023 && mode2
== V4HImode
)
18024 ftype
= v4hi_ftype_v4hi_v4hi_v4hi_si
;
18028 if (mode0
== V2SImode
&& mode1
== V2SImode
18029 && mode2
== V2SImode
)
18030 ftype
= v2si_ftype_v2si_v2si_v2si_si
;
18034 if (mode0
== V2SFmode
&& mode1
== V2SFmode
18035 && mode2
== V2SFmode
)
18036 ftype
= v2sf_ftype_v2sf_v2sf_v2sf_si
;
18040 if (mode0
== V16QImode
&& mode1
== V16QImode
18041 && mode2
== V16QImode
)
18042 ftype
= v16qi_ftype_v16qi_v16qi_v16qi_si
;
18046 if (mode0
== V8HImode
&& mode1
== V8HImode
18047 && mode2
== V8HImode
)
18048 ftype
= v8hi_ftype_v8hi_v8hi_v8hi_si
;
18049 else if (mode0
== V8HImode
&& mode1
== V8QImode
18050 && mode2
== V8QImode
)
18051 ftype
= v8hi_ftype_v8hi_v8qi_v8qi_si
;
18055 if (mode0
== V4SImode
&& mode1
== V4SImode
18056 && mode2
== V4SImode
)
18057 ftype
= v4si_ftype_v4si_v4si_v4si_si
;
18058 else if (mode0
== V4SImode
&& mode1
== V4HImode
18059 && mode2
== V4HImode
)
18060 ftype
= v4si_ftype_v4si_v4hi_v4hi_si
;
18064 if (mode0
== V4SFmode
&& mode1
== V4SFmode
18065 && mode2
== V4SFmode
)
18066 ftype
= v4sf_ftype_v4sf_v4sf_v4sf_si
;
18070 if (mode0
== V2DImode
&& mode1
== V2SImode
18071 && mode2
== V2SImode
)
18072 ftype
= v2di_ftype_v2di_v2si_v2si_si
;
18076 gcc_unreachable ();
18081 /* Vector lane extraction. */
18082 gcc_assert (valid_neon_mode (mode0
) && mode1
== SImode
18083 && mode2
== SImode
);
18087 if (mode0
== V8QImode
)
18088 ftype
= qi_ftype_v8qi_si_si
;
18089 else if (mode0
== V16QImode
)
18090 ftype
= qi_ftype_v16qi_si_si
;
18094 if (mode0
== V4HImode
)
18095 ftype
= hi_ftype_v4hi_si_si
;
18096 else if (mode0
== V8HImode
)
18097 ftype
= hi_ftype_v8hi_si_si
;
18101 if (mode0
== V2SImode
)
18102 ftype
= si_ftype_v2si_si_si
;
18103 else if (mode0
== V4SImode
)
18104 ftype
= si_ftype_v4si_si_si
;
18108 if (mode0
== V2SFmode
)
18109 ftype
= sf_ftype_v2sf_si_si
;
18110 else if (mode0
== V4SFmode
)
18111 ftype
= sf_ftype_v4sf_si_si
;
18114 /* LLVM LOCAL begin */
18116 if (mode0
== V1DImode
)
18117 ftype
= di_ftype_v1di_si_si
;
18118 else if (mode0
== V2DImode
)
18119 ftype
= di_ftype_v2di_si_si
;
18121 /* LLVM LOCAL end */
18124 gcc_unreachable ();
18130 /* Set lanes in vector. */
18131 gcc_assert (valid_neon_mode (mode1
) && mode2
== SImode
);
18135 if (mode0
== QImode
&& mode1
== V8QImode
)
18136 ftype
= v8qi_ftype_qi_v8qi_si
;
18140 if (mode0
== HImode
&& mode1
== V4HImode
)
18141 ftype
= v4hi_ftype_hi_v4hi_si
;
18145 if (mode0
== SImode
&& mode1
== V2SImode
)
18146 ftype
= v2si_ftype_si_v2si_si
;
18150 if (mode0
== SFmode
&& mode1
== V2SFmode
)
18151 ftype
= v2sf_ftype_sf_v2sf_si
;
18154 /* LLVM LOCAL begin */
18156 if (mode0
== DImode
&& mode1
== V1DImode
)
18157 ftype
= v1di_ftype_di_v1di_si
;
18159 /* LLVM LOCAL end */
18162 if (mode0
== QImode
&& mode1
== V16QImode
)
18163 ftype
= v16qi_ftype_qi_v16qi_si
;
18167 if (mode0
== HImode
&& mode1
== V8HImode
)
18168 ftype
= v8hi_ftype_hi_v8hi_si
;
18172 if (mode0
== SImode
&& mode1
== V4SImode
)
18173 ftype
= v4si_ftype_si_v4si_si
;
18177 if (mode0
== SFmode
&& mode1
== V4SFmode
)
18178 ftype
= v4sf_ftype_sf_v4sf_si
;
18182 if (mode0
== DImode
&& mode1
== V2DImode
)
18183 ftype
= v2di_ftype_di_v2di_si
;
18187 gcc_unreachable ();
18193 gcc_assert (mode0
== DImode
);
18194 /* Create vector from bit pattern. */
18197 case V8QImode
: ftype
= v8qi_ftype_di
; break;
18198 case V4HImode
: ftype
= v4hi_ftype_di
; break;
18199 case V2SImode
: ftype
= v2si_ftype_di
; break;
18200 case V2SFmode
: ftype
= v2sf_ftype_di
; break;
18201 /* LLVM LOCAL begin */
18202 case V1DImode
: ftype
= v1di_ftype_di
; break;
18203 /* LLVM LOCAL end */
18204 default: gcc_unreachable ();
18209 gcc_assert ((mode0
== DImode
&& tmode
== V1DImode
)
18210 || mode0
== GET_MODE_INNER (tmode
));
18213 case V8QImode
: ftype
= v8qi_ftype_qi
; break;
18214 case V4HImode
: ftype
= v4hi_ftype_hi
; break;
18215 case V2SImode
: ftype
= v2si_ftype_si
; break;
18216 case V2SFmode
: ftype
= v2sf_ftype_sf
; break;
18217 /* LLVM LOCAL begin */
18218 case V1DImode
: ftype
= v1di_ftype_di
; break;
18219 /* LLVM LOCAL end */
18220 case V16QImode
: ftype
= v16qi_ftype_qi
; break;
18221 case V8HImode
: ftype
= v8hi_ftype_hi
; break;
18222 case V4SImode
: ftype
= v4si_ftype_si
; break;
18223 case V4SFmode
: ftype
= v4sf_ftype_sf
; break;
18224 case V2DImode
: ftype
= v2di_ftype_di
; break;
18225 default: gcc_unreachable ();
18230 gcc_assert (valid_neon_mode (mode0
) && mode1
== SImode
);
18233 case V8QImode
: ftype
= v8qi_ftype_v8qi_si
; break;
18234 case V4HImode
: ftype
= v4hi_ftype_v4hi_si
; break;
18235 case V2SImode
: ftype
= v2si_ftype_v2si_si
; break;
18236 case V2SFmode
: ftype
= v2sf_ftype_v2sf_si
; break;
18237 /* LLVM LOCAL begin */
18238 case V1DImode
: ftype
= v1di_ftype_v1di_si
; break;
18239 /* LLVM LOCAL end */
18240 case V16QImode
: ftype
= v16qi_ftype_v8qi_si
; break;
18241 case V8HImode
: ftype
= v8hi_ftype_v4hi_si
; break;
18242 case V4SImode
: ftype
= v4si_ftype_v2si_si
; break;
18243 case V4SFmode
: ftype
= v4sf_ftype_v2sf_si
; break;
18244 /* LLVM LOCAL begin */
18245 case V2DImode
: ftype
= v2di_ftype_v1di_si
; break;
18246 /* LLVM LOCAL end */
18247 default: gcc_unreachable ();
18251 case NEON_SHIFTIMM
:
18252 gcc_assert (mode1
== SImode
&& mode2
== SImode
);
18256 if (mode0
== V8QImode
)
18257 ftype
= v8qi_ftype_v8qi_si_si
;
18258 else if (mode0
== V8HImode
)
18259 ftype
= v8qi_ftype_v8hi_si_si
;
18263 if (mode0
== V4HImode
)
18264 ftype
= v4hi_ftype_v4hi_si_si
;
18265 else if (mode0
== V4SImode
)
18266 ftype
= v4hi_ftype_v4si_si_si
;
18270 if (mode0
== V2SImode
)
18271 ftype
= v2si_ftype_v2si_si_si
;
18272 else if (mode0
== V2DImode
)
18273 ftype
= v2si_ftype_v2di_si_si
;
18276 /* LLVM LOCAL begin */
18278 if (mode0
== V1DImode
)
18279 ftype
= v1di_ftype_v1di_si_si
;
18281 /* LLVM LOCAL end */
18284 if (mode0
== V16QImode
)
18285 ftype
= v16qi_ftype_v16qi_si_si
;
18289 if (mode0
== V8HImode
)
18290 ftype
= v8hi_ftype_v8hi_si_si
;
18291 else if (mode0
== V8QImode
)
18292 ftype
= v8hi_ftype_v8qi_si_si
;
18296 if (mode0
== V4SImode
)
18297 ftype
= v4si_ftype_v4si_si_si
;
18298 else if (mode0
== V4HImode
)
18299 ftype
= v4si_ftype_v4hi_si_si
;
18303 if (mode0
== V2DImode
)
18304 ftype
= v2di_ftype_v2di_si_si
;
18305 else if (mode0
== V2SImode
)
18306 ftype
= v2di_ftype_v2si_si_si
;
18309 default: gcc_unreachable ();
18313 case NEON_SHIFTACC
:
18314 gcc_assert (tmode
== mode0
&& mode0
== mode1
&& mode2
== SImode
18315 && mode3
== SImode
);
18318 case V8QImode
: ftype
= v8qi_ftype_v8qi_v8qi_si_si
; break;
18319 case V4HImode
: ftype
= v4hi_ftype_v4hi_v4hi_si_si
; break;
18320 case V2SImode
: ftype
= v2si_ftype_v2si_v2si_si_si
; break;
18321 case V2SFmode
: ftype
= v2sf_ftype_v2sf_v2sf_si_si
; break;
18322 /* LLVM LOCAL begin */
18323 case V1DImode
: ftype
= v1di_ftype_v1di_v1di_si_si
; break;
18324 /* LLVM LOCAL end */
18325 case V16QImode
: ftype
= v16qi_ftype_v16qi_v16qi_si_si
; break;
18326 case V8HImode
: ftype
= v8hi_ftype_v8hi_v8hi_si_si
; break;
18327 case V4SImode
: ftype
= v4si_ftype_v4si_v4si_si_si
; break;
18328 case V4SFmode
: ftype
= v4sf_ftype_v4sf_v4sf_si_si
; break;
18329 case V2DImode
: ftype
= v2di_ftype_v2di_v2di_si_si
; break;
18330 default: gcc_unreachable ();
18335 gcc_assert (valid_neon_mode (mode0
) && valid_neon_mode (mode1
));
18339 if (mode0
== V8QImode
&& mode1
== V8QImode
)
18340 ftype
= v16qi_ftype_v8qi_v8qi
;
18344 if (mode0
== V4HImode
&& mode1
== V4HImode
)
18345 ftype
= v8hi_ftype_v4hi_v4hi
;
18349 if (mode0
== V2SImode
&& mode1
== V2SImode
)
18350 ftype
= v4si_ftype_v2si_v2si
;
18354 if (mode0
== V2SFmode
&& mode1
== V2SFmode
)
18355 ftype
= v4sf_ftype_v2sf_v2sf
;
18358 /* LLVM LOCAL begin */
18360 if (mode0
== V1DImode
&& mode1
== V1DImode
)
18361 ftype
= v2di_ftype_v1di_v1di
;
18363 /* LLVM LOCAL end */
18366 gcc_unreachable ();
18371 gcc_assert (valid_neon_mode (mode0
));
18375 if (mode0
== V16QImode
)
18376 ftype
= v8qi_ftype_v16qi
;
18380 if (mode0
== V8HImode
)
18381 ftype
= v4hi_ftype_v8hi
;
18385 if (mode0
== V4SImode
)
18386 ftype
= v2si_ftype_v4si
;
18390 if (mode0
== V4SFmode
)
18391 ftype
= v2sf_ftype_v4sf
;
18394 /* LLVM LOCAL begin */
18396 if (mode0
== V2DImode
)
18397 ftype
= v1di_ftype_v2di
;
18399 /* LLVM LOCAL end */
18402 gcc_unreachable ();
18407 gcc_assert (valid_neon_mode (mode0
) && mode1
== SImode
);
18411 if (mode0
== V2SFmode
)
18412 ftype
= v2si_ftype_v2sf_si
;
18416 if (mode0
== V2SImode
)
18417 ftype
= v2sf_ftype_v2si_si
;
18421 if (mode0
== V4SFmode
)
18422 ftype
= v4si_ftype_v4sf_si
;
18426 if (mode0
== V4SImode
)
18427 ftype
= v4sf_ftype_v4si_si
;
18430 default: gcc_unreachable ();
18435 gcc_assert (valid_neon_mode (mode0
) && mode1
== SImode
18436 && mode2
== SImode
);
18440 if (mode0
== V2SFmode
)
18441 ftype
= v2si_ftype_v2sf_si_si
;
18445 if (mode0
== V2SImode
)
18446 ftype
= v2sf_ftype_v2si_si_si
;
18450 if (mode0
== V4SFmode
)
18451 ftype
= v4si_ftype_v4sf_si_si
;
18455 if (mode0
== V4SImode
)
18456 ftype
= v4sf_ftype_v4si_si_si
;
18460 gcc_unreachable ();
18466 enum machine_mode mode3
= insn_data
[icode
].operand
[4].mode
;
18467 gcc_assert (valid_neon_mode (mode0
) && valid_neon_mode (mode1
)
18468 && mode2
== SImode
&& mode3
== SImode
);
18472 if (mode0
== V4HImode
&& mode1
== V4HImode
)
18473 ftype
= v4hi_ftype_v4hi_v4hi_si_si
;
18477 if (mode0
== V2SImode
&& mode1
== V2SImode
)
18478 ftype
= v2si_ftype_v2si_v2si_si_si
;
18482 if (mode0
== V2SFmode
&& mode1
== V2SFmode
)
18483 ftype
= v2sf_ftype_v2sf_v2sf_si_si
;
18487 if (mode0
== V8HImode
&& mode1
== V4HImode
)
18488 ftype
= v8hi_ftype_v8hi_v4hi_si_si
;
18492 if (mode0
== V4SImode
&& mode1
== V2SImode
)
18493 ftype
= v4si_ftype_v4si_v2si_si_si
;
18497 if (mode0
== V4SFmode
&& mode1
== V2SFmode
)
18498 ftype
= v4sf_ftype_v4sf_v2sf_si_si
;
18502 gcc_unreachable ();
18507 case NEON_LANEMULL
:
18509 enum machine_mode mode3
= insn_data
[icode
].operand
[4].mode
;
18510 gcc_assert (valid_neon_mode (mode0
) && valid_neon_mode (mode1
)
18511 && mode2
== SImode
&& mode3
== SImode
);
18515 if (mode0
== V4HImode
&& mode1
== V4HImode
)
18516 ftype
= v4si_ftype_v4hi_v4hi_si_si
;
18520 if (mode0
== V2SImode
&& mode1
== V2SImode
)
18521 ftype
= v2di_ftype_v2si_v2si_si_si
;
18525 gcc_unreachable ();
18530 case NEON_LANEMULH
:
18532 enum machine_mode mode3
= insn_data
[icode
].operand
[4].mode
;
18533 gcc_assert (valid_neon_mode (mode0
) && valid_neon_mode (mode1
)
18534 && mode2
== SImode
&& mode3
== SImode
);
18538 if (mode0
== V4SImode
&& mode1
== V2SImode
)
18539 ftype
= v4si_ftype_v4si_v2si_si_si
;
18543 if (mode0
== V8HImode
&& mode1
== V4HImode
)
18544 ftype
= v8hi_ftype_v8hi_v4hi_si_si
;
18548 if (mode0
== V2SImode
&& mode1
== V2SImode
)
18549 ftype
= v2si_ftype_v2si_v2si_si_si
;
18553 if (mode0
== V4HImode
&& mode1
== V4HImode
)
18554 ftype
= v4hi_ftype_v4hi_v4hi_si_si
;
18558 gcc_unreachable ();
18565 enum machine_mode mode3
= insn_data
[icode
].operand
[4].mode
;
18566 enum machine_mode mode4
= insn_data
[icode
].operand
[5].mode
;
18567 gcc_assert (valid_neon_mode (mode0
) && valid_neon_mode (mode1
)
18568 && valid_neon_mode (mode2
) && mode3
== SImode
18569 && mode4
== SImode
);
18573 if (mode0
== V4HImode
&& mode1
== V4HImode
18574 && mode2
== V4HImode
)
18575 ftype
= v4hi_ftype_v4hi_v4hi_v4hi_si_si
;
18579 if (mode0
== V2SImode
&& mode1
== V2SImode
18580 && mode2
== V2SImode
)
18581 ftype
= v2si_ftype_v2si_v2si_v2si_si_si
;
18585 if (mode0
== V2SFmode
&& mode1
== V2SFmode
18586 && mode2
== V2SFmode
)
18587 ftype
= v2sf_ftype_v2sf_v2sf_v2sf_si_si
;
18591 if (mode0
== V8HImode
&& mode1
== V8HImode
18592 && mode2
== V4HImode
)
18593 ftype
= v8hi_ftype_v8hi_v8hi_v4hi_si_si
;
18597 if (mode0
== V4SImode
&& mode1
== V4SImode
18598 && mode2
== V2SImode
)
18599 ftype
= v4si_ftype_v4si_v4si_v2si_si_si
;
18600 else if (mode0
== V4SImode
&& mode1
== V4HImode
18601 && mode2
== V4HImode
)
18602 ftype
= v4si_ftype_v4si_v4hi_v4hi_si_si
;
18606 if (mode0
== V4SFmode
&& mode1
== V4SFmode
18607 && mode2
== V2SFmode
)
18608 ftype
= v4sf_ftype_v4sf_v4sf_v2sf_si_si
;
18612 if (mode0
== V2DImode
&& mode1
== V2SImode
18613 && mode2
== V2SImode
)
18614 ftype
= v2di_ftype_v2di_v2si_v2si_si_si
;
18618 gcc_unreachable ();
18623 case NEON_SCALARMUL
:
18627 if (mode0
== V4HImode
&& mode1
== HImode
)
18628 ftype
= v4hi_ftype_v4hi_hi_si
;
18632 if (mode0
== V2SImode
&& mode1
== SImode
)
18633 ftype
= v2si_ftype_v2si_si_si
;
18637 if (mode0
== V2SFmode
&& mode1
== SFmode
)
18638 ftype
= v2sf_ftype_v2sf_sf_si
;
18642 if (mode0
== V8HImode
&& mode1
== HImode
)
18643 ftype
= v8hi_ftype_v8hi_hi_si
;
18647 if (mode0
== V4SImode
&& mode1
== SImode
)
18648 ftype
= v4si_ftype_v4si_si_si
;
18652 if (mode0
== V4SFmode
&& mode1
== SFmode
)
18653 ftype
= v4sf_ftype_v4sf_sf_si
;
18657 gcc_unreachable ();
18661 case NEON_SCALARMULL
:
18665 if (mode0
== V4HImode
&& mode1
== HImode
)
18666 ftype
= v4si_ftype_v4hi_hi_si
;
18670 if (mode0
== V2SImode
&& mode1
== SImode
)
18671 ftype
= v2di_ftype_v2si_si_si
;
18675 gcc_unreachable ();
18679 case NEON_SCALARMULH
:
18684 if (mode0
== V4SImode
&& mode1
== SImode
)
18685 ftype
= v4si_ftype_v4si_si_si
;
18689 if (mode0
== V8HImode
&& mode1
== HImode
)
18690 ftype
= v8hi_ftype_v8hi_hi_si
;
18694 if (mode0
== V2SImode
&& mode1
== SImode
)
18695 ftype
= v2si_ftype_v2si_si_si
;
18699 if (mode0
== V4HImode
&& mode1
== HImode
)
18700 ftype
= v4hi_ftype_v4hi_hi_si
;
18704 gcc_unreachable ();
18709 case NEON_SCALARMAC
:
18711 gcc_assert (mode2
== GET_MODE_INNER (mode1
));
18715 if (mode0
== V4HImode
&& mode1
== V4HImode
)
18716 ftype
= v4hi_ftype_v4hi_v4hi_hi_si
;
18720 if (mode0
== V2SImode
&& mode1
== V2SImode
)
18721 ftype
= v2si_ftype_v2si_v2si_si_si
;
18725 if (mode0
== V2SFmode
&& mode1
== V2SFmode
)
18726 ftype
= v2sf_ftype_v2sf_v2sf_sf_si
;
18730 if (mode0
== V8HImode
&& mode1
== V8HImode
)
18731 ftype
= v8hi_ftype_v8hi_v8hi_hi_si
;
18735 if (mode0
== V4SImode
&& mode1
== V4SImode
)
18736 ftype
= v4si_ftype_v4si_v4si_si_si
;
18737 else if (mode0
== V4SImode
&& mode1
== V4HImode
)
18738 ftype
= v4si_ftype_v4si_v4hi_hi_si
;
18742 if (mode0
== V4SFmode
&& mode1
== V4SFmode
)
18743 ftype
= v4sf_ftype_v4sf_v4sf_sf_si
;
18747 if (mode0
== V2DImode
&& mode1
== V2SImode
)
18748 ftype
= v2di_ftype_v2di_v2si_si_si
;
18752 gcc_unreachable ();
18758 gcc_assert (mode1
== mode2
18760 || (mode0
== V2SImode
&& mode1
== V2SFmode
)
18761 || (mode0
== V4SImode
&& mode1
== V4SFmode
)));
18764 case V8QImode
: ftype
= v8qi_ftype_v8qi_v8qi_v8qi
; break;
18765 case V4HImode
: ftype
= v4hi_ftype_v4hi_v4hi_v4hi
; break;
18766 case V2SImode
: ftype
= v2si_ftype_v2si_v2si_v2si
; break;
18767 case V2SFmode
: ftype
= v2sf_ftype_v2si_v2sf_v2sf
; break;
18768 /* LLVM LOCAL begin */
18769 case V1DImode
: ftype
= v1di_ftype_v1di_v1di_v1di
; break;
18770 /* LLVM LOCAL end */
18771 case V16QImode
: ftype
= v16qi_ftype_v16qi_v16qi_v16qi
; break;
18772 case V8HImode
: ftype
= v8hi_ftype_v8hi_v8hi_v8hi
; break;
18773 case V4SImode
: ftype
= v4si_ftype_v4si_v4si_v4si
; break;
18774 case V4SFmode
: ftype
= v4sf_ftype_v4si_v4sf_v4sf
; break;
18775 case V2DImode
: ftype
= v2di_ftype_v2di_v2di_v2di
; break;
18776 default: gcc_unreachable ();
18782 gcc_assert (tmode
== V8QImode
&& mode1
== V8QImode
);
18785 case V8QImode
: ftype
= v8qi_ftype_v8qi_v8qi
; break;
18786 case TImode
: ftype
= v8qi_ftype_ti_v8qi
; break;
18787 case EImode
: ftype
= v8qi_ftype_ei_v8qi
; break;
18788 case OImode
: ftype
= v8qi_ftype_oi_v8qi
; break;
18789 default: gcc_unreachable ();
18796 gcc_assert (tmode
== V8QImode
&& mode0
== V8QImode
18797 && mode2
== V8QImode
);
18800 case V8QImode
: ftype
= v8qi_ftype_v8qi_v8qi_v8qi
; break;
18801 case TImode
: ftype
= v8qi_ftype_v8qi_ti_v8qi
; break;
18802 case EImode
: ftype
= v8qi_ftype_v8qi_ei_v8qi
; break;
18803 case OImode
: ftype
= v8qi_ftype_v8qi_oi_v8qi
; break;
18804 default: gcc_unreachable ();
18809 case NEON_RESULTPAIR
:
18813 case V8QImode
: ftype
= void_ftype_pv8qi_v8qi_v8qi
; break;
18814 case V4HImode
: ftype
= void_ftype_pv4hi_v4hi_v4hi
; break;
18815 case V2SImode
: ftype
= void_ftype_pv2si_v2si_v2si
; break;
18816 case V2SFmode
: ftype
= void_ftype_pv2sf_v2sf_v2sf
; break;
18817 /* LLVM LOCAL begin */
18818 case V1DImode
: ftype
= void_ftype_pv1di_v1di_v1di
; break;
18819 /* LLVM LOCAL end */
18820 case V16QImode
: ftype
= void_ftype_pv16qi_v16qi_v16qi
; break;
18821 case V8HImode
: ftype
= void_ftype_pv8hi_v8hi_v8hi
; break;
18822 case V4SImode
: ftype
= void_ftype_pv4si_v4si_v4si
; break;
18823 case V4SFmode
: ftype
= void_ftype_pv4sf_v4sf_v4sf
; break;
18824 case V2DImode
: ftype
= void_ftype_pv2di_v2di_v2di
; break;
18825 default: gcc_unreachable ();
18830 case NEON_REINTERP
:
18832 /* We iterate over 5 doubleword types, then 5 quadword
18837 case V8QImode
: ftype
= reinterp_ftype_dreg
[0][rhs
]; break;
18838 case V4HImode
: ftype
= reinterp_ftype_dreg
[1][rhs
]; break;
18839 case V2SImode
: ftype
= reinterp_ftype_dreg
[2][rhs
]; break;
18840 case V2SFmode
: ftype
= reinterp_ftype_dreg
[3][rhs
]; break;
18841 /* LLVM LOCAL begin */
18842 case V1DImode
: ftype
= reinterp_ftype_dreg
[4][rhs
]; break;
18843 /* LLVM LOCAL end */
18844 case V16QImode
: ftype
= reinterp_ftype_qreg
[0][rhs
]; break;
18845 case V8HImode
: ftype
= reinterp_ftype_qreg
[1][rhs
]; break;
18846 case V4SImode
: ftype
= reinterp_ftype_qreg
[2][rhs
]; break;
18847 case V4SFmode
: ftype
= reinterp_ftype_qreg
[3][rhs
]; break;
18848 case V2DImode
: ftype
= reinterp_ftype_qreg
[4][rhs
]; break;
18849 default: gcc_unreachable ();
18857 case V8QImode
: ftype
= v8qi_ftype_const_qi_pointer
; break;
18858 case V4HImode
: ftype
= v4hi_ftype_const_hi_pointer
; break;
18859 case V2SImode
: ftype
= v2si_ftype_const_si_pointer
; break;
18860 case V2SFmode
: ftype
= v2sf_ftype_const_sf_pointer
; break;
18861 /* LLVM LOCAL begin */
18862 case V1DImode
: ftype
= v1di_ftype_const_di_pointer
; break;
18863 /* LLVM LOCAL end */
18864 case V16QImode
: ftype
= v16qi_ftype_const_qi_pointer
; break;
18865 case V8HImode
: ftype
= v8hi_ftype_const_hi_pointer
; break;
18866 case V4SImode
: ftype
= v4si_ftype_const_si_pointer
; break;
18867 case V4SFmode
: ftype
= v4sf_ftype_const_sf_pointer
; break;
18868 case V2DImode
: ftype
= v2di_ftype_const_di_pointer
; break;
18869 default: gcc_unreachable ();
18873 case NEON_LOAD1LANE
:
18877 ftype
= v8qi_ftype_const_qi_pointer_v8qi_si
;
18880 ftype
= v4hi_ftype_const_hi_pointer_v4hi_si
;
18883 ftype
= v2si_ftype_const_si_pointer_v2si_si
;
18886 ftype
= v2sf_ftype_const_sf_pointer_v2sf_si
;
18888 /* LLVM LOCAL begin */
18890 ftype
= v1di_ftype_const_di_pointer_v1di_si
;
18892 /* LLVM LOCAL end */
18894 ftype
= v16qi_ftype_const_qi_pointer_v16qi_si
;
18897 ftype
= v8hi_ftype_const_hi_pointer_v8hi_si
;
18900 ftype
= v4si_ftype_const_si_pointer_v4si_si
;
18903 ftype
= v4sf_ftype_const_sf_pointer_v4sf_si
;
18906 ftype
= v2di_ftype_const_di_pointer_v2di_si
;
18909 gcc_unreachable ();
18916 case V8QImode
: ftype
= void_ftype_qi_pointer_v8qi
; break;
18917 case V4HImode
: ftype
= void_ftype_hi_pointer_v4hi
; break;
18918 case V2SImode
: ftype
= void_ftype_si_pointer_v2si
; break;
18919 case V2SFmode
: ftype
= void_ftype_sf_pointer_v2sf
; break;
18920 /* LLVM LOCAL begin */
18921 case V1DImode
: ftype
= void_ftype_di_pointer_v1di
; break;
18922 /* LLVM LOCAL end */
18923 case V16QImode
: ftype
= void_ftype_qi_pointer_v16qi
; break;
18924 case V8HImode
: ftype
= void_ftype_hi_pointer_v8hi
; break;
18925 case V4SImode
: ftype
= void_ftype_si_pointer_v4si
; break;
18926 case V4SFmode
: ftype
= void_ftype_sf_pointer_v4sf
; break;
18927 case V2DImode
: ftype
= void_ftype_di_pointer_v2di
; break;
18928 default: gcc_unreachable ();
18932 case NEON_STORE1LANE
:
18935 case V8QImode
: ftype
= void_ftype_qi_pointer_v8qi_si
; break;
18936 case V4HImode
: ftype
= void_ftype_hi_pointer_v4hi_si
; break;
18937 case V2SImode
: ftype
= void_ftype_si_pointer_v2si_si
; break;
18938 case V2SFmode
: ftype
= void_ftype_sf_pointer_v2sf_si
; break;
18939 /* LLVM LOCAL begin */
18940 case V1DImode
: ftype
= void_ftype_di_pointer_v1di_si
; break;
18941 /* LLVM LOCAL end */
18942 case V16QImode
: ftype
= void_ftype_qi_pointer_v16qi_si
; break;
18943 case V8HImode
: ftype
= void_ftype_hi_pointer_v8hi_si
; break;
18944 case V4SImode
: ftype
= void_ftype_si_pointer_v4si_si
; break;
18945 case V4SFmode
: ftype
= void_ftype_sf_pointer_v4sf_si
; break;
18946 case V2DImode
: ftype
= void_ftype_di_pointer_v2di_si
; break;
18947 default: gcc_unreachable ();
18951 case NEON_LOADSTRUCT
:
18958 case T_V8QI
: ftype
= ti_ftype_const_qi_pointer
; break;
18959 case T_V4HI
: ftype
= ti_ftype_const_hi_pointer
; break;
18960 case T_V2SI
: ftype
= ti_ftype_const_si_pointer
; break;
18961 case T_V2SF
: ftype
= ti_ftype_const_sf_pointer
; break;
18962 /* LLVM LOCAL begin */
18963 case T_V1DI
: ftype
= ti_ftype_const_di_pointer
; break;
18964 /* LLVM LOCAL end */
18965 default: gcc_unreachable ();
18973 case T_V8QI
: ftype
= ei_ftype_const_qi_pointer
; break;
18974 case T_V4HI
: ftype
= ei_ftype_const_hi_pointer
; break;
18975 case T_V2SI
: ftype
= ei_ftype_const_si_pointer
; break;
18976 case T_V2SF
: ftype
= ei_ftype_const_sf_pointer
; break;
18977 /* LLVM LOCAL begin */
18978 case T_V1DI
: ftype
= ei_ftype_const_di_pointer
; break;
18979 /* LLVM LOCAL end */
18980 default: gcc_unreachable ();
18985 /* vld2q and vld4 cases. */
18989 /* LLVM LOCAL begin multi-vector types */
18990 case T_V16QI
: ftype
= oiq_ftype_const_qi_pointer
; break;
18991 case T_V8HI
: ftype
= oiq_ftype_const_hi_pointer
; break;
18992 case T_V4SI
: ftype
= oiq_ftype_const_si_pointer
; break;
18993 case T_V4SF
: ftype
= oiq_ftype_const_sf_pointer
; break;
18995 case T_V8QI
: ftype
= oid_ftype_const_qi_pointer
; break;
18996 case T_V4HI
: ftype
= oid_ftype_const_hi_pointer
; break;
18997 case T_V2SI
: ftype
= oid_ftype_const_si_pointer
; break;
18998 case T_V2SF
: ftype
= oid_ftype_const_sf_pointer
; break;
18999 /* LLVM LOCAL end multi-vector types */
19000 /* LLVM LOCAL begin */
19001 case T_V1DI
: ftype
= oi_ftype_const_di_pointer
; break;
19002 /* LLVM LOCAL end */
19003 default: gcc_unreachable ();
19011 case T_V16QI
: ftype
= ci_ftype_const_qi_pointer
; break;
19012 case T_V8HI
: ftype
= ci_ftype_const_hi_pointer
; break;
19013 case T_V4SI
: ftype
= ci_ftype_const_si_pointer
; break;
19014 case T_V4SF
: ftype
= ci_ftype_const_sf_pointer
; break;
19015 default: gcc_unreachable ();
19023 case T_V16QI
: ftype
= xi_ftype_const_qi_pointer
; break;
19024 case T_V8HI
: ftype
= xi_ftype_const_hi_pointer
; break;
19025 case T_V4SI
: ftype
= xi_ftype_const_si_pointer
; break;
19026 case T_V4SF
: ftype
= xi_ftype_const_sf_pointer
; break;
19027 default: gcc_unreachable ();
19032 gcc_unreachable ();
19036 case NEON_LOADSTRUCTLANE
:
19040 /* vld2_lane cases. */
19044 ftype
= ti_ftype_const_qi_pointer_ti_si
;
19047 ftype
= ti_ftype_const_hi_pointer_ti_si
;
19050 ftype
= ti_ftype_const_si_pointer_ti_si
;
19053 ftype
= ti_ftype_const_sf_pointer_ti_si
;
19056 gcc_unreachable ();
19061 /* vld3_lane cases. */
19065 ftype
= ei_ftype_const_qi_pointer_ei_si
;
19068 ftype
= ei_ftype_const_hi_pointer_ei_si
;
19071 ftype
= ei_ftype_const_si_pointer_ei_si
;
19074 ftype
= ei_ftype_const_sf_pointer_ei_si
;
19077 gcc_unreachable ();
19082 /* vld2q_lane and vld4_lane cases. */
19085 /* vld2q_lane cases. */
19086 /* LLVM LOCAL begin multi-vector types */
19088 ftype
= oiq_ftype_const_hi_pointer_oiq_si
;
19091 ftype
= oiq_ftype_const_si_pointer_oiq_si
;
19094 ftype
= oiq_ftype_const_sf_pointer_oiq_si
;
19096 /* vld4_lane cases. */
19098 ftype
= oi_ftype_const_qi_pointer_oi_si
;
19101 ftype
= oid_ftype_const_hi_pointer_oid_si
;
19104 ftype
= oid_ftype_const_si_pointer_oid_si
;
19107 ftype
= oid_ftype_const_sf_pointer_oid_si
;
19109 /* LLVM LOCAL end multi-vector types */
19111 gcc_unreachable ();
19116 /* vld3q_lane cases. */
19120 ftype
= ci_ftype_const_hi_pointer_ci_si
;
19123 ftype
= ci_ftype_const_si_pointer_ci_si
;
19126 ftype
= ci_ftype_const_sf_pointer_ci_si
;
19129 gcc_unreachable ();
19134 /* vld4q_lane cases. */
19138 ftype
= xi_ftype_const_hi_pointer_xi_si
;
19141 ftype
= xi_ftype_const_si_pointer_xi_si
;
19144 ftype
= xi_ftype_const_sf_pointer_xi_si
;
19147 gcc_unreachable ();
19152 gcc_unreachable ();
19157 case NEON_STORESTRUCT
:
19164 case T_V8QI
: ftype
= void_ftype_qi_pointer_ti
; break;
19165 case T_V4HI
: ftype
= void_ftype_hi_pointer_ti
; break;
19166 case T_V2SI
: ftype
= void_ftype_si_pointer_ti
; break;
19167 case T_V2SF
: ftype
= void_ftype_sf_pointer_ti
; break;
19168 /* LLVM LOCAL begin */
19169 case T_V1DI
: ftype
= void_ftype_di_pointer_ti
; break;
19170 /* LLVM LOCAL end */
19171 default: gcc_unreachable ();
19179 case T_V8QI
: ftype
= void_ftype_qi_pointer_ei
; break;
19180 case T_V4HI
: ftype
= void_ftype_hi_pointer_ei
; break;
19181 case T_V2SI
: ftype
= void_ftype_si_pointer_ei
; break;
19182 case T_V2SF
: ftype
= void_ftype_sf_pointer_ei
; break;
19183 /* LLVM LOCAL begin */
19184 case T_V1DI
: ftype
= void_ftype_di_pointer_ei
; break;
19185 /* LLVM LOCAL end */
19186 default: gcc_unreachable ();
19191 /* vst2q and vst4 cases. */
19195 /* LLVM LOCAL begin multi-vector types */
19196 case T_V16QI
: ftype
= void_ftype_qi_pointer_oiq
; break;
19197 case T_V8HI
: ftype
= void_ftype_hi_pointer_oiq
; break;
19198 case T_V4SI
: ftype
= void_ftype_si_pointer_oiq
; break;
19199 case T_V4SF
: ftype
= void_ftype_sf_pointer_oiq
; break;
19201 case T_V8QI
: ftype
= void_ftype_qi_pointer_oid
; break;
19202 case T_V4HI
: ftype
= void_ftype_hi_pointer_oid
; break;
19203 case T_V2SI
: ftype
= void_ftype_si_pointer_oid
; break;
19204 case T_V2SF
: ftype
= void_ftype_sf_pointer_oid
; break;
19205 /* LLVM LOCAL end multi-vector types */
19206 /* LLVM LOCAL begin */
19207 case T_V1DI
: ftype
= void_ftype_di_pointer_oi
; break;
19208 /* LLVM LOCAL end */
19209 default: gcc_unreachable ();
19217 case T_V16QI
: ftype
= void_ftype_qi_pointer_ci
; break;
19218 case T_V8HI
: ftype
= void_ftype_hi_pointer_ci
; break;
19219 case T_V4SI
: ftype
= void_ftype_si_pointer_ci
; break;
19220 case T_V4SF
: ftype
= void_ftype_sf_pointer_ci
; break;
19221 default: gcc_unreachable ();
19229 case T_V16QI
: ftype
= void_ftype_qi_pointer_xi
; break;
19230 case T_V8HI
: ftype
= void_ftype_hi_pointer_xi
; break;
19231 case T_V4SI
: ftype
= void_ftype_si_pointer_xi
; break;
19232 case T_V4SF
: ftype
= void_ftype_sf_pointer_xi
; break;
19233 default: gcc_unreachable ();
19238 gcc_unreachable ();
19242 case NEON_STORESTRUCTLANE
:
19246 /* vst2_lane cases. */
19250 ftype
= void_ftype_qi_pointer_ti_si
;
19253 ftype
= void_ftype_hi_pointer_ti_si
;
19256 ftype
= void_ftype_si_pointer_ti_si
;
19259 ftype
= void_ftype_sf_pointer_ti_si
;
19262 gcc_unreachable ();
19267 /* vst3_lane cases. */
19271 ftype
= void_ftype_qi_pointer_ei_si
;
19274 ftype
= void_ftype_hi_pointer_ei_si
;
19277 ftype
= void_ftype_si_pointer_ei_si
;
19280 ftype
= void_ftype_sf_pointer_ei_si
;
19283 gcc_unreachable ();
19288 /* vst2q_lane and vst4_lane cases. */
19291 /* vst2q_lane cases. */
19292 /* LLVM LOCAL begin multi-vector types */
19294 ftype
= void_ftype_hi_pointer_oiq_si
;
19297 ftype
= void_ftype_si_pointer_oiq_si
;
19300 ftype
= void_ftype_sf_pointer_oiq_si
;
19302 /* vst4_lane cases. */
19304 ftype
= void_ftype_qi_pointer_oi_si
;
19307 ftype
= void_ftype_hi_pointer_oid_si
;
19310 ftype
= void_ftype_si_pointer_oid_si
;
19313 ftype
= void_ftype_sf_pointer_oid_si
;
19315 /* LLVM LOCAL end multi-vector types */
19317 gcc_unreachable ();
19322 /* vst3q_lane cases. */
19326 ftype
= void_ftype_hi_pointer_ci_si
;
19329 ftype
= void_ftype_si_pointer_ci_si
;
19332 ftype
= void_ftype_sf_pointer_ci_si
;
19335 gcc_unreachable ();
19340 /* vst4q_lane cases. */
19344 ftype
= void_ftype_hi_pointer_xi_si
;
19347 ftype
= void_ftype_si_pointer_xi_si
;
19350 ftype
= void_ftype_sf_pointer_xi_si
;
19353 gcc_unreachable ();
19358 gcc_unreachable ();
19363 gcc_unreachable ();
19366 gcc_assert (ftype
!= NULL
);
19368 sprintf (namebuf
, "__builtin_neon_%s%s", d
->name
, modenames
[j
]);
19370 lang_hooks
.builtin_function (namebuf
, ftype
, fcode
++, BUILT_IN_MD
,
19419 arm_init_builtins (void)
19421 arm_init_tls_builtins ();
19423 if (TARGET_REALLY_IWMMXT
)
19424 arm_init_iwmmxt_builtins ();
19427 arm_init_neon_builtins ();
19428 /* APPLE LOCAL begin ARM darwin builtins */
19429 #ifdef SUBTARGET_INIT_BUILTINS
19430 SUBTARGET_INIT_BUILTINS
;
19432 /* APPLE LOCAL end ARM darwin builtins */
19434 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
19436 /* Errors in the source file can cause expand_expr to return const0_rtx
19437 where we expect a vector. To avoid crashing, use one of the vector
19438 clear instructions. */
19441 safe_vector_operand (rtx x
, enum machine_mode mode
)
19443 if (x
!= const0_rtx
)
19445 x
= gen_reg_rtx (mode
);
19447 emit_insn (gen_iwmmxt_clrdi (mode
== DImode
? x
19448 : gen_rtx_SUBREG (DImode
, x
, 0)));
19452 /* Subroutine of arm_expand_builtin to take care of binop insns. */
19455 arm_expand_binop_builtin (enum insn_code icode
,
19456 tree arglist
, rtx target
)
19459 tree arg0
= TREE_VALUE (arglist
);
19460 tree arg1
= TREE_VALUE (TREE_CHAIN (arglist
));
19461 rtx op0
= expand_normal (arg0
);
19462 rtx op1
= expand_normal (arg1
);
19463 enum machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
19464 enum machine_mode mode0
= insn_data
[icode
].operand
[1].mode
;
19465 enum machine_mode mode1
= insn_data
[icode
].operand
[2].mode
;
19467 if (VECTOR_MODE_P (mode0
))
19468 op0
= safe_vector_operand (op0
, mode0
);
19469 if (VECTOR_MODE_P (mode1
))
19470 op1
= safe_vector_operand (op1
, mode1
);
19473 || GET_MODE (target
) != tmode
19474 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
19475 target
= gen_reg_rtx (tmode
);
19477 gcc_assert (GET_MODE (op0
) == mode0
&& GET_MODE (op1
) == mode1
);
19479 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
19480 op0
= copy_to_mode_reg (mode0
, op0
);
19481 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
19482 op1
= copy_to_mode_reg (mode1
, op1
);
19484 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
19491 /* Subroutine of arm_expand_builtin to take care of unop insns. */
19494 arm_expand_unop_builtin (enum insn_code icode
,
19495 tree arglist
, rtx target
, int do_load
)
19498 tree arg0
= TREE_VALUE (arglist
);
19499 rtx op0
= expand_normal (arg0
);
19500 enum machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
19501 enum machine_mode mode0
= insn_data
[icode
].operand
[1].mode
;
19504 || GET_MODE (target
) != tmode
19505 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
19506 target
= gen_reg_rtx (tmode
);
19508 op0
= gen_rtx_MEM (mode0
, copy_to_mode_reg (Pmode
, op0
));
19511 if (VECTOR_MODE_P (mode0
))
19512 op0
= safe_vector_operand (op0
, mode0
);
19514 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
19515 op0
= copy_to_mode_reg (mode0
, op0
);
19518 pat
= GEN_FCN (icode
) (target
, op0
);
19525 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
19527 neon_builtin_compare (const void *a
, const void *b
)
19529 const neon_builtin_datum
*key
= a
;
19530 const neon_builtin_datum
*memb
= b
;
19531 unsigned int soughtcode
= key
->base_fcode
;
19533 if (soughtcode
>= memb
->base_fcode
19534 && soughtcode
< memb
->base_fcode
+ memb
->num_vars
)
19536 else if (soughtcode
< memb
->base_fcode
)
19542 /* LLVM LOCAL begin
19543 Added neon_code argument below and made the function
19544 non-static. This is needed when translating Neon builtins to LLVM. */
19545 extern enum insn_code
19546 locate_neon_builtin_icode (int, neon_itype
*, enum neon_builtins
*);
19549 locate_neon_builtin_icode (int fcode
, neon_itype
*itype
,
19550 enum neon_builtins
*neon_code
)
19551 /* LLVM LOCAL end */
19553 neon_builtin_datum key
, *found
;
19556 key
.base_fcode
= fcode
;
19557 found
= bsearch (&key
, &neon_builtin_data
[0], ARRAY_SIZE (neon_builtin_data
),
19558 sizeof (neon_builtin_data
[0]), neon_builtin_compare
);
19559 gcc_assert (found
);
19560 idx
= fcode
- (int) found
->base_fcode
;
19561 gcc_assert (idx
>= 0 && idx
< T_MAX
&& idx
< (int)found
->num_vars
);
19564 *itype
= found
->itype
;
19566 /* LLVM LOCAL begin */
19568 *neon_code
= found
->neon_code
;
19569 /* LLVM LOCAL end */
19571 return found
->codes
[idx
];
19575 NEON_ARG_COPY_TO_REG
,
19580 #define NEON_MAX_BUILTIN_ARGS 5
19582 /* Expand a Neon builtin. */
19584 arm_expand_neon_args (rtx target
, int icode
, int have_retval
,
19589 tree arg
[NEON_MAX_BUILTIN_ARGS
];
19590 rtx op
[NEON_MAX_BUILTIN_ARGS
];
19591 enum machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
19592 enum machine_mode mode
[NEON_MAX_BUILTIN_ARGS
];
19597 || GET_MODE (target
) != tmode
19598 || !(*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
)))
19599 target
= gen_reg_rtx (tmode
);
19601 va_start (ap
, arglist
);
19605 builtin_arg thisarg
= va_arg (ap
, int);
19607 if (thisarg
== NEON_ARG_STOP
)
19611 arg
[argc
] = TREE_VALUE (arglist
);
19612 op
[argc
] = expand_expr (arg
[argc
], NULL_RTX
, VOIDmode
, 0);
19613 mode
[argc
] = insn_data
[icode
].operand
[argc
+ have_retval
].mode
;
19615 arglist
= TREE_CHAIN (arglist
);
19619 case NEON_ARG_COPY_TO_REG
:
19620 /*gcc_assert (GET_MODE (op[argc]) == mode[argc]);*/
19621 if (!(*insn_data
[icode
].operand
[argc
+ have_retval
].predicate
)
19622 (op
[argc
], mode
[argc
]))
19623 op
[argc
] = copy_to_mode_reg (mode
[argc
], op
[argc
]);
19626 case NEON_ARG_CONSTANT
:
19627 /* FIXME: This error message is somewhat unhelpful. */
19628 if (!(*insn_data
[icode
].operand
[argc
+ have_retval
].predicate
)
19629 (op
[argc
], mode
[argc
]))
19630 error ("argument must be a constant");
19633 case NEON_ARG_STOP
:
19634 gcc_unreachable ();
19647 pat
= GEN_FCN (icode
) (target
, op
[0]);
19651 pat
= GEN_FCN (icode
) (target
, op
[0], op
[1]);
19655 pat
= GEN_FCN (icode
) (target
, op
[0], op
[1], op
[2]);
19659 pat
= GEN_FCN (icode
) (target
, op
[0], op
[1], op
[2], op
[3]);
19663 pat
= GEN_FCN (icode
) (target
, op
[0], op
[1], op
[2], op
[3], op
[4]);
19667 gcc_unreachable ();
19673 pat
= GEN_FCN (icode
) (op
[0]);
19677 pat
= GEN_FCN (icode
) (op
[0], op
[1]);
19681 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2]);
19685 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2], op
[3]);
19689 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2], op
[3], op
[4]);
19693 gcc_unreachable ();
19704 /* Expand a Neon builtin. These are "special" because they don't have symbolic
19705 constants defined per-instruction or per instruction-variant. Instead, the
19706 required info is looked up in the table neon_builtin_data. */
19708 arm_expand_neon_builtin (rtx target
, int fcode
, tree arglist
)
19711 /* LLVM LOCAL Added 0 argument to following call. */
19712 enum insn_code icode
= locate_neon_builtin_icode (fcode
, &itype
, 0);
19719 return arm_expand_neon_args (target
, icode
, 1, arglist
,
19720 NEON_ARG_COPY_TO_REG
, NEON_ARG_CONSTANT
, NEON_ARG_STOP
);
19724 case NEON_SCALARMUL
:
19725 case NEON_SCALARMULL
:
19726 case NEON_SCALARMULH
:
19727 case NEON_SHIFTINSERT
:
19728 case NEON_LOGICBINOP
:
19729 return arm_expand_neon_args (target
, icode
, 1, arglist
,
19730 NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
, NEON_ARG_CONSTANT
,
19734 return arm_expand_neon_args (target
, icode
, 1, arglist
,
19735 NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
,
19736 NEON_ARG_CONSTANT
, NEON_ARG_STOP
);
19740 case NEON_SHIFTIMM
:
19741 return arm_expand_neon_args (target
, icode
, 1, arglist
,
19742 NEON_ARG_COPY_TO_REG
, NEON_ARG_CONSTANT
, NEON_ARG_CONSTANT
,
19746 return arm_expand_neon_args (target
, icode
, 1, arglist
,
19747 NEON_ARG_COPY_TO_REG
, NEON_ARG_STOP
);
19751 case NEON_REINTERP
:
19752 return arm_expand_neon_args (target
, icode
, 1, arglist
,
19753 NEON_ARG_COPY_TO_REG
, NEON_ARG_STOP
);
19757 return arm_expand_neon_args (target
, icode
, 1, arglist
,
19758 NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
, NEON_ARG_STOP
);
19760 case NEON_RESULTPAIR
:
19761 return arm_expand_neon_args (target
, icode
, 0, arglist
,
19762 NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
,
19766 case NEON_LANEMULL
:
19767 case NEON_LANEMULH
:
19768 return arm_expand_neon_args (target
, icode
, 1, arglist
,
19769 NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
, NEON_ARG_CONSTANT
,
19770 NEON_ARG_CONSTANT
, NEON_ARG_STOP
);
19773 return arm_expand_neon_args (target
, icode
, 1, arglist
,
19774 NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
,
19775 NEON_ARG_CONSTANT
, NEON_ARG_CONSTANT
, NEON_ARG_STOP
);
19777 case NEON_SHIFTACC
:
19778 return arm_expand_neon_args (target
, icode
, 1, arglist
,
19779 NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
, NEON_ARG_CONSTANT
,
19780 NEON_ARG_CONSTANT
, NEON_ARG_STOP
);
19782 case NEON_SCALARMAC
:
19783 return arm_expand_neon_args (target
, icode
, 1, arglist
,
19784 NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
,
19785 NEON_ARG_CONSTANT
, NEON_ARG_STOP
);
19789 return arm_expand_neon_args (target
, icode
, 1, arglist
,
19790 NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
,
19794 case NEON_LOADSTRUCT
:
19795 return arm_expand_neon_args (target
, icode
, 1, arglist
,
19796 NEON_ARG_COPY_TO_REG
, NEON_ARG_STOP
);
19798 case NEON_LOAD1LANE
:
19799 case NEON_LOADSTRUCTLANE
:
19800 return arm_expand_neon_args (target
, icode
, 1, arglist
,
19801 NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
, NEON_ARG_CONSTANT
,
19805 case NEON_STORESTRUCT
:
19806 return arm_expand_neon_args (target
, icode
, 0, arglist
,
19807 NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
, NEON_ARG_STOP
);
19809 case NEON_STORE1LANE
:
19810 case NEON_STORESTRUCTLANE
:
19811 return arm_expand_neon_args (target
, icode
, 0, arglist
,
19812 NEON_ARG_COPY_TO_REG
, NEON_ARG_COPY_TO_REG
, NEON_ARG_CONSTANT
,
19816 gcc_unreachable ();
19819 /* Emit code to reinterpret one Neon type as another, without altering bits. */
19821 neon_reinterpret (rtx dest
, rtx src
)
19823 emit_move_insn (dest
, gen_lowpart (GET_MODE (dest
), src
));
19826 /* Emit code to place a Neon pair result in memory locations (with equal
19829 neon_emit_pair_result_insn (enum machine_mode mode
,
19830 rtx (*intfn
) (rtx
, rtx
, rtx
, rtx
), rtx destaddr
,
19833 rtx mem
= gen_rtx_MEM (mode
, destaddr
);
19834 rtx tmp1
= gen_reg_rtx (mode
);
19835 rtx tmp2
= gen_reg_rtx (mode
);
19837 emit_insn (intfn (tmp1
, op1
, tmp2
, op2
));
19839 emit_move_insn (mem
, tmp1
);
19840 mem
= adjust_address (mem
, mode
, GET_MODE_SIZE (mode
));
19841 emit_move_insn (mem
, tmp2
);
19844 /* Set up operands for a register copy from src to dest, taking care not to
19845 clobber registers in the process.
19846 FIXME: This has rather high polynomial complexity (O(n^3)?) but shouldn't
19847 be called with a large N, so that should be OK. */
19850 neon_disambiguate_copy (rtx
*operands
, rtx
*dest
, rtx
*src
, unsigned int count
)
19852 unsigned int copied
= 0, opctr
= 0;
19853 unsigned int done
= (1 << count
) - 1;
19856 while (copied
!= done
)
19858 for (i
= 0; i
< count
; i
++)
19862 for (j
= 0; good
&& j
< count
; j
++)
19863 if (i
!= j
&& (copied
& (1 << j
)) == 0
19864 && reg_overlap_mentioned_p (src
[j
], dest
[i
]))
19869 operands
[opctr
++] = dest
[i
];
19870 operands
[opctr
++] = src
[i
];
19876 gcc_assert (opctr
== count
* 2);
19879 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
19880 /* Expand an expression EXP that calls a built-in function,
19881 with result going to TARGET if that's convenient
19882 (and in mode MODE if that's convenient).
19883 SUBTARGET may be used as the target for computing one of EXP's operands.
19884 IGNORE is nonzero if the value is to be ignored. */
19887 arm_expand_builtin (tree exp
,
19889 rtx subtarget ATTRIBUTE_UNUSED
,
19890 enum machine_mode mode ATTRIBUTE_UNUSED
,
19891 int ignore ATTRIBUTE_UNUSED
)
19893 const struct builtin_description
* d
;
19894 enum insn_code icode
;
19895 tree fndecl
= TREE_OPERAND (TREE_OPERAND (exp
, 0), 0);
19896 tree arglist
= TREE_OPERAND (exp
, 1);
19904 int fcode
= DECL_FUNCTION_CODE (fndecl
);
19906 enum machine_mode tmode
;
19907 enum machine_mode mode0
;
19908 enum machine_mode mode1
;
19909 enum machine_mode mode2
;
19911 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
19912 if (fcode
>= ARM_BUILTIN_NEON_BASE
)
19913 return arm_expand_neon_builtin (target
, fcode
, arglist
);
19915 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
19918 case ARM_BUILTIN_TEXTRMSB
:
19919 case ARM_BUILTIN_TEXTRMUB
:
19920 case ARM_BUILTIN_TEXTRMSH
:
19921 case ARM_BUILTIN_TEXTRMUH
:
19922 case ARM_BUILTIN_TEXTRMSW
:
19923 case ARM_BUILTIN_TEXTRMUW
:
19924 icode
= (fcode
== ARM_BUILTIN_TEXTRMSB
? CODE_FOR_iwmmxt_textrmsb
19925 : fcode
== ARM_BUILTIN_TEXTRMUB
? CODE_FOR_iwmmxt_textrmub
19926 : fcode
== ARM_BUILTIN_TEXTRMSH
? CODE_FOR_iwmmxt_textrmsh
19927 : fcode
== ARM_BUILTIN_TEXTRMUH
? CODE_FOR_iwmmxt_textrmuh
19928 : CODE_FOR_iwmmxt_textrmw
);
19930 arg0
= TREE_VALUE (arglist
);
19931 arg1
= TREE_VALUE (TREE_CHAIN (arglist
));
19932 op0
= expand_normal (arg0
);
19933 op1
= expand_normal (arg1
);
19934 tmode
= insn_data
[icode
].operand
[0].mode
;
19935 mode0
= insn_data
[icode
].operand
[1].mode
;
19936 mode1
= insn_data
[icode
].operand
[2].mode
;
19938 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
19939 op0
= copy_to_mode_reg (mode0
, op0
);
19940 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
19942 /* @@@ better error message */
19943 error ("selector must be an immediate");
19944 return gen_reg_rtx (tmode
);
19947 || GET_MODE (target
) != tmode
19948 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
19949 target
= gen_reg_rtx (tmode
);
19950 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
19956 case ARM_BUILTIN_TINSRB
:
19957 case ARM_BUILTIN_TINSRH
:
19958 case ARM_BUILTIN_TINSRW
:
19959 icode
= (fcode
== ARM_BUILTIN_TINSRB
? CODE_FOR_iwmmxt_tinsrb
19960 : fcode
== ARM_BUILTIN_TINSRH
? CODE_FOR_iwmmxt_tinsrh
19961 : CODE_FOR_iwmmxt_tinsrw
);
19962 arg0
= TREE_VALUE (arglist
);
19963 arg1
= TREE_VALUE (TREE_CHAIN (arglist
));
19964 arg2
= TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist
)));
19965 op0
= expand_normal (arg0
);
19966 op1
= expand_normal (arg1
);
19967 op2
= expand_normal (arg2
);
19968 tmode
= insn_data
[icode
].operand
[0].mode
;
19969 mode0
= insn_data
[icode
].operand
[1].mode
;
19970 mode1
= insn_data
[icode
].operand
[2].mode
;
19971 mode2
= insn_data
[icode
].operand
[3].mode
;
19973 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
19974 op0
= copy_to_mode_reg (mode0
, op0
);
19975 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
19976 op1
= copy_to_mode_reg (mode1
, op1
);
19977 if (! (*insn_data
[icode
].operand
[3].predicate
) (op2
, mode2
))
19979 /* @@@ better error message */
19980 error ("selector must be an immediate");
19984 || GET_MODE (target
) != tmode
19985 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
19986 target
= gen_reg_rtx (tmode
);
19987 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
19993 case ARM_BUILTIN_SETWCX
:
19994 arg0
= TREE_VALUE (arglist
);
19995 arg1
= TREE_VALUE (TREE_CHAIN (arglist
));
19996 op0
= force_reg (SImode
, expand_normal (arg0
));
19997 op1
= expand_normal (arg1
);
19998 emit_insn (gen_iwmmxt_tmcr (op1
, op0
));
20001 case ARM_BUILTIN_GETWCX
:
20002 arg0
= TREE_VALUE (arglist
);
20003 op0
= expand_normal (arg0
);
20004 target
= gen_reg_rtx (SImode
);
20005 emit_insn (gen_iwmmxt_tmrc (target
, op0
));
20008 case ARM_BUILTIN_WSHUFH
:
20009 icode
= CODE_FOR_iwmmxt_wshufh
;
20010 arg0
= TREE_VALUE (arglist
);
20011 arg1
= TREE_VALUE (TREE_CHAIN (arglist
));
20012 op0
= expand_normal (arg0
);
20013 op1
= expand_normal (arg1
);
20014 tmode
= insn_data
[icode
].operand
[0].mode
;
20015 mode1
= insn_data
[icode
].operand
[1].mode
;
20016 mode2
= insn_data
[icode
].operand
[2].mode
;
20018 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode1
))
20019 op0
= copy_to_mode_reg (mode1
, op0
);
20020 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode2
))
20022 /* @@@ better error message */
20023 error ("mask must be an immediate");
20027 || GET_MODE (target
) != tmode
20028 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
20029 target
= gen_reg_rtx (tmode
);
20030 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
20036 case ARM_BUILTIN_WSADB
:
20037 return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadb
, arglist
, target
);
20038 case ARM_BUILTIN_WSADH
:
20039 return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadh
, arglist
, target
);
20040 case ARM_BUILTIN_WSADBZ
:
20041 return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadbz
, arglist
, target
);
20042 case ARM_BUILTIN_WSADHZ
:
20043 return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadhz
, arglist
, target
);
20045 /* Several three-argument builtins. */
20046 case ARM_BUILTIN_WMACS
:
20047 case ARM_BUILTIN_WMACU
:
20048 case ARM_BUILTIN_WALIGN
:
20049 case ARM_BUILTIN_TMIA
:
20050 case ARM_BUILTIN_TMIAPH
:
20051 case ARM_BUILTIN_TMIATT
:
20052 case ARM_BUILTIN_TMIATB
:
20053 case ARM_BUILTIN_TMIABT
:
20054 case ARM_BUILTIN_TMIABB
:
20055 icode
= (fcode
== ARM_BUILTIN_WMACS
? CODE_FOR_iwmmxt_wmacs
20056 : fcode
== ARM_BUILTIN_WMACU
? CODE_FOR_iwmmxt_wmacu
20057 : fcode
== ARM_BUILTIN_TMIA
? CODE_FOR_iwmmxt_tmia
20058 : fcode
== ARM_BUILTIN_TMIAPH
? CODE_FOR_iwmmxt_tmiaph
20059 : fcode
== ARM_BUILTIN_TMIABB
? CODE_FOR_iwmmxt_tmiabb
20060 : fcode
== ARM_BUILTIN_TMIABT
? CODE_FOR_iwmmxt_tmiabt
20061 : fcode
== ARM_BUILTIN_TMIATB
? CODE_FOR_iwmmxt_tmiatb
20062 : fcode
== ARM_BUILTIN_TMIATT
? CODE_FOR_iwmmxt_tmiatt
20063 : CODE_FOR_iwmmxt_walign
);
20064 arg0
= TREE_VALUE (arglist
);
20065 arg1
= TREE_VALUE (TREE_CHAIN (arglist
));
20066 arg2
= TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist
)));
20067 op0
= expand_normal (arg0
);
20068 op1
= expand_normal (arg1
);
20069 op2
= expand_normal (arg2
);
20070 tmode
= insn_data
[icode
].operand
[0].mode
;
20071 mode0
= insn_data
[icode
].operand
[1].mode
;
20072 mode1
= insn_data
[icode
].operand
[2].mode
;
20073 mode2
= insn_data
[icode
].operand
[3].mode
;
20075 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
20076 op0
= copy_to_mode_reg (mode0
, op0
);
20077 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
20078 op1
= copy_to_mode_reg (mode1
, op1
);
20079 if (! (*insn_data
[icode
].operand
[3].predicate
) (op2
, mode2
))
20080 op2
= copy_to_mode_reg (mode2
, op2
);
20082 || GET_MODE (target
) != tmode
20083 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
20084 target
= gen_reg_rtx (tmode
);
20085 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
20091 case ARM_BUILTIN_WZERO
:
20092 target
= gen_reg_rtx (DImode
);
20093 emit_insn (gen_iwmmxt_clrdi (target
));
20096 case ARM_BUILTIN_THREAD_POINTER
:
20097 return arm_load_tp (target
);
20103 for (i
= 0, d
= bdesc_2arg
; i
< ARRAY_SIZE (bdesc_2arg
); i
++, d
++)
20104 if (d
->code
== (const enum arm_builtins
) fcode
)
20105 return arm_expand_binop_builtin (d
->icode
, arglist
, target
);
20107 for (i
= 0, d
= bdesc_1arg
; i
< ARRAY_SIZE (bdesc_1arg
); i
++, d
++)
20108 if (d
->code
== (const enum arm_builtins
) fcode
)
20109 return arm_expand_unop_builtin (d
->icode
, arglist
, target
, 0);
20111 /* @@@ Should really do something sensible here. */
20115 /* Return the number (counting from 0) of
20116 the least significant set bit in MASK. */
20119 number_of_first_bit_set (unsigned mask
)
20124 (mask
& (1 << bit
)) == 0;
20131 /* APPLE LOCAL begin ARM compact switch tables */
20132 /* Handle push or pop of registers from the stack.
20133 If EMIT is true, generate the code.
20134 If EMIT is false, compute and return the number of bytes that
20135 would result from a call with EMIT true. In this case F is
20136 not necessarily valid and should not be referenced.
20138 F is the assembly file. MASK is the registers to push or pop. PUSH is
20139 nonzero if we should push, and zero if we should pop. For debugging
20140 output, if pushing, adjust CFA_OFFSET by the amount of space added
20141 to the stack. REAL_REGS should have the same number of bits set as
20142 MASK, and will be used instead (in the same order) to describe which
20143 registers were saved - this is used to mark the save slots when we
20144 push high registers after moving them to low registers.
20147 handle_thumb_pushpop (FILE *f
, unsigned long mask
, int push
, int *cfa_offset
,
20148 unsigned long real_regs
, bool emit
)
20151 int lo_mask
= mask
& 0xFF;
20152 int pushed_words
= 0;
20157 if (lo_mask
== 0 && !push
&& (mask
& (1 << PC_REGNUM
)))
20159 /* Special case. Do not generate a POP PC statement here, do it in
20161 return handle_thumb_exit (f
, -1, emit
);
20164 if (ARM_EABI_UNWIND_TABLES
&& push
&& emit
)
20166 fprintf (f
, "\t.save\t{");
20167 for (regno
= 0; regno
< 15; regno
++)
20169 if (real_regs
& (1 << regno
))
20171 if (real_regs
& ((1 << regno
) -1))
20173 asm_fprintf (f
, "%r", regno
);
20176 fprintf (f
, "}\n");
20181 fprintf (f
, "\t%s\t{", push
? "push" : "pop");
20183 /* Look at the low registers first. */
20184 for (regno
= 0; regno
<= LAST_LO_REGNUM
; regno
++, lo_mask
>>= 1)
20190 asm_fprintf (f
, "%r", regno
);
20192 if ((lo_mask
& ~1) != 0)
20200 if (push
&& (mask
& (1 << LR_REGNUM
)))
20202 /* Catch pushing the LR. */
20208 asm_fprintf (f
, "%r", LR_REGNUM
);
20213 else if (!push
&& (mask
& (1 << PC_REGNUM
)))
20215 /* Catch popping the PC. */
20216 /* APPLE LOCAL begin ARM interworking */
20217 if ((TARGET_INTERWORK
&& !arm_arch5
)
20218 || TARGET_BACKTRACE
20219 || current_function_calls_eh_return
)
20220 /* APPLE LOCAL end ARM interworking */
20222 /* The PC is never poped directly, instead
20223 it is popped into r3 and then BX is used. */
20225 fprintf (f
, "}\n");
20227 bytes
+= handle_thumb_exit (f
, -1, emit
);
20236 asm_fprintf (f
, "%r", PC_REGNUM
);
20241 fprintf (f
, "}\n");
20243 if (emit
&& push
&& pushed_words
&& dwarf2out_do_frame ())
20245 char *l
= dwarf2out_cfi_label ();
20246 int pushed_mask
= real_regs
;
20248 *cfa_offset
+= pushed_words
* 4;
20249 dwarf2out_def_cfa (l
, SP_REGNUM
, *cfa_offset
);
20252 pushed_mask
= real_regs
;
20253 for (regno
= 0; regno
<= 14; regno
++, pushed_mask
>>= 1)
20255 if (pushed_mask
& 1)
20256 dwarf2out_reg_save (l
, regno
, 4 * pushed_words
++ - *cfa_offset
);
20262 /* Handle return from a thumb function.
20263 If EMIT is true, generate the code.
20264 If EMIT is false, compute and return the number of bytes that
20265 would result from a call with EMIT true. In this case F is
20266 not necessarily valid and should not be referenced.
20267 If 'reg_containing_return_addr' is -1, then the return address is
20268 actually on the stack, at the stack pointer.
20271 handle_thumb_exit (FILE *f
, int reg_containing_return_addr
, bool emit
)
20273 unsigned regs_available_for_popping
;
20274 unsigned regs_to_pop
;
20276 unsigned available
;
20280 int restore_a4
= FALSE
;
20283 /* Compute the registers we need to pop. */
20287 if (reg_containing_return_addr
== -1)
20289 regs_to_pop
|= 1 << LR_REGNUM
;
20293 if (TARGET_BACKTRACE
)
20295 /* Restore the (ARM) frame pointer and stack pointer. */
20296 regs_to_pop
|= (1 << ARM_HARD_FRAME_POINTER_REGNUM
) | (1 << SP_REGNUM
);
20300 /* If there is nothing to pop then just emit the BX instruction and
20302 if (pops_needed
== 0)
20304 if (current_function_calls_eh_return
)
20308 asm_fprintf (f
, "\tadd\t%r, %r\n", SP_REGNUM
, ARM_EH_STACKADJ_REGNUM
);
20313 asm_fprintf (f
, "\tbx\t%r\n", reg_containing_return_addr
);
20317 /* Otherwise if we are not supporting interworking and we have not created
20318 a backtrace structure and the function was not entered in ARM mode then
20319 just pop the return address straight into the PC. */
20320 /* APPLE LOCAL ARM interworking */
20321 else if ((!TARGET_INTERWORK
|| arm_arch5
)
20322 && !TARGET_BACKTRACE
20323 && !is_called_in_ARM_mode (current_function_decl
)
20324 && !current_function_calls_eh_return
)
20328 asm_fprintf (f
, "\tpop\t{%r}\n", PC_REGNUM
);
20332 /* Find out how many of the (return) argument registers we can corrupt. */
20333 regs_available_for_popping
= 0;
20335 /* If returning via __builtin_eh_return, the bottom three registers
20336 all contain information needed for the return. */
20337 if (current_function_calls_eh_return
)
20341 /* If we can deduce the registers used from the function's
20342 return value. This is more reliable that examining
20343 regs_ever_live[] because that will be set if the register is
20344 ever used in the function, not just if the register is used
20345 to hold a return value. */
20347 if (current_function_return_rtx
!= 0)
20348 mode
= GET_MODE (current_function_return_rtx
);
20350 mode
= DECL_MODE (DECL_RESULT (current_function_decl
));
20352 size
= GET_MODE_SIZE (mode
);
20356 /* In a void function we can use any argument register.
20357 In a function that returns a structure on the stack
20358 we can use the second and third argument registers. */
20359 if (mode
== VOIDmode
)
20360 regs_available_for_popping
=
20361 (1 << ARG_REGISTER (1))
20362 | (1 << ARG_REGISTER (2))
20363 | (1 << ARG_REGISTER (3));
20365 regs_available_for_popping
=
20366 (1 << ARG_REGISTER (2))
20367 | (1 << ARG_REGISTER (3));
20369 else if (size
<= 4)
20370 regs_available_for_popping
=
20371 (1 << ARG_REGISTER (2))
20372 | (1 << ARG_REGISTER (3));
20373 else if (size
<= 8)
20374 regs_available_for_popping
=
20375 (1 << ARG_REGISTER (3));
20378 /* Match registers to be popped with registers into which we pop them. */
20379 for (available
= regs_available_for_popping
,
20380 required
= regs_to_pop
;
20381 required
!= 0 && available
!= 0;
20382 available
&= ~(available
& - available
),
20383 required
&= ~(required
& - required
))
20386 /* If we have any popping registers left over, remove them. */
20388 regs_available_for_popping
&= ~available
;
20390 /* Otherwise if we need another popping register we can use
20391 the fourth argument register. */
20392 else if (pops_needed
)
20394 /* If we have not found any free argument registers and
20395 reg a4 contains the return address, we must move it. */
20396 if (regs_available_for_popping
== 0
20397 && reg_containing_return_addr
== LAST_ARG_REGNUM
)
20401 asm_fprintf (f
, "\tmov\t%r, %r\n", LR_REGNUM
, LAST_ARG_REGNUM
);
20402 reg_containing_return_addr
= LR_REGNUM
;
20404 else if (size
> 12)
20406 /* Register a4 is being used to hold part of the return value,
20407 but we have dire need of a free, low register. */
20412 asm_fprintf (f
, "\tmov\t%r, %r\n",IP_REGNUM
, LAST_ARG_REGNUM
);
20415 if (reg_containing_return_addr
!= LAST_ARG_REGNUM
)
20417 /* The fourth argument register is available. */
20418 regs_available_for_popping
|= 1 << LAST_ARG_REGNUM
;
20424 /* Pop as many registers as we can. */
20425 bytes
+= handle_thumb_pushpop (f
, regs_available_for_popping
, FALSE
, NULL
,
20426 regs_available_for_popping
, emit
);
20428 /* Process the registers we popped. */
20429 if (reg_containing_return_addr
== -1)
20431 /* The return address was popped into the lowest numbered register. */
20432 regs_to_pop
&= ~(1 << LR_REGNUM
);
20434 reg_containing_return_addr
=
20435 number_of_first_bit_set (regs_available_for_popping
);
20437 /* Remove this register for the mask of available registers, so that
20438 the return address will not be corrupted by further pops. */
20439 regs_available_for_popping
&= ~(1 << reg_containing_return_addr
);
20442 /* If we popped other registers then handle them here. */
20443 if (regs_available_for_popping
)
20447 /* Work out which register currently contains the frame pointer. */
20448 frame_pointer
= number_of_first_bit_set (regs_available_for_popping
);
20450 /* Move it into the correct place. */
20453 asm_fprintf (f
, "\tmov\t%r, %r\n",
20454 ARM_HARD_FRAME_POINTER_REGNUM
, frame_pointer
);
20456 /* (Temporarily) remove it from the mask of popped registers. */
20457 regs_available_for_popping
&= ~(1 << frame_pointer
);
20458 regs_to_pop
&= ~(1 << ARM_HARD_FRAME_POINTER_REGNUM
);
20460 if (regs_available_for_popping
)
20464 /* We popped the stack pointer as well,
20465 find the register that contains it. */
20466 stack_pointer
= number_of_first_bit_set (regs_available_for_popping
);
20468 /* Move it into the stack register. */
20471 asm_fprintf (f
, "\tmov\t%r, %r\n", SP_REGNUM
, stack_pointer
);
20473 /* At this point we have popped all necessary registers, so
20474 do not worry about restoring regs_available_for_popping
20475 to its correct value:
20477 assert (pops_needed == 0)
20478 assert (regs_available_for_popping == (1 << frame_pointer))
20479 assert (regs_to_pop == (1 << STACK_POINTER)) */
20483 /* Since we have just move the popped value into the frame
20484 pointer, the popping register is available for reuse, and
20485 we know that we still have the stack pointer left to pop. */
20486 regs_available_for_popping
|= (1 << frame_pointer
);
20490 /* If we still have registers left on the stack, but we no longer have
20491 any registers into which we can pop them, then we must move the return
20492 address into the link register and make available the register that
20494 if (regs_available_for_popping
== 0 && pops_needed
> 0)
20496 regs_available_for_popping
|= 1 << reg_containing_return_addr
;
20500 asm_fprintf (f
, "\tmov\t%r, %r\n", LR_REGNUM
,
20501 reg_containing_return_addr
);
20503 reg_containing_return_addr
= LR_REGNUM
;
20506 /* If we have registers left on the stack then pop some more.
20507 We know that at most we will want to pop FP and SP. */
20508 if (pops_needed
> 0)
20513 bytes
+= handle_thumb_pushpop (f
, regs_available_for_popping
, FALSE
, NULL
,
20514 regs_available_for_popping
, emit
);
20516 /* We have popped either FP or SP.
20517 Move whichever one it is into the correct register. */
20518 popped_into
= number_of_first_bit_set (regs_available_for_popping
);
20519 move_to
= number_of_first_bit_set (regs_to_pop
);
20523 asm_fprintf (f
, "\tmov\t%r, %r\n", move_to
, popped_into
);
20525 regs_to_pop
&= ~(1 << move_to
);
20530 /* If we still have not popped everything then we must have only
20531 had one register available to us and we are now popping the SP. */
20532 if (pops_needed
> 0)
20536 bytes
+= handle_thumb_pushpop (f
, regs_available_for_popping
, FALSE
, NULL
,
20537 regs_available_for_popping
, emit
);
20539 popped_into
= number_of_first_bit_set (regs_available_for_popping
);
20543 asm_fprintf (f
, "\tmov\t%r, %r\n", SP_REGNUM
, popped_into
);
20545 assert (regs_to_pop == (1 << STACK_POINTER))
20546 assert (pops_needed == 1)
20550 /* If necessary restore the a4 register. */
20553 if (reg_containing_return_addr
!= LR_REGNUM
)
20557 asm_fprintf (f
, "\tmov\t%r, %r\n", LR_REGNUM
, LAST_ARG_REGNUM
);
20558 reg_containing_return_addr
= LR_REGNUM
;
20563 asm_fprintf (f
, "\tmov\t%r, %r\n", LAST_ARG_REGNUM
, IP_REGNUM
);
20566 if (current_function_calls_eh_return
)
20570 asm_fprintf (f
, "\tadd\t%r, %r\n", SP_REGNUM
, ARM_EH_STACKADJ_REGNUM
);
20573 /* Return to caller. */
20576 asm_fprintf (f
, "\tbx\t%r\n", reg_containing_return_addr
);
20579 /* APPLE LOCAL end ARM compact switch tables */
20583 /* APPLE LOCAL v7 support. Merge from mainline */
20584 thumb1_final_prescan_insn (rtx insn
)
20586 if (flag_print_asm_name
)
20587 asm_fprintf (asm_out_file
, "%@ 0x%04x\n",
20588 INSN_ADDRESSES (INSN_UID (insn
)));
20592 thumb_shiftable_const (unsigned HOST_WIDE_INT val
)
20594 unsigned HOST_WIDE_INT mask
= 0xff;
20597 if (val
== 0) /* XXX */
20600 for (i
= 0; i
< 25; i
++)
20601 if ((val
& (mask
<< i
)) == val
)
20607 /* Returns nonzero if the current function contains,
20608 or might contain a far jump. */
20610 thumb_far_jump_used_p (void)
20612 /* LLVM LOCAL begin */
20616 /* LLVM LOCAL end */
20619 /* This test is only important for leaf functions. */
20620 /* assert (!leaf_function_p ()); */
20622 /* If we have already decided that far jumps may be used,
20623 do not bother checking again, and always return true even if
20624 it turns out that they are not being used. Once we have made
20625 the decision that far jumps are present (and that hence the link
20626 register will be pushed onto the stack) we cannot go back on it. */
20627 if (cfun
->machine
->far_jump_used
)
20630 /* If this function is not being called from the prologue/epilogue
20631 generation code then it must be being called from the
20632 INITIAL_ELIMINATION_OFFSET macro. */
20633 if (!(ARM_DOUBLEWORD_ALIGN
|| reload_completed
))
20635 /* In this case we know that we are being asked about the elimination
20636 of the arg pointer register. If that register is not being used,
20637 then there are no arguments on the stack, and we do not have to
20638 worry that a far jump might force the prologue to push the link
20639 register, changing the stack offsets. In this case we can just
20640 return false, since the presence of far jumps in the function will
20641 not affect stack offsets.
20643 If the arg pointer is live (or if it was live, but has now been
20644 eliminated and so set to dead) then we do have to test to see if
20645 the function might contain a far jump. This test can lead to some
20646 false negatives, since before reload is completed, then length of
20647 branch instructions is not known, so gcc defaults to returning their
20648 longest length, which in turn sets the far jump attribute to true.
20650 A false negative will not result in bad code being generated, but it
20651 will result in a needless push and pop of the link register. We
20652 hope that this does not occur too often.
20654 If we need doubleword stack alignment this could affect the other
20655 elimination offsets so we can't risk getting it wrong. */
20656 if (regs_ever_live
[ARG_POINTER_REGNUM
])
20657 cfun
->machine
->arg_pointer_live
= 1;
20658 else if (!cfun
->machine
->arg_pointer_live
)
20662 /* Check to see if the function contains a branch
20663 insn with the far jump attribute set. */
20664 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
20666 if (GET_CODE (insn
) == JUMP_INSN
20667 /* Ignore tablejump patterns. */
20668 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
20669 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
20670 && get_attr_far_jump (insn
) == FAR_JUMP_YES
20673 /* Record the fact that we have decided that
20674 the function does use far jumps. */
20675 cfun
->machine
->far_jump_used
= 1;
20685 /* Return nonzero if FUNC must be entered in ARM mode. */
20687 is_called_in_ARM_mode (tree func
)
20689 gcc_assert (TREE_CODE (func
) == FUNCTION_DECL
);
20691 /* Ignore the problem about functions whose address is taken. */
20692 if (TARGET_CALLEE_INTERWORKING
&& TREE_PUBLIC (func
))
20696 return lookup_attribute ("interfacearm", DECL_ATTRIBUTES (func
)) != NULL_TREE
;
20702 /* APPLE LOCAL begin ARM compact switch tables */
20703 /* This handles the part of the epilogue that is not expressed as RTL.
20704 It computes and returns the number of bytes in this part of the epilogue.
20705 When EMIT is true, it additionally outputs this part of the epilogue.
20706 When !EMIT, this function does not output anything; in this case
20707 F need not be valid and should not be referenced.
20710 handle_thumb_unexpanded_epilogue (bool emit
)
20713 unsigned long live_regs_mask
= 0;
20714 int high_regs_pushed
= 0;
20715 int had_to_push_lr
;
20719 if (return_used_this_function
)
20722 if (IS_NAKED (arm_current_func_type ()))
20725 /* APPLE LOCAL begin 6465387 exception handling interworking VFP save */
20726 if (current_function_has_nonlocal_label
&& arm_arch6
)
20730 asm_fprintf (asm_out_file
, "\tblx ___restore_vfp_d8_d15_regs\n");
20732 /* APPLE LOCAL end 6465387 exception handling interworking VFP save */
20734 /* APPLE LOCAL v7 support. Merge from mainline */
20735 live_regs_mask
= thumb1_compute_save_reg_mask ();
20736 high_regs_pushed
= bit_count (live_regs_mask
& 0x0f00);
20738 /* If we can deduce the registers used from the function's return value.
20739 This is more reliable that examining regs_ever_live[] because that
20740 will be set if the register is ever used in the function, not just if
20741 the register is used to hold a return value. */
20742 size
= arm_size_return_regs ();
20744 /* The prolog may have pushed some high registers to use as
20745 work registers. e.g. the testsuite file:
20746 gcc/testsuite/gcc/gcc.c-torture/execute/complex-2.c
20747 compiles to produce:
20748 push {r4, r5, r6, r7, lr}
20752 as part of the prolog. We have to undo that pushing here. */
20754 if (high_regs_pushed
)
20756 unsigned long mask
= live_regs_mask
& 0xff;
20759 /* The available low registers depend on the size of the value we are
20767 /* Oh dear! We have no low registers into which we can pop
20770 ("no low registers available for popping high registers");
20772 for (next_hi_reg
= 8; next_hi_reg
< 13; next_hi_reg
++)
20773 if (live_regs_mask
& (1 << next_hi_reg
))
20776 while (high_regs_pushed
)
20778 /* Find lo register(s) into which the high register(s) can
20780 for (regno
= 0; regno
<= LAST_LO_REGNUM
; regno
++)
20782 if (mask
& (1 << regno
))
20783 high_regs_pushed
--;
20784 if (high_regs_pushed
== 0)
20788 mask
&= (2 << regno
) - 1; /* A noop if regno == 8 */
20790 /* Pop the values into the low register(s). */
20791 bytes
+= handle_thumb_pushpop (asm_out_file
, mask
, 0, NULL
, mask
, emit
);
20793 /* Move the value(s) into the high registers. */
20794 for (regno
= 0; regno
<= LAST_LO_REGNUM
; regno
++)
20796 if (mask
& (1 << regno
))
20800 asm_fprintf (asm_out_file
, "\tmov\t%r, %r\n", next_hi_reg
,
20803 for (next_hi_reg
++; next_hi_reg
< 13; next_hi_reg
++)
20804 if (live_regs_mask
& (1 << next_hi_reg
))
20809 live_regs_mask
&= ~0x0f00;
20812 had_to_push_lr
= (live_regs_mask
& (1 << LR_REGNUM
)) != 0;
20813 live_regs_mask
&= 0xff;
20815 if (current_function_pretend_args_size
== 0 || TARGET_BACKTRACE
)
20817 /* Pop the return address into the PC. */
20818 if (had_to_push_lr
)
20819 live_regs_mask
|= 1 << PC_REGNUM
;
20821 /* Either no argument registers were pushed or a backtrace
20822 structure was created which includes an adjusted stack
20823 pointer, so just pop everything. */
20824 if (live_regs_mask
)
20825 bytes
+= handle_thumb_pushpop (asm_out_file
, live_regs_mask
, FALSE
, NULL
,
20826 live_regs_mask
, emit
);
20828 /* We have either just popped the return address into the
20829 PC or it is was kept in LR for the entire function. */
20830 if (!had_to_push_lr
)
20831 bytes
+= handle_thumb_exit (asm_out_file
, LR_REGNUM
, emit
);
20835 /* Pop everything but the return address. */
20836 if (live_regs_mask
)
20837 bytes
+= handle_thumb_pushpop (asm_out_file
, live_regs_mask
, FALSE
, NULL
,
20838 live_regs_mask
, emit
);
20840 if (had_to_push_lr
)
20844 /* We have no free low regs, so save one. */
20847 asm_fprintf (asm_out_file
, "\tmov\t%r, %r\n", IP_REGNUM
,
20851 /* Get the return address into a temporary register. */
20852 bytes
+= handle_thumb_pushpop (asm_out_file
, 1 << LAST_ARG_REGNUM
, 0, NULL
,
20853 1 << LAST_ARG_REGNUM
, emit
);
20860 /* Move the return address to lr. */
20861 asm_fprintf (asm_out_file
, "\tmov\t%r, %r\n", LR_REGNUM
,
20863 /* Restore the low register. */
20864 asm_fprintf (asm_out_file
, "\tmov\t%r, %r\n", LAST_ARG_REGNUM
,
20870 regno
= LAST_ARG_REGNUM
;
20875 /* Remove the argument registers that were pushed onto the stack. */
20878 asm_fprintf (asm_out_file
, "\tadd\t%r, %r, #%d\n",
20879 SP_REGNUM
, SP_REGNUM
,
20880 current_function_pretend_args_size
);
20882 bytes
+= handle_thumb_exit (asm_out_file
, regno
, emit
);
20888 /* This is the externally visible entry point for generating code for the
20889 part of the epilogue that is not stored as RTL. This is just a wrapper
20890 around the previous, with the correct externally imposed interface. */
20892 const char * thumb_unexpanded_epilogue (void)
20894 (void) handle_thumb_unexpanded_epilogue (true);
20897 /* APPLE LOCAL end ARM compact switch tables */
20899 /* Functions to save and restore machine-specific function data. */
20900 static struct machine_function
*
20901 arm_init_machine_status (void)
20903 struct machine_function
*machine
;
20904 machine
= (machine_function
*) ggc_alloc_cleared (sizeof (machine_function
));
20906 #if ARM_FT_UNKNOWN != 0
20907 machine
->func_type
= ARM_FT_UNKNOWN
;
20912 /* Return an RTX indicating where the return address to the
20913 calling function can be found. */
20914 /* APPLE LOCAL begin ARM reliable backtraces */
20916 arm_return_addr (int count
, rtx frame
)
20919 return gen_rtx_MEM (Pmode
, plus_constant (frame
, 4));
20921 return get_hard_reg_initial_val (Pmode
, LR_REGNUM
);
20923 /* APPLE LOCAL end ARM reliable backtraces */
20925 /* Do anything needed before RTL is emitted for each function. */
20927 arm_init_expanders (void)
20929 /* Arrange to initialize and mark the machine per-function status. */
20930 init_machine_status
= arm_init_machine_status
;
20932 /* This is to stop the combine pass optimizing away the alignment
20933 adjustment of va_arg. */
20934 /* ??? It is claimed that this should not be necessary. */
20936 mark_reg_pointer (arg_pointer_rtx
, PARM_BOUNDARY
);
20940 /* Like arm_compute_initial_elimination offset. Simpler because there
20941 isn't an ABI specified frame pointer for Thumb. Instead, we set it
20942 to point at the base of the local variables after static stack
20943 space for a function has been allocated. */
20946 thumb_compute_initial_elimination_offset (unsigned int from
, unsigned int to
)
20948 arm_stack_offsets
*offsets
;
20950 offsets
= arm_get_frame_offsets ();
20954 case ARG_POINTER_REGNUM
:
20957 case STACK_POINTER_REGNUM
:
20958 return offsets
->outgoing_args
- offsets
->saved_args
;
20960 case FRAME_POINTER_REGNUM
:
20961 return offsets
->soft_frame
- offsets
->saved_args
;
20963 /* APPLE LOCAL begin ARM custom frame layout */
20964 case HARD_FRAME_POINTER_REGNUM
:
20965 return offsets
->frame
- offsets
->saved_args
;
20966 /* APPLE LOCAL end ARM custom frame layout */
20969 gcc_unreachable ();
20973 case FRAME_POINTER_REGNUM
:
20976 case STACK_POINTER_REGNUM
:
20977 return offsets
->outgoing_args
- offsets
->soft_frame
;
20979 /* APPLE LOCAL begin ARM custom frame layout */
20980 case HARD_FRAME_POINTER_REGNUM
:
20981 return offsets
->frame
- offsets
->soft_frame
;
20982 /* APPLE LOCAL end ARM custom frame layout */
20985 gcc_unreachable ();
20990 gcc_unreachable ();
20995 /* Generate the rest of a function's prologue. */
20997 /* APPLE LOCAL v7 support. Merge from mainline */
20998 thumb1_expand_prologue (void)
21002 HOST_WIDE_INT amount
;
21003 arm_stack_offsets
*offsets
;
21004 unsigned long func_type
;
21006 unsigned long live_regs_mask
;
21008 func_type
= arm_current_func_type ();
21010 /* Naked functions don't have prologues. */
21011 if (IS_NAKED (func_type
))
21014 if (IS_INTERRUPT (func_type
))
21016 error ("interrupt Service Routines cannot be coded in Thumb mode");
21020 /* APPLE LOCAL v7 support. Merge from mainline */
21021 live_regs_mask
= thumb1_compute_save_reg_mask ();
21022 /* Load the pic register before setting the frame pointer,
21023 so we can use r7 as a temporary work register. */
21024 if (flag_pic
&& arm_pic_register
!= INVALID_REGNUM
)
21025 arm_load_pic_register (live_regs_mask
);
21027 /* APPLE LOCAL begin ARM custom frame layout */
21028 offsets
= arm_get_frame_offsets ();
21030 if (frame_pointer_needed
)
21032 insn
= emit_insn (gen_addsi3 (hard_frame_pointer_rtx
,
21034 GEN_INT (offsets
->saved_regs
21035 - offsets
->frame
)));
21036 RTX_FRAME_RELATED_P (insn
) = 1;
21038 else if (CALLER_INTERWORKING_SLOT_SIZE
> 0)
21040 emit_move_insn (gen_rtx_REG (Pmode
, ARM_HARD_FRAME_POINTER_REGNUM
),
21041 stack_pointer_rtx
);
21043 /* APPLE LOCAL end ARM custom frame layout */
21045 amount
= offsets
->outgoing_args
- offsets
->saved_regs
;
21050 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
21051 GEN_INT (- amount
)));
21052 RTX_FRAME_RELATED_P (insn
) = 1;
21058 /* The stack decrement is too big for an immediate value in a single
21059 insn. In theory we could issue multiple subtracts, but after
21060 three of them it becomes more space efficient to place the full
21061 value in the constant pool and load into a register. (Also the
21062 ARM debugger really likes to see only one stack decrement per
21063 function). So instead we look for a scratch register into which
21064 we can load the decrement, and then we subtract this from the
21065 stack pointer. Unfortunately on the thumb the only available
21066 scratch registers are the argument registers, and we cannot use
21067 these as they may hold arguments to the function. Instead we
21068 attempt to locate a call preserved register which is used by this
21069 function. If we can find one, then we know that it will have
21070 been pushed at the start of the prologue and so we can corrupt
21072 for (regno
= LAST_ARG_REGNUM
+ 1; regno
<= LAST_LO_REGNUM
; regno
++)
21073 if (live_regs_mask
& (1 << regno
)
21074 && !(frame_pointer_needed
21075 && (regno
== THUMB_HARD_FRAME_POINTER_REGNUM
)))
21078 if (regno
> LAST_LO_REGNUM
) /* Very unlikely. */
21080 rtx spare
= gen_rtx_REG (SImode
, IP_REGNUM
);
21082 /* Choose an arbitrary, non-argument low register. */
21083 /* APPLE LOCAL ARM custom frame layout */
21084 reg
= gen_rtx_REG (SImode
, LAST_LO_REGNUM
- 1);
21086 /* Save it by copying it into a high, scratch register. */
21087 emit_insn (gen_movsi (spare
, reg
));
21088 /* Add a USE to stop propagate_one_insn() from barfing. */
21089 emit_insn (gen_prologue_use (spare
));
21091 /* Decrement the stack. */
21092 emit_insn (gen_movsi (reg
, GEN_INT (- amount
)));
21093 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
,
21094 stack_pointer_rtx
, reg
));
21095 RTX_FRAME_RELATED_P (insn
) = 1;
21096 dwarf
= gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
21097 plus_constant (stack_pointer_rtx
,
21099 RTX_FRAME_RELATED_P (dwarf
) = 1;
21101 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR
, dwarf
,
21104 /* Restore the low register's original value. */
21105 emit_insn (gen_movsi (reg
, spare
));
21107 /* Emit a USE of the restored scratch register, so that flow
21108 analysis will not consider the restore redundant. The
21109 register won't be used again in this function and isn't
21110 restored by the epilogue. */
21111 emit_insn (gen_prologue_use (reg
));
21115 reg
= gen_rtx_REG (SImode
, regno
);
21117 emit_insn (gen_movsi (reg
, GEN_INT (- amount
)));
21119 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
,
21120 stack_pointer_rtx
, reg
));
21121 RTX_FRAME_RELATED_P (insn
) = 1;
21122 dwarf
= gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
21123 plus_constant (stack_pointer_rtx
,
21125 RTX_FRAME_RELATED_P (dwarf
) = 1;
21127 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR
, dwarf
,
21133 /* APPLE LOCAL begin ARM custom frame layout */
21134 /* Removed lines. */
21135 /* APPLE LOCAL end ARM custom frame layout */
21137 /* If we are profiling, make sure no instructions are scheduled before
21138 the call to mcount. Similarly if the user has requested no
21139 scheduling in the prolog. Similarly if we want non-call exceptions
21140 using the EABI unwinder, to prevent faulting instructions from being
21141 swapped with a stack adjustment. */
21142 if (current_function_profile
|| !TARGET_SCHED_PROLOG
21143 || (ARM_EABI_UNWIND_TABLES
&& flag_non_call_exceptions
))
21144 emit_insn (gen_blockage ());
21146 cfun
->machine
->lr_save_eliminated
= !thumb_force_lr_save ();
21147 if (live_regs_mask
& 0xff)
21148 cfun
->machine
->lr_save_eliminated
= 0;
21150 /* If the link register is being kept alive, with the return address in it,
21151 then make sure that it does not get reused by the ce2 pass. */
21152 if (cfun
->machine
->lr_save_eliminated
)
21153 emit_insn (gen_prologue_use (gen_rtx_REG (SImode
, LR_REGNUM
)));
21158 /* APPLE LOCAL v7 support. Merge from mainline */
21159 thumb1_expand_epilogue (void)
21161 HOST_WIDE_INT amount
;
21162 arm_stack_offsets
*offsets
;
21165 /* Naked functions don't have prologues. */
21166 if (IS_NAKED (arm_current_func_type ()))
21169 offsets
= arm_get_frame_offsets ();
21170 amount
= offsets
->outgoing_args
- offsets
->saved_regs
;
21172 /* APPLE LOCAL begin ARM custom frame layout */
21173 /* Because popping the stack frame using the frame pointer is so much
21174 more expensive than just popping it from the SP, only use the FP
21175 when we must -- i.e., when we don't know the SP offset because it
21176 has changed since the beginning of the function. */
21177 if (! current_function_sp_is_unchanging
)
21179 int fp_offset
= offsets
->frame
- offsets
->saved_regs
;
21183 /* r3 is always free in the epilogue. */
21184 rtx reg
= gen_rtx_REG (SImode
, LAST_ARG_REGNUM
);
21186 emit_insn (gen_movsi (reg
, hard_frame_pointer_rtx
));
21187 emit_insn (gen_addsi3 (reg
, reg
, GEN_INT (fp_offset
)));
21188 emit_insn (gen_movsi (stack_pointer_rtx
, reg
));
21192 emit_insn (gen_movsi (stack_pointer_rtx
,
21193 hard_frame_pointer_rtx
));
21197 /* APPLE LOCAL end ARM custom frame layout */
21200 emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
21201 GEN_INT (amount
)));
21204 /* r3 is always free in the epilogue. */
21205 rtx reg
= gen_rtx_REG (SImode
, LAST_ARG_REGNUM
);
21207 emit_insn (gen_movsi (reg
, GEN_INT (amount
)));
21208 emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
, reg
));
21212 /* Emit a USE (stack_pointer_rtx), so that
21213 the stack adjustment will not be deleted. */
21214 emit_insn (gen_prologue_use (stack_pointer_rtx
));
21216 if (current_function_profile
|| !TARGET_SCHED_PROLOG
)
21217 emit_insn (gen_blockage ());
21219 /* Emit a clobber for each insn that will be restored in the epilogue,
21220 so that flow2 will get register lifetimes correct. */
21221 for (regno
= 0; regno
< 13; regno
++)
21222 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
21223 emit_insn (gen_rtx_CLOBBER (VOIDmode
, gen_rtx_REG (SImode
, regno
)));
21225 if (! regs_ever_live
[LR_REGNUM
])
21226 emit_insn (gen_rtx_USE (VOIDmode
, gen_rtx_REG (SImode
, LR_REGNUM
)));
21229 /* APPLE LOCAL begin ARM 4790140 compact switch tables */
21230 /* This handles the part of the prologue that is not expressed as RTL.
21231 It computes and returns the number of bytes in this part of the prologue.
21232 When EMIT is true, it additionally outputs this part of the prologue.
21233 When !EMIT, this function does not output anything; in this case
21234 F need not be valid and should not be referenced.
21237 handle_thumb_unexpanded_prologue (FILE *f
, bool emit
)
21239 unsigned long live_regs_mask
= 0;
21240 unsigned long l_mask
;
21241 unsigned high_regs_pushed
= 0;
21242 int cfa_offset
= 0;
21246 if (IS_NAKED (arm_current_func_type ()))
21249 if (is_called_in_ARM_mode (current_function_decl
))
21253 gcc_assert (GET_CODE (DECL_RTL (current_function_decl
)) == MEM
);
21254 gcc_assert (GET_CODE (XEXP (DECL_RTL (current_function_decl
), 0))
21261 name
= XSTR (XEXP (DECL_RTL (current_function_decl
), 0), 0);
21263 /* Generate code sequence to switch us into Thumb mode. */
21264 /* The .code 32 directive has already been emitted by
21265 ASM_DECLARE_FUNCTION_NAME. */
21266 asm_fprintf (f
, "\torr\t%r, %r, #1\n", IP_REGNUM
, PC_REGNUM
);
21267 asm_fprintf (f
, "\tbx\t%r\n", IP_REGNUM
);
21269 /* Generate a label, so that the debugger will notice the
21270 change in instruction sets. This label is also used by
21271 the assembler to bypass the ARM code when this function
21272 is called from a Thumb encoded function elsewhere in the
21273 same file. Hence the definition of STUB_NAME here must
21274 agree with the definition in gas/config/tc-arm.c. */
21276 #define STUB_NAME ".real_start_of"
21278 fprintf (f
, "\t.code\t16\n");
21280 if (arm_dllexport_name_p (name
))
21281 name
= arm_strip_name_encoding (name
);
21283 asm_fprintf (f
, "\t.globl %s%U%s\n", STUB_NAME
, name
);
21284 /* APPLE LOCAL begin ARM thumb_func <symbol_name> */
21286 asm_fprintf (f
, "\t.thumb_func %s%U%s\n", STUB_NAME
, name
);
21288 fprintf (f
, "\t.thumb_func\n");
21289 /* APPLE LOCAL end ARM thumb_func <symbol_name> */
21291 asm_fprintf (f
, "%s%U%s:\n", STUB_NAME
, name
);
21295 if (current_function_pretend_args_size
)
21297 /* Output unwind directive for the stack adjustment. */
21298 if (emit
&& ARM_EABI_UNWIND_TABLES
)
21299 fprintf (f
, "\t.pad #%d\n",
21300 current_function_pretend_args_size
);
21304 if (cfun
->machine
->uses_anonymous_args
)
21308 fprintf (f
, "\tpush\t{");
21310 num_pushes
= ARM_NUM_INTS (current_function_pretend_args_size
);
21312 for (regno
= LAST_ARG_REGNUM
+ 1 - num_pushes
;
21313 regno
<= LAST_ARG_REGNUM
;
21315 asm_fprintf (f
, "%r%s", regno
,
21316 regno
== LAST_ARG_REGNUM
? "" : ", ");
21318 fprintf (f
, "}\n");
21321 asm_fprintf (f
, "\tsub\t%r, %r, #%d\n",
21322 SP_REGNUM
, SP_REGNUM
,
21323 current_function_pretend_args_size
);
21326 /* We don't need to record the stores for unwinding (would it
21327 help the debugger any if we did?), but record the change in
21328 the stack pointer. */
21329 if (emit
&& dwarf2out_do_frame ())
21331 char *l
= dwarf2out_cfi_label ();
21333 cfa_offset
= cfa_offset
+ current_function_pretend_args_size
;
21334 dwarf2out_def_cfa (l
, SP_REGNUM
, cfa_offset
);
21338 /* Get the registers we are going to push. */
21339 /* APPLE LOCAL v7 support. Merge from mainline */
21340 live_regs_mask
= thumb1_compute_save_reg_mask ();
21341 /* Extract a mask of the ones we can give to the Thumb's push instruction. */
21342 l_mask
= live_regs_mask
& 0x40ff;
21343 /* Then count how many other high registers will need to be pushed. */
21344 high_regs_pushed
= bit_count (live_regs_mask
& 0x0f00);
21346 if (TARGET_BACKTRACE
)
21349 unsigned work_register
;
21351 /* We have been asked to create a stack backtrace structure.
21352 The code looks like this:
21356 0 sub SP, #16 Reserve space for 4 registers.
21357 2 push {R7} Push low registers.
21358 4 add R7, SP, #20 Get the stack pointer before the push.
21359 6 str R7, [SP, #8] Store the stack pointer (before reserving the space).
21360 8 mov R7, PC Get hold of the start of this code plus 12.
21361 10 str R7, [SP, #16] Store it.
21362 12 mov R7, FP Get hold of the current frame pointer.
21363 14 str R7, [SP, #4] Store it.
21364 16 mov R7, LR Get hold of the current return address.
21365 18 str R7, [SP, #12] Store it.
21366 20 add R7, SP, #16 Point at the start of the backtrace structure.
21367 22 mov FP, R7 Put this value into the frame pointer. */
21369 work_register
= thumb_find_work_register (live_regs_mask
);
21371 if (emit
&& ARM_EABI_UNWIND_TABLES
)
21372 asm_fprintf (f
, "\t.pad #16\n");
21377 (f
, "\tsub\t%r, %r, #16\t%@ Create stack backtrace structure\n",
21378 SP_REGNUM
, SP_REGNUM
);
21380 if (emit
&& dwarf2out_do_frame ())
21382 char *l
= dwarf2out_cfi_label ();
21384 cfa_offset
= cfa_offset
+ 16;
21385 dwarf2out_def_cfa (l
, SP_REGNUM
, cfa_offset
);
21390 bytes
+= handle_thumb_pushpop (f
, l_mask
, 1, &cfa_offset
, l_mask
, emit
);
21391 offset
= bit_count (l_mask
) * UNITS_PER_WORD
;
21399 asm_fprintf (f
, "\tadd\t%r, %r, #%d\n", work_register
, SP_REGNUM
,
21400 offset
+ 16 + current_function_pretend_args_size
);
21402 asm_fprintf (f
, "\tstr\t%r, [%r, #%d]\n", work_register
, SP_REGNUM
,
21409 /* Make sure that the instruction fetching the PC is in the right place
21410 to calculate "start of backtrace creation code + 12". */
21413 asm_fprintf (f
, "\tmov\t%r, %r\n", work_register
, PC_REGNUM
);
21414 asm_fprintf (f
, "\tstr\t%r, [%r, #%d]\n", work_register
, SP_REGNUM
,
21416 asm_fprintf (f
, "\tmov\t%r, %r\n", work_register
,
21417 ARM_HARD_FRAME_POINTER_REGNUM
);
21418 asm_fprintf (f
, "\tstr\t%r, [%r, #%d]\n", work_register
, SP_REGNUM
,
21423 asm_fprintf (f
, "\tmov\t%r, %r\n", work_register
,
21424 ARM_HARD_FRAME_POINTER_REGNUM
);
21425 asm_fprintf (f
, "\tstr\t%r, [%r, #%d]\n", work_register
, SP_REGNUM
,
21427 asm_fprintf (f
, "\tmov\t%r, %r\n", work_register
, PC_REGNUM
);
21428 asm_fprintf (f
, "\tstr\t%r, [%r, #%d]\n", work_register
, SP_REGNUM
,
21436 asm_fprintf (f
, "\tmov\t%r, %r\n", work_register
, LR_REGNUM
);
21437 asm_fprintf (f
, "\tstr\t%r, [%r, #%d]\n", work_register
, SP_REGNUM
,
21439 asm_fprintf (f
, "\tadd\t%r, %r, #%d\n", work_register
, SP_REGNUM
,
21441 asm_fprintf (f
, "\tmov\t%r, %r\t\t%@ Backtrace structure created\n",
21442 ARM_HARD_FRAME_POINTER_REGNUM
, work_register
);
21445 /* Optimization: If we are not pushing any low registers but we are going
21446 to push some high registers then delay our first push. This will just
21447 be a push of LR and we can combine it with the push of the first high
21449 else if ((l_mask
& 0xff) != 0
21450 || (high_regs_pushed
== 0 && l_mask
))
21451 bytes
+= handle_thumb_pushpop (f
, l_mask
, 1, &cfa_offset
, l_mask
, emit
);
21453 if (high_regs_pushed
)
21455 unsigned pushable_regs
;
21456 unsigned next_hi_reg
;
21458 for (next_hi_reg
= 12; next_hi_reg
> LAST_LO_REGNUM
; next_hi_reg
--)
21459 if (live_regs_mask
& (1 << next_hi_reg
))
21462 /* APPLE LOCAL ARM thumb requires FP */
21463 pushable_regs
= l_mask
& 0x7f;
21465 if (pushable_regs
== 0)
21466 pushable_regs
= 1 << thumb_find_work_register (live_regs_mask
);
21468 while (high_regs_pushed
> 0)
21470 unsigned long real_regs_mask
= 0;
21472 for (regno
= LAST_LO_REGNUM
; regno
>= 0; regno
--)
21474 if (pushable_regs
& (1 << regno
))
21478 asm_fprintf (f
, "\tmov\t%r, %r\n", regno
, next_hi_reg
);
21480 high_regs_pushed
--;
21481 real_regs_mask
|= (1 << next_hi_reg
);
21483 if (high_regs_pushed
)
21485 for (next_hi_reg
--; next_hi_reg
> LAST_LO_REGNUM
;
21487 if (live_regs_mask
& (1 << next_hi_reg
))
21492 pushable_regs
&= ~((1 << regno
) - 1);
21498 /* If we had to find a work register and we have not yet
21499 saved the LR then add it to the list of regs to push. */
21500 if (l_mask
== (1 << LR_REGNUM
))
21502 bytes
+= handle_thumb_pushpop
21503 (f
, pushable_regs
| (1 << LR_REGNUM
),
21505 real_regs_mask
| (1 << LR_REGNUM
), emit
);
21509 bytes
+= handle_thumb_pushpop (f
, pushable_regs
, 1, &cfa_offset
, real_regs_mask
, emit
);
21512 /* APPLE LOCAL begin 6465387 exception handling interworking VFP save */
21513 if (current_function_has_nonlocal_label
&& arm_arch6
)
21517 asm_fprintf (f
, "\tblx ___save_vfp_d8_d15_regs\n");
21519 /* APPLE LOCAL end 6465387 exception handling interworking VFP save */
21524 /* APPLE LOCAL v7 support. Merge from mainline */
21525 thumb1_output_function_prologue (FILE *f
, HOST_WIDE_INT size ATTRIBUTE_UNUSED
)
21527 (void) handle_thumb_unexpanded_prologue (f
, true);
21530 int count_thumb_unexpanded_prologue (void)
21532 return handle_thumb_unexpanded_prologue (NULL
, false);
21534 /* APPLE LOCAL end ARM compact switch tables */
21536 /* Handle the case of a double word load into a low register from
21537 a computed memory address. The computed address may involve a
21538 register which is overwritten by the load. */
21540 thumb_load_double_from_address (rtx
*operands
)
21548 gcc_assert (GET_CODE (operands
[0]) == REG
);
21549 gcc_assert (GET_CODE (operands
[1]) == MEM
);
21551 /* Get the memory address. */
21552 addr
= XEXP (operands
[1], 0);
21554 /* Work out how the memory address is computed. */
21555 switch (GET_CODE (addr
))
21558 operands
[2] = adjust_address (operands
[1], SImode
, 4);
21560 if (REGNO (operands
[0]) == REGNO (addr
))
21562 output_asm_insn ("ldr\t%H0, %2", operands
);
21563 output_asm_insn ("ldr\t%0, %1", operands
);
21567 output_asm_insn ("ldr\t%0, %1", operands
);
21568 output_asm_insn ("ldr\t%H0, %2", operands
);
21573 /* Compute <address> + 4 for the high order load. */
21574 operands
[2] = adjust_address (operands
[1], SImode
, 4);
21576 output_asm_insn ("ldr\t%0, %1", operands
);
21577 output_asm_insn ("ldr\t%H0, %2", operands
);
21581 arg1
= XEXP (addr
, 0);
21582 arg2
= XEXP (addr
, 1);
21584 if (CONSTANT_P (arg1
))
21585 base
= arg2
, offset
= arg1
;
21587 base
= arg1
, offset
= arg2
;
21589 gcc_assert (GET_CODE (base
) == REG
);
21591 /* Catch the case of <address> = <reg> + <reg> */
21592 if (GET_CODE (offset
) == REG
)
21594 /* APPLE LOCAL begin ARM compact switch tables */
21595 /* thumb_legitimate_address_p won't allow this form,
21596 and allowing a 3-instruction variant confuses
21597 our instruction length counts, so remove it.
21598 Details in rdar://5435967. */
21600 /* APPLE LOCAL end ARM compact switch tables */
21604 /* Compute <address> + 4 for the high order load. */
21605 operands
[2] = adjust_address (operands
[1], SImode
, 4);
21607 /* If the computed address is held in the low order register
21608 then load the high order register first, otherwise always
21609 load the low order register first. */
21610 if (REGNO (operands
[0]) == REGNO (base
))
21612 output_asm_insn ("ldr\t%H0, %2", operands
);
21613 output_asm_insn ("ldr\t%0, %1", operands
);
21617 output_asm_insn ("ldr\t%0, %1", operands
);
21618 output_asm_insn ("ldr\t%H0, %2", operands
);
21624 /* With no registers to worry about we can just load the value
21626 operands
[2] = adjust_address (operands
[1], SImode
, 4);
21628 output_asm_insn ("ldr\t%H0, %2", operands
);
21629 output_asm_insn ("ldr\t%0, %1", operands
);
21633 gcc_unreachable ();
21640 thumb_output_move_mem_multiple (int n
, rtx
*operands
)
21647 if (REGNO (operands
[4]) > REGNO (operands
[5]))
21650 operands
[4] = operands
[5];
21653 output_asm_insn ("ldmia\t%1!, {%4, %5}", operands
);
21654 output_asm_insn ("stmia\t%0!, {%4, %5}", operands
);
21658 if (REGNO (operands
[4]) > REGNO (operands
[5]))
21661 operands
[4] = operands
[5];
21664 if (REGNO (operands
[5]) > REGNO (operands
[6]))
21667 operands
[5] = operands
[6];
21670 if (REGNO (operands
[4]) > REGNO (operands
[5]))
21673 operands
[4] = operands
[5];
21677 output_asm_insn ("ldmia\t%1!, {%4, %5, %6}", operands
);
21678 output_asm_insn ("stmia\t%0!, {%4, %5, %6}", operands
);
21682 gcc_unreachable ();
21688 /* Output a call-via instruction for thumb state. */
21690 thumb_call_via_reg (rtx reg
)
21692 int regno
= REGNO (reg
);
21695 gcc_assert (regno
< LR_REGNUM
);
21697 /* If we are in the normal text section we can use a single instance
21698 per compilation unit. If we are doing function sections, then we need
21699 an entry per section, since we can't rely on reachability. */
21700 if (in_section
== text_section
)
21702 thumb_call_reg_needed
= 1;
21704 if (thumb_call_via_label
[regno
] == NULL
)
21705 thumb_call_via_label
[regno
] = gen_label_rtx ();
21706 labelp
= thumb_call_via_label
+ regno
;
21710 if (cfun
->machine
->call_via
[regno
] == NULL
)
21711 cfun
->machine
->call_via
[regno
] = gen_label_rtx ();
21712 labelp
= cfun
->machine
->call_via
+ regno
;
21715 output_asm_insn ("bl\t%a0", labelp
);
21719 /* Routines for generating rtl. */
21721 thumb_expand_movmemqi (rtx
*operands
)
21723 rtx out
= copy_to_mode_reg (SImode
, XEXP (operands
[0], 0));
21724 rtx in
= copy_to_mode_reg (SImode
, XEXP (operands
[1], 0));
21725 HOST_WIDE_INT len
= INTVAL (operands
[2]);
21726 HOST_WIDE_INT offset
= 0;
21730 emit_insn (gen_movmem12b (out
, in
, out
, in
));
21736 emit_insn (gen_movmem8b (out
, in
, out
, in
));
21742 rtx reg
= gen_reg_rtx (SImode
);
21743 emit_insn (gen_movsi (reg
, gen_rtx_MEM (SImode
, in
)));
21744 emit_insn (gen_movsi (gen_rtx_MEM (SImode
, out
), reg
));
21751 rtx reg
= gen_reg_rtx (HImode
);
21752 emit_insn (gen_movhi (reg
, gen_rtx_MEM (HImode
,
21753 plus_constant (in
, offset
))));
21754 emit_insn (gen_movhi (gen_rtx_MEM (HImode
, plus_constant (out
, offset
)),
21762 rtx reg
= gen_reg_rtx (QImode
);
21763 emit_insn (gen_movqi (reg
, gen_rtx_MEM (QImode
,
21764 plus_constant (in
, offset
))));
21765 emit_insn (gen_movqi (gen_rtx_MEM (QImode
, plus_constant (out
, offset
)),
21771 thumb_reload_out_hi (rtx
*operands
)
21773 emit_insn (gen_thumb_movhi_clobber (operands
[0], operands
[1], operands
[2]));
21776 /* Handle reading a half-word from memory during reload. */
21778 thumb_reload_in_hi (rtx
*operands ATTRIBUTE_UNUSED
)
21780 gcc_unreachable ();
21783 /* Return the length of a function name prefix
21784 that starts with the character 'c'. */
21786 arm_get_strip_length (int c
)
21790 ARM_NAME_ENCODING_LENGTHS
21795 /* Return a pointer to a function's name with any
21796 and all prefix encodings stripped from it. */
21798 arm_strip_name_encoding (const char *name
)
21802 while ((skip
= arm_get_strip_length (* name
)))
21808 /* If there is a '*' anywhere in the name's prefix, then
21809 emit the stripped name verbatim, otherwise prepend an
21810 underscore if leading underscores are being used. */
21812 arm_asm_output_labelref (FILE *stream
, const char *name
)
21817 while ((skip
= arm_get_strip_length (* name
)))
21819 verbatim
|= (*name
== '*');
21824 fputs (name
, stream
);
21826 asm_fprintf (stream
, "%U%s", name
);
21829 /* APPLE LOCAL begin v7 support. Merge from mainline */
21831 arm_file_start (void)
21835 if (TARGET_UNIFIED_ASM
)
21836 asm_fprintf (asm_out_file
, "\t.syntax unified\n");
21840 const char *fpu_name
;
21841 if (arm_select
[0].string
)
21842 asm_fprintf (asm_out_file
, "\t.cpu %s\n", arm_select
[0].string
);
21843 else if (arm_select
[1].string
)
21844 asm_fprintf (asm_out_file
, "\t.arch %s\n", arm_select
[1].string
);
21846 asm_fprintf (asm_out_file
, "\t.cpu %s\n",
21847 all_cores
[arm_default_cpu
].name
);
21849 if (TARGET_SOFT_FLOAT
)
21852 fpu_name
= "softvfp";
21854 fpu_name
= "softfpa";
21858 int set_float_abi_attributes
= 0;
21859 switch (arm_fpu_arch
)
21864 case FPUTYPE_FPA_EMU2
:
21867 case FPUTYPE_FPA_EMU3
:
21870 case FPUTYPE_MAVERICK
:
21871 fpu_name
= "maverick";
21875 set_float_abi_attributes
= 1;
21879 set_float_abi_attributes
= 1;
21883 set_float_abi_attributes
= 1;
21888 if (set_float_abi_attributes
)
21890 if (TARGET_HARD_FLOAT
)
21891 asm_fprintf (asm_out_file
, "\t.eabi_attribute 27, 3\n");
21892 if (TARGET_HARD_FLOAT_ABI
)
21893 asm_fprintf (asm_out_file
, "\t.eabi_attribute 28, 1\n");
21896 asm_fprintf (asm_out_file
, "\t.fpu %s\n", fpu_name
);
21898 /* Some of these attributes only apply when the corresponding features
21899 are used. However we don't have any easy way of figuring this out.
21900 Conservatively record the setting that would have been used. */
21902 /* Tag_ABI_PCS_wchar_t. */
21903 asm_fprintf (asm_out_file
, "\t.eabi_attribute 18, %d\n",
21904 (int)WCHAR_TYPE_SIZE
/ BITS_PER_UNIT
);
21906 /* Tag_ABI_FP_rounding. */
21907 if (flag_rounding_math
)
21908 asm_fprintf (asm_out_file
, "\t.eabi_attribute 19, 1\n");
21909 if (!flag_unsafe_math_optimizations
)
21911 /* Tag_ABI_FP_denomal. */
21912 asm_fprintf (asm_out_file
, "\t.eabi_attribute 20, 1\n");
21913 /* Tag_ABI_FP_exceptions. */
21914 asm_fprintf (asm_out_file
, "\t.eabi_attribute 21, 1\n");
21916 /* Tag_ABI_FP_user_exceptions. */
21917 if (flag_signaling_nans
)
21918 asm_fprintf (asm_out_file
, "\t.eabi_attribute 22, 1\n");
21919 /* Tag_ABI_FP_number_model. */
21920 asm_fprintf (asm_out_file
, "\t.eabi_attribute 23, %d\n",
21921 flag_finite_math_only
? 1 : 3);
21923 /* Tag_ABI_align8_needed. */
21924 asm_fprintf (asm_out_file
, "\t.eabi_attribute 24, 1\n");
21925 /* Tag_ABI_align8_preserved. */
21926 asm_fprintf (asm_out_file
, "\t.eabi_attribute 25, 1\n");
21927 /* Tag_ABI_enum_size. */
21928 asm_fprintf (asm_out_file
, "\t.eabi_attribute 26, %d\n",
21929 flag_short_enums
? 1 : 2);
21931 /* Tag_ABI_optimization_goals. */
21934 else if (optimize
>= 2)
21940 asm_fprintf (asm_out_file
, "\t.eabi_attribute 30, %d\n", val
);
21942 /* APPLE LOCAL 6345234 begin place text sections together */
21944 /* Emit declarations for all code sections at the beginning of the file;
21945 this keeps them from being separated by data sections, which can
21946 lead to out-of-range branches. */
21947 if (flag_pic
|| MACHO_DYNAMIC_NO_PIC_P
)
21949 fprintf (asm_out_file
, "\t.section __TEXT,__text,regular\n");
21950 fprintf (asm_out_file
, "\t.section __TEXT,__textcoal_nt,coalesced\n");
21951 fprintf (asm_out_file
, "\t.section __TEXT,__const_coal,coalesced\n");
21952 if (MACHO_DYNAMIC_NO_PIC_P
)
21953 fprintf (asm_out_file
,
21954 "\t.section __TEXT,__symbol_stub4,symbol_stubs,none,12\n");
21956 fprintf (asm_out_file
,
21957 "\t.section __TEXT,__picsymbolstub4,symbol_stubs,none,16\n");
21960 /* APPLE LOCAL 6345234 end place text sections together */
21961 default_file_start();
21964 /* APPLE LOCAL end v7 support. Merge from mainline */
21966 arm_file_end (void)
21970 if (! thumb_call_reg_needed
)
21973 switch_to_section (text_section
);
21974 asm_fprintf (asm_out_file
, "\t.code 16\n");
21975 ASM_OUTPUT_ALIGN (asm_out_file
, 1);
21977 for (regno
= 0; regno
< LR_REGNUM
; regno
++)
21979 rtx label
= thumb_call_via_label
[regno
];
21983 targetm
.asm_out
.internal_label (asm_out_file
, "L",
21984 CODE_LABEL_NUMBER (label
));
21985 asm_fprintf (asm_out_file
, "\tbx\t%r\n", regno
);
21990 /* APPLE LOCAL begin ARM asm file hooks */
21993 arm_darwin_file_start (void)
21995 /* APPLE LOCAL v7 support. Merge from mainline */
21997 darwin_file_start();
22001 arm_darwin_file_end (void)
22003 darwin_file_end ();
22007 /* APPLE LOCAL end ARM asm file hooks */
22011 #ifdef AOF_ASSEMBLER
22012 /* Special functions only needed when producing AOF syntax assembler. */
22016 struct pic_chain
* next
;
22017 const char * symname
;
22020 static struct pic_chain
* aof_pic_chain
= NULL
;
22023 aof_pic_entry (rtx x
)
22025 struct pic_chain
** chainp
;
22028 if (aof_pic_label
== NULL_RTX
)
22030 aof_pic_label
= gen_rtx_SYMBOL_REF (Pmode
, "x$adcons");
22033 for (offset
= 0, chainp
= &aof_pic_chain
; *chainp
;
22034 offset
+= 4, chainp
= &(*chainp
)->next
)
22035 if ((*chainp
)->symname
== XSTR (x
, 0))
22036 return plus_constant (aof_pic_label
, offset
);
22038 *chainp
= (struct pic_chain
*) xmalloc (sizeof (struct pic_chain
));
22039 (*chainp
)->next
= NULL
;
22040 (*chainp
)->symname
= XSTR (x
, 0);
22041 return plus_constant (aof_pic_label
, offset
);
22045 aof_dump_pic_table (FILE *f
)
22047 struct pic_chain
* chain
;
22049 if (aof_pic_chain
== NULL
)
22052 asm_fprintf (f
, "\tAREA |%r$$adcons|, BASED %r\n",
22053 PIC_OFFSET_TABLE_REGNUM
,
22054 PIC_OFFSET_TABLE_REGNUM
);
22055 fputs ("|x$adcons|\n", f
);
22057 for (chain
= aof_pic_chain
; chain
; chain
= chain
->next
)
22059 fputs ("\tDCD\t", f
);
22060 assemble_name (f
, chain
->symname
);
22065 int arm_text_section_count
= 1;
22067 /* A get_unnamed_section callback for switching to the text section. */
22070 aof_output_text_section_asm_op (const void *data ATTRIBUTE_UNUSED
)
22072 fprintf (asm_out_file
, "\tAREA |C$$code%d|, CODE, READONLY",
22073 arm_text_section_count
++);
22075 fprintf (asm_out_file
, ", PIC, REENTRANT");
22076 fprintf (asm_out_file
, "\n");
22079 static int arm_data_section_count
= 1;
22081 /* A get_unnamed_section callback for switching to the data section. */
22084 aof_output_data_section_asm_op (const void *data ATTRIBUTE_UNUSED
)
22086 fprintf (asm_out_file
, "\tAREA |C$$data%d|, DATA\n",
22087 arm_data_section_count
++);
22090 /* Implement TARGET_ASM_INIT_SECTIONS.
22092 AOF Assembler syntax is a nightmare when it comes to areas, since once
22093 we change from one area to another, we can't go back again. Instead,
22094 we must create a new area with the same attributes and add the new output
22095 to that. Unfortunately, there is nothing we can do here to guarantee that
22096 two areas with the same attributes will be linked adjacently in the
22097 resulting executable, so we have to be careful not to do pc-relative
22098 addressing across such boundaries. */
22101 aof_asm_init_sections (void)
22103 text_section
= get_unnamed_section (SECTION_CODE
,
22104 aof_output_text_section_asm_op
, NULL
);
22105 data_section
= get_unnamed_section (SECTION_WRITE
,
22106 aof_output_data_section_asm_op
, NULL
);
22107 readonly_data_section
= text_section
;
22111 zero_init_section (void)
22113 static int zero_init_count
= 1;
22115 fprintf (asm_out_file
, "\tAREA |C$$zidata%d|,NOINIT\n", zero_init_count
++);
22119 /* The AOF assembler is religiously strict about declarations of
22120 imported and exported symbols, so that it is impossible to declare
22121 a function as imported near the beginning of the file, and then to
22122 export it later on. It is, however, possible to delay the decision
22123 until all the functions in the file have been compiled. To get
22124 around this, we maintain a list of the imports and exports, and
22125 delete from it any that are subsequently defined. At the end of
22126 compilation we spit the remainder of the list out before the END
22131 struct import
* next
;
22135 static struct import
* imports_list
= NULL
;
22138 aof_add_import (const char *name
)
22140 struct import
* new;
22142 for (new = imports_list
; new; new = new->next
)
22143 if (new->name
== name
)
22146 new = (struct import
*) xmalloc (sizeof (struct import
));
22147 new->next
= imports_list
;
22148 imports_list
= new;
22153 aof_delete_import (const char *name
)
22155 struct import
** old
;
22157 for (old
= &imports_list
; *old
; old
= & (*old
)->next
)
22159 if ((*old
)->name
== name
)
22161 *old
= (*old
)->next
;
22167 int arm_main_function
= 0;
22170 aof_dump_imports (FILE *f
)
22172 /* The AOF assembler needs this to cause the startup code to be extracted
22173 from the library. Brining in __main causes the whole thing to work
22175 if (arm_main_function
)
22177 switch_to_section (text_section
);
22178 fputs ("\tIMPORT __main\n", f
);
22179 fputs ("\tDCD __main\n", f
);
22182 /* Now dump the remaining imports. */
22183 while (imports_list
)
22185 fprintf (f
, "\tIMPORT\t");
22186 assemble_name (f
, imports_list
->name
);
22188 imports_list
= imports_list
->next
;
22193 aof_globalize_label (FILE *stream
, const char *name
)
22195 default_globalize_label (stream
, name
);
22196 if (! strcmp (name
, "main"))
22197 arm_main_function
= 1;
22201 aof_file_start (void)
22203 fputs ("__r0\tRN\t0\n", asm_out_file
);
22204 fputs ("__a1\tRN\t0\n", asm_out_file
);
22205 fputs ("__a2\tRN\t1\n", asm_out_file
);
22206 fputs ("__a3\tRN\t2\n", asm_out_file
);
22207 fputs ("__a4\tRN\t3\n", asm_out_file
);
22208 fputs ("__v1\tRN\t4\n", asm_out_file
);
22209 fputs ("__v2\tRN\t5\n", asm_out_file
);
22210 fputs ("__v3\tRN\t6\n", asm_out_file
);
22211 fputs ("__v4\tRN\t7\n", asm_out_file
);
22212 fputs ("__v5\tRN\t8\n", asm_out_file
);
22213 fputs ("__v6\tRN\t9\n", asm_out_file
);
22214 fputs ("__sl\tRN\t10\n", asm_out_file
);
22215 fputs ("__fp\tRN\t11\n", asm_out_file
);
22216 fputs ("__ip\tRN\t12\n", asm_out_file
);
22217 fputs ("__sp\tRN\t13\n", asm_out_file
);
22218 fputs ("__lr\tRN\t14\n", asm_out_file
);
22219 fputs ("__pc\tRN\t15\n", asm_out_file
);
22220 fputs ("__f0\tFN\t0\n", asm_out_file
);
22221 fputs ("__f1\tFN\t1\n", asm_out_file
);
22222 fputs ("__f2\tFN\t2\n", asm_out_file
);
22223 fputs ("__f3\tFN\t3\n", asm_out_file
);
22224 fputs ("__f4\tFN\t4\n", asm_out_file
);
22225 fputs ("__f5\tFN\t5\n", asm_out_file
);
22226 fputs ("__f6\tFN\t6\n", asm_out_file
);
22227 fputs ("__f7\tFN\t7\n", asm_out_file
);
22228 switch_to_section (text_section
);
22232 aof_file_end (void)
22235 aof_dump_pic_table (asm_out_file
);
22237 aof_dump_imports (asm_out_file
);
22238 fputs ("\tEND\n", asm_out_file
);
22240 #endif /* AOF_ASSEMBLER */
22242 /* APPLE LOCAL ARM darwin section_info */
22243 #if !defined(ARM_PE) && !TARGET_MACHO
22244 /* Symbols in the text segment can be accessed without indirecting via the
22245 constant pool; it may take an extra binary operation, but this is still
22246 faster than indirecting via memory. Don't do this when not optimizing,
22247 since we won't be calculating al of the offsets necessary to do this
22251 arm_encode_section_info (tree decl
, rtx rtl
, int first
)
22253 /* This doesn't work with AOF syntax, since the string table may be in
22254 a different AREA. */
22255 #ifndef AOF_ASSEMBLER
22256 if (optimize
> 0 && TREE_CONSTANT (decl
))
22257 SYMBOL_REF_FLAG (XEXP (rtl
, 0)) = 1;
22260 /* If we are referencing a function that is weak then encode a long call
22261 flag in the function name, otherwise if the function is static or
22262 or known to be defined in this file then encode a short call flag. */
22263 if (first
&& DECL_P (decl
))
22265 if (TREE_CODE (decl
) == FUNCTION_DECL
&& DECL_WEAK (decl
))
22266 arm_encode_call_attribute (decl
, LONG_CALL_FLAG_CHAR
);
22267 else if (! TREE_PUBLIC (decl
))
22268 arm_encode_call_attribute (decl
, SHORT_CALL_FLAG_CHAR
);
22271 default_encode_section_info (decl
, rtl
, first
);
22273 /* APPLE LOCAL begin ARM darwin section_info */
22274 #endif /* !ARM_PE && !TARGET_MACHO*/
22277 /* Encode the standard darwin attributes, plus the longcall flag. */
22280 arm_darwin_encode_section_info (tree decl
, rtx rtl
, int first
)
22282 darwin_encode_section_info (decl
, rtl
, first
);
22284 if (optimize
> 0 && TREE_CONSTANT (decl
))
22285 SYMBOL_REF_FLAG (XEXP (rtl
, 0)) = 1;
22287 /* If we are referencing a function with default visibility that is
22288 weak then encode a long call flag in the function name, otherwise
22289 if the function is static or or known to be defined in this file
22290 then encode a short call flag. */
22293 if (TREE_CODE (decl
) == FUNCTION_DECL
22294 && DECL_WEAK (decl
)
22295 && DECL_VISIBILITY (decl
) == VISIBILITY_DEFAULT
)
22296 arm_encode_call_attribute (decl
, SYMBOL_LONG_CALL
);
22297 /* Should this be binds_local_p??? */
22298 else if (! TREE_PUBLIC (decl
))
22299 arm_encode_call_attribute (decl
, SYMBOL_SHORT_CALL
);
22303 /* APPLE LOCAL end ARM darwin section_info */
22306 arm_internal_label (FILE *stream
, const char *prefix
, unsigned long labelno
)
22308 if (arm_ccfsm_state
== 3 && (unsigned) arm_target_label
== labelno
22309 && !strcmp (prefix
, "L"))
22311 arm_ccfsm_state
= 0;
22312 arm_target_insn
= NULL
;
22314 default_internal_label (stream
, prefix
, labelno
);
22317 /* Output code to add DELTA to the first argument, and then jump
22318 to FUNCTION. Used for C++ multiple inheritance. */
22320 arm_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
22321 HOST_WIDE_INT delta
,
22322 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED
,
22325 /* APPLE LOCAL begin ARM 4620953 4745175 5920116 */
22326 static int thunk_label
= 0;
22329 int mi_delta
= delta
;
22330 const char *const mi_op
= mi_delta
< 0 ? "sub" : "add";
22332 int this_regno
= (aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
)
22334 rtx function_rtx
= XEXP (DECL_RTL (function
), 0);
22335 const char *function_name
;
22336 bool is_longcall
= arm_is_longcall_p (function_rtx
,
22337 SYMBOL_REF_FLAGS (function_rtx
),
22339 bool is_indirected
= false;
22342 /* Darwin/mach-o: use a stub for dynamic references. */
22345 && MACHOPIC_INDIRECT
22346 && (! machopic_data_defined_p (function_rtx
)))
22348 function_name
= machopic_indirection_name (function_rtx
, !is_longcall
);
22349 /* APPLE LOCAL 6858124 don't indirect if it's just a stub */
22350 is_indirected
= is_longcall
;
22354 function_name
= XSTR (function_rtx
, 0);
22357 mi_delta
= - mi_delta
;
22358 /* APPLE LOCAL begin v7 support. Merge from mainline */
22359 /* APPLE LOCAL 6361608 begin Thumb-2 longcall thunks */
22360 /* When generating 16-bit thumb-1 code, thunks are entered in arm mode.
22361 In thumb-2, thunks can be in thumb mode. */
22362 /* APPLE LOCAL 6361608 end Thumb-2 longcall thunks */
22363 if (TARGET_THUMB1
|| is_longcall
)
22364 /* APPLE LOCAL end v7 support. Merge from mainline */
22366 int labelno
= thunk_label
++;
22367 ASM_GENERATE_INTERNAL_LABEL (label
, "LTHUMBFUNC", labelno
);
22368 fputs ("\tldr\tr12, ", file
);
22369 assemble_name (file
, label
);
22370 fputc ('\n', file
);
22373 /* If we are generating PIC, the ldr instruction below loads
22374 "(target - 7) - .LTHUNKPCn" into r12. The pc reads as
22375 the address of the add + 8, so we have:
22377 r12 = (target - 7) - .LTHUNKPCn + (.LTHUNKPCn + 8)
22380 Note that we have "+ 1" because some versions of GNU ld
22381 don't set the low bit of the result for R_ARM_REL32
22382 relocations against thumb function symbols. */
22383 ASM_GENERATE_INTERNAL_LABEL (labelpc
, "LTHUNKPC", labelno
);
22384 assemble_name (file
, labelpc
);
22385 fputs (":\n", file
);
22386 fputs ("\tadd\tr12, pc, r12\n", file
);
22389 fputs ("\tldr\tr12, [r12]\n", file
);
22391 /* APPLE LOCAL v7 support. Merge from mainline */
22392 /* TODO: Use movw/movt for large constants when available. */
22393 while (mi_delta
!= 0)
22395 if ((mi_delta
& (3 << shift
)) == 0)
22399 asm_fprintf (file
, "\t%s\t%r, %r, #%d\n",
22400 mi_op
, this_regno
, this_regno
,
22401 mi_delta
& (0xff << shift
));
22402 mi_delta
&= ~(0xff << shift
);
22406 /* APPLE LOCAL v7 support. Merge from mainline */
22407 if (TARGET_THUMB1
|| is_longcall
)
22409 fprintf (file
, "\tbx\tr12\n");
22410 ASM_OUTPUT_ALIGN (file
, 2);
22411 assemble_name (file
, label
);
22412 fputs (":\n", file
);
22415 /* APPLE LOCAL 6361608 begin Thumb-2 longcall thunks */
22417 /* If we're branching to a local Thumb routine, output:
22418 ".word .LTHUNKn-7-.LTHUNKPCn".
22420 ".word .LTHUNKn-8-.LTHUNKPCn".
22421 (inter-module thumbness is fixed up by the linker).
22422 If we're in a Thumb2 thunk, it's -4 and -3, respectively. */
22423 rtx tem
= gen_rtx_SYMBOL_REF (Pmode
, function_name
);
22425 /* Thumb2 add instructions w/ PC source have a +4 bias. ARM
22427 pc_offset
= TARGET_THUMB2
? -4 : -8;
22428 if (TARGET_MACHO
&& (TARGET_ARM
|| is_indirected
))
22429 tem
= gen_rtx_PLUS (GET_MODE (tem
), tem
, GEN_INT (pc_offset
));
22431 tem
= gen_rtx_PLUS (GET_MODE (tem
), tem
, GEN_INT (pc_offset
+1));
22432 /* APPLE LOCAL 6361608 end Thumb-2 longcall thunks */
22434 tem
= gen_rtx_MINUS (GET_MODE (tem
),
22436 gen_rtx_SYMBOL_REF (Pmode
,
22437 ggc_strdup (labelpc
)));
22438 assemble_integer (tem
, 4, BITS_PER_WORD
, 1);
22441 /* Output ".word .LTHUNKn". */
22442 assemble_integer (gen_rtx_SYMBOL_REF (Pmode
, function_name
),
22443 4, BITS_PER_WORD
, 1);
22447 /* APPLE LOCAL begin 6297258 */
22449 fputs ("\tb.w\t", file
);
22451 fputs ("\tb\t", file
);
22452 /* APPLE LOCAL end 6297258 */
22454 assemble_name (file
, function_name
);
22455 if (NEED_PLT_RELOC
)
22456 fputs ("(PLT)", file
);
22457 fputc ('\n', file
);
22459 /* APPLE LOCAL end ARM 4620953 4745175 5920116 */
22463 arm_emit_vector_const (FILE *file
, rtx x
)
22466 const char * pattern
;
22468 gcc_assert (GET_CODE (x
) == CONST_VECTOR
);
22470 switch (GET_MODE (x
))
22472 case V2SImode
: pattern
= "%08x"; break;
22473 case V4HImode
: pattern
= "%04x"; break;
22474 case V8QImode
: pattern
= "%02x"; break;
22475 default: gcc_unreachable ();
22478 fprintf (file
, "0x");
22479 for (i
= CONST_VECTOR_NUNITS (x
); i
--;)
22483 element
= CONST_VECTOR_ELT (x
, i
);
22484 fprintf (file
, pattern
, INTVAL (element
));
22491 arm_output_load_gr (rtx
*operands
)
22498 if (GET_CODE (operands
[1]) != MEM
22499 || GET_CODE (sum
= XEXP (operands
[1], 0)) != PLUS
22500 || GET_CODE (reg
= XEXP (sum
, 0)) != REG
22501 || GET_CODE (offset
= XEXP (sum
, 1)) != CONST_INT
22502 || ((INTVAL (offset
) < 1024) && (INTVAL (offset
) > -1024)))
22503 return "wldrw%?\t%0, %1";
22505 /* Fix up an out-of-range load of a GR register. */
22506 output_asm_insn ("str%?\t%0, [sp, #-4]!\t@ Start of GR load expansion", & reg
);
22507 wcgr
= operands
[0];
22509 output_asm_insn ("ldr%?\t%0, %1", operands
);
22511 operands
[0] = wcgr
;
22513 output_asm_insn ("tmcr%?\t%0, %1", operands
);
22514 output_asm_insn ("ldr%?\t%0, [sp], #4\t@ End of GR load expansion", & reg
);
22519 /* Worker function for TARGET_SETUP_INCOMING_VARARGS.
22521 On the ARM, PRETEND_SIZE is set in order to have the prologue push the last
22522 named arg and all anonymous args onto the stack.
22523 XXX I know the prologue shouldn't be pushing registers, but it is faster
22527 arm_setup_incoming_varargs (CUMULATIVE_ARGS
*cum
,
22528 enum machine_mode mode ATTRIBUTE_UNUSED
,
22529 tree type ATTRIBUTE_UNUSED
,
22531 int second_time ATTRIBUTE_UNUSED
)
22533 cfun
->machine
->uses_anonymous_args
= 1;
22534 if (cum
->nregs
< NUM_ARG_REGS
)
22535 *pretend_size
= (NUM_ARG_REGS
- cum
->nregs
) * UNITS_PER_WORD
;
22538 /* Return nonzero if the CONSUMER instruction (a store) does not need
22539 PRODUCER's value to calculate the address. */
22542 arm_no_early_store_addr_dep (rtx producer
, rtx consumer
)
22544 rtx value
= PATTERN (producer
);
22545 rtx addr
= PATTERN (consumer
);
22547 if (GET_CODE (value
) == COND_EXEC
)
22548 value
= COND_EXEC_CODE (value
);
22549 if (GET_CODE (value
) == PARALLEL
)
22550 value
= XVECEXP (value
, 0, 0);
22551 value
= XEXP (value
, 0);
22552 if (GET_CODE (addr
) == COND_EXEC
)
22553 addr
= COND_EXEC_CODE (addr
);
22554 if (GET_CODE (addr
) == PARALLEL
)
22555 addr
= XVECEXP (addr
, 0, 0);
22556 addr
= XEXP (addr
, 0);
22558 return !reg_overlap_mentioned_p (value
, addr
);
22561 /* Return nonzero if the CONSUMER instruction (an ALU op) does not
22562 have an early register shift value or amount dependency on the
22563 result of PRODUCER. */
22566 arm_no_early_alu_shift_dep (rtx producer
, rtx consumer
)
22568 rtx value
= PATTERN (producer
);
22569 rtx op
= PATTERN (consumer
);
22572 if (GET_CODE (value
) == COND_EXEC
)
22573 value
= COND_EXEC_CODE (value
);
22574 if (GET_CODE (value
) == PARALLEL
)
22575 value
= XVECEXP (value
, 0, 0);
22576 value
= XEXP (value
, 0);
22577 if (GET_CODE (op
) == COND_EXEC
)
22578 op
= COND_EXEC_CODE (op
);
22579 if (GET_CODE (op
) == PARALLEL
)
22580 op
= XVECEXP (op
, 0, 0);
22583 early_op
= XEXP (op
, 0);
22584 /* This is either an actual independent shift, or a shift applied to
22585 the first operand of another operation. We want the whole shift
22587 if (GET_CODE (early_op
) == REG
)
22590 return !reg_overlap_mentioned_p (value
, early_op
);
22593 /* Return nonzero if the CONSUMER instruction (an ALU op) does not
22594 have an early register shift value dependency on the result of
22598 arm_no_early_alu_shift_value_dep (rtx producer
, rtx consumer
)
22600 rtx value
= PATTERN (producer
);
22601 rtx op
= PATTERN (consumer
);
22604 if (GET_CODE (value
) == COND_EXEC
)
22605 value
= COND_EXEC_CODE (value
);
22606 if (GET_CODE (value
) == PARALLEL
)
22607 value
= XVECEXP (value
, 0, 0);
22608 value
= XEXP (value
, 0);
22609 if (GET_CODE (op
) == COND_EXEC
)
22610 op
= COND_EXEC_CODE (op
);
22611 if (GET_CODE (op
) == PARALLEL
)
22612 op
= XVECEXP (op
, 0, 0);
22615 early_op
= XEXP (op
, 0);
22617 /* This is either an actual independent shift, or a shift applied to
22618 the first operand of another operation. We want the value being
22619 shifted, in either case. */
22620 if (GET_CODE (early_op
) != REG
)
22621 early_op
= XEXP (early_op
, 0);
22623 return !reg_overlap_mentioned_p (value
, early_op
);
22626 /* Return nonzero if the CONSUMER (a mul or mac op) does not
22627 have an early register mult dependency on the result of
22631 arm_no_early_mul_dep (rtx producer
, rtx consumer
)
22633 rtx value
= PATTERN (producer
);
22634 rtx op
= PATTERN (consumer
);
22636 if (GET_CODE (value
) == COND_EXEC
)
22637 value
= COND_EXEC_CODE (value
);
22638 if (GET_CODE (value
) == PARALLEL
)
22639 value
= XVECEXP (value
, 0, 0);
22640 value
= XEXP (value
, 0);
22641 if (GET_CODE (op
) == COND_EXEC
)
22642 op
= COND_EXEC_CODE (op
);
22643 if (GET_CODE (op
) == PARALLEL
)
22644 op
= XVECEXP (op
, 0, 0);
22647 return (GET_CODE (op
) == PLUS
22648 && !reg_overlap_mentioned_p (value
, XEXP (op
, 0)));
22651 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
22652 /* Return non-zero if the consumer (a multiply-accumulate instruction)
22653 has an accumulator dependency on the result of the producer (a
22654 multiplication instruction) and no other dependency on that result. */
22656 arm_mac_accumulator_is_mul_result (rtx producer
, rtx consumer
)
22658 rtx mul
= PATTERN (producer
);
22659 rtx mac
= PATTERN (consumer
);
22661 rtx mac_op0
, mac_op1
, mac_acc
;
22663 if (GET_CODE (mul
) == COND_EXEC
)
22664 mul
= COND_EXEC_CODE (mul
);
22665 if (GET_CODE (mac
) == COND_EXEC
)
22666 mac
= COND_EXEC_CODE (mac
);
22668 /* Check that mul is of the form (set (...) (mult ...))
22669 and mla is of the form (set (...) (plus (mult ...) (...))). */
22670 if ((GET_CODE (mul
) != SET
|| GET_CODE (XEXP (mul
, 1)) != MULT
)
22671 || (GET_CODE (mac
) != SET
|| GET_CODE (XEXP (mac
, 1)) != PLUS
22672 || GET_CODE (XEXP (XEXP (mac
, 1), 0)) != MULT
))
22675 mul_result
= XEXP (mul
, 0);
22676 mac_op0
= XEXP (XEXP (XEXP (mac
, 1), 0), 0);
22677 mac_op1
= XEXP (XEXP (XEXP (mac
, 1), 0), 1);
22678 mac_acc
= XEXP (XEXP (mac
, 1), 1);
22680 return (reg_overlap_mentioned_p (mul_result
, mac_acc
)
22681 && !reg_overlap_mentioned_p (mul_result
, mac_op0
)
22682 && !reg_overlap_mentioned_p (mul_result
, mac_op1
));
22686 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
22687 /* We can't rely on the caller doing the proper promotion when
22688 using APCS or ATPCS. */
22691 arm_promote_prototypes (tree t ATTRIBUTE_UNUSED
)
22693 return !TARGET_AAPCS_BASED
;
22697 /* AAPCS based ABIs use short enums by default. */
22700 arm_default_short_enums (void)
22702 return TARGET_AAPCS_BASED
&& arm_abi
!= ARM_ABI_AAPCS_LINUX
;
22706 /* AAPCS requires that anonymous bitfields affect structure alignment. */
22709 arm_align_anon_bitfield (void)
22711 return TARGET_AAPCS_BASED
;
22715 /* The generic C++ ABI says 64-bit (long long). The EABI says 32-bit. */
22718 arm_cxx_guard_type (void)
22720 return TARGET_AAPCS_BASED
? integer_type_node
: long_long_integer_type_node
;
22724 /* The EABI says test the least significant bit of a guard variable. */
22727 arm_cxx_guard_mask_bit (void)
22729 return TARGET_AAPCS_BASED
;
22733 /* The EABI specifies that all array cookies are 8 bytes long. */
22736 arm_get_cookie_size (tree type
)
22740 if (!TARGET_AAPCS_BASED
)
22741 return default_cxx_get_cookie_size (type
);
22743 size
= build_int_cst (sizetype
, 8);
22748 /* The EABI says that array cookies should also contain the element size. */
22751 arm_cookie_has_size (void)
22753 return TARGET_AAPCS_BASED
;
22757 /* The EABI says constructors and destructors should return a pointer to
22758 the object constructed/destroyed. */
22761 arm_cxx_cdtor_returns_this (void)
22763 return TARGET_AAPCS_BASED
;
22766 /* The EABI says that an inline function may never be the key
22770 arm_cxx_key_method_may_be_inline (void)
22772 return !TARGET_AAPCS_BASED
;
22776 arm_cxx_determine_class_data_visibility (tree decl
)
22778 if (!TARGET_AAPCS_BASED
)
22781 /* In general, \S 3.2.5.5 of the ARM EABI requires that class data
22782 is exported. However, on systems without dynamic vague linkage,
22783 \S 3.2.5.6 says that COMDAT class data has hidden linkage. */
22784 if (!TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P
&& DECL_COMDAT (decl
))
22785 DECL_VISIBILITY (decl
) = VISIBILITY_HIDDEN
;
22787 DECL_VISIBILITY (decl
) = VISIBILITY_DEFAULT
;
22788 DECL_VISIBILITY_SPECIFIED (decl
) = 1;
22792 arm_cxx_class_data_always_comdat (void)
22794 /* APPLE LOCAL begin ARM follow Darwin semantics on Darwin */
22798 /* APPLE LOCAL end ARM follow Darwin semantics on Darwin */
22800 /* \S 3.2.5.4 of the ARM C++ ABI says that class data only have
22801 vague linkage if the class has no key function. */
22802 return !TARGET_AAPCS_BASED
;
22806 /* The EABI says __aeabi_atexit should be used to register static
22810 arm_cxx_use_aeabi_atexit (void)
22812 return TARGET_AAPCS_BASED
;
22817 arm_set_return_address (rtx source
, rtx scratch
)
22819 arm_stack_offsets
*offsets
;
22820 HOST_WIDE_INT delta
;
22822 unsigned long saved_regs
;
22824 saved_regs
= arm_compute_save_reg_mask ();
22826 if ((saved_regs
& (1 << LR_REGNUM
)) == 0)
22827 emit_move_insn (gen_rtx_REG (Pmode
, LR_REGNUM
), source
);
22830 if (frame_pointer_needed
)
22831 /* APPLE LOCAL ARM custom frame layout */
22832 addr
= plus_constant(hard_frame_pointer_rtx
, 4);
22835 /* LR will be the first saved register. */
22836 offsets
= arm_get_frame_offsets ();
22837 /* APPLE LOCAL ARM custom frame layout */
22838 delta
= offsets
->outgoing_args
- (offsets
->frame
- 4);
22843 emit_insn (gen_addsi3 (scratch
, stack_pointer_rtx
,
22844 GEN_INT (delta
& ~4095)));
22849 addr
= stack_pointer_rtx
;
22851 addr
= plus_constant (addr
, delta
);
22853 emit_move_insn (gen_frame_mem (Pmode
, addr
), source
);
22859 thumb_set_return_address (rtx source
, rtx scratch
)
22861 arm_stack_offsets
*offsets
;
22862 HOST_WIDE_INT delta
;
22865 unsigned long mask
;
22867 emit_insn (gen_rtx_USE (VOIDmode
, source
));
22869 /* APPLE LOCAL v7 support. Merge from mainline */
22870 mask
= thumb1_compute_save_reg_mask ();
22871 if (mask
& (1 << LR_REGNUM
))
22873 offsets
= arm_get_frame_offsets ();
22875 /* Find the saved regs. */
22876 if (frame_pointer_needed
)
22878 /* APPLE LOCAL ARM custom frame layout */
22880 reg
= THUMB_HARD_FRAME_POINTER_REGNUM
;
22884 /* APPLE LOCAL ARM custom frame layout */
22885 delta
= offsets
->outgoing_args
- (offsets
->saved_args
+ 4);
22888 /* Allow for the stack frame. */
22889 /* APPLE LOCAL v7 support. Merge from mainline */
22890 if (TARGET_THUMB1
&& TARGET_BACKTRACE
)
22892 /* APPLE LOCAL ARM custom frame layout */
22893 /* Removed lines. */
22895 /* Construct the address. */
22896 addr
= gen_rtx_REG (SImode
, reg
);
22897 if ((reg
!= SP_REGNUM
&& delta
>= 128)
22900 emit_insn (gen_movsi (scratch
, GEN_INT (delta
)));
22901 emit_insn (gen_addsi3 (scratch
, scratch
, stack_pointer_rtx
));
22905 addr
= plus_constant (addr
, delta
);
22907 emit_move_insn (gen_frame_mem (Pmode
, addr
), source
);
22910 emit_move_insn (gen_rtx_REG (Pmode
, LR_REGNUM
), source
);
22913 /* Implements target hook vector_mode_supported_p. */
22915 arm_vector_mode_supported_p (enum machine_mode mode
)
22917 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
22918 /* Neon also supports V2SImode, etc. listed in the clause below. */
22919 if (TARGET_NEON
&& (mode
== V2SFmode
|| mode
== V4SImode
|| mode
== V8HImode
22920 || mode
== V16QImode
|| mode
== V4SFmode
|| mode
== V2DImode
))
22923 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
22924 if ((mode
== V2SImode
)
22925 || (mode
== V4HImode
)
22926 || (mode
== V8QImode
))
22932 /* APPLE LOCAL begin 7083296 Build without warnings. */
22933 /* Define a separate function to avoid build warnings about missing a
22934 prototype for arm_vector_mode_supported_p. The MODE argument is an int
22935 because arm.h is used in contexts where "enum machine_mode" is not
22936 defined. The return type is "int" instead of "bool" for the same reason. */
22938 valid_iwmmxt_reg_mode (int mode
)
22940 return (arm_vector_mode_supported_p (mode
) || mode
== DImode
);
22942 /* APPLE LOCAL end 7083296 Build without warnings. */
22944 /* Implement TARGET_SHIFT_TRUNCATION_MASK. SImode shifts use normal
22945 ARM insns and therefore guarantee that the shift count is modulo 256.
22946 DImode shifts (those implemented by lib1funcs.asm or by optabs.c)
22947 guarantee no particular behavior for out-of-range counts. */
22949 static unsigned HOST_WIDE_INT
22950 arm_shift_truncation_mask (enum machine_mode mode
)
22952 return mode
== SImode
? 255 : 0;
22956 /* Map internal gcc register numbers to DWARF2 register numbers. */
22959 arm_dbx_register_number (unsigned int regno
)
22964 /* TODO: Legacy targets output FPA regs as registers 16-23 for backwards
22965 compatibility. The EABI defines them as registers 96-103. */
22966 if (IS_FPA_REGNUM (regno
))
22967 return (TARGET_AAPCS_BASED
? 96 : 16) + regno
- FIRST_FPA_REGNUM
;
22969 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
22970 if (IS_VFP_REGNUM (regno
))
22972 /* See comment in arm_dwarf_register_span. */
22973 if (VFP_REGNO_OK_FOR_SINGLE (regno
))
22974 /* APPLE LOCAL ARM 5757769 */
22975 return 256 + regno
- FIRST_VFP_REGNUM
;
22977 return 256 + (regno
- FIRST_VFP_REGNUM
) / 2;
22979 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
22981 if (IS_IWMMXT_GR_REGNUM (regno
))
22982 return 104 + regno
- FIRST_IWMMXT_GR_REGNUM
;
22984 if (IS_IWMMXT_REGNUM (regno
))
22985 return 112 + regno
- FIRST_IWMMXT_REGNUM
;
22987 gcc_unreachable ();
22990 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
22991 /* Dwarf models VFPv3 registers as 32 64-bit registers.
22992 GCC models tham as 64 32-bit registers, so we need to describe this to
22993 the DWARF generation code. Other registers can use the default. */
22995 arm_dwarf_register_span(rtx rtl
)
23002 regno
= REGNO (rtl
);
23003 if (!IS_VFP_REGNUM (regno
))
23006 /* The EABI defines two VFP register ranges:
23007 64-95: Legacy VFPv2 numbering for S0-S31 (obsolescent)
23009 The recommended encodings for s0-s31 is a DW_OP_bit_piece of the
23010 corresponding D register. However gdb6.6 does not support this, so
23011 we use the legacy encodings. We also use these encodings for D0-D15
23012 for compatibility with older debuggers. */
23013 if (VFP_REGNO_OK_FOR_SINGLE (regno
))
23016 nregs
= GET_MODE_SIZE (GET_MODE (rtl
)) / 8;
23017 p
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc(nregs
));
23018 regno
= (regno
- FIRST_VFP_REGNUM
) / 2;
23019 for (i
= 0; i
< nregs
; i
++)
23020 XVECEXP (p
, 0, i
) = gen_rtx_REG (DImode
, 256 + regno
+ i
);
23024 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
23026 #ifdef TARGET_UNWIND_INFO
23027 /* APPLE LOCAL begin v7 support. Merge from mainline */
23028 /* Emit unwind directives for a store-multiple instruction or stack pointer
23029 push during alignment.
23030 These should only ever be generated by the function prologue code, so
23031 expect them to have a particular form. */
23034 arm_unwind_emit_sequence (FILE * asm_out_file
, rtx p
)
23035 /* APPLE LOCAL end v7 support. Merge from mainline */
23038 HOST_WIDE_INT offset
;
23039 HOST_WIDE_INT nregs
;
23045 /* APPLE LOCAL begin v7 support. Merge from mainline */
23046 e
= XVECEXP (p
, 0, 0);
23047 if (GET_CODE (e
) != SET
)
23050 /* First insn will adjust the stack pointer. */
23051 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
23052 if (GET_CODE (e
) != SET
23053 || GET_CODE (XEXP (e
, 0)) != REG
23054 || REGNO (XEXP (e
, 0)) != SP_REGNUM
23055 || GET_CODE (XEXP (e
, 1)) != PLUS
)
23058 offset
= -INTVAL (XEXP (XEXP (e
, 1), 1));
23059 nregs
= XVECLEN (p
, 0) - 1;
23061 /* APPLE LOCAL begin v7 support. Merge from mainline */
23062 reg
= REGNO (XEXP (XVECEXP (p
, 0, 1), 1));
23065 /* The function prologue may also push pc, but not annotate it as it is
23066 never restored. We turn this into a stack pointer adjustment. */
23067 if (nregs
* 4 == offset
- 4)
23069 fprintf (asm_out_file
, "\t.pad #4\n");
23073 fprintf (asm_out_file
, "\t.save {");
23075 else if (IS_VFP_REGNUM (reg
))
23078 fprintf (asm_out_file
, "\t.vsave {");
23080 /* APPLE LOCAL end v7 support. Merge from mainline */
23081 else if (reg
>= FIRST_FPA_REGNUM
&& reg
<= LAST_FPA_REGNUM
)
23083 /* FPA registers are done differently. */
23084 asm_fprintf (asm_out_file
, "\t.save %r, %wd\n", reg
, nregs
);
23088 /* Unknown register type. */
23091 /* If the stack increment doesn't match the size of the saved registers,
23092 something has gone horribly wrong. */
23093 if (offset
!= nregs
* reg_size
)
23096 /* APPLE LOCAL v7 support. Merge from mainline */
23097 /* Removed lines */
23100 /* The remaining insns will describe the stores. */
23101 for (i
= 1; i
<= nregs
; i
++)
23103 /* Expect (set (mem <addr>) (reg)).
23104 Where <addr> is (reg:SP) or (plus (reg:SP) (const_int)). */
23105 e
= XVECEXP (p
, 0, i
);
23106 if (GET_CODE (e
) != SET
23107 || GET_CODE (XEXP (e
, 0)) != MEM
23108 || GET_CODE (XEXP (e
, 1)) != REG
)
23111 reg
= REGNO (XEXP (e
, 1));
23116 fprintf (asm_out_file
, ", ");
23117 /* We can't use %r for vfp because we need to use the
23118 double precision register names. */
23119 if (IS_VFP_REGNUM (reg
))
23120 asm_fprintf (asm_out_file
, "d%d", (reg
- FIRST_VFP_REGNUM
) / 2);
23122 asm_fprintf (asm_out_file
, "%r", reg
);
23124 #ifdef ENABLE_CHECKING
23125 /* Check that the addresses are consecutive. */
23126 e
= XEXP (XEXP (e
, 0), 0);
23127 if (GET_CODE (e
) == PLUS
)
23129 offset
+= reg_size
;
23130 if (GET_CODE (XEXP (e
, 0)) != REG
23131 || REGNO (XEXP (e
, 0)) != SP_REGNUM
23132 || GET_CODE (XEXP (e
, 1)) != CONST_INT
23133 || offset
!= INTVAL (XEXP (e
, 1)))
23137 || GET_CODE (e
) != REG
23138 || REGNO (e
) != SP_REGNUM
)
23142 fprintf (asm_out_file
, "}\n");
23145 /* Emit unwind directives for a SET. */
23148 arm_unwind_emit_set (FILE * asm_out_file
, rtx p
)
23152 /* APPLE LOCAL v7 support. Merge from mainline */
23157 switch (GET_CODE (e0
))
23160 /* Pushing a single register. */
23161 if (GET_CODE (XEXP (e0
, 0)) != PRE_DEC
23162 || GET_CODE (XEXP (XEXP (e0
, 0), 0)) != REG
23163 || REGNO (XEXP (XEXP (e0
, 0), 0)) != SP_REGNUM
)
23166 asm_fprintf (asm_out_file
, "\t.save ");
23167 if (IS_VFP_REGNUM (REGNO (e1
)))
23168 asm_fprintf(asm_out_file
, "{d%d}\n",
23169 (REGNO (e1
) - FIRST_VFP_REGNUM
) / 2);
23171 asm_fprintf(asm_out_file
, "{%r}\n", REGNO (e1
));
23175 if (REGNO (e0
) == SP_REGNUM
)
23177 /* A stack increment. */
23178 if (GET_CODE (e1
) != PLUS
23179 || GET_CODE (XEXP (e1
, 0)) != REG
23180 || REGNO (XEXP (e1
, 0)) != SP_REGNUM
23181 || GET_CODE (XEXP (e1
, 1)) != CONST_INT
)
23184 asm_fprintf (asm_out_file
, "\t.pad #%wd\n",
23185 -INTVAL (XEXP (e1
, 1)));
23187 else if (REGNO (e0
) == HARD_FRAME_POINTER_REGNUM
)
23189 HOST_WIDE_INT offset
;
23190 /* APPLE LOCAL v7 support. Merge from mainline */
23191 /* moved 'reg' to function level scope */
23193 if (GET_CODE (e1
) == PLUS
)
23195 if (GET_CODE (XEXP (e1
, 0)) != REG
23196 || GET_CODE (XEXP (e1
, 1)) != CONST_INT
)
23198 reg
= REGNO (XEXP (e1
, 0));
23199 offset
= INTVAL (XEXP (e1
, 1));
23200 asm_fprintf (asm_out_file
, "\t.setfp %r, %r, #%wd\n",
23201 HARD_FRAME_POINTER_REGNUM
, reg
,
23202 INTVAL (XEXP (e1
, 1)));
23204 else if (GET_CODE (e1
) == REG
)
23207 asm_fprintf (asm_out_file
, "\t.setfp %r, %r\n",
23208 HARD_FRAME_POINTER_REGNUM
, reg
);
23213 else if (GET_CODE (e1
) == REG
&& REGNO (e1
) == SP_REGNUM
)
23215 /* Move from sp to reg. */
23216 asm_fprintf (asm_out_file
, "\t.movsp %r\n", REGNO (e0
));
23218 else if (GET_CODE (e1
) == PLUS
23219 && GET_CODE (XEXP (e1
, 0)) == REG
23220 && REGNO (XEXP (e1
, 0)) == SP_REGNUM
23221 && GET_CODE (XEXP (e1
, 1)) == CONST_INT
)
23223 /* Set reg to offset from sp. */
23224 asm_fprintf (asm_out_file
, "\t.movsp %r, #%d\n",
23225 REGNO (e0
), (int)INTVAL(XEXP (e1
, 1)));
23227 /* APPLE LOCAL begin v7 support. Merge from mainline */
23228 else if (GET_CODE (e1
) == UNSPEC
&& XINT (e1
, 1) == UNSPEC_STACK_ALIGN
)
23230 /* Stack pointer save before alignment. */
23232 asm_fprintf (asm_out_file
, "\t.unwind_raw 0, 0x%x @ vsp = r%d\n",
23235 /* APPLE LOCAL end v7 support. Merge from mainline */
23246 /* Emit unwind directives for the given insn. */
23249 arm_unwind_emit (FILE * asm_out_file
, rtx insn
)
23253 if (!ARM_EABI_UNWIND_TABLES
)
23256 if (GET_CODE (insn
) == NOTE
|| !RTX_FRAME_RELATED_P (insn
))
23259 pat
= find_reg_note (insn
, REG_FRAME_RELATED_EXPR
, NULL_RTX
);
23261 pat
= XEXP (pat
, 0);
23263 pat
= PATTERN (insn
);
23265 switch (GET_CODE (pat
))
23268 arm_unwind_emit_set (asm_out_file
, pat
);
23272 /* Store multiple. */
23273 /* APPLE LOCAL v7 support. Merge from mainline */
23274 arm_unwind_emit_sequence (asm_out_file
, pat
);
23283 /* Output a reference from a function exception table to the type_info
23284 object X. The EABI specifies that the symbol should be relocated by
23285 an R_ARM_TARGET2 relocation. */
23288 arm_output_ttype (rtx x
)
23290 fputs ("\t.word\t", asm_out_file
);
23291 output_addr_const (asm_out_file
, x
);
23292 /* Use special relocations for symbol references. */
23293 if (GET_CODE (x
) != CONST_INT
)
23294 fputs ("(TARGET2)", asm_out_file
);
23295 fputc ('\n', asm_out_file
);
23299 #endif /* TARGET_UNWIND_INFO */
23302 /* APPLE LOCAL begin v7 support. Merge from mainline */
23303 /* Handle UNSPEC DWARF call frame instructions. These are needed for dynamic
23304 stack alignment. */
23307 arm_dwarf_handle_frame_unspec (const char *label
, rtx pattern
, int index
)
23309 rtx unspec
= SET_SRC (pattern
);
23310 gcc_assert (GET_CODE (unspec
) == UNSPEC
);
23314 case UNSPEC_STACK_ALIGN
:
23315 /* ??? We should set the CFA = (SP & ~7). At this point we haven't
23316 put anything on the stack, so hopefully it won't matter.
23317 CFA = SP will be correct after alignment. */
23318 dwarf2out_reg_save_reg (label
, stack_pointer_rtx
,
23319 SET_DEST (pattern
));
23322 gcc_unreachable ();
23327 /* APPLE LOCAL end v7 support. Merge from mainline */
23328 /* Output unwind directives for the start/end of a function. */
23331 arm_output_fn_unwind (FILE * f
, bool prologue
)
23333 if (!ARM_EABI_UNWIND_TABLES
)
23337 fputs ("\t.fnstart\n", f
);
23339 fputs ("\t.fnend\n", f
);
23343 arm_emit_tls_decoration (FILE *fp
, rtx x
)
23345 enum tls_reloc reloc
;
23348 val
= XVECEXP (x
, 0, 0);
23349 reloc
= INTVAL (XVECEXP (x
, 0, 1));
23351 output_addr_const (fp
, val
);
23356 fputs ("(tlsgd)", fp
);
23359 fputs ("(tlsldm)", fp
);
23362 fputs ("(tlsldo)", fp
);
23365 fputs ("(gottpoff)", fp
);
23368 fputs ("(tpoff)", fp
);
23371 gcc_unreachable ();
23379 fputs (" + (. - ", fp
);
23380 output_addr_const (fp
, XVECEXP (x
, 0, 2));
23382 output_addr_const (fp
, XVECEXP (x
, 0, 3));
23393 arm_output_addr_const_extra (FILE *fp
, rtx x
)
23395 if (GET_CODE (x
) == UNSPEC
&& XINT (x
, 1) == UNSPEC_TLS
)
23396 return arm_emit_tls_decoration (fp
, x
);
23397 else if (GET_CODE (x
) == UNSPEC
&& XINT (x
, 1) == UNSPEC_PIC_LABEL
)
23400 int labelno
= INTVAL (XVECEXP (x
, 0, 0));
23402 ASM_GENERATE_INTERNAL_LABEL (label
, "LPIC", labelno
);
23403 assemble_name_raw (fp
, label
);
23407 else if (GET_CODE (x
) == CONST_VECTOR
)
23408 return arm_emit_vector_const (fp
, x
);
23413 /* APPLE LOCAL begin ARM darwin local binding */
23415 /* Cross-module name binding. Darwin does not support overriding
23416 functions at dynamic-link time. */
23419 arm_binds_local_p (tree decl
)
23421 return default_binds_local_p_1 (decl
,
23422 flag_apple_kext
&& lang_hooks
.vtable_p (decl
));
23425 /* APPLE LOCAL end ARM darwin local binding */
23427 /* APPLE LOCAL begin ARM setjmp/longjmp interworking */
23429 arm_builtin_setjmp_frame_value (void)
23431 static rtx arm_hard_frame_pointer_rtx
;
23432 if (! arm_hard_frame_pointer_rtx
)
23433 arm_hard_frame_pointer_rtx
=
23434 gen_rtx_REG (Pmode
, ARM_HARD_FRAME_POINTER_REGNUM
);
23435 return arm_hard_frame_pointer_rtx
;
23437 /* APPLE LOCAL end ARM setjmp/longjmp interworking */
23439 /* APPLE LOCAL begin ARM optimization pragmas */
23440 /* Version of the above for use from #pragma optimization_level. Only
23441 per-function flags are reset. */
23444 reset_optimization_options (int level ATTRIBUTE_UNUSED
, int size ATTRIBUTE_UNUSED
)
23448 /* APPLE LOCAL end ARM optimization pragmas */
23450 /* APPLE LOCAL begin ARM pic support */
23451 #ifdef OBJECT_FORMAT_MACHO
23453 /* Generate PIC and indirect symbol stubs. */
23456 machopic_output_stub (FILE *file
, const char *symb
, const char *stub
)
23458 unsigned int length
;
23459 char *symbol_name
, *lazy_ptr_name
, *slp_label_name
;
23460 static int label
= 0;
23462 /* Lose our funky encoding stuff so it doesn't contaminate the stub. */
23463 symb
= (*targetm
.strip_name_encoding
) (symb
);
23465 length
= strlen (symb
);
23466 symbol_name
= alloca (length
+ 32);
23467 GEN_SYMBOL_NAME_FOR_SYMBOL (symbol_name
, symb
, length
);
23469 lazy_ptr_name
= alloca (length
+ 32);
23470 GEN_LAZY_PTR_NAME_FOR_SYMBOL (lazy_ptr_name
, symb
, length
);
23472 slp_label_name
= alloca (length
+ 32);
23473 GEN_SUFFIXED_NAME_FOR_SYMBOL (slp_label_name
, symb
, length
, "$slp");
23476 switch_to_section (darwin_sections
[machopic_picsymbol_stub4_section
]);
23478 switch_to_section (darwin_sections
[machopic_symbol_stub4_section
]);
23480 fprintf (file
, "\t.align 2\n");
23483 fprintf (file
, "\t.code 32\n");
23485 fprintf (file
, "%s:\n", stub
);
23486 fprintf (file
, "\t.indirect_symbol %s\n", symbol_name
);
23487 fprintf (file
, "\tldr\tip, %s\n", slp_label_name
);
23492 fprintf (file
, "L%d$scv:\tadd\tip, pc, ip\n", label
);
23494 fprintf (file
, "\tldr\tpc, [ip, #0]\n");
23497 fprintf (file
, "%s:\n\t.long\t%s - (L%d$scv + 8)\n",
23498 slp_label_name
, lazy_ptr_name
, label
);
23500 fprintf (file
, "%s:\n\t.long\t%s\n",
23501 slp_label_name
, lazy_ptr_name
);
23503 switch_to_section (darwin_sections
[machopic_lazy_symbol_ptr_section
]);
23504 fprintf (file
, "%s:\n", lazy_ptr_name
);
23505 fprintf (file
, "\t.indirect_symbol\t%s\n", symbol_name
);
23506 fprintf (file
, "\t.long\tdyld_stub_binding_helper\n");
23510 /* APPLE LOCAL end ARM pic support */
23512 /* APPLE LOCAL begin ARM MACH assembler */
23513 extern bool iasm_memory_clobber (const char *);
23515 /* FIXME: we can be more specific here. */
23516 bool iasm_memory_clobber (const char *ARG_UNUSED (opcode
))
23520 /* APPLE LOCAL end ARM MACH assembler */
23522 /* APPLE LOCAL begin ARM darwin optimization defaults */
23523 /* LLVM LOCAL fix warning on non-Darwin */
23525 optimization_options (int level ATTRIBUTE_UNUSED
, int size ATTRIBUTE_UNUSED
)
23527 /* disable strict aliasing; breaks too much existing code. */
23529 flag_strict_aliasing
= 0;
23531 /* Trapping math is not needed by many users, and is expensive.
23532 C99 permits us to default it off and we do that. It is
23533 turned on when <fenv.h> is included (see darwin_pragma_fenv
23535 flag_trapping_math
= 0;
23537 /* APPLE LOCAL conditionally disable local RA */
23538 flag_local_alloc
= 0;
23539 /* APPLE LOCAL rerun cse after combine */
23540 /* flag_rerun_cse_after_combine = 1; */
23542 /* For -O2 and beyond, turn off -fschedule-insns by default. It tends to
23543 make the problem with not enough registers even worse. */
23544 #ifdef INSN_SCHEDULING
23546 flag_schedule_insns
= 0;
23549 /* radar 4094534. */
23550 /* The Darwin libraries never set errno, so we might as well
23551 avoid calling them when that's the only reason we would. */
23552 flag_errno_math
= 0;
23555 #ifdef SUBTARGET_OPTIMIZATION_OPTIONS
23556 SUBTARGET_OPTIMIZATION_OPTIONS
;
23559 /* APPLE LOCAL end ARM darwin optimization defaults */
23561 /* APPLE LOCAL begin ARM prefer SP to FP */
23562 /* Stabs is so much fun. Stabs doesn't distinguish between a SP and a
23563 FP offset -- if your function has a frame pointer, it is assumed
23564 that is what offsets to locals are from. So, in the cases where we
23565 have a FP, but are using a SP anyway, we have to adjust the values
23568 arm_local_debug_offset (rtx var
)
23573 if (GET_CODE (var
) == PLUS
)
23575 reg
= REGNO (XEXP (var
, 0));
23576 offset
= INTVAL (XEXP (var
, 1));
23578 else if (GET_CODE (var
) == REG
)
23588 if (frame_pointer_needed
&& reg
== SP_REGNUM
)
23590 arm_stack_offsets
*offsets
= arm_get_frame_offsets();
23592 return offset
+ (offsets
->frame
- offsets
->outgoing_args
);
23597 /* APPLE LOCAL end ARM prefer SP to FP */
23599 /* APPLE LOCAL begin ARM compact switch tables */
23600 int arm_label_align (rtx label
)
23602 rtx insn
= NEXT_INSN (label
);
23604 && GET_CODE (insn
) == INSN
23605 && GET_CODE (PATTERN (insn
)) == UNSPEC_VOLATILE
)
23607 /* APPLE LOCAL 7083296 Build without warnings. */
23608 if (XINT (PATTERN (insn
), 1) == VUNSPEC_ALIGN
)
23610 /* APPLE LOCAL 7083296 Build without warnings. */
23611 if (XINT (PATTERN (insn
), 1) == VUNSPEC_ALIGN8
)
23614 return align_labels_log
;
23616 /* APPLE LOCAL end ARM compact switch tables */
23618 /* APPLE LOCAL begin v7 support. Merge from mainline */
23619 /* Output assembly for a shift instruction.
23620 SET_FLAGS determines how the instruction modifies the condition codes.
23621 0 - Do not set conditiona codes.
23622 1 - Set condition codes.
23623 2 - Use smallest instruction. */
23625 arm_output_shift(rtx
* operands
, int set_flags
)
23628 static const char flag_chars
[3] = {'?', '.', '!'};
23633 c
= flag_chars
[set_flags
];
23634 if (TARGET_UNIFIED_ASM
)
23636 shift
= shift_op(operands
[3], &val
);
23640 operands
[2] = GEN_INT(val
);
23641 sprintf (pattern
, "%s%%%c\t%%0, %%1, %%2", shift
, c
);
23644 sprintf (pattern
, "mov%%%c\t%%0, %%1", c
);
23647 sprintf (pattern
, "mov%%%c\t%%0, %%1%%S3", c
);
23648 output_asm_insn (pattern
, operands
);
23652 /* Output a Thumb-2 casesi instruction. */
23654 thumb2_output_casesi (rtx
*operands
)
23656 rtx diff_vec
= PATTERN (next_real_insn (operands
[2]));
23658 gcc_assert (GET_CODE (diff_vec
) == ADDR_DIFF_VEC
);
23660 output_asm_insn ("cmp\t%0, %1", operands
);
23661 output_asm_insn ("bhi\t%l3", operands
);
23662 switch (GET_MODE(diff_vec
))
23665 return "tbb\t[%|pc, %0]";
23667 return "tbh\t[%|pc, %0, lsl #1]";
23669 /* APPLE LOCAL begin 6152801 SImode thumb2 switch table dispatch */
23670 output_asm_insn ("adr\t%4, %l2", operands
);
23671 output_asm_insn ("add\t%4, %4, %0, lsl #2", operands
);
23672 return "mov\t%|pc, %4";
23673 /* APPLE LOCAL end 6152801 SImode thumb2 switch table dispatch */
23675 gcc_unreachable ();
23678 /* APPLE LOCAL end v7 support. Merge from mainline */
23679 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
23681 /* A table and a function to perform ARM-specific name mangling for
23682 NEON vector types in order to conform to the AAPCS (see "Procedure
23683 Call Standard for the ARM Architecture", Appendix A). To qualify
23684 for emission with the mangled names defined in that document, a
23685 vector type must not only be of the correct mode but also be
23686 composed of NEON vector element types (e.g. __builtin_neon_qi). */
23689 enum machine_mode mode
;
23690 const char *element_type_name
;
23691 const char *aapcs_name
;
23692 } arm_mangle_map_entry
;
23694 static arm_mangle_map_entry arm_mangle_map
[] = {
23695 /* 64-bit containerized types. */
23696 { V8QImode
, "__builtin_neon_qi", "15__simd64_int8_t" },
23697 { V8QImode
, "__builtin_neon_uqi", "16__simd64_uint8_t" },
23698 { V4HImode
, "__builtin_neon_hi", "16__simd64_int16_t" },
23699 { V4HImode
, "__builtin_neon_uhi", "17__simd64_uint16_t" },
23700 { V2SImode
, "__builtin_neon_si", "16__simd64_int32_t" },
23701 { V2SImode
, "__builtin_neon_usi", "17__simd64_uint32_t" },
23702 { V2SFmode
, "__builtin_neon_sf", "18__simd64_float32_t" },
23703 { V8QImode
, "__builtin_neon_poly8", "16__simd64_poly8_t" },
23704 { V4HImode
, "__builtin_neon_poly16", "17__simd64_poly16_t" },
23705 /* 128-bit containerized types. */
23706 { V16QImode
, "__builtin_neon_qi", "16__simd128_int8_t" },
23707 { V16QImode
, "__builtin_neon_uqi", "17__simd128_uint8_t" },
23708 { V8HImode
, "__builtin_neon_hi", "17__simd128_int16_t" },
23709 { V8HImode
, "__builtin_neon_uhi", "18__simd128_uint16_t" },
23710 { V4SImode
, "__builtin_neon_si", "17__simd128_int32_t" },
23711 { V4SImode
, "__builtin_neon_usi", "18__simd128_uint32_t" },
23712 { V4SFmode
, "__builtin_neon_sf", "19__simd128_float32_t" },
23713 { V16QImode
, "__builtin_neon_poly8", "17__simd128_poly8_t" },
23714 { V8HImode
, "__builtin_neon_poly16", "18__simd128_poly16_t" },
23715 { VOIDmode
, NULL
, NULL
}
23719 arm_mangle_type (tree type
)
23721 arm_mangle_map_entry
*pos
= arm_mangle_map
;
23723 if (TREE_CODE (type
) != VECTOR_TYPE
)
23726 /* Check the mode of the vector type, and the name of the vector
23727 element type, against the table. */
23728 while (pos
->mode
!= VOIDmode
)
23730 tree elt_type
= TREE_TYPE (type
);
23732 if (pos
->mode
== TYPE_MODE (type
)
23733 && TREE_CODE (TYPE_NAME (elt_type
)) == TYPE_DECL
23734 && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (elt_type
))),
23735 pos
->element_type_name
))
23736 return pos
->aapcs_name
;
23741 /* Use the default mangling for unrecognized (possibly user-defined)
23747 arm_asm_output_addr_diff_vec (FILE *file
, rtx label
, rtx body
)
23749 int idx
, size
= GET_MODE_SIZE (GET_MODE (body
));
23750 int pack
= (TARGET_THUMB
) ? 2 : 4;
23751 /* APPLE LOCAL 5837498 assembler expr for (L1-L2)/2 */
23752 /* removed unused variable "base_addr" */
23753 int base_label_no
= CODE_LABEL_NUMBER (label
);
23754 int vlen
= XVECLEN (body
, 1); /*includes trailing default */
23755 const char* directive
;
23756 if (GET_MODE (body
) == QImode
)
23757 directive
= ".byte";
23758 else if (GET_MODE (body
) == HImode
)
23759 directive
= ".short";
23763 directive
= ".long";
23765 /* Alignment of table was handled by aligning its label,
23766 in final_scan_insn. */
23767 targetm
.asm_out
.internal_label (file
, "L", base_label_no
);
23768 /* Default is not included in output count */
23769 if (TARGET_COMPACT_SWITCH_TABLES
)
23770 asm_fprintf (file
, "\t%s\t%d @ size\n", directive
, vlen
- 1);
23771 for (idx
= 0; idx
< vlen
; idx
++)
23773 rtx target_label
= XEXP (XVECEXP (body
, 1, idx
), 0);
23774 /* APPLE LOCAL begin 5837498 assembler expr for (L1-L2)/2 */
23775 if (GET_MODE (body
) != SImode
)
23777 /* ARM mode is always SImode bodies */
23778 asm_fprintf (file
, "\t%s\t(L%d-L%d)/%d\n",
23780 CODE_LABEL_NUMBER (target_label
), base_label_no
, pack
);
23782 /* APPLE LOCAL end 5837498 assembler expr for (L1-L2)/2 */
23783 /* APPLE LOCAL begin 6152801 SImode thumb2 switch table dispatch */
23784 else if (TARGET_ARM
)
23785 asm_fprintf (file
, "\tb\tL%d\n",
23786 CODE_LABEL_NUMBER (target_label
));
23787 else if (TARGET_THUMB2
)
23788 asm_fprintf (file
, "\tb.w\tL%d\n",
23789 CODE_LABEL_NUMBER (target_label
));
23790 /* APPLE LOCAL end 6152801 SImode thumb2 switch table dispatch */
23791 else if (TARGET_COMPACT_SWITCH_TABLES
|| flag_pic
)
23792 /* Let the assembler do the computation here; one case that
23793 uses is this is when there are asm's, which makes
23794 compile time computations unreliable. */
23795 asm_fprintf (file
, "\t%s\tL%d-L%d\n",
23797 CODE_LABEL_NUMBER (target_label
), base_label_no
);
23799 asm_fprintf (file
, "\t%s\tL%d\n", directive
,
23800 CODE_LABEL_NUMBER (target_label
));
23802 /* Pad to instruction boundary. */
23803 if (TARGET_COMPACT_SWITCH_TABLES
)
23804 vlen
= (vlen
+ 1/*count*/) * size
;
23806 vlen
= vlen
* size
;
23807 while (vlen
% pack
!= 0)
23809 asm_fprintf (file
, "\t%s\t0 @ pad\n", directive
);
23813 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
23815 /* APPLE LOCAL begin ARM enhance conditional insn generation */
23816 /* A C expression to modify the code described by the conditional if
23817 information CE_INFO, for the basic block BB, possibly updating the tests in
23818 TRUE_EXPR, and FALSE_EXPR for converting the && and || parts of if-then or
23819 if-then-else code to conditional instructions. Set either TRUE_EXPR or
23820 FALSE_EXPR to a null pointer if the tests cannot be converted. */
23822 /* p_true and p_false are given expressions of the form:
23824 (and (relop:CC (reg:CC) (const_int 0))
23825 (relop:CC (reg:CC) (const_int 0)))
23827 We try to simplify them to something that will work in a branch instruction.
23828 If we can't do anything useful, return; the caller will try to substitute
23829 the complex expression and will fail.
23830 Currently the true and false cases are not handled.
23831 It's surprising that there isn't already a routine somewhere that does this,
23832 but I couldn't find one. */
23835 arm_ifcvt_modify_multiple_tests (ce_if_block_t
*ce_info ATTRIBUTE_UNUSED
,
23836 basic_block bb ATTRIBUTE_UNUSED
,
23840 /* There is a dependency here on the order of codes in rtl.def,
23841 also an assumption that none of the useful enum values will
23842 collide with 0 or 1.
23843 Order is: NE EQ GE GT LE LT GEU GTU LEU LTU */
23844 static RTX_CODE and_codes
[10][10] =
23845 { { NE
, 0, GT
, GT
, LT
, LT
, GTU
, GTU
, LTU
, LTU
},
23846 { 0, EQ
, EQ
, 0, EQ
, 0, EQ
, 0, EQ
, 0 },
23847 { GT
, EQ
, GE
, GT
, EQ
, 0, 0, 0, 0, 0 },
23848 { GT
, 0, GT
, GT
, 0, 0, 0, 0, 0, 0 },
23849 { LT
, EQ
, EQ
, 0, LE
, LT
, 0, 0, 0, 0 },
23850 { LT
, 0, 0, 0, LT
, LT
, 0, 0, 0, 0 },
23851 { GTU
, EQ
, 0, 0, 0, 0, GEU
, GTU
, EQ
, 0 },
23852 { GTU
, 0, 0, 0, 0, 0, GTU
, GTU
, 0, 0 },
23853 { LTU
, EQ
, 0, 0, 0, 0, EQ
, 0, LEU
, LTU
},
23854 { LTU
, 0, 0, 0, 0, 0, 0, 0, LTU
, LTU
} };
23856 static RTX_CODE or_codes
[10][10] =
23857 { { NE
, 1, 1, NE
, 1, NE
, 1, NE
, 1, NE
},
23858 { 1, EQ
, GE
, GE
, LE
, LE
, GEU
, GEU
, LEU
, LEU
},
23859 { 1, GE
, GE
, GE
, 1, 1, 0, 0, 0, 0 },
23860 { NE
, GE
, GE
, GT
, 1, NE
, 0, 0, 0, 0 },
23861 { 1, LE
, 1, 1, LE
, LE
, 0, 0, 0, 0 },
23862 { NE
, LE
, 1, NE
, LE
, LT
, 0, 0, 0, 0 },
23863 { 1, GEU
, 0, 0, 0, 0, GEU
, GEU
, 1, 1 },
23864 { NE
, GEU
, 0, 0, 0, 0, GEU
, GTU
, 1, NE
},
23865 { 1, LEU
, 0, 0, 0, 0, 1, 1, LEU
, LEU
},
23866 { NE
, LEU
, 0, 0, 0, 0, 1, NE
, LEU
, LTU
} };
23868 rtx true_lhs
= XEXP (*p_true
, 0);
23869 rtx false_lhs
= XEXP (*p_false
, 0);
23870 rtx true_rhs
= XEXP (*p_true
, 1);
23871 rtx false_rhs
= XEXP (*p_false
, 1);
23872 int true_and_p
, false_and_p
;
23873 RTX_CODE merged_code
;
23878 if (GET_CODE (*p_true
) == AND
)
23880 else if (GET_CODE (*p_true
) == IOR
)
23881 true_and_p
= false;
23885 if (GET_CODE (*p_false
) == AND
)
23886 false_and_p
= true;
23887 else if (GET_CODE (*p_false
) == IOR
)
23888 false_and_p
= false;
23892 if (!cc_register (XEXP (true_lhs
, 0), CCmode
)
23893 || !cc_register (XEXP (true_lhs
, 0), CCmode
)
23894 || !cc_register (XEXP (true_lhs
, 0), CCmode
)
23895 || !cc_register (XEXP (true_lhs
, 0), CCmode
))
23898 if (XEXP (true_lhs
, 1) != const0_rtx
23899 || XEXP (true_rhs
, 1) != const0_rtx
23900 || XEXP (false_lhs
, 1) != const0_rtx
23901 || XEXP (false_rhs
, 1) != const0_rtx
)
23904 if (GET_CODE (true_lhs
) < NE
|| GET_CODE (true_lhs
) > LTU
23905 || GET_CODE (true_rhs
) < NE
|| GET_CODE (true_rhs
) > LTU
)
23910 merged_code
= and_codes
[GET_CODE (true_lhs
) - NE
][GET_CODE (true_rhs
) - NE
];
23912 merged_code
= or_codes
[GET_CODE (true_lhs
) - NE
][GET_CODE (true_rhs
) - NE
];
23913 if (merged_code
== 0 || merged_code
== 1)
23916 *p_true
= gen_rtx_fmt_ee (merged_code
, VOIDmode
, gen_rtx_REG (CCmode
, CC_REGNUM
), const0_rtx
);
23919 if (GET_CODE (false_lhs
) < NE
|| GET_CODE (false_lhs
) > LTU
23920 || GET_CODE (false_rhs
) < NE
|| GET_CODE (false_rhs
) > LTU
)
23925 merged_code
= and_codes
[GET_CODE (false_lhs
) - NE
][GET_CODE (false_rhs
) - NE
];
23927 merged_code
= or_codes
[GET_CODE (false_lhs
) - NE
][GET_CODE (false_rhs
) - NE
];
23928 if (merged_code
== 0 || merged_code
== 1)
23931 *p_false
= gen_rtx_fmt_ee (merged_code
, VOIDmode
, gen_rtx_REG (CCmode
, CC_REGNUM
), const0_rtx
);
23934 /* APPLE LOCAL end ARM enhance conditional insn generation */
23936 /* APPLE LOCAL begin 5946347 ms_struct support */
23937 /* Handle a "ms_struct" attribute; arguments as in struct
23938 attribute_spec.handler. */
23940 arm_handle_ms_struct_attribute (tree
*node
, tree name
,
23941 tree args ATTRIBUTE_UNUSED
,
23942 int flags ATTRIBUTE_UNUSED
, bool *no_add_attrs
)
23945 if (DECL_P (*node
))
23947 if (TREE_CODE (*node
) == TYPE_DECL
)
23948 type
= &TREE_TYPE (*node
);
23953 if (!(type
&& (TREE_CODE (*type
) == RECORD_TYPE
23954 || TREE_CODE (*type
) == UNION_TYPE
)))
23956 warning (OPT_Wattributes
, "%qs attribute ignored",
23957 IDENTIFIER_POINTER (name
));
23958 *no_add_attrs
= true;
23960 else if (lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (*type
)))
23962 warning (OPT_Wattributes
, "%qs incompatible attribute ignored",
23963 IDENTIFIER_POINTER (name
));
23964 *no_add_attrs
= true;
23970 /* Handle a "gcc_struct" attribute; arguments as in struct
23971 attribute_spec.handler. */
23973 arm_handle_gcc_struct_attribute (tree
*node
, tree name
,
23974 tree args ATTRIBUTE_UNUSED
,
23975 int flags ATTRIBUTE_UNUSED
, bool *no_add_attrs
)
23978 if (DECL_P (*node
))
23980 if (TREE_CODE (*node
) == TYPE_DECL
)
23981 type
= &TREE_TYPE (*node
);
23986 if (!(type
&& (TREE_CODE (*type
) == RECORD_TYPE
23987 || TREE_CODE (*type
) == UNION_TYPE
)))
23989 warning (OPT_Wattributes
, "%qs attribute ignored",
23990 IDENTIFIER_POINTER (name
));
23991 *no_add_attrs
= true;
23993 else if (lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (*type
)))
23995 /* ms_struct may be on the type by default (-mms-bitfields or
23996 #pragma ms_struct), so gcc_struct simply means that if there
23997 is an ms_struct attribute on type, remove it. */
23998 remove_attribute ("ms_struct", TYPE_ATTRIBUTES (*type
));
23999 *no_add_attrs
= true;
24006 arm_ms_bitfield_layout_p (tree record_type
)
24008 return (lookup_attribute ("ms_struct",
24009 TYPE_ATTRIBUTES (record_type
)) != NULL
);
24012 /* Return the alignment necessary for the field when it's part of
24013 an ms_struct attributed structure. */
24015 arm_field_ms_struct_align (tree field
)
24017 tree type
= TREE_TYPE (field
);
24020 if (TREE_CODE (type
) == RECORD_TYPE
|| TREE_CODE (type
) == UNION_TYPE
)
24021 desired_align
= TYPE_ALIGN (type
);
24024 enum machine_mode mode
;
24025 /* For non-aggregate types of BIGGEST_ALIGNMENT bits or greater,
24026 the alignment should be the size of the type. For arrays, it
24027 should be the alignement of the members of the array. */
24028 mode
= TYPE_MODE (TREE_CODE (type
) == ARRAY_TYPE
24029 ? get_inner_array_type (type
) : type
);
24030 desired_align
= GET_MODE_BITSIZE (mode
) > BIGGEST_ALIGNMENT
?
24031 GET_MODE_BITSIZE (mode
) : TYPE_ALIGN (type
);
24032 gcc_assert (desired_align
<= BIGGEST_MS_STRUCT_ALIGNMENT
);
24034 return desired_align
;
24037 /* APPLE LOCAL end 5946347 ms_struct support */
24039 /* APPLE LOCAL begin ARM 6008578 */
24040 /* Minimum alignment of a function entry point, in bits. */
24042 arm_function_boundary (void)
24044 /* APPLE LOCAL 6357106 thumb2 functions should be 4-byte aligned */
24045 int min_align
= TARGET_32BIT
? 32 : 16;
24047 /* Even in Thumb mode, thunks are output as ARM functions. */
24048 if (cfun
&& current_function_is_thunk
)
24049 min_align
= MAX (min_align
, 32);
24051 /* e.g., Thumb functions with jump tables. */
24052 if (cfun
&& cfun
->needs_4byte_alignment
)
24053 min_align
= MAX (min_align
, 32);
24055 /* If -falign-loops was specified, use that alignment. This is _not_
24056 needed to guarantee that loop alignments within the function are
24057 honored -- that's handled by the assembler and linker. However,
24058 if we don't align the function, then our address calculations (in
24059 arm_reorg) are incorrect, potentially wreaking havoc on the
24060 constant pool calculations. */
24061 min_align
= MAX (min_align
, align_loops
* BITS_PER_UNIT
);
24065 /* APPLE LOCAL end ARM 6008578 */
24067 /* APPLE LOCAL begin 6160917 */
24068 /* Handle the cases where SECONDARY_INPUT_RELOAD_CLASS said that we
24069 needed a scratch register. Currently, we only handle the case
24070 where there was indexed literal addressing with an out-of-range
24073 neon_reload_in (rtx
*operands
, enum machine_mode mode
)
24075 if (GET_CODE (operands
[1]) == MEM
)
24077 rtx mem_addr
= XEXP (operands
[1], 0);
24078 if (GET_CODE (mem_addr
) == PLUS
24079 && GET_CODE (XEXP (mem_addr
, 0)) == REG
24080 && REG_MODE_OK_FOR_BASE_P (XEXP (mem_addr
, 0), VOIDmode
)
24081 && ! arm_legitimate_index_p (mode
, XEXP (mem_addr
, 1), SET
, 0))
24085 /* Load the address into the scratch register provided,
24086 and then indirect it. */
24087 emit_move_insn (operands
[2], mem_addr
);
24088 scratch
= gen_rtx_MEM (mode
, operands
[2]);
24089 emit_move_insn (operands
[0], scratch
);
24093 /* If you reach here, SECONDARY_INPUT_RELOAD_CLASS is indicating that
24094 a scratch register is needed, but we don't have any code to
24095 handle it. Add that code here. */
24096 gcc_unreachable ();
24099 /* Handle the cases where SECONDARY_OUTPUT_RELOAD_CLASS said that we
24100 needed a scratch register. Currently, we only handle the case
24101 where there was indexed literal addressing with an out-of-range
24104 neon_reload_out (rtx
*operands
, enum machine_mode mode
)
24106 if (GET_CODE (operands
[0]) == MEM
)
24108 rtx mem_addr
= XEXP (operands
[0], 0);
24109 if (GET_CODE (mem_addr
) == PLUS
24110 && GET_CODE (XEXP (mem_addr
, 0)) == REG
24111 && REG_MODE_OK_FOR_BASE_P (XEXP (mem_addr
, 0), VOIDmode
)
24112 && ! arm_legitimate_index_p (mode
, XEXP (mem_addr
, 1), SET
, 0))
24116 /* Load the address into the scratch register provided,
24117 and then indirect it. */
24118 emit_move_insn (operands
[2], mem_addr
);
24119 scratch
= gen_rtx_MEM (mode
, operands
[2]);
24120 emit_move_insn (scratch
, operands
[1]);
24124 /* If you reach here, SECONDARY_OUTPUT_RELOAD_CLASS is indicating that
24125 a scratch register is needed, but we don't have any code to
24126 handle it. Add that code here. */
24127 gcc_unreachable ();
24129 /* APPLE LOCAL end 6160917 */
24131 /* APPLE LOCAL begin 5571707 Allow R9 as caller-saved register */
24132 /* For v4 and v5, we always reserve R9 for thread local data. For v6 and
24133 v7, we can make it available when the target is iPhoneOS v3.0 or later. */
24135 arm_darwin_subtarget_conditional_register_usage (void)
24137 if (!(arm_arch6
&& !darwin_reserve_r9_on_v6
) && !arm_arch7a
)
24139 call_used_regs
[9] = 1;
24143 fixed_regs
[THUMB_HARD_FRAME_POINTER_REGNUM
] = 1;
24144 call_used_regs
[THUMB_HARD_FRAME_POINTER_REGNUM
] = 1;
24145 global_regs
[THUMB_HARD_FRAME_POINTER_REGNUM
] = 1;
24148 /* APPLE LOCAL end 5571707 Allow R9 as caller-saved register */
24150 /* APPLE LOCAL begin 6902792 Q register clobbers in inline asm */
24151 /* Worker function for TARGET_MD_ASM_CLOBBERS.
24152 We do this to translate references to Qn registers into the equivalent
24153 D(2n)/D(2n+1) register pairs. */
24155 arm_md_asm_clobbers (tree outputs ATTRIBUTE_UNUSED
,
24156 tree inputs ATTRIBUTE_UNUSED
,
24161 for (tail
= clobbers
; tail
; tail
= TREE_CHAIN (tail
))
24163 const char *clobber_name
;
24164 clobber_name
= TREE_STRING_POINTER (TREE_VALUE (tail
));
24165 if (TOLOWER (clobber_name
[0]) == 'q' && ISDIGIT (clobber_name
[1])
24166 && (ISDIGIT (clobber_name
[2]) || clobber_name
[2] == '\0'))
24168 char regname
[4] = "dXX";
24169 /* found a Q register in the clobber list, so add the D reference
24170 to the upper dword of it. The existing clobber for the Q
24171 register will automatically translate to the low dword. */
24172 int regno
= atoi (clobber_name
+ 1) * 2 + 1;
24173 snprintf (regname
+ 1, 3, "%d", regno
);
24175 tree_cons (NULL_TREE
, build_string (strlen(regname
), regname
),
24181 /* APPLE LOCAL end 6902792 Q register clobbers in inline asm */
24183 #include "gt-arm.h"