Missed part from my V1DI'fication. This makes something around 50
[llvm-gcc-4.2.git] / gcc / config / arm / arm.c
blob981b6d77e3cb65ecc37b140b3c01e8a3e90825fc
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 */
26 #include <stdlib.h>
27 /* APPLE LOCAL end 6902792 Q register clobbers in inline asm */
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tm.h"
32 #include "rtl.h"
33 #include "tree.h"
34 #include "obstack.h"
35 #include "regs.h"
36 #include "hard-reg-set.h"
37 #include "real.h"
38 #include "insn-config.h"
39 #include "conditions.h"
40 #include "output.h"
41 #include "insn-attr.h"
42 #include "flags.h"
43 #include "reload.h"
44 #include "function.h"
45 #include "expr.h"
46 #include "optabs.h"
47 #include "toplev.h"
48 #include "recog.h"
49 #include "ggc.h"
50 #include "except.h"
51 #include "c-pragma.h"
52 #include "integrate.h"
53 #include "tm_p.h"
54 #include "target.h"
55 #include "target-def.h"
56 #include "debug.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 */
61 #include "params.h"
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);
88 #ifndef AOF_ASSEMBLER
89 static bool arm_assemble_integer (rtx, unsigned int, int);
90 #endif
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 */
95 #ifndef ENABLE_LLVM
96 static rtx is_jump_table (rtx);
97 #endif
98 /* LLVM LOCAL end */
99 static const char *output_multi_immediate (rtx *, const char *, const char *,
100 int, HOST_WIDE_INT);
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 */
110 #ifndef ENABLE_LLVM
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,
123 rtx);
124 #endif
125 /* LLVM LOCAL end */
126 static void arm_reorg (void);
127 /* LLVM LOCAL begin */
128 #ifndef ENABLE_LLVM
129 static bool note_invalid_constants (rtx, HOST_WIDE_INT, int);
130 #endif
131 /* LLVM LOCAL end */
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 *);
141 #endif
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,
154 tree);
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 */
163 #ifndef ENABLE_LLVM
164 static bool arm_memory_load_p (rtx);
165 static bool arm_cirrus_insn_p (rtx);
166 static void cirrus_reorg (rtx);
167 #endif
168 /* LLVM LOCAL end */
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,
179 tree, bool);
181 #ifdef OBJECT_FORMAT_ELF
182 static void arm_elf_asm_constructor (rtx, int);
183 #endif
184 /* APPLE LOCAL begin ARM darwin section_info */
185 #if TARGET_MACHO
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);
189 #endif
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 */
197 #if TARGET_MACHO
198 static void arm_darwin_file_start (void);
199 static void arm_darwin_file_end (void);
200 #endif
201 /* APPLE LOCAL end ARM asm file hooks */
203 #ifdef AOF_ASSEMBLER
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);
210 #endif
211 static void arm_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
212 tree, int *, int);
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);
223 #endif
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 */
250 #if TARGET_MACHO
251 static bool arm_binds_local_p (tree);
252 #endif
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 */
261 #ifndef ENABLE_LLVM
262 static HOST_WIDE_INT get_label_pad (rtx, HOST_WIDE_INT);
263 #endif
264 /* LLVM LOCAL end */
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
273 #endif
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 */
282 #if TARGET_MACHO
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
287 #endif
288 /* APPLE LOCAL end ARM asm file hooks */
290 #ifdef AOF_ASSEMBLER
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
303 #else
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
308 #endif
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"
314 #endif
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
339 #ifdef ARM_PE
340 #define TARGET_ENCODE_SECTION_INFO arm_pe_encode_section_info
341 /* APPLE LOCAL begin ARM darwin section_info */
342 #elif TARGET_MACHO
343 #define TARGET_ENCODE_SECTION_INFO arm_darwin_encode_section_info
344 /* APPLE LOCAL end ARM darwin section_info */
345 #else
346 #define TARGET_ENCODE_SECTION_INFO arm_encode_section_info
347 #endif
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
467 #ifdef HAVE_AS_TLS
468 #undef TARGET_HAVE_TLS
469 #define TARGET_HAVE_TLS true
470 #endif
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 */
488 #if TARGET_MACHO
489 #undef TARGET_BINDS_LOCAL_P
490 #define TARGET_BINDS_LOCAL_P arm_binds_local_p
491 #endif
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'
604 profile. */
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
644 be used. */
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. */
651 int arm_arch3m = 0;
653 /* Nonzero if this chip supports the ARM Architecture 4 extensions. */
654 int arm_arch4 = 0;
656 /* Nonzero if this chip supports the ARM Architecture 4t extensions. */
657 int arm_arch4t = 0;
659 /* Nonzero if this chip supports the ARM Architecture 5 extensions. */
660 int arm_arch5 = 0;
662 /* Nonzero if this chip supports the ARM Architecture 5E extensions. */
663 int arm_arch5e = 0;
665 /* Nonzero if this chip supports the ARM Architecture 6 extensions. */
666 int arm_arch6 = 0;
668 /* Nonzero if this chip supports the ARM 6K extensions. */
669 int arm_arch6k = 0;
671 /* APPLE LOCAL begin 6093388 -mfpu=neon default for v7a */
672 /* Nonzero if this chip supports the ARM 7A extensions. */
673 int arm_arch7a = 0;
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. */
704 int thumb_code = 0;
706 /* Nonzero if we should define __THUMB_INTERWORK__ in the
707 preprocessor.
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. */
715 int arm_arch_thumb2;
717 /* Nonzero if chip supports integer division instruction. */
718 int arm_arch_hwdiv;
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
730 is not needed. */
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. */
741 int arm_ccfsm_state;
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;
745 rtx arm_target_insn;
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. */
774 struct processors
776 const char *const name;
777 enum processor_type core;
778 const char *arch;
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[] =
787 /* ARM 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"
791 #undef ARM_CORE
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
799 from the core. */
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 */
809 #if TARGET_MACHO
810 {"armv4t", arm7tdmi, "4T", FL_CO_PROC | FL_FOR_ARCH4, NULL},
811 #else
812 {"armv4t", arm7tdmi, "4T", FL_CO_PROC | FL_FOR_ARCH4T, NULL},
813 #endif
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 */
820 #if TARGET_MACHO
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},
826 #else
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},
830 #endif
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
853 const char * string;
854 const char * name;
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 */
882 struct fpu_desc
884 const char * name;
885 enum fputype fpu;
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 */
926 struct float_abi
928 const char * name;
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}
943 struct abi_name
945 const char *name;
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. */
963 enum tls_reloc {
964 TLS_GD32,
965 TLS_LDM32,
966 TLS_LDO32,
967 TLS_IE32,
968 TLS_LE32
971 /* Emit an insn that's a simple single-set. Both the operands must be known
972 to be valid. */
973 inline static rtx
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. */
980 static unsigned
981 bit_count (unsigned long value)
983 unsigned long count = 0;
985 while (value)
987 count++;
988 value &= value - 1; /* Clear the least-significant set bit. */
991 return count;
994 /* APPLE LOCAL begin ARM custom frame layout */
995 /* Generate a bitmask that has bits end:start (inclusive) set. */
996 static unsigned long
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)
1012 #if TARGET_MACHO
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));
1019 #endif
1022 void register_switchu8_libfunc (void)
1024 #if TARGET_MACHO
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));
1031 #endif
1034 void register_switch16_libfunc (void)
1036 #if TARGET_MACHO
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));
1043 #endif
1046 void register_switch32_libfunc (void)
1048 #if TARGET_MACHO
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));
1055 #endif
1057 /* APPLE LOCAL end ARM compact switch tables */
1059 /* Set up library functions unique to ARM. */
1061 static void
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");
1119 return;
1121 /* APPLE LOCAL end ARM 4702983 Thumb VFP math */
1123 /* There are no special library functions unless we are using the
1124 ARM BPABI. */
1125 if (!TARGET_BPABI)
1126 return;
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
1209 routines. */
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. */
1228 static bool
1229 arm_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
1231 switch (code)
1233 case OPT_march_:
1234 arm_select[1].string = arg;
1235 return true;
1237 case OPT_mcpu_:
1238 arm_select[0].string = arg;
1239 return true;
1241 case OPT_mhard_float:
1242 target_float_abi_name = "hard";
1243 return true;
1245 case OPT_msoft_float:
1246 target_float_abi_name = "soft";
1247 return true;
1249 case OPT_mtune_:
1250 arm_select[2].string = arg;
1251 return true;
1253 default:
1254 return true;
1258 /* Fix up any incompatible options that the user has specified.
1259 This has now turned into a maze. */
1260 void
1261 arm_override_options (void)
1263 unsigned i;
1264 /* APPLE LOCAL v7 support. Merge from Codesourcery */
1265 int len;
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
1301 options. */
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 */
1308 #if !TARGET_MACHO
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
1312 architecture. */
1313 if (insn_flags != 0 && (insn_flags ^ sel->flags))
1314 warning (0, "switch -mcpu=%s conflicts with -march= switch",
1315 ptr->string);
1316 #else
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. */
1321 #endif
1322 /* APPLE LOCAL end ARM darwin driver */
1324 insn_flags = sel->flags;
1327 break;
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
1351 configure. */
1352 cpu = SUBTARGET_CPU_DEFAULT;
1353 #endif
1354 /* Default to ARM6. */
1355 if (cpu == arm_none)
1356 cpu = arm6;
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. */
1364 sought = 0;
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
1381 the user. */
1382 for (sel = all_cores; sel->name != NULL; sel++)
1383 if ((sel->flags & sought) == (sought | insn_flags))
1384 break;
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)
1405 unsigned count;
1407 count = bit_count (sel->flags & insn_flags);
1409 if (count >= current_bit_count)
1411 best_fit = sel;
1412 current_bit_count = count;
1416 gcc_assert (best_fit);
1417 sel = 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
1435 chosen. */
1436 gcc_assert (arm_tune != arm_none);
1438 tune_flags = all_cores[(int)arm_tune].flags;
1439 if (optimize_size)
1440 targetm.rtx_costs = arm_size_rtx_costs;
1441 else
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 */
1455 if (! TARGET_MACHO)
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
1464 codegen. */
1465 if ((insn_flags & FL_FOR_ARCH7A) == FL_FOR_ARCH7A
1466 && thumb_option < 0)
1467 thumb_option = 1;
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 */
1474 thumb_option = 0;
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. */
1517 if (TARGET_ARM
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. */
1566 if (TARGET_THUMB1)
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
1588 command line. */
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;
1605 break;
1608 if (i == ARRAY_SIZE (arm_all_abis))
1609 error ("invalid ABI option: -mabi=%s", target_abi_name);
1611 else
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";
1627 else
1628 error ("invalid floating point emulation option: -mfpe=%s",
1629 target_fpe_name);
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];
1641 break;
1644 if (arm_fp_model == ARM_FP_MODEL_UNKNOWN)
1645 error ("invalid floating point option: -mfpu=%s", target_fpu_name);
1647 else
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;
1653 #else
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;
1658 else
1660 if (arm_arch_cirrus)
1661 arm_fpu_arch = FPUTYPE_MAVERICK;
1662 else
1663 arm_fpu_arch = FPUTYPE_FPA_EMU2;
1664 #endif
1665 if (tune_flags & FL_CO_PROC && arm_fpu_arch == FPUTYPE_FPA_EMU2)
1666 arm_fpu_tune = FPUTYPE_FPA;
1667 else
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;
1681 break;
1684 if (i == ARRAY_SIZE (all_float_abis))
1685 error ("invalid floating point abi: -mfloat-abi=%s",
1686 target_float_abi_name);
1688 else
1689 arm_float_abi = TARGET_DEFAULT_FLOAT_ABI;
1691 /* LLVM LOCAL begin */
1692 #ifndef ENABLE_LLVM
1693 if (arm_float_abi == ARM_FLOAT_ABI_HARD && TARGET_VFP)
1694 sorry ("-mfloat-abi=hard and VFP");
1695 #endif
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;
1730 else
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;
1739 else
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;
1759 else
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);
1768 if (!flag_pic)
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);
1777 else
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;
1789 if (optimize_size)
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;
1797 else
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. */
1802 if (arm_ld_sched)
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;
1820 #endif
1822 #ifdef SUBSUBTARGET_OVERRIDE_OPTIONS
1823 SUBSUBTARGET_OVERRIDE_OPTIONS;
1824 #endif
1825 /* APPLE LOCAL end ARM darwin options */
1827 /* Register global variables with the garbage collector. */
1828 arm_add_gc_roots ();
1831 static void
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. */
1841 typedef struct
1843 const char *const arg;
1844 const unsigned long return_value;
1846 isr_attribute_arg;
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;
1872 const char * arg;
1874 /* APPLE LOCAL begin v7 support. Merge from mainline */
1875 if (!arm_arch_notm)
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)
1881 return ARM_FT_ISR;
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;
1905 tree a;
1906 tree attr;
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. */
1914 if (optimize > 0
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);
1927 if (a != NULL_TREE)
1928 type |= ARM_FT_NAKED;
1930 a = lookup_attribute ("isr", attr);
1931 if (a == NULL_TREE)
1932 a = lookup_attribute ("interrupt", attr);
1934 if (a == NULL_TREE)
1935 /* APPLE LOCAL ARM interworking */
1936 type |= (TARGET_INTERWORK && !arm_arch5) ? ARM_FT_INTERWORKED : ARM_FT_NORMAL;
1937 else
1938 type |= arm_isr_value (TREE_VALUE (a));
1940 return type;
1943 /* Returns the type of the current function. */
1945 unsigned long
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.) */
1961 static int
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)
1970 *is_value = 0;
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)
1980 *is_value = 1;
1981 return REGNO (XEXP (XEXP (XEXP (XVECEXP (PATTERN (sibling), 0, 0), 1), 0), 0));
1983 return -1;
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. */
1999 static rtx
2000 indirect_sibreturn_mem (rtx sibling, rtx* reg, bool *is_value)
2002 rtx mem = NULL_RTX;
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)
2009 *is_value = 0;
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)
2019 *is_value = 1;
2020 mem = XEXP (XEXP (XEXP (XVECEXP (PATTERN (sibling), 0, 0), 1), 0), 0);
2022 if (mem
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);
2033 return const0_rtx;
2035 return NULL_RTX;
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)
2046 int regno;
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)
2054 return 0;
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
2060 consideration. */
2061 if (func_type & (ARM_FT_VOLATILE | ARM_FT_NAKED | ARM_FT_STACKALIGN))
2062 return 0;
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))
2067 return 0;
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 */
2084 return 0;
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
2100 chips. */
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])
2107 return 0;
2109 /* ... that it isn't being used for a return value ... */
2110 if (arm_size_return_regs () >= (4 * UNITS_PER_WORD))
2111 return 0;
2113 /* ... or for a tail-call argument ... */
2114 if (sibling)
2116 gcc_assert (GET_CODE (sibling) == CALL_INSN);
2118 if (find_regno_fusage (sibling, USE, 3))
2119 return 0;
2121 /* APPLE LOCAL begin ARM indirect sibcalls */
2122 /* ... or to hold the target address for an indirect sibcall. */
2124 bool ignored;
2125 int regno = indirect_sibreturn_reg (sibling, &ignored);
2126 if (regno == 3)
2127 return 0;
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)
2135 return 0;
2138 /* Can't be done if interworking with Thumb, and any registers have been
2139 stacked. */
2140 /* APPLE LOCAL ARM interworking */
2141 if (TARGET_INTERWORK && !arm_arch5 && saved_int_regs != 0)
2142 return 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))
2151 return 0;
2153 if (flag_pic
2154 && arm_pic_register != INVALID_REGNUM
2155 && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
2156 return 0;
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)))
2162 return 0;
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. */
2167 if (sibling)
2169 bool ignored;
2170 int regno = indirect_sibreturn_reg (sibling, &ignored);
2171 if (regno > 3 && regno != 12)
2172 return 0;
2173 if (regno == -1)
2174 return 0;
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])
2183 return 0;
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])
2189 return 0;
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])
2194 return 0;
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
2199 instruction. */
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))
2203 return 0;
2204 /* APPLE LOCAL end ARM custom frame layout */
2206 return 1;
2209 /* Return TRUE if int I is a valid immediate ARM constant. */
2212 const_ok_for_arm (HOST_WIDE_INT i)
2214 int lowbit;
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)))
2222 return FALSE;
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)
2229 return TRUE;
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. */
2237 if (TARGET_ARM)
2238 lowbit &= ~1;
2240 if ((i & ~(((unsigned HOST_WIDE_INT) 0xff) << lowbit)) == 0)
2241 return TRUE;
2243 if (TARGET_ARM)
2245 /* Allow rotated constants in ARM mode. */
2246 if (lowbit <= 4
2247 && ((i & ~0xc000003f) == 0
2248 || (i & ~0xf000000f) == 0
2249 || (i & ~0xfc000003) == 0))
2250 return TRUE;
2252 else
2254 HOST_WIDE_INT v;
2256 /* Allow repeated pattern. */
2257 v = i & 0xff;
2258 v |= v << 16;
2259 if (i == v || i == (v | (v << 8)))
2260 return TRUE;
2263 /* APPLE LOCAL end v7 support. Merge from mainline */
2264 return FALSE;
2267 /* Return true if I is a valid constant for the operation CODE. */
2268 static int
2269 const_ok_for_op (HOST_WIDE_INT i, enum rtx_code code)
2271 if (const_ok_for_arm (i))
2272 return 1;
2274 switch (code)
2276 case PLUS:
2277 return const_ok_for_arm (ARM_SIGN_EXTEND (-i));
2279 case MINUS: /* Should only occur with (MINUS I reg) => rsb */
2280 case XOR:
2281 case IOR:
2282 return 0;
2284 case AND:
2285 return const_ok_for_arm (ARM_SIGN_EXTEND (~i));
2287 default:
2288 gcc_unreachable ();
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)
2308 rtx cond;
2310 if (insn && GET_CODE (PATTERN (insn)) == COND_EXEC)
2311 cond = COND_EXEC_TEST (PATTERN (insn));
2312 else
2313 cond = NULL_RTX;
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
2329 && !cond
2330 && (arm_gen_constant (code, mode, NULL_RTX, val, target, source,
2331 1, 0)
2332 > arm_constant_limit + (code != SET)))
2334 if (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));
2339 return 1;
2341 else
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. */
2348 if (code == MINUS)
2349 emit_set_insn (target, gen_rtx_MINUS (mode, temp, source));
2350 else
2351 emit_set_insn (target,
2352 gen_rtx_fmt_ee (code, mode, source, temp));
2353 return 2;
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
2364 constant. */
2365 /* APPLE LOCAL end v7 support. Merge from mainline */
2366 static int
2367 count_insns_for_constant (HOST_WIDE_INT remainder, int i)
2369 HOST_WIDE_INT temp1;
2370 int num_insns = 0;
2373 int end;
2375 if (i <= 0)
2376 i += 32;
2377 if (remainder & (3 << (i - 2)))
2379 end = i - 8;
2380 if (end < 0)
2381 end += 32;
2382 temp1 = remainder & ((0x0ff << end)
2383 | ((i < end) ? (0xff >> (32 - end)) : 0));
2384 remainder &= ~temp1;
2385 num_insns++;
2386 i -= 6;
2388 i -= 2;
2389 } while (remainder);
2390 return num_insns;
2393 /* Emit an instruction with the indicated PATTERN. If COND is
2394 non-NULL, conditionalize the execution of the instruction on COND
2395 being true. */
2397 static void
2398 emit_constant_insn (rtx cond, rtx pattern)
2400 if (cond)
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
2406 RTL generation. */
2407 /* APPLE LOCAL v7 support. Merge from mainline */
2408 /* ??? This needs more work for thumb2. */
2410 static int
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,
2413 int generate)
2415 int can_invert = 0;
2416 int can_negate = 0;
2417 int can_negate_initial = 0;
2418 int can_shift = 0;
2419 int i;
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;
2425 int insns = 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
2431 are split. */
2432 switch (code)
2434 case SET:
2435 can_invert = 1;
2436 can_shift = 1;
2437 can_negate = 1;
2438 break;
2440 case PLUS:
2441 can_negate = 1;
2442 can_negate_initial = 1;
2443 break;
2445 case IOR:
2446 if (remainder == 0xffffffff)
2448 if (generate)
2449 emit_constant_insn (cond,
2450 gen_rtx_SET (VOIDmode, target,
2451 GEN_INT (ARM_SIGN_EXTEND (val))));
2452 return 1;
2454 if (remainder == 0)
2456 if (reload_completed && rtx_equal_p (target, source))
2457 return 0;
2458 if (generate)
2459 emit_constant_insn (cond,
2460 gen_rtx_SET (VOIDmode, target, source));
2461 return 1;
2463 break;
2465 case AND:
2466 if (remainder == 0)
2468 if (generate)
2469 emit_constant_insn (cond,
2470 gen_rtx_SET (VOIDmode, target, const0_rtx));
2471 return 1;
2473 if (remainder == 0xffffffff)
2475 if (reload_completed && rtx_equal_p (target, source))
2476 return 0;
2477 if (generate)
2478 emit_constant_insn (cond,
2479 gen_rtx_SET (VOIDmode, target, source));
2480 return 1;
2482 can_invert = 1;
2483 break;
2485 case XOR:
2486 if (remainder == 0)
2488 if (reload_completed && rtx_equal_p (target, source))
2489 return 0;
2490 if (generate)
2491 emit_constant_insn (cond,
2492 gen_rtx_SET (VOIDmode, target, source));
2493 return 1;
2496 /* We don't know how to handle other cases yet. */
2497 gcc_assert (remainder == 0xffffffff);
2499 if (generate)
2500 emit_constant_insn (cond,
2501 gen_rtx_SET (VOIDmode, target,
2502 gen_rtx_NOT (mode, source)));
2503 return 1;
2505 case MINUS:
2506 /* We treat MINUS as (val - source), since (source - val) is always
2507 passed as (source + (-val)). */
2508 if (remainder == 0)
2510 if (generate)
2511 emit_constant_insn (cond,
2512 gen_rtx_SET (VOIDmode, target,
2513 gen_rtx_NEG (mode, source)));
2514 return 1;
2516 if (const_ok_for_arm (val))
2518 if (generate)
2519 emit_constant_insn (cond,
2520 gen_rtx_SET (VOIDmode, target,
2521 gen_rtx_MINUS (mode, GEN_INT (val),
2522 source)));
2523 return 1;
2525 can_negate = 1;
2527 break;
2529 default:
2530 gcc_unreachable ();
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)))
2538 if (generate)
2539 emit_constant_insn (cond,
2540 gen_rtx_SET (VOIDmode, target,
2541 (source
2542 ? gen_rtx_fmt_ee (code, mode, source,
2543 GEN_INT (val))
2544 : GEN_INT (val))));
2545 return 1;
2548 /* Calculate a few attributes that may be useful for specific
2549 optimizations. */
2550 for (i = 31; i >= 0; i--)
2552 if ((remainder & (1 << i)) == 0)
2553 clear_sign_bit_copies++;
2554 else
2555 break;
2558 for (i = 31; i >= 0; i--)
2560 if ((remainder & (1 << i)) != 0)
2561 set_sign_bit_copies++;
2562 else
2563 break;
2566 for (i = 0; i <= 31; i++)
2568 if ((remainder & (1 << i)) == 0)
2569 clear_zero_bit_copies++;
2570 else
2571 break;
2574 for (i = 0; i <= 31; i++)
2576 if ((remainder & (1 << i)) != 0)
2577 set_zero_bit_copies++;
2578 else
2579 break;
2582 switch (code)
2584 case SET:
2585 /* APPLE LOCAL begin v7 support. Merge from mainline */
2586 /* See if we can use movw. */
2587 if (arm_arch_thumb2 && (remainder & 0xffff0000) == 0)
2589 if (generate)
2590 emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target,
2591 GEN_INT (val)));
2592 return 1;
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))))
2605 if (generate)
2607 rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
2608 emit_constant_insn (cond,
2609 gen_rtx_SET (VOIDmode, new_src,
2610 GEN_INT (temp1)));
2611 emit_constant_insn (cond,
2612 gen_ashrsi3 (target, new_src,
2613 GEN_INT (set_sign_bit_copies - 1)));
2615 return 2;
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))
2622 if (generate)
2624 rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
2625 emit_constant_insn (cond,
2626 gen_rtx_SET (VOIDmode, new_src,
2627 GEN_INT (temp1)));
2628 emit_constant_insn (cond,
2629 gen_ashrsi3 (target, new_src,
2630 GEN_INT (set_sign_bit_copies - 1)));
2632 return 2;
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))
2656 if (generate)
2658 rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
2659 emit_constant_insn (cond,
2660 gen_rtx_SET (VOIDmode, new_src,
2661 GEN_INT (temp1)));
2662 emit_constant_insn (cond,
2663 gen_addsi3 (target, new_src,
2664 GEN_INT (-temp2)));
2667 return 2;
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)
2689 : target);
2690 insns = arm_gen_constant (code, mode, cond, temp2, new_src,
2691 source, subtargets, generate);
2692 source = new_src;
2693 if (generate)
2694 emit_constant_insn
2695 (cond,
2696 gen_rtx_SET
2697 (VOIDmode, target,
2698 gen_rtx_IOR (mode,
2699 gen_rtx_ASHIFT (mode, source,
2700 GEN_INT (i)),
2701 source)));
2702 return insns + 1;
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)
2714 : target);
2715 insns = arm_gen_constant (code, mode, cond, temp1, new_src,
2716 source, subtargets, generate);
2717 source = new_src;
2718 if (generate)
2719 emit_constant_insn
2720 (cond,
2721 gen_rtx_SET (VOIDmode, target,
2722 gen_rtx_IOR
2723 (mode,
2724 gen_rtx_LSHIFTRT (mode, source,
2725 GEN_INT (i)),
2726 source)));
2727 return insns + 1;
2731 break;
2733 case IOR:
2734 case XOR:
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. */
2738 if (subtargets
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)))
2744 if (generate)
2746 rtx sub = subtargets ? gen_reg_rtx (mode) : target;
2748 emit_constant_insn (cond,
2749 gen_rtx_SET (VOIDmode, sub,
2750 GEN_INT (val)));
2751 emit_constant_insn (cond,
2752 gen_rtx_SET (VOIDmode, target,
2753 gen_rtx_fmt_ee (code, mode,
2754 source, sub)));
2756 return 2;
2760 if (code == XOR)
2761 break;
2763 if (set_sign_bit_copies > 8
2764 && (val & (-1 << (32 - set_sign_bit_copies))) == val)
2766 if (generate)
2768 rtx sub = subtargets ? gen_reg_rtx (mode) : target;
2769 rtx shift = GEN_INT (set_sign_bit_copies);
2771 emit_constant_insn
2772 (cond,
2773 gen_rtx_SET (VOIDmode, sub,
2774 gen_rtx_NOT (mode,
2775 gen_rtx_ASHIFT (mode,
2776 source,
2777 shift))));
2778 emit_constant_insn
2779 (cond,
2780 gen_rtx_SET (VOIDmode, target,
2781 gen_rtx_NOT (mode,
2782 gen_rtx_LSHIFTRT (mode, sub,
2783 shift))));
2785 return 2;
2788 if (set_zero_bit_copies > 8
2789 && (remainder & ((1 << set_zero_bit_copies) - 1)) == remainder)
2791 if (generate)
2793 rtx sub = subtargets ? gen_reg_rtx (mode) : target;
2794 rtx shift = GEN_INT (set_zero_bit_copies);
2796 emit_constant_insn
2797 (cond,
2798 gen_rtx_SET (VOIDmode, sub,
2799 gen_rtx_NOT (mode,
2800 gen_rtx_LSHIFTRT (mode,
2801 source,
2802 shift))));
2803 emit_constant_insn
2804 (cond,
2805 gen_rtx_SET (VOIDmode, target,
2806 gen_rtx_NOT (mode,
2807 gen_rtx_ASHIFT (mode, sub,
2808 shift))));
2810 return 2;
2813 if (const_ok_for_arm (temp1 = ARM_SIGN_EXTEND (~val)))
2815 if (generate)
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)));
2821 source = sub;
2822 if (subtargets)
2823 sub = gen_reg_rtx (mode);
2824 emit_constant_insn (cond,
2825 gen_rtx_SET (VOIDmode, sub,
2826 gen_rtx_AND (mode, source,
2827 GEN_INT (temp1))));
2828 emit_constant_insn (cond,
2829 gen_rtx_SET (VOIDmode, target,
2830 gen_rtx_NOT (mode, sub)));
2832 return 3;
2834 break;
2836 case AND:
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))
2842 & 0xffffffff);
2844 if ((remainder | shift_mask) != 0xffffffff)
2846 if (generate)
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);
2852 source = new_src;
2854 else
2856 rtx targ = subtargets ? NULL_RTX : target;
2857 insns = arm_gen_constant (AND, mode, cond,
2858 remainder | shift_mask,
2859 targ, source, subtargets, 0);
2863 if (generate)
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));
2872 return insns + 2;
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)
2881 if (generate)
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);
2888 source = new_src;
2890 else
2892 rtx targ = subtargets ? NULL_RTX : target;
2894 insns = arm_gen_constant (AND, mode, cond,
2895 remainder | shift_mask,
2896 targ, source, subtargets, 0);
2900 if (generate)
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));
2909 return insns + 2;
2912 break;
2914 default:
2915 break;
2918 for (i = 0; i < 32; i++)
2919 if (remainder & (1 << i))
2920 num_bits_set++;
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;
2926 else
2928 can_invert = 0;
2929 can_negate = 0;
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
2934 instructions.
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
2943 the same. */
2945 int best_start = 0;
2946 if (!TARGET_THUMB2)
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;
2959 i += 2;
2961 if (consecutive_zeros > best_consecutive_zeros)
2963 best_consecutive_zeros = consecutive_zeros;
2964 best_start = i - consecutive_zeros;
2966 i -= 2;
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:
2981 mov rA, #0xe0000000
2982 mov rB, #1
2983 str rB, [rA, #0x100]
2984 mov rB, #2
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. */
2993 if (best_start != 0
2994 && ((((unsigned HOST_WIDE_INT) 1) << best_start) < remainder)
2995 && (count_insns_for_constant (remainder, 0) <=
2996 count_insns_for_constant (remainder, best_start)))
2997 best_start = 0;
3000 /* Now start emitting the insns. */
3001 i = best_start;
3004 int end;
3006 if (i <= 0)
3007 i += 32;
3008 if (remainder & (3 << (i - 2)))
3010 end = i - 8;
3011 if (end < 0)
3012 end += 32;
3013 temp1 = remainder & ((0x0ff << end)
3014 | ((i < end) ? (0xff >> (32 - end)) : 0));
3015 remainder &= ~temp1;
3017 if (generate)
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)
3025 temp1 = ~temp1;
3027 else
3029 if (remainder && subtargets)
3030 new_src = gen_reg_rtx (mode);
3031 else
3032 new_src = target;
3033 if (can_invert)
3034 temp1 = ~temp1;
3035 else if (can_negate)
3036 temp1 = -temp1;
3039 temp1 = trunc_int_for_mode (temp1, mode);
3040 temp1_rtx = GEN_INT (temp1);
3042 if (code == SET)
3044 else if (code == MINUS)
3045 temp1_rtx = gen_rtx_MINUS (mode, temp1_rtx, source);
3046 else
3047 temp1_rtx = gen_rtx_fmt_ee (code, mode, source, temp1_rtx);
3049 emit_constant_insn (cond,
3050 gen_rtx_SET (VOIDmode, new_src,
3051 temp1_rtx));
3052 source = new_src;
3055 if (code == SET)
3057 can_invert = 0;
3058 code = PLUS;
3060 else if (code == MINUS)
3061 code = PLUS;
3063 insns++;
3064 if (TARGET_ARM)
3065 i -= 6;
3066 else
3067 i -= 7;
3069 /* Arm allows rotates by a multiple of two. Thumb-2 allows arbitary
3070 shifts. */
3071 if (TARGET_ARM)
3072 i -= 2;
3073 else
3074 i--;
3076 while (remainder);
3078 /* APPLE LOCAL end v7 support. Merge from mainline */
3080 return insns;
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. */
3087 enum rtx_code
3088 arm_canonicalize_comparison (enum rtx_code code, enum machine_mode mode,
3089 rtx * op1)
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;
3095 switch (code)
3097 case EQ:
3098 case NE:
3099 return code;
3101 case GT:
3102 case LE:
3103 if (i != maxval
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;
3109 break;
3111 case GE:
3112 case LT:
3113 if (i != ~maxval
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;
3119 break;
3121 case GTU:
3122 case LEU:
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;
3129 break;
3131 case GEU:
3132 case LTU:
3133 if (i != 0
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;
3139 break;
3141 default:
3142 gcc_unreachable ();
3145 return code;
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)
3183 int size = 16;
3185 if (TARGET_ARM)
3187 if (TARGET_HARD_FLOAT_ABI)
3189 if (TARGET_FPA)
3190 size += 12;
3191 if (TARGET_MAVERICK)
3192 size += 8;
3194 if (TARGET_IWMMXT_ABI)
3195 size += 8;
3198 return size;
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)
3207 HOST_WIDE_INT size;
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. */
3222 return 0;
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 */
3233 /* Removed lines */
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. */
3236 #ifndef ARM_WINCE
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)
3242 return 1;
3244 if (TREE_CODE (type) == RECORD_TYPE)
3246 tree field;
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))
3259 continue;
3261 if (field == NULL)
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)))
3268 return 1;
3270 /* ... Aggregates that are not themselves valid for returning in
3271 a register are not allowed. */
3272 if (RETURN_IN_MEMORY (TREE_TYPE (field)))
3273 return 1;
3275 /* Now check the remaining fields, if any. Only bitfields are allowed,
3276 since they are not addressable. */
3277 for (field = TREE_CHAIN (field);
3278 field;
3279 field = TREE_CHAIN (field))
3281 if (TREE_CODE (field) != FIELD_DECL)
3282 continue;
3284 if (!DECL_BIT_FIELD_TYPE (field))
3285 return 1;
3288 return 0;
3291 if (TREE_CODE (type) == UNION_TYPE)
3293 tree field;
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);
3298 field;
3299 field = TREE_CHAIN (field))
3301 if (TREE_CODE (field) != FIELD_DECL)
3302 continue;
3304 if (FLOAT_TYPE_P (TREE_TYPE (field)))
3305 return 1;
3307 if (RETURN_IN_MEMORY (TREE_TYPE (field)))
3308 return 1;
3311 return 0;
3313 #endif /* not ARM_WINCE */
3315 /* Return all other types in memory. */
3316 return 1;
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)
3325 return 0;
3327 /* For FPA, float words are always big-endian. For VFP, floats words
3328 follow the memory system mode. */
3330 if (TARGET_FPA)
3332 return 1;
3335 if (TARGET_VFP)
3336 return (TARGET_BIG_END ? 1 : 0);
3338 return 1;
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. */
3344 void
3345 arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
3346 rtx libname ATTRIBUTE_UNUSED,
3347 /* APPLE LOCAL 6738583 -mlong-calls PIC static functions */
3348 tree fndecl)
3350 /* On the ARM, the offset starts at 0. */
3351 pcum->nregs = 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. */
3362 if (fntype)
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;
3377 pcum->nargs = 0;
3379 if (TARGET_REALLY_IWMMXT && fntype)
3381 tree fn_arg;
3383 for (fn_arg = TYPE_ARG_TYPES (fntype);
3384 fn_arg;
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. */
3395 bool
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
3410 not be available.
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)
3420 int nregs;
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);
3430 else
3432 pcum->can_split = false;
3433 return NULL_RTX;
3437 /* Put doubleword aligned quantities in even register pairs. */
3438 if (pcum->nregs & 1
3439 && ARM_DOUBLEWORD_ALIGN
3440 && arm_needs_doubleword_align (mode, type))
3441 pcum->nregs++;
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)
3451 nregs = 1;
3452 else
3453 nregs = ARM_NUM_REGS2 (mode, type);
3455 if (!named || pcum->nregs + nregs > NUM_ARG_REGS)
3456 return NULL_RTX;
3458 return gen_rtx_REG (mode, pcum->nregs);
3461 static int
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))
3469 return 0;
3471 if (NUM_ARG_REGS > nregs
3472 && (NUM_ARG_REGS < nregs + ARM_NUM_REGS2 (mode, type))
3473 && pcum->can_split)
3474 return (NUM_ARG_REGS - nregs) * UNITS_PER_WORD;
3476 return 0;
3479 /* Variable sized types are passed by reference. This is a GCC
3480 extension to the ARM ABI. */
3482 static bool
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. */
3491 typedef enum
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. */
3496 } arm_pragma_enum;
3498 static arm_pragma_enum arm_pragma_long_calls = OFF;
3500 void
3501 arm_pr_long_calls (struct cpp_reader * pfile ATTRIBUTE_UNUSED)
3503 arm_pragma_long_calls = LONG;
3506 void
3507 arm_pr_no_long_calls (struct cpp_reader * pfile ATTRIBUTE_UNUSED)
3509 arm_pragma_long_calls = SHORT;
3512 void
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
3524 call. */
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 },
3533 #ifdef ARM_PE
3534 /* ARM/PE has three new attributes:
3535 interfacearm - ?
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
3541 multiple times.
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 },
3550 #endif
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,
3558 #endif
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. */
3565 static tree
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;
3576 return NULL_TREE;
3579 /* Handle an "interrupt" or "isr" attribute;
3580 arguments as in struct attribute_spec.handler. */
3581 static tree
3582 arm_handle_isr_attribute (tree *node, tree name, tree args, int flags,
3583 bool *no_add_attrs)
3585 if (DECL_P (*node))
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? */
3596 else
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
3615 (TREE_TYPE (*node),
3616 tree_cons (name, args, TYPE_ATTRIBUTES (TREE_TYPE (*node))));
3617 *no_add_attrs = true;
3619 else
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);
3629 else
3631 warning (OPT_Wattributes, "%qs attribute ignored",
3632 IDENTIFIER_POINTER (name));
3637 return NULL_TREE;
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
3644 attribute. */
3646 static tree
3647 arm_handle_notshared_attribute (tree *node,
3648 tree name ATTRIBUTE_UNUSED,
3649 tree args ATTRIBUTE_UNUSED,
3650 int flags ATTRIBUTE_UNUSED,
3651 bool *no_add_attrs)
3653 tree decl = TYPE_NAME (*node);
3655 if (decl)
3657 DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
3658 DECL_VISIBILITY_SPECIFIED (decl) = 1;
3659 *no_add_attrs = false;
3661 return NULL_TREE;
3663 #endif
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). */
3668 static int
3669 arm_comp_type_attributes (tree type1, tree type2)
3671 int l1, l2, s1, s2;
3673 /* Check for mismatch of non-default calling convention. */
3674 if (TREE_CODE (type1) != FUNCTION_TYPE)
3675 return 1;
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))
3688 return 0;
3690 /* Disallow mixed attributes. */
3691 if ((l1 & s2) || (l2 & s1))
3692 return 0;
3695 /* Check for mismatched ISR attribute. */
3696 l1 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type1)) != NULL;
3697 if (! l1)
3698 l1 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type1)) != NULL;
3699 l2 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type2)) != NULL;
3700 if (! l2)
3701 l1 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type2)) != NULL;
3702 if (l1 != l2)
3703 return 0;
3705 return 1;
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. */
3711 void
3712 arm_encode_call_attribute (tree decl, int flag)
3714 #if TARGET_MACHO
3715 rtx sym_ref = XEXP (DECL_RTL (decl), 0);
3717 /* Do not allow weak functions with default visibility to be treated
3718 as short call. */
3719 if (DECL_WEAK (decl)
3720 && DECL_VISIBILITY (decl) == VISIBILITY_DEFAULT
3721 && flag == SYMBOL_SHORT_CALL)
3722 return;
3724 SYMBOL_REF_FLAGS (sym_ref) |= flag;
3725 #else
3726 const char * str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
3727 int len = strlen (str);
3728 char * newstr;
3730 /* Do not allow weak functions to be treated as short call. */
3731 if (DECL_WEAK (decl) && flag == SHORT_CALL_FLAG_CHAR)
3732 return;
3734 newstr = alloca (len + 2);
3735 newstr[0] = flag;
3736 strcpy (newstr + 1, str);
3738 newstr = (char *) ggc_alloc_string (newstr, len + 1);
3739 XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
3740 #endif
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. */
3747 static void
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");
3762 else
3763 return;
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. */
3771 #if TARGET_MACHO
3772 else if ((TARGET_MS_BITFIELD_LAYOUT || darwin_ms_struct)
3773 && (TREE_CODE (type) == RECORD_TYPE
3774 || TREE_CODE (type) == UNION_TYPE))
3775 #else
3776 else if (TARGET_MS_BITFIELD_LAYOUT
3777 && (TREE_CODE (type) == RECORD_TYPE
3778 || TREE_CODE (type) == UNION_TYPE))
3779 #endif
3781 TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("ms_struct"),
3782 NULL_TREE,
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. */
3791 static int
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 */
3798 #if TARGET_MACHO
3799 if (SYMBOL_SHORT_CALL_ATTR_P (sym_ref))
3800 #else
3801 if (ENCODED_SHORT_CALL_ATTR_P (XSTR (sym_ref, 0)))
3802 #endif
3803 return 1;
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))
3811 return 1;
3813 /* We cannot make the determination - default to returning 0. */
3814 return 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
3823 . and either:
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)
3844 if (!call_symbol)
3846 if (GET_CODE (sym_ref) != MEM)
3847 return 0;
3849 sym_ref = XEXP (sym_ref, 0);
3852 if (GET_CODE (sym_ref) != SYMBOL_REF)
3853 return 0;
3855 if (call_cookie & CALL_SHORT)
3856 return 0;
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. */
3864 return 1;
3867 if (current_file_function_operand (sym_ref))
3868 return 0;
3870 /* APPLE LOCAL begin ARM longcall */
3871 #if TARGET_MACHO
3872 return (call_cookie & CALL_LONG)
3873 || SYMBOL_LONG_CALL_ATTR_P (sym_ref)
3874 || TARGET_LONG_CALLS;
3875 #else
3876 return (call_cookie & CALL_LONG)
3877 || ENCODED_LONG_CALL_ATTR_P (XSTR (sym_ref, 0))
3878 || TARGET_LONG_CALLS;
3879 #endif
3880 /* APPLE LOCAL end ARM longcall */
3883 /* Return nonzero if it is ok to make a tail-call to DECL. */
3884 static bool
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)
3892 return false;
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. */
3897 if (TARGET_THUMB)
3898 return false;
3900 /* All indirect calls are within range, since we load the address into a
3901 register. */
3902 if (decl == NULL)
3903 return true;
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)))
3916 return false;
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)
3924 if (TARGET_MACHO)
3925 return false;
3926 else if (!arm_arch5)
3927 return false;
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))
3935 return false;
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))
3942 return false;
3944 /* Never tailcall if function may be called with a misaligned SP. */
3945 if (IS_STACKALIGN (func_type))
3946 return false;
3948 /* APPLE LOCAL end v7 support. Merge from mainline */
3949 /* Everything else is ok. */
3950 return true;
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))
3965 return 0;
3967 return 1;
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;
3978 #endif
3979 /* APPLE LOCAL ARM pic support */
3980 rtx norig, l1 = NULL_RTX;
3981 rtx insn;
3982 int subregs = 0;
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
3992 process. */
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
4003 process. */
4004 if (!ir_type())
4005 current_function_uses_pic_offset_table = 1;
4007 else
4009 rtx seq;
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
4015 process. */
4016 if (!ir_type())
4018 current_function_uses_pic_offset_table = 1;
4019 start_sequence ();
4021 arm_load_pic_register (0UL);
4023 seq = get_insns ();
4024 end_sequence ();
4025 emit_insn_after (seq, entry_of_function ());
4030 if (reg == 0)
4032 gcc_assert (!no_new_pseudos);
4033 reg = gen_reg_rtx (Pmode);
4035 subregs = 1;
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));
4042 #else
4043 if (subregs)
4044 address = gen_reg_rtx (Pmode);
4045 else
4046 address = reg;
4048 /* APPLE LOCAL begin ARM pic support */
4049 norig = orig;
4050 #if TARGET_MACHO
4051 if (TARGET_MACHO)
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)
4065 return orig;
4067 if (! defined)
4069 avoid_ind = false;
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;
4076 else
4078 if (MACHO_DYNAMIC_NO_PIC_P)
4079 return orig;
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));
4087 norig = ptr_ref;
4090 #endif
4091 if (TARGET_MACHO && ! MACHO_DYNAMIC_NO_PIC_P)
4093 if (GET_CODE (orig) == SYMBOL_REF
4094 || GET_CODE (orig) == LABEL_REF)
4096 if (TARGET_ARM)
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 */
4114 else
4115 abort ();
4117 else
4119 if (TARGET_ARM)
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)))
4133 && NEED_GOT_RELOC)
4134 pic_ref = gen_rtx_PLUS (Pmode, cfun->machine->pic_reg, address);
4135 else
4137 /* APPLE LOCAL begin ARM pic support */
4138 if (! TARGET_MACHO)
4139 pic_ref = gen_const_mem (Pmode,
4140 gen_rtx_PLUS (Pmode, cfun->machine->pic_reg,
4141 address));
4142 else if (avoid_ind)
4143 pic_ref = address;
4144 else
4145 pic_ref = gen_const_mem (Pmode, address);
4146 /* APPLE LOCAL end ARM pic support */
4149 insn = emit_move_insn (reg, pic_ref);
4150 #endif
4151 /* Put a REG_EQUAL note on this insn, so that it can be optimized
4152 by loop. */
4153 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
4154 REG_NOTES (insn));
4155 return reg;
4157 else if (GET_CODE (orig) == CONST)
4159 rtx base, offset;
4161 if (GET_CODE (XEXP (orig, 0)) == PLUS
4162 && XEXP (XEXP (orig, 0), 0) == cfun->machine->pic_reg)
4163 return orig;
4165 if (GET_CODE (XEXP (orig, 0)) == UNSPEC
4166 && XINT (XEXP (orig, 0), 1) == UNSPEC_TLS)
4167 return orig;
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
4172 CONST_INT. */
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);
4178 return orig;
4181 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
4182 if (reg == 0)
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
4196 bit. */
4197 #if 0
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));
4211 #endif
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));
4218 return reg;
4221 return gen_rtx_PLUS (Pmode, base, offset);
4224 return orig;
4228 /* APPLE LOCAL v7 support. Merge from mainline */
4229 /* Find a spare register to use during the prolog of a function. */
4231 static int
4232 thumb_find_work_register (unsigned long pushed_regs_mask)
4234 int reg;
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])
4241 return 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))
4276 return reg;
4278 /* APPLE LOCAL begin v7 support. Merge from mainline */
4279 if (TARGET_THUMB2)
4281 /* Thumb-2 can use high regs. */
4282 for (reg = FIRST_HI_REGNUM; reg < 15; reg ++)
4283 if (pushed_regs_mask & (1 << reg))
4284 return 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. */
4289 gcc_unreachable ();
4292 static GTY(()) int pic_labelno;
4294 /* Generate code to load the PIC register. In thumb mode SCRATCH is a
4295 low register. */
4297 void
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)
4305 return;
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);
4320 if (GOT_PCREL)
4321 pic_tmp2 = gen_rtx_CONST (VOIDmode,
4322 gen_rtx_PLUS (Pmode, global_offset_table, pc_rtx));
4323 else
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));
4328 if (TARGET_ARM)
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));
4346 else
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,
4353 pic_rtx, l1));
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,
4356 pic_tmp));
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));
4371 else
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. */
4387 static int
4388 arm_address_register_rtx_p (rtx x, int strict_p)
4390 int regno;
4392 if (GET_CODE (x) != REG)
4393 return 0;
4395 regno = REGNO (x);
4397 if (strict_p)
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. */
4410 static int
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));
4416 return FALSE;
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,
4422 int strict_p)
4424 bool use_ldrd;
4425 enum rtx_code code = GET_CODE (x);
4427 if (arm_address_register_rtx_p (x, strict_p))
4428 return 1;
4430 use_ldrd = (TARGET_LDRD
4431 && (mode == DImode
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))
4437 return 0;
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. */
4454 if (use_ldrd
4455 && GET_CODE (x) == POST_MODIFY
4456 && GET_CODE (addend) == REG)
4457 return 0;
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
4467 || (code == CONST
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)))
4471 return 1;
4473 /* APPLE LOCAL v7 support. Merge from mainline */
4474 else if (mode == TImode || (TARGET_NEON && VALID_NEON_STRUCT_MODE (mode)))
4475 return 0;
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)));
4488 #if 0
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));
4498 #endif
4500 else if (GET_MODE_CLASS (mode) != MODE_FLOAT
4501 && code == SYMBOL_REF
4502 && CONSTANT_POOL_ADDRESS_P (x)
4503 && ! (flag_pic
4504 && symbol_mentioned_p (get_pool_constant (x))
4505 && ! pcrel_constant_p (get_pool_constant (x))))
4506 return 1;
4508 return 0;
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)
4516 bool use_ldrd;
4517 enum rtx_code code = GET_CODE (x);
4519 if (arm_address_register_rtx_p (x, strict_p))
4520 return 1;
4522 use_ldrd = (TARGET_LDRD
4523 && (mode == DImode
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))
4529 return 0;
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)
4547 return 0;
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
4561 || (code == CONST
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)))
4565 return 1;
4567 /* APPLE LOCAL v7 support. Merge from Codesourcery */
4568 else if (mode == TImode || (TARGET_NEON && VALID_NEON_STRUCT_MODE (mode)))
4569 return 0;
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)
4585 && ! (flag_pic
4586 && symbol_mentioned_p (get_pool_constant (x))
4587 && ! pcrel_constant_p (get_pool_constant (x))))
4588 return 1;
4590 return 0;
4593 /* APPLE LOCAL end v7 support. Merge from mainline */
4594 /* Return nonzero if INDEX is valid for an address index operand in
4595 ARM state. */
4596 static int
4597 arm_legitimate_index_p (enum machine_mode mode, rtx index, RTX_CODE outer,
4598 int strict_p)
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 */
4625 if (TARGET_NEON
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))
4637 return 1;
4639 if (mode == DImode || mode == DFmode)
4641 if (code == CONST_INT)
4643 HOST_WIDE_INT val = INTVAL (index);
4645 if (TARGET_LDRD)
4646 return val > -256 && val < 256;
4647 else
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
4655 && ! (arm_arch4
4656 && (mode == HImode
4657 || (mode == QImode && outer == SIGN_EXTEND))))
4659 if (code == MULT)
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
4676 && INTVAL (op) > 0
4677 && INTVAL (op) <= 31);
4681 /* For ARM v4 we may be doing a sign-extend operation during the
4682 load. */
4683 if (arm_arch4)
4685 if (mode == HImode || (outer == SIGN_EXTEND && mode == QImode))
4686 range = 256;
4687 else
4688 range = 4096;
4690 else
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. */
4701 static bool
4702 thumb2_index_mul_operand (rtx op)
4704 HOST_WIDE_INT val;
4706 if (GET_CODE(op) != CONST_INT)
4707 return false;
4709 val = INTVAL(op);
4710 return (val == 1 || val == 2 || val == 4 || val == 8);
4713 /* Return nonzero if INDEX is a valid Thumb-2 address index operand. */
4714 static int
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 */
4736 if (TARGET_NEON
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))
4748 return 1;
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)
4756 return 0;
4758 /* ldrd supports offsets of +-1020.
4759 However the ldr fallback does not. */
4760 return val > -256 && val < 256 && (val & 3) == 0;
4763 if (code == MULT)
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
4779 && INTVAL (op) > 0
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. */
4789 static int
4790 thumb1_base_register_rtx_p (rtx x, enum machine_mode mode, int strict_p)
4792 /* APPLE LOCAL end v7 support. Merge from mainline */
4793 int regno;
4795 if (GET_CODE (x) != REG)
4796 return 0;
4798 regno = REGNO (x);
4800 if (strict_p)
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 */
4817 inline static int
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)))
4855 return 0;
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))
4860 return 1;
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)
4866 return 1;
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)))
4875 return 1;
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))
4881 return 1;
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 */
4896 return 1;
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))))
4904 return 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)
4917 return 1;
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)
4924 return 1;
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)
4931 && ! (flag_pic
4932 && symbol_mentioned_p (get_pool_constant (x))
4933 && ! pcrel_constant_p (get_pool_constant (x))))
4934 return 1;
4936 return 0;
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))
4946 case 1:
4947 return val >= 0 && val < 32;
4949 case 2:
4950 return val >= 0 && val < 64 && (val & 1) == 0;
4952 default:
4953 return (val >= 0
4954 && (val + GET_MODE_SIZE (mode)) <= 128
4955 && (val & 3) == 0);
4959 /* Build the SYMBOL_REF for __tls_get_addr. */
4961 static GTY(()) rtx tls_get_addr_libfunc;
4963 static rtx
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;
4971 static rtx
4972 arm_load_tp (rtx target)
4974 if (!target)
4975 target = gen_reg_rtx (SImode);
4977 if (TARGET_HARD_TP)
4979 /* Can return in any reg. */
4980 emit_insn (gen_load_tp_hard (target));
4982 else
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. */
4988 rtx tmp;
4990 emit_insn (gen_load_tp_soft ());
4992 tmp = gen_rtx_REG (SImode, 0);
4993 emit_move_insn (target, tmp);
4995 return target;
4998 static rtx
4999 load_tls_operand (rtx x, rtx reg)
5001 rtx tmp;
5003 if (reg == NULL_RTX)
5004 reg = gen_reg_rtx (SImode);
5006 tmp = gen_rtx_CONST (SImode, x);
5008 emit_move_insn (reg, tmp);
5010 return reg;
5013 static rtx
5014 arm_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc)
5016 rtx insns, label, labelno, sum;
5018 start_sequence ();
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)),
5027 UNSPEC_TLS);
5028 reg = load_tls_operand (sum, reg);
5030 if (TARGET_ARM)
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)
5035 rtx tmp;
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 ();
5050 end_sequence ();
5052 return 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);
5061 switch (model)
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);
5067 return dest;
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),
5075 UNSPEC_TLS);
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)),
5081 UNSPEC_TLS);
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)),
5092 UNSPEC_TLS);
5093 reg = load_tls_operand (sum, reg);
5095 if (TARGET_ARM)
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)
5100 rtx tmp;
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 */
5109 else
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)),
5124 UNSPEC_TLS);
5125 reg = force_reg (SImode, gen_rtx_CONST (SImode, reg));
5127 return gen_rtx_PLUS (Pmode, tp, reg);
5129 default:
5130 abort ();
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 */
5143 if (flag_pic)
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)
5150 x = new_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;
5167 rtx base_reg, val;
5169 /* Look for
5170 (+ (+ (foo, SFP) const)). It is better to rearrange this as
5171 (+ (foo (+ (SFP, const))). The eventual SP + const1 + const will
5172 get folded. */
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),
5183 NULL_RTX);
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);
5187 return x;
5191 n = INTVAL (xop1);
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. */
5198 if (mode == DImode
5199 || ((TARGET_SOFT_FLOAT || TARGET_VFP) && mode == DFmode))
5201 low_n = n & 0x0f;
5202 n &= ~0x0f;
5203 if (low_n > 4)
5205 n += 16;
5206 low_n -= 16;
5209 else if ((mode == HImode || mode == QImode) && arm_arch4)
5211 low_n = n >= 0 ? (n & 0xff) : -((-n) & 0xff);
5212 n -= low_n;
5214 else
5216 low_n = ((mode) == TImode ? 0
5217 : n >= 0 ? (n & 0xfff) : -((-n) & 0xfff));
5218 n -= low_n;
5221 if (n != 0)
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)
5260 unsigned int bits;
5261 HOST_WIDE_INT mask, base, index;
5262 rtx base_reg;
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. */
5275 base |= mask;
5276 index -= mask;
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 */
5283 return x;
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;
5312 if (offset >= 256)
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);
5316 else
5317 delta = offset & (~31 * GET_MODE_SIZE (mode));
5319 xop0 = force_operand (plus_constant (xop0, offset - delta),
5320 NULL_RTX);
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
5326 instructions. */
5327 x = force_operand (x, NULL_RTX);
5328 else
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));
5344 if (flag_pic)
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)
5351 x = new_x;
5354 return 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)
5363 rtx x = *x_p;
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))))
5372 rtx orig_x = x;
5374 x = copy_rtx (x);
5375 push_reload (orig_x, NULL_RTX, x_p, NULL, MODE_BASE_REG_CLASS (mode),
5376 Pmode, VOIDmode, 0, 0, opnum, type);
5377 return x;
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))
5389 rtx orig_x = x;
5391 x = copy_rtx (x);
5392 push_reload (orig_x, NULL_RTX, x_p, NULL, MODE_BASE_REG_CLASS (mode),
5393 Pmode, VOIDmode, 0, 0, opnum, type);
5394 return x;
5397 return NULL;
5400 /* Test for various thread-local symbols. */
5402 /* Return TRUE if X is a thread-local symbol. */
5404 static bool
5405 arm_tls_symbol_p (rtx x)
5407 if (! TARGET_HAVE_TLS)
5408 return false;
5410 if (GET_CODE (x) != SYMBOL_REF)
5411 return false;
5413 return SYMBOL_REF_TLS_MODEL (x) != 0;
5416 /* Helper for arm_tls_referenced_p. */
5418 static int
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)
5428 return -1;
5430 return 0;
5433 /* Return TRUE if X contains any TLS symbol references. */
5435 bool
5436 arm_tls_referenced_p (rtx x)
5438 if (! TARGET_HAVE_TLS)
5439 return false;
5441 return for_each_rtx (&x, arm_tls_operand_p_1, NULL);
5444 /* APPLE LOCAL begin ARM -mdynamic-no-pic support */
5445 static bool
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)
5462 #endif
5463 static inline int
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);
5469 switch (code)
5471 case ASHIFT:
5472 case ASHIFTRT:
5473 case LSHIFTRT:
5474 case ROTATERT:
5475 case PLUS:
5476 case MINUS:
5477 case COMPARE:
5478 case NEG:
5479 case NOT:
5480 return COSTS_N_INSNS (1);
5482 case MULT:
5483 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
5485 int cycles = 0;
5486 unsigned HOST_WIDE_INT i = INTVAL (XEXP (x, 1));
5488 while (i)
5490 i >>= 2;
5491 cycles++;
5493 return COSTS_N_INSNS (2) + cycles;
5495 return COSTS_N_INSNS (1) + 16;
5497 case SET:
5498 return (COSTS_N_INSNS (1)
5499 + 4 * ((GET_CODE (SET_SRC (x)) == MEM)
5500 + GET_CODE (SET_DEST (x)) == MEM));
5502 case CONST_INT:
5503 if (outer == SET)
5505 if ((unsigned HOST_WIDE_INT) INTVAL (x) < 256)
5506 return 0;
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)
5513 return 0;
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)
5519 return 0;
5520 return COSTS_N_INSNS (2);
5522 case CONST:
5523 case CONST_DOUBLE:
5524 case LABEL_REF:
5525 case SYMBOL_REF:
5526 return COSTS_N_INSNS (3);
5528 case UDIV:
5529 case UMOD:
5530 case DIV:
5531 case MOD:
5532 return 100;
5534 case TRUNCATE:
5535 return 99;
5537 case AND:
5538 case XOR:
5539 case IOR:
5540 /* XXX guess. */
5541 return 8;
5543 case MEM:
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))
5549 ? 4 : 0));
5551 case IF_THEN_ELSE:
5552 /* XXX a guess. */
5553 if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
5554 return 14;
5555 return 2;
5557 case ZERO_EXTEND:
5558 /* XXX still guessing. */
5559 switch (GET_MODE (XEXP (x, 0)))
5561 case QImode:
5562 return (1 + (mode == DImode ? 4 : 0)
5563 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
5565 case HImode:
5566 return (4 + (mode == DImode ? 4 : 0)
5567 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
5569 case SImode:
5570 return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
5572 default:
5573 return 99;
5576 default:
5577 return 99;
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
5586 anywhere here.) */
5588 static inline int
5589 thumb1_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer)
5591 enum machine_mode mode = GET_MODE (x);
5593 switch (code)
5595 case ASHIFT:
5596 case ASHIFTRT:
5597 case LSHIFTRT:
5598 case ROTATERT:
5599 case PLUS:
5600 case MINUS:
5601 case COMPARE:
5602 case NEG:
5603 case NOT:
5604 case AND:
5605 case XOR:
5606 case IOR:
5607 case MULT:
5608 return COSTS_N_INSNS (1);
5610 case SET:
5611 return (COSTS_N_INSNS (1)
5612 + 4 * ((GET_CODE (SET_SRC (x)) == MEM)
5613 + GET_CODE (SET_DEST (x)) == MEM));
5615 case CONST_INT:
5616 if (outer == SET)
5618 if ((unsigned HOST_WIDE_INT) INTVAL (x) < 256)
5619 return 0;
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)
5626 return 0;
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)
5632 return 0;
5633 return COSTS_N_INSNS (2);
5635 case CONST:
5636 case CONST_DOUBLE:
5637 case LABEL_REF:
5638 case SYMBOL_REF:
5639 return COSTS_N_INSNS (3);
5641 case UDIV:
5642 case UMOD:
5643 case DIV:
5644 case MOD:
5645 return 100;
5647 case TRUNCATE:
5648 return 99;
5650 case MEM:
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))
5656 ? 4 : 0));
5658 case IF_THEN_ELSE:
5659 /* XXX a guess. */
5660 if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
5661 return 14;
5662 return 2;
5664 case ZERO_EXTEND:
5665 /* XXX still guessing. */
5666 switch (GET_MODE (XEXP (x, 0)))
5668 case QImode:
5669 return (1 + (mode == DImode ? 4 : 0)
5670 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
5672 case HImode:
5673 return (4 + (mode == DImode ? 4 : 0)
5674 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
5676 case SImode:
5677 return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
5679 default:
5680 return 99;
5683 default:
5684 return 99;
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. */
5692 static inline int
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;
5697 int extra_cost;
5699 switch (code)
5701 case MEM:
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));
5708 case DIV:
5709 case MOD:
5710 case UDIV:
5711 case UMOD:
5712 return optimize_size ? COSTS_N_INSNS (2) : 100;
5714 case ROTATE:
5715 if (mode == SImode && GET_CODE (XEXP (x, 1)) == REG)
5716 return 4;
5717 /* Fall through */
5718 case ROTATERT:
5719 if (mode != SImode)
5720 return 8;
5721 /* Fall through */
5722 case ASHIFT: case LSHIFTRT: case ASHIFTRT:
5723 if (mode == DImode)
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))
5728 ? 0 : 8));
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))
5732 ? 0 : 4)
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))
5737 ? 0 : 4));
5739 case MINUS:
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);
5746 return extra_cost;
5749 /* APPLE LOCAL end v7 support. Merge from mainline */
5750 if (mode == DImode)
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)))))
5755 ? 0 : 8));
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))))
5761 ? 0 : 8)
5762 + ((REG_OR_SUBREG_REG (XEXP (x, 0))
5763 || (GET_CODE (XEXP (x, 0)) == CONST_DOUBLE
5764 && arm_const_double_rtx (XEXP (x, 0))))
5765 ? 0 : 8));
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
5773 || (subcode == MULT
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))))
5781 return 1;
5782 /* Fall through */
5784 case PLUS:
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);
5790 return extra_cost;
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))))
5798 ? 0 : 8));
5800 /* Fall through */
5801 case AND: case XOR: case IOR:
5802 extra_cost = 0;
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
5808 operand. */
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)))))
5814 extra_cost = 4;
5816 if (mode == DImode)
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)))
5821 ? 0 : 8));
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)))
5828 ? 0 : 4));
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
5840 || (subcode == MULT
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))
5847 ? 1 : 4));
5848 /* APPLE LOCAL end ARM 4652753 */
5850 return 8;
5852 case MULT:
5853 /* This should have been handled by the CPU specific routines. */
5854 gcc_unreachable ();
5856 case TRUNCATE:
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))
5864 return 8;
5865 return 99;
5867 case NEG:
5868 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
5869 return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 6);
5870 /* Fall through */
5871 case NOT:
5872 if (mode == DImode)
5873 return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4);
5875 return 1 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4);
5877 case IF_THEN_ELSE:
5878 if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
5879 return 14;
5880 return 2;
5882 case COMPARE:
5883 return 1;
5885 case ABS:
5886 return 4 + (mode == DImode ? 4 : 0);
5888 case SIGN_EXTEND:
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));
5894 /* Fall through */
5895 case ZERO_EXTEND:
5896 switch (GET_MODE (XEXP (x, 0)))
5898 case QImode:
5899 return (1 + (mode == DImode ? 4 : 0)
5900 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
5902 case HImode:
5903 return (4 + (mode == DImode ? 4 : 0)
5904 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
5906 case SImode:
5907 return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
5909 case V8QImode:
5910 case V4HImode:
5911 case V2SImode:
5912 case V4QImode:
5913 case V2HImode:
5914 return 1;
5916 default:
5917 gcc_unreachable ();
5919 gcc_unreachable ();
5921 case CONST_INT:
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)))
5926 return -1;
5927 else if ((outer == COMPARE
5928 || outer == PLUS || outer == MINUS)
5929 && const_ok_for_arm (-INTVAL (x)))
5930 return -1;
5931 else
5932 return 5;
5934 case CONST:
5935 case LABEL_REF:
5936 case SYMBOL_REF:
5937 return 6;
5939 case CONST_DOUBLE:
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))
5945 return -1;
5946 return 7;
5948 default:
5949 return 99;
5953 /* RTX costs when optimizing for size. */
5954 static bool
5955 arm_size_rtx_costs (rtx x, int code, int outer_code, int *total)
5957 enum machine_mode mode = GET_MODE (x);
5959 if (TARGET_THUMB)
5961 /* APPLE LOCAL v7 support. Merge from mainline */
5962 *total = thumb1_size_rtx_costs (x, code, outer_code);
5963 return true;
5966 switch (code)
5968 case MEM:
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);
5973 else
5974 *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
5975 return true;
5977 case DIV:
5978 case MOD:
5979 case UDIV:
5980 case UMOD:
5981 /* Needs a libcall, so it costs about this. */
5982 *total = COSTS_N_INSNS (2);
5983 return false;
5985 case ROTATE:
5986 if (mode == SImode && GET_CODE (XEXP (x, 1)) == REG)
5988 *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), code);
5989 return true;
5991 /* Fall through */
5992 case ROTATERT:
5993 case ASHIFT:
5994 case LSHIFTRT:
5995 case ASHIFTRT:
5996 if (mode == DImode && GET_CODE (XEXP (x, 1)) == CONST_INT)
5998 *total = COSTS_N_INSNS (3) + rtx_cost (XEXP (x, 0), code);
5999 return true;
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);
6007 return true;
6010 /* Needs a libcall. */
6011 *total = COSTS_N_INSNS (2);
6012 return false;
6014 case MINUS:
6015 if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
6017 *total = COSTS_N_INSNS (1);
6018 return false;
6021 if (mode == SImode)
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. */
6033 *total = 0;
6034 return false;
6037 *total = COSTS_N_INSNS (1);
6038 return false;
6041 *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
6042 return false;
6044 case PLUS:
6045 if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
6047 *total = COSTS_N_INSNS (1);
6048 return false;
6051 /* Fall through */
6052 case AND: case XOR: case IOR:
6053 if (mode == SImode)
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. */
6062 *total = 0;
6063 return false;
6067 *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
6068 return false;
6070 /* APPLE LOCAL begin DImode multiply enhancement */
6071 case MULT:
6072 if (mode == DImode)
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);
6085 return true;
6087 else
6089 /* broken into 3 insns later, plus cost of kids */
6090 /** does not allow for Cirrus instruction **/
6091 *total = COSTS_N_INSNS (3);
6092 return false;
6095 *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
6096 return false;
6097 /* APPLE LOCAL end DImode multiply enhancement */
6099 case NEG:
6100 if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
6101 *total = COSTS_N_INSNS (1);
6102 /* Fall through */
6103 case NOT:
6104 *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
6106 return false;
6108 case IF_THEN_ELSE:
6109 *total = 0;
6110 return false;
6112 case COMPARE:
6113 if (cc_register (XEXP (x, 0), VOIDmode))
6114 * total = 0;
6115 else
6116 *total = COSTS_N_INSNS (1);
6117 return false;
6119 case ABS:
6120 if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
6121 *total = COSTS_N_INSNS (1);
6122 else
6123 *total = COSTS_N_INSNS (1 + ARM_NUM_REGS (mode));
6124 return false;
6126 case SIGN_EXTEND:
6127 *total = 0;
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);
6133 if (mode == DImode)
6134 *total += COSTS_N_INSNS (1);
6135 return false;
6137 case ZERO_EXTEND:
6138 *total = 0;
6139 if (!(arm_arch4 && MEM_P (XEXP (x, 0))))
6141 switch (GET_MODE (XEXP (x, 0)))
6143 case QImode:
6144 *total += COSTS_N_INSNS (1);
6145 break;
6147 case HImode:
6148 *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2);
6150 case SImode:
6151 break;
6153 default:
6154 *total += COSTS_N_INSNS (2);
6158 if (mode == DImode)
6159 *total += COSTS_N_INSNS (1);
6161 return false;
6163 case CONST_INT:
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)
6172 *total = 0;
6173 else
6174 *total = COSTS_N_INSNS (1);
6176 else
6177 *total = COSTS_N_INSNS (2);
6178 return true;
6180 case CONST:
6181 case LABEL_REF:
6182 case SYMBOL_REF:
6183 *total = COSTS_N_INSNS (2);
6184 return true;
6186 case CONST_DOUBLE:
6187 *total = COSTS_N_INSNS (4);
6188 return true;
6190 default:
6191 if (mode != VOIDmode)
6192 *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
6193 else
6194 *total = COSTS_N_INSNS (4); /* How knows? */
6195 return false;
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 */
6204 static bool
6205 arm_slowmul_rtx_costs (rtx x, int code, int outer_code, int *total)
6207 enum machine_mode mode = GET_MODE (x);
6209 if (TARGET_THUMB)
6211 /* APPLE LOCAL v7 support. Merge from mainline */
6212 *total = thumb1_rtx_costs (x, code, outer_code);
6213 return true;
6216 switch (code)
6218 case MULT:
6219 if (GET_MODE_CLASS (mode) == MODE_FLOAT
6220 || mode == DImode)
6222 *total = 30;
6223 return true;
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;
6239 cost += 2;
6242 *total = cost;
6243 return true;
6246 *total = 30 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)
6247 + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4);
6248 return true;
6250 default:
6251 *total = arm_rtx_costs_1 (x, code, outer_code);
6252 return true;
6257 /* RTX cost for cores with a fast multiply unit (M variants). */
6259 static bool
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 */
6265 if (TARGET_THUMB1)
6267 *total = thumb1_rtx_costs (x, code, outer_code);
6268 return true;
6271 /* ??? should thumb2 use different costs? */
6272 /* APPLE LOCAL end v7 support. Merge from mainline */
6273 switch (code)
6275 case MULT:
6276 /* There is no point basing this on the tuning, since it is always the
6277 fast variant if it exists at all. */
6278 if (mode == DImode
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))
6283 *total = 8;
6284 return true;
6288 if (GET_MODE_CLASS (mode) == MODE_FLOAT
6289 || mode == DImode)
6291 *total = 30;
6292 return true;
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;
6308 cost += 2;
6311 *total = cost;
6312 return true;
6315 *total = 8 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)
6316 + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4);
6317 return true;
6319 default:
6320 *total = arm_rtx_costs_1 (x, code, outer_code);
6321 return true;
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 */
6331 static bool
6332 arm_xscale_rtx_costs (rtx x, int code, int outer_code, int *total)
6334 enum machine_mode mode = GET_MODE (x);
6336 if (TARGET_THUMB)
6338 /* APPLE LOCAL v7 support. Merge from mainline */
6339 *total = thumb1_rtx_costs (x, code, outer_code);
6340 return true;
6343 switch (code)
6345 case MULT:
6346 /* There is no point basing this on the tuning, since it is always the
6347 fast variant if it exists at all. */
6348 if (mode == DImode
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))
6353 *total = 8;
6354 return true;
6358 if (GET_MODE_CLASS (mode) == MODE_FLOAT
6359 || mode == DImode)
6361 *total = 30;
6362 return true;
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. */
6374 cost = 2;
6375 if (! const_ok)
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)
6383 cost += 1;
6384 else
6385 cost += 2;
6387 *total = cost;
6388 return true;
6391 *total = 8 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)
6392 + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4);
6393 return true;
6395 case COMPARE:
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);
6400 else
6401 *total = arm_rtx_costs_1 (x, code, outer_code);
6402 return true;
6404 default:
6405 *total = arm_rtx_costs_1 (x, code, outer_code);
6406 return true;
6411 /* RTX costs for 9e (and later) cores. */
6413 static bool
6414 arm_9e_rtx_costs (rtx x, int code, int outer_code, int *total)
6416 enum machine_mode mode = GET_MODE (x);
6417 int nonreg_cost;
6418 int cost;
6420 /* APPLE LOCAL v7 support. Merge from mainline */
6421 if (TARGET_THUMB1)
6423 switch (code)
6425 case MULT:
6426 *total = COSTS_N_INSNS (3);
6427 return true;
6429 default:
6430 /* APPLE LOCAL v7 support. Merge from mainline */
6431 *total = thumb1_rtx_costs (x, code, outer_code);
6432 return true;
6436 switch (code)
6438 case MULT:
6439 /* There is no point basing this on the tuning, since it is always the
6440 fast variant if it exists at all. */
6441 if (mode == DImode
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))
6446 *total = 3;
6447 return true;
6451 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
6453 *total = 30;
6454 return true;
6456 if (mode == DImode)
6458 cost = 7;
6459 nonreg_cost = 8;
6461 else
6463 cost = 2;
6464 nonreg_cost = 4;
6468 *total = cost + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : nonreg_cost)
6469 + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : nonreg_cost);
6470 return true;
6472 default:
6473 *total = arm_rtx_costs_1 (x, code, outer_code);
6474 return true;
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. */
6481 static inline int
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)
6487 return 0;
6488 if (c == MEM || c == LABEL_REF || c == SYMBOL_REF)
6489 return 10;
6491 if (c == PLUS || c == MINUS)
6493 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
6494 return 2;
6496 if (ARITHMETIC_P (XEXP (x, 0)) || ARITHMETIC_P (XEXP (x, 1)))
6497 return 3;
6499 return 4;
6502 return 6;
6505 static inline int
6506 arm_thumb_address_cost (rtx x)
6508 enum rtx_code c = GET_CODE (x);
6510 if (c == REG)
6511 return 1;
6512 if (c == PLUS
6513 && GET_CODE (XEXP (x, 0)) == REG
6514 && GET_CODE (XEXP (x, 1)) == CONST_INT)
6515 return 1;
6517 return 2;
6520 static 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);
6527 static int
6528 arm_adjust_cost (rtx insn, rtx link, rtx dep, int cost)
6530 /* LLVM LOCAL begin */
6531 #ifdef ENABLE_LLVM
6532 insn = insn;
6533 link = link;
6534 dep = dep;
6535 cost = cost;
6536 return 1;
6537 #else
6538 /* LLVM LOCAL end */
6539 rtx i_pat, d_pat;
6541 /* Some true dependencies can have a higher cost depending
6542 on precisely how certain input operands are used. */
6543 if (arm_tune_xscale
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;
6559 int opno;
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. */
6568 extract_insn (dep);
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)
6574 continue;
6576 if (reg_overlap_mentioned_p (recog_data.operand[opno],
6577 shifted_operand))
6578 return 2;
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)
6586 return 0;
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)
6591 return 1;
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
6602 hack. */
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))
6608 return 1;
6611 return cost;
6612 /* LLVM LOCAL */
6613 #endif
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] =
6621 "0", "1", "2", "3",
6622 "4", "5", "0.5", "10"
6625 static REAL_VALUE_TYPE values_fp[8];
6627 static void
6628 init_fp_table (void)
6630 int i;
6631 REAL_VALUE_TYPE r;
6633 if (TARGET_VFP)
6634 fp_consts_inited = 1;
6635 else
6636 fp_consts_inited = 8;
6638 for (i = 0; i < fp_consts_inited; i++)
6640 r = REAL_VALUE_ATOF (strings_fp[i], DFmode);
6641 values_fp[i] = r;
6645 /* Return TRUE if rtx X is a valid immediate FP constant. */
6647 arm_const_double_rtx (rtx x)
6649 REAL_VALUE_TYPE r;
6650 int i;
6652 if (!fp_consts_inited)
6653 init_fp_table ();
6655 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
6656 if (REAL_VALUE_MINUS_ZERO (r))
6657 return 0;
6659 for (i = 0; i < fp_consts_inited; i++)
6660 if (REAL_VALUES_EQUAL (r, values_fp[i]))
6661 return 1;
6663 return 0;
6666 /* Return TRUE if rtx X is a valid immediate FPA constant. */
6668 neg_const_double_rtx_ok_for_fpa (rtx x)
6670 REAL_VALUE_TYPE r;
6671 int i;
6673 if (!fp_consts_inited)
6674 init_fp_table ();
6676 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
6677 r = REAL_VALUE_NEGATE (r);
6678 if (REAL_VALUE_MINUS_ZERO (r))
6679 return 0;
6681 for (i = 0; i < 8; i++)
6682 if (REAL_VALUES_EQUAL (r, values_fp[i]))
6683 return 1;
6685 return 0;
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):
6694 -1^s * n * 2^-r
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. */
6708 static int
6709 vfp3_const_double_index (rtx x)
6711 REAL_VALUE_TYPE r, m;
6712 int sign, exponent;
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)
6719 return -1;
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))
6725 return -1;
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);
6737 mantissa = m1;
6738 mant_hi = m2;
6740 /* If there are bits set in the low part of the mantissa, we can't
6741 represent this value. */
6742 if (mantissa != 0)
6743 return -1;
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
6747 discarded. */
6748 point_pos -= HOST_BITS_PER_WIDE_INT;
6749 mantissa = mant_hi;
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)
6755 return -1;
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.) */
6763 if (mantissa == 0)
6764 return -1;
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)
6776 return -1;
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)
6787 if (!TARGET_VFP3)
6788 return 0;
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
6820 vmov i8 16 abcdefgh
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
6827 than indices.
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.
6843 static int
6844 neon_valid_immediate (rtx op, enum machine_mode mode, int inverse,
6845 rtx *modconst, int *elementwidth)
6847 #define CHECK(STRIDE, ELSIZE, CLASS, TEST) \
6848 matches = 1; \
6849 for (i = 0; i < idx; i += (STRIDE)) \
6850 if (!(TEST)) \
6851 matches = 0; \
6852 if (matches) \
6854 immtype = (CLASS); \
6855 elsize = (ELSIZE); \
6856 break; \
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);
6869 REAL_VALUE_TYPE r0;
6871 if (!vfp3_const_double_rtx (el0))
6872 return -1;
6874 REAL_VALUE_FROM_CONST_DOUBLE (r0, el0);
6876 for (i = 1; i < n_elts; i++)
6878 rtx elt = CONST_VECTOR_ELT (op, i);
6879 REAL_VALUE_TYPE re;
6881 REAL_VALUE_FROM_CONST_DOUBLE (re, elt);
6883 if (!REAL_VALUES_EQUAL (r0, re))
6884 return -1;
6887 if (modconst)
6888 *modconst = CONST_VECTOR_ELT (op, 0);
6890 if (elementwidth)
6891 *elementwidth = 0;
6893 return 18;
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);
6906 parts = 1;
6908 else if (GET_CODE (el) == CONST_DOUBLE)
6910 elpart = CONST_DOUBLE_LOW (el);
6911 parts = 2;
6913 else
6914 gcc_unreachable ();
6916 for (part = 0; part < parts; part++)
6918 unsigned int byte;
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);
6929 /* Sanity check. */
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]);
6983 while (0);
6985 if (immtype == -1)
6986 return -1;
6988 if (elementwidth)
6989 *elementwidth = elsize;
6991 if (modconst)
6993 unsigned HOST_WIDE_INT imm = 0;
6995 /* Un-invert bytes of recognized vector, if neccessary. */
6996 if (invmask != 0)
6997 for (i = 0; i < idx; i++)
6998 bytes[i] ^= invmask;
7000 if (immtype == 17)
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);
7011 else
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);
7022 return immtype;
7023 #undef CHECK
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)
7035 rtx tmpconst;
7036 int tmpwidth;
7037 int retval = neon_valid_immediate (op, mode, 0, &tmpconst, &tmpwidth);
7039 if (retval == -1)
7040 return 0;
7042 if (modconst)
7043 *modconst = tmpconst;
7045 if (elementwidth)
7046 *elementwidth = tmpwidth;
7048 return 1;
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)
7060 rtx tmpconst;
7061 int tmpwidth;
7062 int retval = neon_valid_immediate (op, mode, inverse, &tmpconst, &tmpwidth);
7064 if (retval < 0 || retval > 5)
7065 return 0;
7067 if (modconst)
7068 *modconst = tmpconst;
7070 if (elementwidth)
7071 *elementwidth = tmpwidth;
7073 return 1;
7076 /* Return a string suitable for output of Neon immediate logic operation
7077 MNEM. */
7079 char *
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);
7090 if (quad)
7091 sprintf (templ, "%s.i%d\t%%q0, %%2", mnem, width);
7092 else
7093 sprintf (templ, "%s.i%d\t%%P0, %%2", mnem, width);
7095 return templ;
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. */
7108 void
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);
7114 rtx tmpsum = op1;
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));
7120 tmpsum = dest;
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. */
7128 void
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);
7134 rtx mem;
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)))
7162 return 0;
7164 if (GET_CODE (op) == MEM)
7166 rtx ind;
7168 ind = XEXP (op, 0);
7170 /* Match: (mem (reg)). */
7171 if (GET_CODE (ind) == REG)
7172 return 1;
7174 /* Match:
7175 (mem (plus (reg)
7176 (const))). */
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)
7181 return 1;
7184 return 0;
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
7191 allowed. */
7192 /* APPLE LOCAL end v7 support. Merge from mainline */
7195 arm_coproc_mem_operand (rtx op, bool wb)
7197 rtx ind;
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)))
7207 return FALSE;
7209 /* Constants are converted into offsets from labels. */
7210 if (GET_CODE (op) != MEM)
7211 return FALSE;
7213 ind = XEXP (op, 0);
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)))
7221 return TRUE;
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
7234 || (wb
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 */
7240 if (wb
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);
7247 /* Match:
7248 (plus (reg)
7249 (const)). */
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)
7257 return TRUE;
7259 return FALSE;
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
7265 registers. */
7267 neon_vector_mem_operand (rtx op, bool core)
7269 rtx ind;
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)))
7279 return FALSE;
7281 /* Constants are converted into offsets from labels. */
7282 if (GET_CODE (op) != MEM)
7283 return FALSE;
7285 ind = XEXP (op, 0);
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)))
7293 return TRUE;
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);
7303 #if 0
7304 /* FIXME: We can support this too if we use VLD1/VST1. */
7305 if (!core
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);
7311 #endif
7313 /* Match:
7314 (plus (reg)
7315 (const)). */
7316 if (!core
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 */
7324 return TRUE;
7326 return FALSE;
7329 /* Return TRUE if OP is a mem suitable for loading/storing a Neon struct
7330 type. */
7332 neon_struct_mem_operand (rtx op)
7334 rtx ind;
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)))
7344 return FALSE;
7346 /* Constants are converted into offsets from labels. */
7347 if (GET_CODE (op) != MEM)
7348 return FALSE;
7350 ind = XEXP (op, 0);
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)))
7358 return TRUE;
7360 /* Match: (mem (reg)). */
7361 if (GET_CODE (ind) == REG)
7362 return arm_address_register_rtx_p (ind, 0);
7364 return FALSE;
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. */
7381 enum reg_class
7382 coproc_secondary_reload_class (enum machine_mode mode, rtx x, bool wb)
7384 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
7385 if (TARGET_NEON
7386 && (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
7387 || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
7388 && neon_vector_mem_operand (x, FALSE))
7389 return NO_REGS;
7391 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
7392 if (arm_coproc_mem_operand (x, wb) || s_register_operand (x, mode))
7393 return NO_REGS;
7395 return GENERAL_REGS;
7398 /* Values which must be returned in the most-significant end of the return
7399 register. */
7401 static bool
7402 arm_return_in_msb (tree valtype)
7404 return (TARGET_AAPCS_BASED
7405 && BYTES_BIG_ENDIAN
7406 && (AGGREGATE_TYPE_P (valtype)
7407 || TREE_CODE (valtype) == COMPLEX_TYPE));
7410 /* LLVM LOCAL */
7411 #ifndef ENABLE_LLVM
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. */
7416 static bool
7417 arm_memory_load_p (rtx insn)
7419 rtx body, lhs, rhs;;
7421 if (insn == NULL_RTX || GET_CODE (insn) != INSN)
7422 return false;
7424 body = PATTERN (insn);
7426 if (GET_CODE (body) != SET)
7427 return false;
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)
7438 return false;
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. */
7449 static bool
7450 arm_cirrus_insn_p (rtx insn)
7452 enum attr_cirrus attr;
7454 /* get_attr cannot accept USE or CLOBBER. */
7455 if (!insn
7456 || GET_CODE (insn) != INSN
7457 || GET_CODE (PATTERN (insn)) == USE
7458 || GET_CODE (PATTERN (insn)) == CLOBBER)
7459 return 0;
7461 attr = get_attr_cirrus (insn);
7463 return attr != CIRRUS_NOT;
7466 /* Cirrus reorg for invalid instruction combinations. */
7467 static void
7468 cirrus_reorg (rtx first)
7470 enum attr_cirrus attr;
7471 rtx body = PATTERN (first);
7472 rtx t;
7473 int nops;
7475 /* Any branch must be followed by 2 non Cirrus instructions. */
7476 if (GET_CODE (first) == JUMP_INSN && GET_CODE (body) != RETURN)
7478 nops = 0;
7479 t = next_nonnote_insn (first);
7481 if (arm_cirrus_insn_p (t))
7482 ++ nops;
7484 if (arm_cirrus_insn_p (next_nonnote_insn (t)))
7485 ++ nops;
7487 while (nops --)
7488 emit_insn_after (gen_nop (), first);
7490 return;
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);
7508 return;
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
7517 insn. Example:
7519 ldr r0, blah
7521 cfmvsr mvf0, r0. */
7523 /* Get Arm register number for ldr insn. */
7524 if (GET_CODE (lhs) == REG)
7525 arm_regno = REGNO (lhs);
7526 else
7528 gcc_assert (GET_CODE (rhs) == REG);
7529 arm_regno = REGNO (rhs);
7532 /* Next insn. */
7533 first = next_nonnote_insn (first);
7535 if (! arm_cirrus_insn_p (first))
7536 return;
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);
7552 return;
7556 /* get_attr cannot accept USE or CLOBBER. */
7557 if (!first
7558 || GET_CODE (first) != INSN
7559 || GET_CODE (PATTERN (first)) == USE
7560 || GET_CODE (PATTERN (first)) == CLOBBER)
7561 return;
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)
7569 nops = 0;
7571 t = next_nonnote_insn (first);
7573 if (arm_cirrus_insn_p (t))
7574 ++ nops;
7576 if (arm_cirrus_insn_p (next_nonnote_insn (t)))
7577 ++ nops;
7579 while (nops --)
7580 emit_insn_after (gen_nop (), first);
7582 return;
7586 /* LLVM LOCAL */
7587 #endif
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)
7606 are ignored. */
7607 static int
7608 symbol_mentioned_with_filter (rtx x, int filter_local)
7610 const char * fmt;
7611 int i;
7613 if (GET_CODE (x) == SYMBOL_REF)
7615 #if TARGET_MACHO
7616 if (filter_local && machopic_data_defined_p (x))
7617 return 0;
7618 else
7619 #endif
7620 return 1;
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)
7626 return 0;
7628 fmt = GET_RTX_FORMAT (GET_CODE (x));
7630 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
7632 if (fmt[i] == 'E')
7634 int j;
7636 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
7637 if (symbol_mentioned_with_filter (XVECEXP (x, i, j),
7638 filter_local))
7639 return 1;
7641 else if (fmt[i] == 'e'
7642 && symbol_mentioned_with_filter (XEXP (x, i),
7643 filter_local))
7644 return 1;
7647 return 0;
7649 /* APPLE LOCAL end ARM -mdynmaic-no-pic support */
7651 /* Return TRUE if X references a LABEL_REF. */
7653 label_mentioned_p (rtx x)
7655 const char * fmt;
7656 int i;
7658 if (GET_CODE (x) == LABEL_REF)
7659 return 1;
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)
7664 return 0;
7666 fmt = GET_RTX_FORMAT (GET_CODE (x));
7667 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
7669 if (fmt[i] == 'E')
7671 int j;
7673 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
7674 if (label_mentioned_p (XVECEXP (x, i, j)))
7675 return 1;
7677 else if (fmt[i] == 'e' && label_mentioned_p (XEXP (x, i)))
7678 return 1;
7681 return 0;
7685 tls_mentioned_p (rtx x)
7687 switch (GET_CODE (x))
7689 case CONST:
7690 return tls_mentioned_p (XEXP (x, 0));
7692 case UNSPEC:
7693 if (XINT (x, 1) == UNSPEC_TLS)
7694 return 1;
7696 default:
7697 return 0;
7701 /* Must not copy a SET whose source operand is PC-relative. */
7703 static bool
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)
7716 return TRUE;
7718 if (GET_CODE (rhs) == MEM
7719 && GET_CODE (XEXP (rhs, 0)) == UNSPEC
7720 && XINT (XEXP (rhs, 0), 1) == UNSPEC_PIC_BASE)
7721 return TRUE;
7723 if (GET_CODE (lhs) == MEM
7724 && GET_CODE (XEXP (lhs, 0)) == UNSPEC
7725 && XINT (XEXP (lhs, 0), 1) == UNSPEC_PIC_BASE)
7726 return TRUE;
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)
7737 return TRUE;
7739 if (GET_CODE (rhs) == MEM
7740 && GET_CODE (XEXP (rhs, 0)) == UNSPEC
7741 && XINT (XEXP (rhs, 0), 1) == UNSPEC_PIC_BASE)
7742 return TRUE;
7745 return FALSE;
7748 enum rtx_code
7749 minmax_code (rtx x)
7751 enum rtx_code code = GET_CODE (x);
7753 switch (code)
7755 case SMAX:
7756 return GE;
7757 case SMIN:
7758 return LE;
7759 case UMIN:
7760 return LEU;
7761 case UMAX:
7762 return GEU;
7763 default:
7764 gcc_unreachable ();
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))
7774 return 0;
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;
7784 rtx reg0, reg1;
7785 int val_diff;
7787 if (GET_CODE (XEXP (a, 0)) == PLUS)
7789 reg0 = XEXP (XEXP (a, 0), 0);
7790 val0 = INTVAL (XEXP (XEXP (a, 0), 1));
7792 else
7793 reg0 = XEXP (a, 0);
7795 if (GET_CODE (XEXP (b, 0)) == PLUS)
7797 reg1 = XEXP (XEXP (b, 0), 0);
7798 val1 = INTVAL (XEXP (XEXP (b, 0), 1));
7800 else
7801 reg1 = XEXP (b, 0);
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))
7807 return 0;
7809 /* Don't allow an eliminable register: register elimination can make
7810 the offset too large. */
7811 if (arm_eliminable_register (reg0))
7812 return 0;
7814 val_diff = val1 - val0;
7816 if (arm_ld_sched)
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));
7830 return 0;
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];
7839 int order[4];
7840 int base_reg = -1;
7841 int i;
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
7850 offsets. */
7851 for (i = 0; i < nops; i++)
7853 rtx reg;
7854 rtx offset;
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]))
7865 return 0;
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))
7874 == REG)
7875 || (GET_CODE (reg) == SUBREG
7876 && GET_CODE (reg = SUBREG_REG (reg)) == REG))
7877 && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1))
7878 == CONST_INT)))
7880 if (i == 0)
7882 base_reg = REGNO (reg);
7883 unsorted_regs[0] = (GET_CODE (operands[i]) == REG
7884 ? REGNO (operands[i])
7885 : REGNO (SUBREG_REG (operands[i])));
7886 order[0] = 0;
7888 else
7890 if (base_reg != (int) REGNO (reg))
7891 /* Not addressed from the same base register. */
7892 return 0;
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]])
7898 order[0] = i;
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))
7906 return 0;
7908 unsorted_offsets[i] = INTVAL (offset);
7910 else
7911 /* Not a suitable memory address. */
7912 return 0;
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++)
7923 int j;
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]]))
7930 order[i] = j;
7932 /* Have we found a suitable register? if not, one must be used more
7933 than once. */
7934 if (order[i] == order[i - 1])
7935 return 0;
7937 /* Is the memory address adjacent and ascending? */
7938 if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
7939 return 0;
7942 if (base)
7944 *base = base_reg;
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
7990 cache.
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)
7996 return 0;
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;
8004 const char *
8005 emit_ldm_seq (rtx *operands, int nops)
8007 int regs[4];
8008 int base_reg;
8009 HOST_WIDE_INT offset;
8010 char buf[100];
8011 int i;
8013 switch (load_multiple_sequence (operands, nops, regs, &base_reg, &offset))
8015 case 1:
8016 /* APPLE LOCAL v7 support. Merge from mainline */
8017 strcpy (buf, "ldm%(ia%)\t");
8018 break;
8020 case 2:
8021 /* APPLE LOCAL v7 support. Merge from mainline */
8022 strcpy (buf, "ldm%(ib%)\t");
8023 break;
8025 case 3:
8026 /* APPLE LOCAL v7 support. Merge from mainline */
8027 strcpy (buf, "ldm%(da%)\t");
8028 break;
8030 case 4:
8031 /* APPLE LOCAL v7 support. Merge from mainline */
8032 strcpy (buf, "ldm%(db%)\t");
8033 break;
8035 case 5:
8036 if (offset >= 0)
8037 sprintf (buf, "add%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
8038 reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
8039 (long) offset);
8040 else
8041 sprintf (buf, "sub%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
8042 reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
8043 (long) -offset);
8044 output_asm_insn (buf, operands);
8045 base_reg = regs[0];
8046 /* APPLE LOCAL v7 support. Merge from mainline */
8047 strcpy (buf, "ldm%(ia%)\t");
8048 break;
8050 default:
8051 gcc_unreachable ();
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);
8064 return "";
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];
8073 int order[4];
8074 int base_reg = -1;
8075 int i;
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
8084 offsets. */
8085 for (i = 0; i < nops; i++)
8087 rtx reg;
8088 rtx offset;
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]))
8099 return 0;
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))
8108 == REG)
8109 || (GET_CODE (reg) == SUBREG
8110 && GET_CODE (reg = SUBREG_REG (reg)) == REG))
8111 && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1))
8112 == CONST_INT)))
8114 if (i == 0)
8116 base_reg = REGNO (reg);
8117 unsorted_regs[0] = (GET_CODE (operands[i]) == REG
8118 ? REGNO (operands[i])
8119 : REGNO (SUBREG_REG (operands[i])));
8120 order[0] = 0;
8122 else
8124 if (base_reg != (int) REGNO (reg))
8125 /* Not addressed from the same base register. */
8126 return 0;
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]])
8132 order[0] = i;
8135 /* If it isn't an integer register, then we can't do this. */
8136 if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14)
8137 return 0;
8139 unsorted_offsets[i] = INTVAL (offset);
8141 else
8142 /* Not a suitable memory address. */
8143 return 0;
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++)
8154 int j;
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]]))
8161 order[i] = j;
8163 /* Have we found a suitable register? if not, one must be used more
8164 than once. */
8165 if (order[i] == order[i - 1])
8166 return 0;
8168 /* Is the memory address adjacent and ascending? */
8169 if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
8170 return 0;
8173 if (base)
8175 *base = base_reg;
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 */
8195 return 0;
8198 const char *
8199 emit_stm_seq (rtx *operands, int nops)
8201 int regs[4];
8202 int base_reg;
8203 HOST_WIDE_INT offset;
8204 char buf[100];
8205 int i;
8207 switch (store_multiple_sequence (operands, nops, regs, &base_reg, &offset))
8209 case 1:
8210 /* APPLE LOCAL v7 support. Merge from mainline */
8211 strcpy (buf, "stm%(ia%)\t");
8212 break;
8214 case 2:
8215 /* APPLE LOCAL v7 support. Merge from mainline */
8216 strcpy (buf, "stm%(ib%)\t");
8217 break;
8219 case 3:
8220 /* APPLE LOCAL v7 support. Merge from mainline */
8221 strcpy (buf, "stm%(da%)\t");
8222 break;
8224 case 4:
8225 /* APPLE LOCAL v7 support. Merge from mainline */
8226 strcpy (buf, "stm%(db%)\t");
8227 break;
8229 default:
8230 gcc_unreachable ();
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);
8243 return "";
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;
8253 int i = 0, j;
8254 rtx result;
8255 int sign = up ? 1 : -1;
8256 rtx mem, addr;
8258 /* XScale has load-store double instructions, but they have stricter
8259 alignment requirements than load-store multiple, so we cannot
8260 use them.
8262 For XScale ldm requires 2 + NREGS cycles to complete and blocks
8263 the pipeline until completion.
8265 NREGS CYCLES
8271 An ldr instruction takes 1-3 cycles, but does not block the
8272 pipeline.
8274 NREGS CYCLES
8275 1 1-3
8276 2 2-6
8277 3 3-9
8278 4 4-12
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)
8288 rtx seq;
8290 start_sequence ();
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);
8297 offset += 4 * sign;
8300 if (write_back)
8302 emit_move_insn (from, plus_constant (from, count * 4 * sign));
8303 *offsetp = offset;
8306 seq = get_insns ();
8307 end_sequence ();
8309 return seq;
8312 result = gen_rtx_PARALLEL (VOIDmode,
8313 rtvec_alloc (count + (write_back ? 1 : 0)));
8314 if (write_back)
8316 XVECEXP (result, 0, 0)
8317 = gen_rtx_SET (VOIDmode, from, plus_constant (from, count * 4 * sign));
8318 i = 1;
8319 count++;
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);
8328 offset += 4 * sign;
8331 if (write_back)
8332 *offsetp = offset;
8334 return result;
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;
8342 int i = 0, j;
8343 rtx result;
8344 int sign = up ? 1 : -1;
8345 rtx mem, addr;
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)
8351 rtx seq;
8353 start_sequence ();
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));
8360 offset += 4 * sign;
8363 if (write_back)
8365 emit_move_insn (to, plus_constant (to, count * 4 * sign));
8366 *offsetp = offset;
8369 seq = get_insns ();
8370 end_sequence ();
8372 return seq;
8375 result = gen_rtx_PARALLEL (VOIDmode,
8376 rtvec_alloc (count + (write_back ? 1 : 0)));
8377 if (write_back)
8379 XVECEXP (result, 0, 0)
8380 = gen_rtx_SET (VOIDmode, to,
8381 plus_constant (to, count * 4 * sign));
8382 i = 1;
8383 count++;
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));
8392 offset += 4 * sign;
8395 if (write_back)
8396 *offsetp = offset;
8398 return result;
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;
8406 int i;
8407 rtx src, dst, srcbase, dstbase;
8408 rtx part_bytes_reg = NULL;
8409 rtx mem;
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)
8415 return 0;
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. */
8423 if (optimize_size
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)
8430 return 0;
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));
8452 else
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,
8463 dst, TRUE,
8464 (last_bytes == 0
8465 ? FALSE : TRUE),
8466 dstbase, &dstoffset));
8467 else
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)));
8474 dstoffset += 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)
8486 rtx sreg;
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);
8493 in_words_to_go--;
8495 gcc_assert (!in_words_to_go); /* Sanity check */
8498 if (in_words_to_go)
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;
8517 while (last_bytes)
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));
8524 if (--last_bytes)
8526 tmp = gen_reg_rtx (SImode);
8527 emit_insn (gen_lshrsi3 (tmp, part_bytes_reg, GEN_INT (8)));
8528 part_bytes_reg = tmp;
8533 else
8535 if (last_bytes > 1)
8537 mem = adjust_automodify_address (dstbase, HImode, dst, dstoffset);
8538 emit_move_insn (mem, gen_lowpart (HImode, part_bytes_reg));
8539 last_bytes -= 2;
8540 if (last_bytes)
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;
8546 dstoffset += 2;
8550 if (last_bytes)
8552 mem = adjust_automodify_address (dstbase, QImode, dst, dstoffset);
8553 emit_move_insn (mem, gen_lowpart (QImode, part_bytes_reg));
8557 return 1;
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. */
8569 enum machine_mode
8570 arm_select_dominance_cc_mode (rtx x, rtx y, HOST_WIDE_INT cond_or)
8572 enum rtx_code cond1, cond2;
8573 int swapped = 0;
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))
8579 != CCmode)
8580 || (arm_select_cc_mode (cond2 = GET_CODE (y), XEXP (y, 0), XEXP (y, 1))
8581 != CCmode))
8582 return CCmode;
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. */
8592 if (cond1 != cond2
8593 && !comparison_dominates_p (cond1, cond2)
8594 && (swapped = 1, !comparison_dominates_p (cond2, cond1)))
8595 return CCmode;
8597 if (swapped)
8599 enum rtx_code temp = cond1;
8600 cond1 = cond2;
8601 cond2 = temp;
8604 switch (cond1)
8606 case EQ:
8607 if (cond_or == DOM_CC_X_AND_Y)
8608 return CC_DEQmode;
8610 switch (cond2)
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 ();
8620 case LT:
8621 if (cond_or == DOM_CC_X_AND_Y)
8622 return CC_DLTmode;
8624 switch (cond2)
8626 case LT:
8627 return CC_DLTmode;
8628 case LE:
8629 return CC_DLEmode;
8630 case NE:
8631 return CC_DNEmode;
8632 default:
8633 gcc_unreachable ();
8636 case GT:
8637 if (cond_or == DOM_CC_X_AND_Y)
8638 return CC_DGTmode;
8640 switch (cond2)
8642 case GT:
8643 return CC_DGTmode;
8644 case GE:
8645 return CC_DGEmode;
8646 case NE:
8647 return CC_DNEmode;
8648 default:
8649 gcc_unreachable ();
8652 case LTU:
8653 if (cond_or == DOM_CC_X_AND_Y)
8654 return CC_DLTUmode;
8656 switch (cond2)
8658 case LTU:
8659 return CC_DLTUmode;
8660 case LEU:
8661 return CC_DLEUmode;
8662 case NE:
8663 return CC_DNEmode;
8664 default:
8665 gcc_unreachable ();
8668 case GTU:
8669 if (cond_or == DOM_CC_X_AND_Y)
8670 return CC_DGTUmode;
8672 switch (cond2)
8674 case GTU:
8675 return CC_DGTUmode;
8676 case GEU:
8677 return CC_DGEUmode;
8678 case NE:
8679 return CC_DNEmode;
8680 default:
8681 gcc_unreachable ();
8684 /* The remaining cases only occur when both comparisons are the
8685 same. */
8686 case NE:
8687 gcc_assert (cond1 == cond2);
8688 return CC_DNEmode;
8690 case LE:
8691 gcc_assert (cond1 == cond2);
8692 return CC_DLEmode;
8694 case GE:
8695 gcc_assert (cond1 == cond2);
8696 return CC_DGEmode;
8698 case LEU:
8699 gcc_assert (cond1 == cond2);
8700 return CC_DLEUmode;
8702 case GEU:
8703 gcc_assert (cond1 == cond2);
8704 return CC_DGEUmode;
8706 default:
8707 gcc_unreachable ();
8711 enum machine_mode
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)
8718 switch (op)
8720 case EQ:
8721 case NE:
8722 case UNORDERED:
8723 case ORDERED:
8724 case UNLT:
8725 case UNLE:
8726 case UNGT:
8727 case UNGE:
8728 case UNEQ:
8729 case LTGT:
8730 return CCFPmode;
8732 case LT:
8733 case LE:
8734 case GT:
8735 case GE:
8736 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
8737 return CCFPmode;
8738 return CCFPEmode;
8740 default:
8741 gcc_unreachable ();
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))
8751 return CC_SWPmode;
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))
8758 return CC_Zmode;
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)
8773 return CC_Zmode;
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),
8792 DOM_CC_X_AND_Y);
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),
8798 DOM_CC_X_OR_Y);
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 */
8804 if (TARGET_THUMB1
8805 && GET_MODE (x) == SImode
8806 && (op == EQ || op == NE)
8807 && GET_CODE (x) == ZERO_EXTRACT
8808 && XEXP (x, 1) == const1_rtx)
8809 return CC_Nmode;
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"
8814 instead.) */
8815 /* APPLE LOCAL v7 support. Merge from mainline */
8816 /* ??? Does the ZERO_EXTRACT case really apply to thumb2? */
8817 if (GET_MODE (x) == SImode
8818 && y == const0_rtx
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)))
8829 return CC_NOOVmode;
8831 if (GET_MODE (x) == QImode && (op == EQ || op == NE))
8832 return CC_Zmode;
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)))
8837 return CC_Cmode;
8839 return CCmode;
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));
8853 return cc_reg;
8856 /* Generate a sequence of insns that will generate the correct return
8857 address mask depending on the physical architecture that the program
8858 is running on. */
8860 arm_gen_return_addr_mask (void)
8862 rtx reg = gen_reg_rtx (Pmode);
8864 emit_insn (gen_return_addr_mask (reg));
8865 return reg;
8868 void
8869 arm_reload_in_hi (rtx *operands)
8871 rtx ref = operands[1];
8872 rtx base, scratch;
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));
8892 else
8893 /* The slot is out of range, or was dressed up in a SUBREG. */
8894 base = reg_equiv_address[REGNO (ref)];
8896 else
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);
8906 base = base_plus;
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 */
8918 lo = (offset >= 0
8919 ? (offset & 0xfff)
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). */
8925 if (lo == 4095)
8926 lo &= 0x7ff;
8928 hi = ((((offset - lo) & (HOST_WIDE_INT) 0xffffffff)
8929 ^ (HOST_WIDE_INT) 0x80000000)
8930 - (HOST_WIDE_INT) 0x80000000);
8932 gcc_assert (hi + lo == offset);
8934 if (hi != 0)
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)));
8941 base = base_plus;
8942 offset = lo;
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);
8951 else
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,
8957 offset))));
8958 emit_insn (gen_zero_extendqisi2 (gen_rtx_SUBREG (SImode, operands[0], 0),
8959 gen_rtx_MEM (QImode,
8960 plus_constant (base,
8961 offset + 1))));
8962 if (!BYTES_BIG_ENDIAN)
8963 emit_set_insn (gen_rtx_SUBREG (SImode, operands[0], 0),
8964 gen_rtx_IOR (SImode,
8965 gen_rtx_ASHIFT
8966 (SImode,
8967 gen_rtx_SUBREG (SImode, operands[0], 0),
8968 GEN_INT (8)),
8969 scratch));
8970 else
8971 emit_set_insn (gen_rtx_SUBREG (SImode, operands[0], 0),
8972 gen_rtx_IOR (SImode,
8973 gen_rtx_ASHIFT (SImode, scratch,
8974 GEN_INT (8)),
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). */
8984 void
8985 arm_reload_out_hi (rtx *operands)
8987 rtx ref = operands[0];
8988 rtx outval = operands[1];
8989 rtx base, scratch;
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));
9009 else
9010 /* The slot is out of range, or was dressed up in a SUBREG. */
9011 base = reg_equiv_address[REGNO (ref)];
9013 else
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))
9031 rtx tmp = scratch;
9032 scratch = base_plus;
9033 base_plus = tmp;
9035 else
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);
9051 base = base_plus;
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 */
9063 lo = (offset >= 0
9064 ? (offset & 0xfff)
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). */
9070 if (lo == 4095)
9071 lo &= 0x7ff;
9073 hi = ((((offset - lo) & (HOST_WIDE_INT) 0xffffffff)
9074 ^ (HOST_WIDE_INT) 0x80000000)
9075 - (HOST_WIDE_INT) 0x80000000);
9077 gcc_assert (hi + lo == offset);
9079 if (hi != 0)
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))
9090 rtx tmp = scratch;
9091 scratch = base_plus;
9092 base_plus = tmp;
9094 else
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
9103 outval. */
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)));
9112 base = base_plus;
9113 offset = lo;
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),
9124 GEN_INT (8)));
9125 emit_insn (gen_movqi (gen_rtx_MEM (QImode, plus_constant (base, offset)),
9126 gen_lowpart (QImode, scratch)));
9128 else
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),
9134 GEN_INT (8)));
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. */
9144 static bool
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);
9149 else
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. */
9160 bool
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))
9167 return false;
9169 return true;
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
9178 upwards. */
9180 bool
9181 arm_pad_reg_upward (enum machine_mode mode ATTRIBUTE_UNUSED,
9182 tree type, int first ATTRIBUTE_UNUSED)
9184 if (TARGET_AAPCS_BASED
9185 && BYTES_BIG_ENDIAN
9186 && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE)
9187 && int_size_in_bytes (type) <= 4)
9188 return true;
9190 /* Otherwise, use default padding. */
9191 return !BYTES_BIG_ENDIAN;
9195 /* Print a symbolic form of X to the debug file, F. */
9196 static void
9197 arm_print_value (FILE *f, rtx x)
9199 switch (GET_CODE (x))
9201 case CONST_INT:
9202 fprintf (f, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
9203 return;
9205 case CONST_DOUBLE:
9206 fprintf (f, "<0x%lx,0x%lx>", (long)XWINT (x, 2), (long)XWINT (x, 3));
9207 return;
9209 case CONST_VECTOR:
9211 int i;
9213 fprintf (f, "<");
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))
9218 fputc (',', f);
9220 fprintf (f, ">");
9222 return;
9224 case CONST_STRING:
9225 fprintf (f, "\"%s\"", XSTR (x, 0));
9226 return;
9228 case SYMBOL_REF:
9229 fprintf (f, "`%s'", XSTR (x, 0));
9230 return;
9232 case LABEL_REF:
9233 fprintf (f, "L%d", INSN_UID (XEXP (x, 0)));
9234 return;
9236 case CONST:
9237 arm_print_value (f, XEXP (x, 0));
9238 return;
9240 case PLUS:
9241 arm_print_value (f, XEXP (x, 0));
9242 fprintf (f, "+");
9243 arm_print_value (f, XEXP (x, 1));
9244 return;
9246 case PC:
9247 fprintf (f, "pc");
9248 return;
9250 default:
9251 fprintf (f, "????");
9252 return;
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:
9273 ldr rn, L1
9275 b L2
9276 align
9277 L1: .long value
9281 ldr rn, L3
9283 b L4
9284 align
9285 L3: .long value
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
9313 of a pool. */
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. */
9326 Mnode * next;
9327 Mnode * prev;
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. */
9337 int refcount;
9338 /* The offset from the start of the minipool. */
9339 HOST_WIDE_INT offset;
9340 /* The value in table. */
9341 rtx value;
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. */
9346 int fix_size;
9349 struct minipool_fixup
9351 Mfix * next;
9352 rtx insn;
9353 HOST_WIDE_INT address;
9354 rtx * loc;
9355 enum machine_mode mode;
9356 int fix_size;
9357 rtx value;
9358 Mnode * minipool;
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. */
9370 void
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)
9380 *length += 2;
9381 return;
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;
9392 *length = len;
9394 if (!TARGET_THUMB2 && GET_CODE (body) == ADDR_DIFF_VEC)
9396 /* The obvious sizeof(elt)*nelts, plus sizeof(elt) for the
9397 count. */
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
9404 pessimistic. */
9405 if (TARGET_THUMB
9406 && GET_MODE_SIZE (GET_MODE (body)) == 4)
9407 len += 2;
9409 /* Round up to a multiple of instruction size. */
9410 len = ((len + insn_size - 1) / insn_size) * insn_size;
9411 *length = len;
9413 if (TARGET_THUMB
9414 /* APPLE LOCAL 6279481 */
9415 && !TARGET_32BIT
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)
9429 *length = 2;
9430 else
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)
9439 *length = 4;
9440 else
9441 *length = 2;
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)
9451 *length = 2;
9452 else
9454 gcc_assert (GET_CODE (mem) == MEM);
9455 mem = XEXP (mem, 0);
9456 if (GET_CODE (mem) == CONST)
9457 mem = XEXP (mem, 0);
9458 *length = 4;
9459 if (GET_CODE (mem) == LABEL_REF)
9460 *length = 2;
9461 if (GET_CODE (mem) == PLUS)
9463 if (GET_CODE (XEXP (mem, 0)) == LABEL_REF
9464 && GET_CODE (XEXP (mem, 1)) == CONST_INT)
9465 *length = 2;
9466 if (GET_CODE (XEXP (mem, 1)) == REG)
9467 *length = 2;
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)
9476 *length = 2;
9477 else
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)
9484 *length = 2;
9485 else if (GET_CODE (mem) == PLUS
9486 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
9487 *length = 2;
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)
9496 *length = 2;
9497 else if (REGNO (XEXP (mem, 0)) == REGNO (XEXP (body, 0)))
9498 *length = 6;
9499 else
9500 *length = 4;
9502 else
9504 gcc_assert (GET_CODE (XEXP (mem, 1)) == REG);
9505 if (REGNO (XEXP (mem, 1)) == REGNO (XEXP (body, 0)))
9506 *length = 6;
9507 else
9508 *length = 4;
9511 else if (GET_CODE (mem) == REG && REGNO (XEXP (body, 0)) == REGNO (mem))
9512 *length = 6;
9513 else
9514 *length = 4;
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)
9522 *length = 2;
9523 else
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)
9530 *length = 2;
9531 else if (GET_CODE (mem) == PLUS
9532 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
9533 *length = 2;
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)
9542 *length = 2;
9543 else if (REGNO (XEXP (mem, 0)) == REGNO (XEXP (body, 0)))
9544 *length = 4;
9545 else
9546 *length = 4;
9548 else
9550 gcc_assert (GET_CODE (XEXP (mem, 1)) == REG);
9551 if (REGNO (XEXP (mem, 1)) == REGNO (XEXP (body, 0)))
9552 *length = 4;
9553 else
9554 *length = 4;
9557 else if (GET_CODE (mem) == REG && REGNO (XEXP (body, 0)) == REGNO (mem))
9558 *length = 4;
9559 else
9560 *length = 4;
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)
9568 *length = 2;
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)
9572 *length = 4;
9573 else
9574 *length = 2;
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);
9582 /* case 3 */
9583 if (GET_CODE (op0) == MEM &&
9584 (GET_CODE (XEXP (op0, 0)) == PRE_INC
9585 || GET_CODE (XEXP (op0, 0)) == POST_INC))
9586 *length = 2;
9587 /* case 4 */
9588 else if (GET_CODE (op1) == MEM &&
9589 (GET_CODE (XEXP (op1, 0)) == PRE_INC
9590 || GET_CODE (XEXP (op1, 0)) == POST_INC))
9591 *length = 2;
9592 /* case 2 */
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)))
9598 *length = 6;
9599 /* case 0, 1, 6, 7 */
9600 else if (GET_CODE (op1) != MEM)
9601 *length = 4;
9602 /* case 5 */
9603 else
9605 rtx addr = XEXP (op1, 0);
9606 if (GET_CODE (addr) == REG)
9607 *length = 4;
9608 else if (GET_CODE (addr) == CONST)
9609 *length = 4;
9610 else if (GET_CODE (addr) == PLUS)
9612 rtx base = XEXP (addr, 0);
9613 rtx offset = XEXP (addr, 1);
9614 if (CONSTANT_P (base))
9616 rtx temp = base;
9617 base = offset;
9618 offset = temp;
9620 if (GET_CODE (offset) == REG)
9621 *length = 6;
9622 else
9623 *length = 4;
9625 else if (GET_CODE (addr) == LABEL_REF)
9626 *length = 4;
9627 else
9628 abort ();
9632 /* APPLE LOCAL end ARM 4790140 compact switch tables */
9634 /* LLVM LOCAL */
9635 #ifndef ENABLE_LLVM
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. */
9650 static rtx
9651 is_jump_table (rtx insn)
9653 rtx table;
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))
9659 && table != NULL
9660 && GET_CODE (table) == JUMP_INSN
9661 && (GET_CODE (PATTERN (table)) == ADDR_VEC
9662 || GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC))
9663 return table;
9665 return NULL_RTX;
9668 #ifndef JUMP_TABLES_IN_TEXT_SECTION
9669 #define JUMP_TABLES_IN_TEXT_SECTION 0
9670 #endif
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
9676 section. */
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 */
9682 HOST_WIDE_INT size;
9683 HOST_WIDE_INT modesize;
9685 modesize = GET_MODE_SIZE (GET_MODE (body));
9686 size = modesize * XVECLEN (body, elt);
9687 switch (modesize)
9689 case 1:
9690 /* Round up size of TBB table to a hafword boundary. */
9691 size = (size + 1) & ~(HOST_WIDE_INT)1;
9692 break;
9693 case 2:
9694 /* No padding neccessary for TBH. */
9695 break;
9696 case 4:
9697 /* Add two bytes for alignment on Thumb. */
9698 if (TARGET_THUMB)
9699 size += 2;
9700 break;
9701 default:
9702 gcc_unreachable ();
9704 return size;
9705 /* APPLE LOCAL end v7 support. Merge from mainline */
9708 return 0;
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. */
9714 static Mnode *
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);
9721 if (max_mp == NULL)
9723 if (max_address < mp->max_address)
9724 mp->max_address = max_address;
9726 else
9728 if (max_address > max_mp->max_address - mp->fix_size)
9729 mp->max_address = max_mp->max_address - mp->fix_size;
9730 else
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;
9738 else
9739 minipool_vector_tail = mp->prev;
9741 /* Re-insert it before MAX_MP. */
9742 mp->next = max_mp;
9743 mp->prev = max_mp->prev;
9744 max_mp->prev = mp;
9746 if (mp->prev != NULL)
9747 mp->prev->next = mp;
9748 else
9749 minipool_vector_head = mp;
9752 /* Save the new entry. */
9753 max_mp = mp;
9755 /* Scan over the preceding entries and adjust their addresses as
9756 required. */
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;
9761 mp = mp->prev;
9764 return max_mp;
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. */
9769 static Mnode *
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;
9776 Mnode * mp;
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
9781 earlier. */
9782 if (minipool_vector_head &&
9783 (fix->address + get_attr_length (fix->insn)
9784 >= minipool_vector_head->max_address - fix->fix_size))
9785 return NULL;
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
9790 exist. */
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. */
9801 mp->refcount++;
9802 return move_minipool_fix_forward_ref (mp, max_mp, max_address);
9805 /* Note the insertion point if necessary. */
9806 if (max_mp == NULL
9807 && mp->max_address > max_address)
9808 max_mp = mp;
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
9815 && max_mp == NULL
9816 && fix->fix_size == 8
9817 && mp->fix_size != 8)
9819 max_mp = mp;
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
9829 entries. */
9830 mp = XNEW (Mnode);
9831 mp->fix_size = fix->fix_size;
9832 mp->mode = fix->mode;
9833 mp->value = fix->value;
9834 mp->refcount = 1;
9835 /* Not yet required for a backwards ref. */
9836 mp->min_address = -65536;
9838 if (max_mp == NULL)
9840 mp->max_address = max_address;
9841 mp->next = NULL;
9842 mp->prev = minipool_vector_tail;
9844 if (mp->prev == NULL)
9846 minipool_vector_head = mp;
9847 minipool_vector_label = gen_label_rtx ();
9849 else
9850 mp->prev->next = mp;
9852 minipool_vector_tail = mp;
9854 else
9856 if (max_address > max_mp->max_address - mp->fix_size)
9857 mp->max_address = max_mp->max_address - mp->fix_size;
9858 else
9859 mp->max_address = max_address;
9861 mp->next = max_mp;
9862 mp->prev = max_mp->prev;
9863 max_mp->prev = mp;
9864 if (mp->prev != NULL)
9865 mp->prev->next = mp;
9866 else
9867 minipool_vector_head = mp;
9870 /* Save the new entry. */
9871 max_mp = mp;
9873 /* Scan over the preceding entries and adjust their addresses as
9874 required. */
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;
9879 mp = mp->prev;
9882 return max_mp;
9885 static Mnode *
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);
9894 if (min_mp == NULL)
9896 if (min_address > mp->min_address)
9897 mp->min_address = min_address;
9899 else
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;
9909 else
9910 minipool_vector_head = mp->next;
9912 /* Reinsert it after MIN_MP. */
9913 mp->prev = min_mp;
9914 mp->next = min_mp->next;
9915 min_mp->next = mp;
9916 if (mp->next != NULL)
9917 mp->next->prev = mp;
9918 else
9919 minipool_vector_tail = mp;
9922 min_mp = mp;
9924 offset = 0;
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;
9935 return min_mp;
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
9944 construction. */
9945 static Mnode *
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;
9953 Mnode *mp;
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))
9962 return NULL;
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
9967 exist. */
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). */
9978 && (mp->max_address
9979 > (minipool_barrier->address
9980 + minipool_vector_tail->offset
9981 + minipool_vector_tail->fix_size)))
9983 mp->refcount++;
9984 return move_minipool_fix_backward_ref (mp, min_mp, min_address);
9987 if (min_mp != NULL)
9988 mp->min_address += fix->fix_size;
9989 else
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)
9998 return NULL;
9999 else
10000 min_mp = mp;
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
10008 after it. */
10009 min_mp = mp;
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
10017 && min_mp == NULL
10018 && fix->fix_size == 8
10019 && mp->fix_size < 8)
10021 min_mp = mp;
10022 min_address = mp->min_address + fix->fix_size;
10027 /* We need to create a new entry. */
10028 mp = XNEW (Mnode);
10029 mp->fix_size = fix->fix_size;
10030 mp->mode = fix->mode;
10031 mp->value = fix->value;
10032 mp->refcount = 1;
10033 mp->max_address = minipool_barrier->address + 65536;
10035 mp->min_address = min_address;
10037 if (min_mp == NULL)
10039 mp->prev = NULL;
10040 mp->next = minipool_vector_head;
10042 if (mp->next == NULL)
10044 minipool_vector_tail = mp;
10045 minipool_vector_label = gen_label_rtx ();
10047 else
10048 mp->next->prev = mp;
10050 minipool_vector_head = mp;
10052 else
10054 mp->next = min_mp->next;
10055 mp->prev = min_mp;
10056 min_mp->next = mp;
10058 if (mp->next != NULL)
10059 mp->next->prev = mp;
10060 else
10061 minipool_vector_tail = mp;
10064 /* Save the new entry. */
10065 min_mp = mp;
10067 if (mp->prev)
10068 mp = mp->prev;
10069 else
10070 mp->offset = 0;
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;
10078 if (mp->refcount)
10079 mp->next->offset = mp->offset + mp->fix_size;
10080 else
10081 mp->next->offset = mp->offset;
10083 mp = mp->next;
10086 return min_mp;
10089 static void
10090 assign_minipool_offsets (Mfix *barrier)
10092 HOST_WIDE_INT offset = 0;
10093 Mnode *mp;
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 */
10107 static void
10108 dump_minipool (rtx scan)
10110 Mnode * mp;
10111 Mnode * nmp;
10112 int align64 = 0;
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)
10118 align64 = 1;
10119 break;
10122 if (dump_file)
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)
10135 if (dump_file)
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
10148 case 1:
10149 scan = emit_insn_after (gen_consttable_1 (mp->value), scan);
10150 break;
10152 #endif
10153 #ifdef HAVE_consttable_2
10154 case 2:
10155 scan = emit_insn_after (gen_consttable_2 (mp->value), scan);
10156 break;
10158 #endif
10159 #ifdef HAVE_consttable_4
10160 case 4:
10161 scan = emit_insn_after (gen_consttable_4 (mp->value), scan);
10162 break;
10164 #endif
10165 #ifdef HAVE_consttable_8
10166 case 8:
10167 scan = emit_insn_after (gen_consttable_8 (mp->value), scan);
10168 break;
10170 #endif
10171 /* APPLE LOCAL begin v7 support. Merge from mainline */
10172 #ifdef HAVE_consttable_16
10173 case 16:
10174 scan = emit_insn_after (gen_consttable_16 (mp->value), scan);
10175 break;
10177 #endif
10178 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
10179 default:
10180 gcc_unreachable ();
10184 nmp = mp->next;
10185 free (mp);
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. */
10194 static int
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)
10204 base_cost -= 20;
10206 switch (GET_CODE (insn))
10208 case CODE_LABEL:
10209 /* It will always be better to place the table before the label, rather
10210 than after it. */
10211 return 50;
10213 case INSN:
10214 case CALL_INSN:
10215 return base_cost;
10217 case JUMP_INSN:
10218 return base_cost - 10;
10220 default:
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
10228 it. */
10229 static Mfix *
10230 create_fix_barrier (Mfix *fix, HOST_WIDE_INT max_address)
10232 HOST_WIDE_INT count = 0;
10233 rtx barrier;
10234 rtx from = fix->insn;
10235 /* The instruction after which we will insert the jump. */
10236 rtx selected = NULL;
10237 int selected_cost;
10238 /* The address at which the jump instruction will be placed. */
10239 HOST_WIDE_INT selected_address;
10240 Mfix * new_fix;
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)
10249 rtx tmp;
10250 int new_cost;
10252 /* This code shouldn't have been called if there was a natural barrier
10253 within range. */
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);
10266 if (tmp != NULL)
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))
10278 selected = tmp;
10279 selected_cost = new_cost;
10280 selected_address = fix->address + count;
10283 /* Continue after the dispatch table. */
10284 from = NEXT_INSN (tmp);
10285 continue;
10288 new_cost = arm_barrier_cost (from);
10290 if (count < max_count
10291 && (!selected || new_cost <= selected_cost))
10293 selected = from;
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;
10317 return new_fix;
10320 /* Record that there is a natural barrier in the insn stream at
10321 ADDRESS. */
10322 static void
10323 push_minipool_barrier (rtx insn, HOST_WIDE_INT address)
10325 Mfix * fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (* fix));
10327 fix->insn = insn;
10328 fix->address = address;
10330 fix->next = NULL;
10331 if (minipool_fix_head != NULL)
10332 minipool_fix_tail->next = fix;
10333 else
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
10343 MODE. */
10344 static void
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
10352 based area. */
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 */
10358 fix->insn = insn;
10359 fix->address = address;
10360 fix->loc = loc;
10361 fix->mode = mode;
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)
10377 minipool_pad = 4;
10379 if (dump_file)
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. */
10391 fix->next = NULL;
10393 if (minipool_fix_head != NULL)
10394 minipool_fix_tail->next = fix;
10395 else
10396 minipool_fix_head = fix;
10398 minipool_fix_tail = fix;
10401 /* LLVM LOCAL */
10402 #endif
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
10406 do it. */
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)
10416 mode = DImode;
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
10436 not considered.)
10439 bool
10440 const64_ok_for_arm_immediate (rtx val)
10442 rtx lowpart, highpart;
10443 enum machine_mode mode;
10445 if (!TARGET_ARM)
10446 return false;
10448 mode = GET_MODE (val);
10450 if (mode == VOIDmode)
10451 mode = DImode;
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
10467 or as negated. */
10468 bool
10469 const64_ok_for_arm_add (rtx val)
10471 rtx lowpart, highpart, lowpart_neg, highpart_neg, val_neg;
10472 enum machine_mode mode;
10474 if (!TARGET_ARM)
10475 return false;
10477 mode = GET_MODE (val);
10479 if (mode == VOIDmode)
10480 mode = DImode;
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. */
10505 bool
10506 arm_const_double_by_parts (rtx val)
10508 enum machine_mode mode = GET_MODE (val);
10509 rtx part;
10511 if (optimize_size || arm_ld_sched)
10512 return true;
10514 if (mode == VOIDmode)
10515 mode = DImode;
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)))
10523 return true;
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)))
10531 return true;
10533 return false;
10536 /* LLVM LOCAL */
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. */
10544 static bool
10545 note_invalid_constants (rtx insn, HOST_WIDE_INT address, int do_pushes)
10547 bool result = false;
10548 int opno;
10550 extract_insn (insn);
10552 if (!constrain_operands (1))
10553 fatal_insn_not_found (insn);
10555 if (recog_data.n_alternatives == 0)
10556 return false;
10558 /* Fill in recog_op_alt with information about the constraints of
10559 this insn. */
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)
10566 continue;
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))
10578 if (do_pushes)
10579 push_minipool_fix (insn, address, recog_data.operand_loc[opno],
10580 recog_data.operand_mode[opno], op);
10581 result = true;
10583 else if (GET_CODE (op) == MEM
10584 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
10585 && CONSTANT_POOL_ADDRESS_P (XEXP (op, 0)))
10587 if (do_pushes)
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. */
10596 if (op == cop)
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);
10604 result = true;
10609 return result;
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;
10619 int pad_needed;
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)
10629 return 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))
10636 return 0;
10638 return pad_needed;
10640 /* APPLE LOCAL end ARM 6008578 */
10642 /* LLVM LOCAL */
10643 #endif
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. */
10649 static void
10650 arm_reorg (void)
10652 /* LLVM LOCAL */
10653 #ifndef ENABLE_LLVM
10654 rtx insn;
10655 HOST_WIDE_INT address = 0;
10656 Mfix * fix;
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. */
10662 if (TARGET_THUMB)
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);
10670 minipool_pad = 0;
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))
10689 rtx table;
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);
10699 insn = table;
10704 fix = minipool_fix_head;
10706 /* Now scan the fixups and perform the required changes. */
10707 while (fix)
10709 Mfix * ftmp;
10710 Mfix * fdel;
10711 Mfix * last_added_fix;
10712 Mfix * last_barrier = NULL;
10713 Mfix * this_fix;
10715 /* Skip any further barriers before the next fix. */
10716 while (fix && GET_CODE (fix->insn) == BARRIER)
10717 fix = fix->next;
10719 /* No more fixes. */
10720 if (fix == NULL)
10721 break;
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)
10730 break;
10732 last_barrier = ftmp;
10734 else if ((ftmp->minipool = add_minipool_forward_ref (ftmp)) == NULL)
10735 break;
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
10746 pool after all. */
10747 for (fdel = last_barrier->next;
10748 fdel && fdel != ftmp;
10749 fdel = fdel->next)
10751 fdel->minipool->refcount--;
10752 fdel->minipool = NULL;
10755 ftmp = last_barrier;
10757 else
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. */
10768 gcc_assert (ftmp);
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);
10785 while (ftmp)
10787 if (GET_CODE (ftmp->insn) != BARRIER
10788 && ((ftmp->minipool = add_minipool_backward_ref (ftmp))
10789 == NULL))
10790 break;
10792 ftmp = ftmp->next;
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)
10801 rtx addr
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);
10809 fix = ftmp;
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);
10819 /* LLVM LOCAL */
10820 #endif
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. */
10828 const char *
10829 fp_immediate_constant (rtx x)
10831 REAL_VALUE_TYPE r;
10832 int i;
10834 if (!fp_consts_inited)
10835 init_fp_table ();
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)
10849 int i;
10851 if (!fp_consts_inited)
10852 init_fp_table ();
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. */
10866 static void
10867 print_multi_reg (FILE *stream, const char *instr, unsigned reg,
10868 unsigned long mask)
10870 unsigned i;
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 */
10882 if (not_first)
10883 fprintf (stream, ", ");
10885 asm_fprintf (stream, "%r", i);
10886 not_first = TRUE;
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. */
10904 static void
10905 vfp_output_fldmd (FILE * stream, unsigned int base, int reg, int count)
10906 /* APPLE LOCAL end v7 support. Merge from mainline */
10908 int i;
10910 /* Workaround ARM10 VFPr1 bug. */
10911 if (count == 2 && !arm_arch6)
10913 if (reg == 15)
10914 reg--;
10915 count++;
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. */
10921 if (count > 16)
10923 vfp_output_fldmd (stream, base, reg, 16);
10924 vfp_output_fldmd (stream, base, reg + 16, count - 16);
10925 return;
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++)
10934 if (i > reg)
10935 fputs (", ", stream);
10936 asm_fprintf (stream, "d%d", i);
10938 fputs ("}\n", stream);
10943 /* Output the assembly for a store multiple. */
10945 const char *
10946 /* APPLE LOCAL v7 support. Merge from mainline */
10947 vfp_output_fstmd (rtx * operands)
10949 char pattern[100];
10950 int p;
10951 int base;
10952 int i;
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);
10968 return "";
10972 /* Emit RTL to save block of VFP register pairs to the stack. Returns the
10973 number of bytes pushed. */
10975 static int
10976 /* APPLE LOCAL v7 support. Merge from mainline */
10977 vfp_emit_fstmd (int base_reg, int count)
10979 rtx par;
10980 rtx dwarf;
10981 rtx tmp, reg;
10982 int i;
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)
10990 base_reg -= 2;
10991 count++;
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
10997 practice). */
10998 if (count > 16)
11000 int saved;
11001 /* NOTE: base_reg is an internal register number, so each D register
11002 counts as 2. */
11003 saved = vfp_emit_fstmd (base_reg + 32, count - 16);
11004 saved += vfp_emit_fstmd (base_reg, 16);
11005 return saved;
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);
11013 base_reg += 2;
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),
11032 reg);
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);
11039 base_reg += 2;
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,
11045 i * 8)),
11046 reg);
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,
11053 REG_NOTES (par));
11054 RTX_FRAME_RELATED_P (par) = 1;
11056 /* APPLE LOCAL v7 support. Merge from mainline */
11057 return count * 8;
11061 /* Output a 'call' insn. */
11062 const char *
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);
11078 else
11079 output_asm_insn ("mov%?\t%|pc, %0", operands);
11081 return "";
11084 /* Output a 'call' insn that is a reference in memory. */
11085 const char *
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);
11100 if (arm_arch5)
11101 output_asm_insn ("blx%?\t%|ip", operands);
11102 else
11104 output_asm_insn ("mov%?\t%|lr, %|pc", operands);
11105 if (arm_arch4t)
11106 output_asm_insn ("bx%?\t%|ip", operands);
11107 else
11108 output_asm_insn ("mov%?\t%|pc, %|ip", operands);
11111 else
11113 output_asm_insn ("mov%?\t%|lr, %|pc", operands);
11114 output_asm_insn ("ldr%?\t%|pc, %0", operands);
11117 return "";
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. */
11124 const char *
11125 output_mov_long_double_fpa_from_arm (rtx *operands)
11127 int arm_reg0 = REGNO (operands[1]);
11128 rtx ops[3];
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);
11140 return "";
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. */
11146 const char *
11147 output_mov_long_double_arm_from_fpa (rtx *operands)
11149 int arm_reg0 = REGNO (operands[0]);
11150 rtx ops[3];
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);
11161 return "";
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. */
11167 const char *
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]);
11173 rtx ops[2];
11174 int i;
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);
11185 else
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);
11195 return "";
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. */
11202 const char *
11203 output_mov_double_fpa_from_arm (rtx *operands)
11205 int arm_reg0 = REGNO (operands[1]);
11206 rtx ops[2];
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);
11215 return "";
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. */
11221 const char *
11222 output_mov_double_arm_from_fpa (rtx *operands)
11224 int arm_reg0 = REGNO (operands[0]);
11225 rtx ops[2];
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);
11234 return "";
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. */
11240 const char *
11241 output_move_double (rtx *operands)
11243 enum rtx_code code0 = GET_CODE (operands[0]);
11244 enum rtx_code code1 = GET_CODE (operands[1]);
11245 rtx otherops[3];
11247 if (code0 == REG)
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)))
11257 case REG:
11258 /* APPLE LOCAL v7 support. Merge from mainline */
11259 output_asm_insn ("ldm%(ia%)\t%m1, %M0", operands);
11260 break;
11262 case PRE_INC:
11263 gcc_assert (TARGET_LDRD);
11264 /* APPLE LOCAL v7 support. Merge from mainline */
11265 output_asm_insn ("ldr%(d%)\t%0, [%m1, #8]!", operands);
11266 break;
11268 case PRE_DEC:
11269 /* APPLE LOCAL begin v7 support. Merge from mainline */
11270 if (TARGET_LDRD)
11271 output_asm_insn ("ldr%(d%)\t%0, [%m1, #-8]!", operands);
11272 else
11273 output_asm_insn ("ldm%(db%)\t%m1!, %M0", operands);
11274 /* APPLE LOCAL end v7 support. Merge from mainline */
11275 break;
11277 case POST_INC:
11278 /* APPLE LOCAL v7 support. Merge from mainline */
11279 output_asm_insn ("ldm%(ia%)\t%m1!, %M0", operands);
11280 break;
11282 case POST_DEC:
11283 gcc_assert (TARGET_LDRD);
11284 /* APPLE LOCAL v7 support. Merge from mainline */
11285 output_asm_insn ("ldr%(d%)\t%0, [%m1], #-8", operands);
11286 break;
11288 case PRE_MODIFY:
11289 case POST_MODIFY:
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);
11303 else
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);
11315 else
11316 output_asm_insn ("ldr%(d%)\t%0, [%1, %2]!", otherops);
11319 else
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);
11332 else
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 */
11337 break;
11339 case LABEL_REF:
11340 case CONST:
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);
11344 break;
11346 /* APPLE LOCAL v7 support. Merge from mainline */
11347 /* ??? This needs checking for thumb2. */
11348 default:
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]))
11363 case -8:
11364 output_asm_insn ("ldm%(db%)\t%1, %M0", otherops);
11365 return "";
11366 case -4:
11367 if (TARGET_THUMB2)
11368 break;
11369 output_asm_insn ("ldm%(da%)\t%1, %M0", otherops);
11370 return "";
11371 case 4:
11372 if (TARGET_THUMB2)
11373 break;
11374 output_asm_insn ("ldm%(ib%)\t%1, %M0", otherops);
11375 return "";
11377 /* APPLE LOCAL end v7 support. Merge from mainline */
11379 if (TARGET_LDRD
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],
11386 otherops[2]))
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]",
11400 otherops);
11402 else
11403 /* APPLE LOCAL v7 support. Merge from mainline */
11404 output_asm_insn ("ldr%(d%)\t%0, [%1, %2]", otherops);
11405 return "";
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);
11412 else
11413 output_asm_insn ("add%?\t%0, %1, %2", otherops);
11415 else
11416 output_asm_insn ("add%?\t%0, %1, %2", otherops);
11418 else
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";
11424 else
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);
11433 else
11435 output_asm_insn ("ldr%?\t%0, %1", operands);
11436 output_asm_insn ("ldr%?\t%0, %1", otherops);
11441 else
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)))
11449 case REG:
11450 /* APPLE LOCAL v7 support. Merge from mainline */
11451 output_asm_insn ("stm%(ia%)\t%m0, %M1", operands);
11452 break;
11454 case PRE_INC:
11455 gcc_assert (TARGET_LDRD);
11456 /* APPLE LOCAL v7 support. Merge from mainline */
11457 output_asm_insn ("str%(d%)\t%1, [%m0, #8]!", operands);
11458 break;
11460 case PRE_DEC:
11461 /* APPLE LOCAL begin v7 support. Merge from mainline */
11462 if (TARGET_LDRD)
11463 output_asm_insn ("str%(d%)\t%1, [%m0, #-8]!", operands);
11464 else
11465 output_asm_insn ("stm%(db%)\t%m0!, %M1", operands);
11466 /* APPLE LOCAL end v7 support. Merge from mainline */
11467 break;
11469 case POST_INC:
11470 /* APPLE LOCAL v7 support. Merge from mainline */
11471 output_asm_insn ("stm%(ia%)\t%m0!, %M1", operands);
11472 break;
11474 case POST_DEC:
11475 gcc_assert (TARGET_LDRD);
11476 /* APPLE LOCAL v7 support. Merge from mainline */
11477 output_asm_insn ("str%(d%)\t%1, [%m0], #-8", operands);
11478 break;
11480 case PRE_MODIFY:
11481 case POST_MODIFY:
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))
11494 rtx reg1;
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);
11502 else
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);
11513 else
11514 /* APPLE LOCAL v7 support. Merge from mainline */
11515 output_asm_insn ("str%(d%)\t%0, [%1], %2", otherops);
11516 break;
11518 case PLUS:
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)))
11525 case -8:
11526 output_asm_insn ("stm%(db%)\t%m0, %M1", operands);
11527 return "";
11529 case -4:
11530 if (TARGET_THUMB2)
11531 break;
11532 output_asm_insn ("stm%(da%)\t%m0, %M1", operands);
11533 return "";
11535 case 4:
11536 if (TARGET_THUMB2)
11537 break;
11538 output_asm_insn ("stm%(ib%)\t%m0, %M1", operands);
11539 return "";
11541 /* APPLE LOCAL end v7 support. Merge from mainline */
11543 if (TARGET_LDRD
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);
11553 return "";
11555 /* Fall through */
11557 default:
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);
11565 return "";
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. */
11572 const char *
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)))
11583 case REG:
11584 output_asm_insn ("ldm%(ia%)\t%m1, %M0", operands);
11585 break;
11587 case LABEL_REF:
11588 case CONST:
11589 output_asm_insn ("adr%?\t%0, %1", operands);
11590 output_asm_insn ("ldm%(ia%)\t%0, %M0", operands);
11591 break;
11593 default:
11594 gcc_unreachable ();
11597 else
11599 rtx ops[2];
11600 int dest, src, i;
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
11608 very often. */
11609 if (dest < src)
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);
11616 else
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);
11625 else
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)))
11633 case REG:
11634 output_asm_insn ("stm%(ia%)\t%m0, %M1", operands);
11635 break;
11637 default:
11638 gcc_unreachable ();
11642 return "";
11645 /* Output a VFP load or store instruction. */
11647 const char *
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;
11655 char buff[50];
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
11666 || mode == DFmode
11667 || mode == SImode
11668 || mode == DImode
11669 || (TARGET_NEON && VALID_NEON_DREG_MODE (mode)));
11670 gcc_assert (MEM_P (mem));
11672 addr = XEXP (mem, 0);
11674 switch (GET_CODE (addr))
11676 case PRE_DEC:
11677 template = "f%smdb%c%%?\t%%0!, {%%%s1}%s";
11678 ops[0] = XEXP (addr, 0);
11679 ops[1] = reg;
11680 break;
11682 case POST_INC:
11683 template = "f%smia%c%%?\t%%0!, {%%%s1}%s";
11684 ops[0] = XEXP (addr, 0);
11685 ops[1] = reg;
11686 break;
11688 default:
11689 template = "f%s%c%%?\t%%%s0, %%1%s";
11690 ops[0] = reg;
11691 ops[1] = mem;
11692 break;
11695 sprintf (buff, template,
11696 load ? "ld" : "st",
11697 dp ? 'd' : 's',
11698 dp ? "P" : "",
11699 integer_p ? "\t%@ int" : "");
11700 output_asm_insn (buff, ops);
11702 return "";
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
11723 rN in the order:
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. */
11732 const char *
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;
11738 char buff[50];
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))
11763 case POST_INC:
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);
11767 ops[1] = reg;
11768 break;
11770 case POST_MODIFY:
11771 /* FIXME: Not currently enabled in neon_vector_mem_operand. */
11772 gcc_unreachable ();
11774 case LABEL_REF:
11775 case PLUS:
11777 int nregs = HARD_REGNO_NREGS (REGNO (reg), mode) / 2;
11778 int i;
11779 int overlap = -1;
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
11784 changes. */
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);
11790 overlap = i;
11792 else
11794 sprintf (buff, "v%sr%%?\t%%P0, %%1", load ? "ld" : "st");
11795 output_asm_insn (buff, ops);
11798 if (overlap != -1)
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);
11806 return "";
11809 default:
11810 /* FIXME: See POST_INC. */
11811 template = "v%smia%%?\t%%m0, %%h1";
11812 ops[0] = mem;
11813 ops[1] = reg;
11816 sprintf (buff, template, load ? "ld" : "st");
11817 output_asm_insn (buff, ops);
11819 return "";
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. */
11825 const char *
11826 output_add_immediate (rtx *operands)
11828 HOST_WIDE_INT n = INTVAL (operands[2]);
11830 if (n != 0 || REGNO (operands[0]) != REGNO (operands[1]))
11832 if (n < 0)
11833 output_multi_immediate (operands,
11834 "sub%?\t%0, %1, %2", "sub%?\t%0, %0, %2", 2,
11835 -n);
11836 else
11837 output_multi_immediate (operands,
11838 "add%?\t%0, %1, %2", "add%?\t%0, %0, %2", 2,
11842 return "";
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
11856 n &= 0xffffffff;
11857 #endif
11859 if (n == 0)
11861 /* Quick and easy output. */
11862 operands[immed_op] = const0_rtx;
11863 output_asm_insn (instr1, operands);
11865 else
11867 int i;
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)
11873 if (n & (3 << i))
11875 operands[immed_op] = GEN_INT (n & (255 << i));
11876 output_asm_insn (instr, operands);
11877 instr = instr2;
11878 i += 6;
11883 return "";
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)
11891 switch (code)
11893 case ASHIFT:
11894 return ARM_LSL_NAME;
11896 case ASHIFTRT:
11897 return "asr";
11899 case LSHIFTRT:
11900 return "lsr";
11902 case ROTATERT:
11903 return "ror";
11905 default:
11906 abort();
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
11914 was shifted. */
11915 const char *
11916 arithmetic_instr (rtx op, int shift_first_arg)
11918 switch (GET_CODE (op))
11920 case PLUS:
11921 return "add";
11923 case MINUS:
11924 return shift_first_arg ? "rsb" : "sub";
11926 case IOR:
11927 return "orr";
11929 case XOR:
11930 return "eor";
11932 case AND:
11933 return "and";
11935 /* APPLE LOCAL begin v7 support. Merge from mainline */
11936 case ASHIFT:
11937 case ASHIFTRT:
11938 case LSHIFTRT:
11939 case ROTATERT:
11940 return arm_shift_nmem(GET_CODE(op));
11941 /* APPLE LOCAL end v7 support. Merge from mainline */
11943 default:
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
11952 shift. */
11953 static const char *
11954 shift_op (rtx op, HOST_WIDE_INT *amountp)
11956 const char * mnem;
11957 enum rtx_code code = GET_CODE (op);
11959 switch (GET_CODE (XEXP (op, 1)))
11961 case REG:
11962 case SUBREG:
11963 *amountp = -1;
11964 break;
11966 case CONST_INT:
11967 *amountp = INTVAL (XEXP (op, 1));
11968 break;
11970 default:
11971 gcc_unreachable ();
11974 /* APPLE LOCAL begin v7 support. Merge from mainline */
11975 switch (code)
11977 case ROTATE:
11978 gcc_assert (*amountp != -1);
11979 *amountp = 32 - *amountp;
11980 code = ROTATERT;
11982 /* Fall through. */
11984 case ASHIFT:
11985 case ASHIFTRT:
11986 case LSHIFTRT:
11987 case ROTATERT:
11988 mnem = arm_shift_nmem(code);
11989 break;
11991 case MULT:
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;
11998 default:
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. */
12013 *amountp &= 31;
12014 else if (*amountp != (*amountp & 31))
12016 if (code == ASHIFT)
12017 mnem = "lsr";
12018 *amountp = 32;
12021 /* Shifts of 0 are no-ops. */
12022 if (*amountp == 0)
12023 return NULL;
12025 /* APPLE LOCAL end v7 support. Merge from mainline */
12027 return mnem;
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);
12040 shift++;
12043 return shift;
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
12056 void
12057 output_ascii_pseudo_op (FILE *stream, const unsigned char *p, int len)
12059 int i;
12060 int len_so_far = 0;
12062 fputs ("\t.ascii\t\"", stream);
12064 for (i = 0; i < len; i++)
12066 int c = p[i];
12068 if (len_so_far >= MAX_ASCII_LEN)
12070 fputs ("\"\n\t.ascii\t\"", stream);
12071 len_so_far = 0;
12074 if (ISPRINT (c))
12076 if (c == '\\' || c == '\"')
12078 putc ('\\', stream);
12079 len_so_far++;
12081 putc (c, stream);
12082 len_so_far++;
12084 else
12086 fprintf (stream, "\\%03o", c);
12087 len_so_far += 4;
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;
12102 unsigned int reg;
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. */
12119 max_reg = 7;
12120 else
12121 max_reg = 12;
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. */
12129 if (flag_pic
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;
12135 else
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. */
12151 if (flag_pic
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)
12168 unsigned int i;
12170 for (i = 0; ; i++)
12172 reg = EH_RETURN_DATA_REGNO (i);
12173 if (reg == INVALID_REGNUM)
12174 break;
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 */
12191 unsigned int reg;
12193 if (IS_NAKED (func_type))
12194 /* This should never really happen. */
12195 return 0;
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]
12214 || (save_reg_mask
12215 && optimize_size
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)
12247 break;
12249 if (reg <= 12)
12250 save_reg_mask |= (1 << reg);
12251 else
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;
12281 unsigned reg;
12283 mask = 0;
12284 for (reg = 0; reg < 12; reg ++)
12285 if (regs_ever_live[reg] && !call_used_regs[reg])
12286 mask |= 1 << 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 */
12293 if (flag_pic
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])
12321 mask |= 1 << 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 */
12337 return mask;
12341 /* Return the number of bytes required to save VFP registers. */
12342 static int
12343 arm_get_vfp_saved_size (void)
12345 unsigned int regno;
12346 int count;
12347 int saved;
12349 saved = 0;
12350 /* Space for saved VFP registers. */
12351 if (TARGET_HARD_FLOAT && TARGET_VFP)
12353 count = 0;
12354 for (regno = FIRST_VFP_REGNUM;
12355 regno < LAST_VFP_REGNUM;
12356 regno += 2)
12358 if ((!regs_ever_live[regno] || call_used_regs[regno])
12359 && (!regs_ever_live[regno + 1] || call_used_regs[regno + 1]))
12361 if (count > 0)
12363 /* Workaround ARM10 VFPr1 bug. */
12364 if (count == 2 && !arm_arch6)
12365 count++;
12366 /* APPLE LOCAL v7 support. Merge from mainline */
12367 saved += count * 8;
12369 count = 0;
12371 else
12372 count++;
12374 if (count > 0)
12376 if (count == 2 && !arm_arch6)
12377 count++;
12378 /* APPLE LOCAL v7 support. Merge from mainline */
12379 saved += count * 8;
12382 return saved;
12386 /* Generate a function exit sequence. If REALLY_RETURN is false, then do
12387 everything bar the final return instruction. */
12388 const char *
12389 output_return_instruction (rtx operand, int really_return, int reverse)
12391 char conditional[10];
12392 char instr[100];
12393 unsigned reg;
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))
12401 return "";
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. */
12408 if (really_return)
12410 rtx ops[2];
12412 /* Otherwise, trap an attempted return by aborting. */
12413 ops[0] = operand;
12414 ops[1] = gen_rtx_SYMBOL_REF (Pmode, NEED_PLT_RELOC ? "abort(PLT)"
12415 : "abort");
12416 assemble_external_libcall (ops[1]);
12417 output_asm_insn (reverse ? "bl%D0\t%a1" : "bl%d0\t%a1", ops);
12420 return "";
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. */
12438 if (really_return
12439 /* APPLE LOCAL ARM interworking */
12440 && (! TARGET_INTERWORK || arm_arch5))
12441 return_reg = reg_names[PC_REGNUM];
12442 else
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
12452 restore IP. */
12453 if (frame_pointer_needed)
12455 live_regs_mask &= ~ (1 << IP_REGNUM);
12456 live_regs_mask |= (1 << SP_REGNUM);
12458 else
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
12466 restored. */
12467 for (reg = 0; reg <= LAST_ARM_REGNUM; reg++)
12468 if (live_regs_mask == (1U << reg))
12469 break;
12471 if (reg <= LAST_ARM_REGNUM
12472 && (reg != LR_REGNUM
12473 || ! really_return
12474 || ! IS_INTERRUPT (func_type)))
12476 sprintf (instr, "ldr%s\t%%|%s, [%%|sp], #4", conditional,
12477 (reg == LR_REGNUM) ? return_reg : reg_names[reg]);
12479 else
12481 char *p;
12482 int first = 1;
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);
12499 else
12501 /* If we can't use ldmib (SA110 bug),
12502 then try to pop r3 instead. */
12503 if (stack_adjust)
12504 live_regs_mask |= 1 << 3;
12505 sprintf (instr, "ldm%sfd\t%%|sp, {", conditional);
12508 else
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]);
12518 if (first)
12519 first = 0;
12520 else
12522 memcpy (p, ", ", 2);
12523 p += 2;
12526 memcpy (p, "%|", 2);
12527 memcpy (p + 2, reg_names[reg], l);
12528 p += l + 2;
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))
12536 strcat (p, "^");
12538 else
12539 strcpy (p, "}");
12542 output_asm_insn (instr, & operand);
12544 /* See if we need to generate an extra instruction to
12545 perform the actual function return. */
12546 if (really_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. */
12552 really_return = 0;
12556 if (really_return)
12558 switch ((int) ARM_FUNC_TYPE (func_type))
12560 case ARM_FT_ISR:
12561 case ARM_FT_FIQ:
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);
12565 break;
12567 case ARM_FT_INTERWORKED:
12568 sprintf (instr, "bx%s\t%%|lr", conditional);
12569 break;
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);
12575 break;
12577 default:
12578 /* Use bx if it's available. */
12579 if (arm_arch5 || arm_arch4t)
12580 sprintf (instr, "bx%s\t%%|lr", conditional);
12581 else
12582 sprintf (instr, "mov%s\t%%|pc, %%|lr", conditional);
12583 break;
12586 output_asm_insn (instr, & operand);
12589 return "";
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
12598 .align
12600 .word 0xff000000 + (t1 - t0)
12601 arm_poke_function_name
12602 mov ip, sp
12603 stmfd sp!, {fp, ip, lr, pc}
12604 sub fp, ip, #4
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
12617 function name. */
12618 void
12619 arm_poke_function_name (FILE *stream, const char *name)
12621 unsigned long alignlength;
12622 unsigned long length;
12623 rtx x;
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. */
12636 static void
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 */
12642 if (TARGET_THUMB1)
12644 thumb1_output_function_prologue (f, frame_size);
12645 return;
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))
12656 default:
12657 case ARM_FT_NORMAL:
12658 break;
12659 case ARM_FT_INTERWORKED:
12660 asm_fprintf (f, "\t%@ Function supports interworking.\n");
12661 break;
12662 case ARM_FT_ISR:
12663 asm_fprintf (f, "\t%@ Interrupt Service Routine.\n");
12664 break;
12665 case ARM_FT_FIQ:
12666 asm_fprintf (f, "\t%@ Fast Interrupt Service Routine.\n");
12667 break;
12668 case ARM_FT_EXCEPTION:
12669 asm_fprintf (f, "\t%@ ARM Exception Handler.\n");
12670 break;
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
12701 if (flag_pic)
12702 asm_fprintf (f, "\tmov\t%r, %r\n", IP_REGNUM, PIC_OFFSET_TABLE_REGNUM);
12703 #endif
12705 return_used_this_function = 0;
12708 /* APPLE LOCAL begin 6902937 out of order VFP restore */
12709 static void
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 */
12734 const char *
12735 arm_output_epilogue (rtx sibling)
12737 int reg;
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;
12743 rtx operands[3];
12744 FILE * f = asm_out_file;
12745 unsigned int lrm_count = 0;
12746 int really_return = (sibling == NULL);
12747 int start_reg;
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)
12755 return "";
12757 func_type = arm_current_func_type ();
12759 if (IS_NAKED (func_type))
12760 /* Naked functions don't have epilogues. */
12761 return "";
12763 if (IS_VOLATILE (func_type) && TARGET_ABORT_NORETURN)
12765 rtx op;
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);
12772 return "";
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 ();
12782 if (TARGET_IWMMXT)
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);
12811 else
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;
12829 else
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)
12848 int saved_size;
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 */
12869 if (TARGET_IWMMXT)
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);
12885 lrm_count += 2;
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. */
12896 if (sibling)
12898 bool is_value;
12899 int regno = indirect_sibreturn_reg (sibling, &is_value);
12900 if (regno > 3 && regno != 12)
12902 if (is_value)
12903 XEXP (XEXP (XEXP (XVECEXP (PATTERN (sibling), 0, 0), 1), 0), 0)
12904 = gen_rtx_REG (SImode, IP_REGNUM);
12905 else
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);
12910 if (regno == -1)
12912 rtx stack_reg, offset;
12913 offset = indirect_sibreturn_mem (sibling, &stack_reg, &is_value);
12914 if (offset)
12916 if (is_value)
12917 XEXP (XEXP (XEXP (XVECEXP (PATTERN (sibling), 0, 0), 1), 0), 0)
12918 = gen_rtx_REG (SImode, IP_REGNUM);
12919 else
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
12949 && really_return
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 */
12962 if (TARGET_ARM)
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);
12975 else
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);
12995 else
12997 /* APPLE LOCAL begin ARM indirect sibcalls */
12998 int ip_ok = 1;
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. */
13003 if (sibling)
13005 bool is_value;
13006 int regno = indirect_sibreturn_reg (sibling, &is_value);
13007 if (regno > 3 && regno != 12)
13009 ip_ok = 0;
13010 if (is_value)
13011 XEXP (XEXP (XEXP (XVECEXP (PATTERN (sibling), 0, 0), 1), 0), 0)
13012 = gen_rtx_REG (SImode, IP_REGNUM);
13013 else
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);
13018 if (regno == -1)
13020 rtx stack_reg, offset;
13021 offset = indirect_sibreturn_mem (sibling, &stack_reg, &is_value);
13022 if (offset)
13024 ip_ok = 0;
13025 if (is_value)
13026 XEXP (XEXP (XEXP (XVECEXP (PATTERN (sibling), 0, 0), 1), 0), 0)
13027 = gen_rtx_REG (SImode, IP_REGNUM);
13028 else
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;
13043 int maxpopsize;
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)
13048 maxpopsize = 20;
13049 else if (TYPE_MODE (rettype) == DFmode
13050 || TYPE_MODE (rettype) == DImode)
13051 maxpopsize = 12;
13052 else
13053 maxpopsize = 16;
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)))
13060 ip_ok = 0;
13061 if (!ip_ok)
13062 maxpopsize -= 4;
13063 if (optimize_size
13064 && delta <= maxpopsize && delta % 4 == 0
13065 && !TARGET_IWMMXT
13066 && really_return
13067 && TARGET_SOFT_FLOAT
13068 && arm_fpu_arch == FPUTYPE_NONE
13069 && !flag_pic
13070 && !frame_pointer_needed)
13072 int reg = ip_ok ? 12 : 3;
13073 while (delta)
13075 saved_regs_mask |= (1 << reg);
13076 reg = (reg == 12) ? 3 : reg - 1;
13077 delta -= 4;
13080 else
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",
13095 reg, SP_REGNUM);
13097 else
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;
13112 else
13114 if (reg != start_reg)
13115 asm_fprintf (f, "\tlfmfd\t%r, %d, [%r]!\n",
13116 start_reg, reg - start_reg,
13117 SP_REGNUM);
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 ();
13134 if (TARGET_IWMMXT)
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)
13143 && really_return
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);
13170 else
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))
13186 return "";
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))
13196 case ARM_FT_ISR:
13197 case ARM_FT_FIQ:
13198 asm_fprintf (f, "\tsubs\t%r, %r, #4\n", PC_REGNUM, LR_REGNUM);
13199 break;
13201 case ARM_FT_EXCEPTION:
13202 asm_fprintf (f, "\tmovs\t%r, %r\n", PC_REGNUM, LR_REGNUM);
13203 break;
13205 case ARM_FT_INTERWORKED:
13206 asm_fprintf (f, "\tbx\t%r\n", LR_REGNUM);
13207 break;
13209 default:
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);
13219 else
13220 asm_fprintf (f, "\tmov\t%r, %r\n", PC_REGNUM, LR_REGNUM);
13221 break;
13224 return "";
13227 static void
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 */
13234 if (TARGET_THUMB1)
13236 int regno;
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];
13244 if (label != NULL)
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 */
13274 #if TARGET_MACHO
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 ();
13279 while (insn
13280 && NOTE_P (insn)
13281 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED_LABEL)
13282 insn = PREV_INSN (insn);
13283 if (insn
13284 && (LABEL_P (insn)
13285 || (NOTE_P (insn)
13286 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL)))
13287 fputs ("\tnop\n", file);
13289 #endif
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. */
13297 static rtx
13298 emit_multi_reg_push (unsigned long mask)
13300 int num_regs = 0;
13301 int num_dwarf_regs;
13302 int i, j;
13303 rtx par;
13304 rtx dwarf;
13305 int dwarf_par_index;
13306 rtx tmp, reg;
13308 for (i = 0; i <= LAST_ARM_REGNUM; i++)
13309 if (mask & (1 << i))
13310 num_regs++;
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))
13317 num_dwarf_regs--;
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:
13324 (parallel [
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:
13340 (sequence [
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),
13374 reg);
13375 RTX_FRAME_RELATED_P (tmp) = 1;
13376 XVECEXP (dwarf, 0, dwarf_par_index) = tmp;
13377 dwarf_par_index++;
13380 break;
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,
13398 4 * j)),
13399 reg);
13400 RTX_FRAME_RELATED_P (tmp) = 1;
13401 XVECEXP (dwarf, 0, dwarf_par_index++) = tmp;
13404 j++;
13408 par = emit_insn (par);
13410 tmp = gen_rtx_SET (VOIDmode,
13411 stack_pointer_rtx,
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,
13417 REG_NOTES (par));
13418 return par;
13421 /* Calculate the size of the return value that is passed in registers. */
13422 static int
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);
13429 else
13430 mode = DECL_MODE (DECL_RESULT (current_function_decl));
13432 return GET_MODE_SIZE (mode);
13435 static rtx
13436 emit_sfm (int base_reg, int count)
13438 rtx par;
13439 rtx dwarf;
13440 rtx tmp, reg;
13441 int i;
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,
13469 i * 12)),
13470 reg);
13471 RTX_FRAME_RELATED_P (tmp) = 1;
13472 XVECEXP (dwarf, 0, i + 1) = tmp;
13475 tmp = gen_rtx_SET (VOIDmode,
13476 stack_pointer_rtx,
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,
13484 REG_NOTES (par));
13485 return par;
13489 /* Return true if the current function needs to save/restore LR. */
13491 static bool
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 -> | |
13508 ----
13509 | | \
13510 | | saved arguments for
13511 | | vararg functions
13512 | | /
13514 hard FP & arg pointer -> | | \
13515 | | stack
13516 | | frame
13517 | | /
13519 | | \
13520 | | call saved
13521 | | registers
13522 soft frame pointer -> | | /
13524 | | \
13525 | | local
13526 | | variables
13527 locals base pointer -> | | /
13529 | | \
13530 | | outgoing
13531 | | arguments
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
13547 alignment. */
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;
13558 int leaf;
13559 int saved;
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)
13575 return offsets;
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 */
13590 if (TARGET_32BIT)
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;
13605 regno++)
13606 if (regs_ever_live [regno] && ! call_used_regs [regno])
13607 saved += 8;
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])
13616 saved += 12;
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)
13629 saved += 16;
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)
13634 saved += 64;
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
13642 on the stack. */
13643 if (leaf && frame_size == 0)
13645 offsets->outgoing_args = offsets->soft_frame;
13646 offsets->locals_base = offsets->soft_frame;
13647 return offsets;
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));
13667 return offsets;
13671 /* Calculate the relative offsets for the different stack pointers. Positive
13672 offsets are in the direction of stack growth. */
13674 HOST_WIDE_INT
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. */
13685 switch (from)
13687 case ARG_POINTER_REGNUM:
13688 switch (to)
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);
13708 default:
13709 gcc_unreachable ();
13711 gcc_unreachable ();
13713 case FRAME_POINTER_REGNUM:
13714 switch (to)
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;
13729 default:
13730 gcc_unreachable ();
13732 gcc_unreachable ();
13734 default:
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. */
13749 static int
13750 arm_save_coproc_regs(void)
13752 int saved_size = 0;
13753 unsigned reg;
13754 unsigned start_reg;
13755 rtx insn;
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;
13764 saved_size += 8;
13767 /* Save any floating point call-saved registers used by this
13768 function. */
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;
13778 saved_size += 12;
13781 else
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;
13793 saved_size += 48;
13794 start_reg = reg - 1;
13797 else
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);
13835 return saved_size;
13839 /* Set the Thumb frame pointer from the stack pointer. */
13841 static void
13842 thumb_set_frame_pointer (arm_stack_offsets *offsets)
13844 HOST_WIDE_INT amount;
13845 rtx insn, dwarf;
13847 amount = offsets->outgoing_args - offsets->locals_base;
13848 if (amount < 1024)
13849 insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx,
13850 stack_pointer_rtx, GEN_INT (amount)));
13851 else
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,
13861 REG_NOTES (insn));
13864 RTX_FRAME_RELATED_P (insn) = 1;
13867 /* Generate the prologue instructions for entry into an ARM or Thumb-2
13868 function. */
13869 /* APPLE LOCAL end v7 support. Merge from mainline */
13870 void
13871 arm_expand_prologue (void)
13873 /* APPLE LOCAL v7 support. Merge from mainline */
13874 /* Remove 'reg' variable */
13875 rtx amount;
13876 rtx insn;
13877 rtx ip_rtx;
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))
13890 return;
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))
13903 rtx dwarf;
13904 rtx r0;
13905 rtx r1;
13906 /* Handle a word-aligned stack pointer. We generate the following:
13908 mov r0, sp
13909 bic r1, r0, #7
13910 mov sp, r1
13911 <save and restore r0 in normal prologue/epilogue>
13912 mov sp, r0
13913 bx lr
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));
13927 emit_insn (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 */
13962 if (args_to_push)
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);
13968 else
13969 insn = emit_insn
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. */
14003 if (optimize_size
14004 && !flag_pic
14005 && !frame_pointer_needed
14006 && arm_fpu_arch == FPUTYPE_NONE
14007 && TARGET_SOFT_FLOAT
14008 && !TARGET_IWMMXT)
14010 int ip_ok = 1;
14011 int delta = offsets->outgoing_args - offsets->saved_args - saved_regs;
14012 if (delta < 0)
14013 abort();
14014 if (live_regs_mask
14015 & ((1<<4) | (1<<5) | (1<<6) | (1<<7) | (1<<8) | (1<<9) | (1<<10) | (1<<11)))
14016 ip_ok = 0;
14017 if (delta <= (ip_ok ? 20 : 16) && delta % 4 == 0)
14019 int reg = (ip_ok ? 12 : 3);
14020 while (delta)
14022 delta -= 4;
14023 live_regs_mask |= (1<<reg);
14024 reg = (reg == 12) ? 3 : reg - 1;
14025 saved_regs += 4;
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
14036 & ~regs_above_fp;
14037 unsigned long second_push_regs = live_regs_mask
14038 & regs_above_fp;
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. */
14046 insn = emit_insn (
14047 gen_addsi3 (hard_frame_pointer_rtx, stack_pointer_rtx,
14048 GEN_INT ((bit_count (initial_push_regs) - 2)
14049 * 4)));
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;
14063 else
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,
14092 amount));
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. */
14146 static void
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. */
14152 if (TARGET_THUMB)
14154 output_operand_lossage ("predicated Thumb instruction");
14155 return;
14157 if (current_insn_predicate != NULL)
14159 output_operand_lossage
14160 ("predicated instruction in conditional sequence");
14161 return;
14164 fputs (arm_condition_codes[arm_current_cc], stream);
14166 else if (current_insn_predicate)
14168 enum arm_cond_code code;
14170 if (TARGET_THUMB1)
14172 output_operand_lossage ("predicated Thumb instruction");
14173 return;
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
14193 before output.
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. */
14196 void
14197 arm_print_operand (FILE *stream, rtx x, int code)
14199 switch (code)
14201 /* APPLE LOCAL begin ARM MACH assembler */
14202 /* APPLE LOCAL change appple '.' code to '~' for v7 to avoid conflict */
14203 case '~':
14204 #ifdef LOCAL_LABEL_PREFIX
14205 fputs (LOCAL_LABEL_PREFIX, stream);
14206 #endif
14207 return;
14208 /* APPLE LOCAL end ARM MACH assembler */
14210 case '@':
14211 fputs (ASM_COMMENT_START, stream);
14212 return;
14214 case '_':
14215 fputs (user_label_prefix, stream);
14216 return;
14218 case '|':
14219 fputs (REGISTER_PREFIX, stream);
14220 return;
14222 /* APPLE LOCAL begin v7 support. Merge from mainline */
14223 case '?':
14224 arm_print_condition (stream);
14225 return;
14227 case '(':
14228 /* Nothing in unified syntax, otherwise the current condition code. */
14229 if (!TARGET_UNIFIED_ASM)
14230 arm_print_condition (stream);
14231 break;
14233 case ')':
14234 /* The current condition code in unified syntax, otherwise nothing. */
14235 if (TARGET_UNIFIED_ASM)
14236 arm_print_condition (stream);
14237 break;
14239 case '.':
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);
14247 else
14249 arm_print_condition (stream);
14250 fputc('s', stream);
14252 return;
14254 case '!':
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);
14260 else
14261 fputc('s', stream);
14262 break;
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
14269 number. */
14270 case '#':
14271 return;
14272 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
14274 case 'N':
14276 REAL_VALUE_TYPE r;
14277 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
14278 r = REAL_VALUE_NEGATE (r);
14279 fprintf (stream, "%s", fp_const_from_val (&r));
14281 return;
14283 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
14284 /* An integer without a preceding # sign. */
14285 case 'c':
14286 gcc_assert (GET_CODE (x) == CONST_INT);
14287 fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
14288 return;
14290 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
14291 case 'B':
14292 if (GET_CODE (x) == CONST_INT)
14294 HOST_WIDE_INT val;
14295 val = ARM_SIGN_EXTEND (~INTVAL (x));
14296 fprintf (stream, HOST_WIDE_INT_PRINT_DEC, val);
14298 else
14300 putc ('~', stream);
14301 output_addr_const (stream, x);
14303 return;
14305 /* APPLE LOCAL begin v7 support. Merge from mainline */
14306 case 'L':
14307 /* The low 16 bits of an immediate constant. */
14308 fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL(x) & 0xffff);
14309 return;
14311 /* APPLE LOCAL end v7 support. Merge from mainline */
14312 case 'i':
14313 fprintf (stream, "%s", arithmetic_instr (x, 1));
14314 return;
14316 /* Truncate Cirrus shift counts. */
14317 case 's':
14318 if (GET_CODE (x) == CONST_INT)
14320 fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0x3f);
14321 return;
14323 arm_print_operand (stream, x, 0);
14324 return;
14326 case 'I':
14327 fprintf (stream, "%s", arithmetic_instr (x, 0));
14328 return;
14330 case 'S':
14332 HOST_WIDE_INT val;
14333 const char *shift;
14335 if (!shift_operator (x, SImode))
14337 output_operand_lossage ("invalid shift operand");
14338 break;
14341 shift = shift_op (x, &val);
14343 if (shift)
14345 fprintf (stream, ", %s ", shift);
14346 if (val == -1)
14347 arm_print_operand (stream, XEXP (x, 1), 0);
14348 else
14349 fprintf (stream, "#" HOST_WIDE_INT_PRINT_DEC, val);
14352 return;
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. */
14381 case 'Q':
14382 if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
14384 output_operand_lossage ("invalid operand for code '%c'", code);
14385 return;
14388 asm_fprintf (stream, "%r", REGNO (x) + (WORDS_BIG_ENDIAN ? 1 : 0));
14389 return;
14391 case 'R':
14392 if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
14394 output_operand_lossage ("invalid operand for code '%c'", code);
14395 return;
14398 asm_fprintf (stream, "%r", REGNO (x) + (WORDS_BIG_ENDIAN ? 0 : 1));
14399 return;
14401 case 'H':
14402 if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
14404 output_operand_lossage ("invalid operand for code '%c'", code);
14405 return;
14408 asm_fprintf (stream, "%r", REGNO (x) + 1);
14409 return;
14411 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
14412 case 'J':
14413 if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
14415 output_operand_lossage ("invalid operand for code '%c'", code);
14416 return;
14419 asm_fprintf (stream, "%r", REGNO (x) + (WORDS_BIG_ENDIAN ? 3 : 2));
14420 return;
14422 case 'K':
14423 if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
14425 output_operand_lossage ("invalid operand for code '%c'", code);
14426 return;
14429 asm_fprintf (stream, "%r", REGNO (x) + (WORDS_BIG_ENDIAN ? 2 : 3));
14430 return;
14432 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
14433 case 'm':
14434 asm_fprintf (stream, "%r",
14435 GET_CODE (XEXP (x, 0)) == REG
14436 ? REGNO (XEXP (x, 0)) : REGNO (XEXP (XEXP (x, 0), 0)));
14437 return;
14439 case 'M':
14440 asm_fprintf (stream, "{%r-%r}",
14441 REGNO (x),
14442 REGNO (x) + ARM_NUM_REGS (GET_MODE (x)) - 1);
14443 return;
14445 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
14446 /* Like 'M', but writing doubleword vector registers, for use by Neon
14447 insns. */
14448 case 'h':
14450 int regno = (REGNO (x) - FIRST_VFP_REGNUM) / 2;
14451 int numregs = ARM_NUM_REGS (GET_MODE (x)) / 2;
14452 if (numregs == 1)
14453 asm_fprintf (stream, "{d%d}", regno);
14454 else
14455 asm_fprintf (stream, "{d%d-d%d}", regno, regno + numregs - 1);
14457 return;
14459 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
14460 case 'd':
14461 /* CONST_TRUE_RTX means always -- that's the default. */
14462 if (x == const_true_rtx)
14463 return;
14465 if (!COMPARISON_P (x))
14467 output_operand_lossage ("invalid operand for code '%c'", code);
14468 return;
14471 fputs (arm_condition_codes[get_arm_condition_code (x)],
14472 stream);
14473 return;
14475 case 'D':
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");
14481 return;
14483 if (!COMPARISON_P (x))
14485 output_operand_lossage ("invalid operand for code '%c'", code);
14486 return;
14489 fputs (arm_condition_codes[ARM_INVERSE_CONDITION_CODE
14490 (get_arm_condition_code (x))],
14491 stream);
14492 return;
14494 /* Cirrus registers can be accessed in a variety of ways:
14495 single floating point (f)
14496 double floating point (d)
14497 32bit integer (fx)
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",
14507 code == 'W' ? "f"
14508 : code == 'X' ? "d"
14509 : code == 'Y' ? "fx" : "dx", reg_names[REGNO (x)] + 2);
14511 return;
14513 /* Print cirrus register in the mode specified by the register's mode. */
14514 case 'V':
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);
14521 return;
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);
14530 return;
14533 case 'U':
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);
14540 return;
14543 else
14544 fprintf (stream, "%d", REGNO (x) - FIRST_IWMMXT_GR_REGNUM);
14545 return;
14547 /* Print an iWMMXt control register name. */
14548 case 'w':
14549 if (GET_CODE (x) != CONST_INT
14550 || INTVAL (x) < 0
14551 || INTVAL (x) >= 16)
14552 /* Bad value for wC register number. */
14554 output_operand_lossage ("invalid operand for code '%c'", code);
14555 return;
14558 else
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)]);
14571 return;
14573 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
14574 /* Print a VFP/Neon double precision or quad precision register name. */
14575 case 'P':
14576 case 'q':
14578 int mode = GET_MODE (x);
14579 int is_quad = (code == 'q');
14580 int regno;
14582 if (GET_MODE_SIZE (mode) != (is_quad ? 16 : 8))
14584 output_operand_lossage ("invalid operand for code '%c'", code);
14585 return;
14588 if (GET_CODE (x) != REG
14589 || !IS_VFP_REGNUM (REGNO (x)))
14591 output_operand_lossage ("invalid operand for code '%c'", code);
14592 return;
14595 regno = REGNO (x);
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);
14600 return;
14603 fprintf (stream, "%c%d", is_quad ? 'q' : 'd',
14604 (regno - FIRST_VFP_REGNUM) >> (is_quad ? 2 : 1));
14606 return;
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. */
14611 case 'p':
14613 int mode = GET_MODE (x);
14614 int regno;
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);
14620 return;
14623 regno = REGNO (x);
14624 if (((regno - FIRST_VFP_REGNUM) & 0x1) != 0)
14626 output_operand_lossage ("invalid operand for code '%c'", code);
14627 return;
14630 fprintf (stream, "d%d", (regno - FIRST_VFP_REGNUM) >> 1);
14632 return;
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. */
14638 case 'e':
14639 case 'f':
14641 int mode = GET_MODE (x);
14642 int regno;
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);
14648 return;
14651 regno = REGNO (x);
14652 if (!NEON_REGNO_OK_FOR_QUAD (regno))
14654 output_operand_lossage ("invalid operand for code '%c'", code);
14655 return;
14658 if (GET_MODE_SIZE (mode) == 16)
14659 fprintf (stream, "d%d", ((regno - FIRST_VFP_REGNUM) >> 1)
14660 + (code == 'f' ? 1 : 0));
14661 else
14662 fprintf (stream, "q%d", ((regno - FIRST_VFP_REGNUM) >> 2)
14663 + (code == 'f' ? 1 : 0));
14665 return;
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
14670 index. */
14671 case 'G':
14673 int index = vfp3_const_double_index (x);
14674 gcc_assert (index != -1);
14675 fprintf (stream, "%d", index);
14677 return;
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'. */
14691 case 'T':
14693 HOST_WIDE_INT bits = INTVAL (x);
14694 fputc ((bits & 1) != 0
14695 ? ((bits & 4) != 0 ? 'f' : 's')
14696 : ((bits & 4) != 0 ? 'p' : 'u'),
14697 stream);
14699 return;
14701 /* Likewise, but signed and unsigned integers are both 'i'. */
14702 case 'F':
14704 HOST_WIDE_INT bits = INTVAL (x);
14705 fputc ((bits & 4) != 0
14706 ? ((bits & 1) != 0 ? 'f' : 'p')
14707 : 'i',
14708 stream);
14710 return;
14712 /* As for 'T', but emit 'u' instead of 'p'. */
14713 case 't':
14715 HOST_WIDE_INT bits = INTVAL (x);
14716 fputc ((bits & 1) != 0
14717 ? ((bits & 4) != 0 ? 'f' : 's')
14718 : 'u',
14719 stream);
14721 return;
14723 /* Bit 1: rounding (vs none). */
14724 case 'O':
14726 HOST_WIDE_INT bits = INTVAL (x);
14727 fputs ((bits & 2) != 0 ? "r" : "", stream);
14729 return;
14731 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
14732 default:
14733 if (x == 0)
14735 output_operand_lossage ("missing operand");
14736 return;
14739 switch (GET_CODE (x))
14741 case REG:
14742 asm_fprintf (stream, "%r", REGNO (x));
14743 break;
14745 case MEM:
14746 output_memory_reference_mode = GET_MODE (x);
14747 output_address (XEXP (x, 0));
14748 break;
14750 case CONST_DOUBLE:
14751 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
14752 if (TARGET_NEON)
14754 char fpstr[20];
14755 real_to_decimal (fpstr, CONST_DOUBLE_REAL_VALUE (x),
14756 sizeof (fpstr), 0, 1);
14757 fprintf (stream, "#%s", fpstr);
14759 else
14760 fprintf (stream, "#%s", fp_immediate_constant (x));
14761 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
14762 break;
14764 default:
14765 gcc_assert (GET_CODE (x) != NEG);
14766 fputc ('#', stream);
14767 output_addr_const (stream, x);
14768 break;
14773 #ifndef AOF_ASSEMBLER
14774 /* Target hook for assembling integer objects. The ARM version needs to
14775 handle word-sized values specially. */
14776 static bool
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. */
14785 if (TARGET_MACHO)
14786 aligned_p = 1;
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);
14806 else
14807 fputs ("(GOT)", asm_out_file);
14809 fputc ('\n', asm_out_file);
14810 return true;
14813 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
14814 mode = GET_MODE (x);
14816 if (arm_vector_mode_supported_p (mode))
14818 int i, units;
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);
14841 assemble_integer
14842 (elt, size, i == 0 ? BIGGEST_ALIGNMENT : size * BITS_PER_UNIT, 1);
14844 else
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);
14852 assemble_real
14853 (rval, GET_MODE_INNER (mode),
14854 i == 0 ? BIGGEST_ALIGNMENT : size * BITS_PER_UNIT);
14857 return true;
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. */
14869 static void
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);
14875 return;
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 */
14886 #endif
14887 #endif
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));
14936 int code;
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));
14943 switch (mode)
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;
14956 dominance:
14957 gcc_assert (comp_code == EQ || comp_code == NE);
14959 if (comp_code == EQ)
14960 return ARM_INVERSE_CONDITION_CODE (code);
14961 return code;
14963 case CC_NOOVmode:
14964 switch (comp_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 ();
14973 case CC_Zmode:
14974 switch (comp_code)
14976 case NE: return ARM_NE;
14977 case EQ: return ARM_EQ;
14978 default: gcc_unreachable ();
14981 case CC_Nmode:
14982 switch (comp_code)
14984 case NE: return ARM_MI;
14985 case EQ: return ARM_PL;
14986 default: gcc_unreachable ();
14989 case CCFPEmode:
14990 case CCFPmode:
14991 /* These encodings assume that AC=1 in the FPA system control
14992 byte. This allows us to handle all cases except UNEQ and
14993 LTGT. */
14994 switch (comp_code)
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 ();
15014 case CC_SWPmode:
15015 switch (comp_code)
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 ();
15030 case CC_Cmode:
15031 switch (comp_code)
15033 case LTU: return ARM_CS;
15034 case GEU: return ARM_CC;
15035 default: gcc_unreachable ();
15038 case CCmode:
15039 switch (comp_code)
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
15060 instructions. */
15061 void
15062 thumb2_final_prescan_insn (rtx insn)
15064 rtx first_insn = insn;
15065 rtx body = PATTERN (insn);
15066 rtx predicate;
15067 enum arm_cond_code code;
15068 int n;
15069 int mask;
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)
15077 return;
15079 if (GET_CODE (body) != COND_EXEC)
15080 return;
15082 /* Conditional jumps are implemented directly. */
15083 if (GET_CODE (insn) == JUMP_INSN)
15084 return;
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. */
15094 for (;;)
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)
15101 break;
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)
15107 continue;
15109 /* ??? Recognise conditional jumps, and combine them with IT blocks. */
15110 if (GET_CODE (body) != COND_EXEC)
15111 break;
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)
15115 break;
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))
15123 break;
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)
15130 break;
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 */
15139 void
15140 arm_final_prescan_insn (rtx insn)
15142 /* LLVM LOCAL begin */
15143 #ifdef ENABLE_LLVM
15144 insn = insn;
15145 return;
15146 #else
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. */
15153 int reverse = 0;
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;
15177 return;
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)
15197 reverse = TRUE;
15198 else
15199 return;
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)
15210 reverse = TRUE;
15211 seeking_return = 1;
15213 else
15214 return;
15216 else
15217 return;
15220 gcc_assert (!arm_ccfsm_state || reverse);
15221 if (GET_CODE (insn) != JUMP_INSN)
15222 return;
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);
15229 if (reverse
15230 || (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == PC
15231 && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE))
15233 int insns_skipped;
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)
15243 jump_clobbers = 1;
15244 return;
15247 /* Register the insn jumped to. */
15248 if (reverse)
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;
15267 else
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;)
15276 rtx scanbody;
15278 this_insn = next_nonnote_insn (this_insn);
15279 if (!this_insn)
15280 break;
15282 switch (GET_CODE (this_insn))
15284 case CODE_LABEL:
15285 /* Succeed if it is the target label, otherwise fail since
15286 control falls in from somewhere else. */
15287 if (this_insn == label)
15289 if (jump_clobbers)
15291 arm_ccfsm_state = 2;
15292 this_insn = next_nonnote_insn (this_insn);
15294 else
15295 arm_ccfsm_state = 1;
15296 succeed = TRUE;
15298 else
15299 fail = TRUE;
15300 break;
15302 case BARRIER:
15303 /* Succeed if the following insn is the target label.
15304 Otherwise fail.
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)
15310 if (jump_clobbers)
15312 arm_ccfsm_state = 2;
15313 this_insn = next_nonnote_insn (this_insn);
15315 else
15316 arm_ccfsm_state = 1;
15317 succeed = TRUE;
15319 else
15320 fail = TRUE;
15321 break;
15323 case CALL_INSN:
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. */
15328 if (arm_arch5)
15330 fail = TRUE;
15331 break;
15334 /* Succeed if the following insn is the target label, or
15335 if the following two insns are a barrier and the
15336 target label. */
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)
15344 if (jump_clobbers)
15346 arm_ccfsm_state = 2;
15347 this_insn = next_nonnote_insn (this_insn);
15349 else
15350 arm_ccfsm_state = 1;
15351 succeed = TRUE;
15353 else
15354 fail = TRUE;
15355 break;
15357 case JUMP_INSN:
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,
15360 fail. */
15361 /* XXX Probably, the tests for SET and the PC are
15362 unnecessary. */
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;
15372 succeed = TRUE;
15374 else if (GET_CODE (SET_SRC (scanbody)) == IF_THEN_ELSE)
15375 fail = TRUE;
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)
15381 && !optimize_size)
15382 fail = TRUE;
15383 else if (GET_CODE (scanbody) == RETURN
15384 && seeking_return)
15386 arm_ccfsm_state = 2;
15387 succeed = TRUE;
15389 else if (GET_CODE (scanbody) == PARALLEL)
15391 switch (get_attr_conds (this_insn))
15393 case CONDS_NOCOND:
15394 break;
15395 default:
15396 fail = TRUE;
15397 break;
15400 else
15401 fail = TRUE; /* Unrecognized jump (e.g. epilogue). */
15403 break;
15405 case INSN:
15406 /* Instructions using or affecting the condition codes make it
15407 fail. */
15408 scanbody = PATTERN (this_insn);
15409 if (!(GET_CODE (scanbody) == SET
15410 || GET_CODE (scanbody) == PARALLEL)
15411 || get_attr_conds (this_insn) != CONDS_NOCOND)
15412 fail = TRUE;
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)
15424 fail = TRUE;
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)
15432 fail = TRUE;
15433 /* APPLE LOCAL end 6280380 */
15434 break;
15436 default:
15437 break;
15440 if (succeed)
15442 if ((!seeking_return) && (arm_ccfsm_state == 1 || reverse))
15443 arm_target_label = CODE_LABEL_NUMBER (label);
15444 else
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));
15455 if (!this_insn)
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;
15462 return;
15464 arm_target_insn = this_insn;
15466 if (jump_clobbers)
15468 gcc_assert (!reverse);
15469 arm_current_cc =
15470 get_arm_condition_code (XEXP (XEXP (XEXP (SET_SRC (body),
15471 0), 0), 1));
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);
15477 else
15479 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
15480 what it was. */
15481 if (!reverse)
15482 arm_current_cc = get_arm_condition_code (XEXP (SET_SRC (body),
15483 0));
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);
15496 /* LLVM LOCAL */
15497 #endif
15499 /* APPLE LOCAL end v7 support. Merge from mainline */
15501 /* APPLE LOCAL begin v7 support. Merge from mainline */
15502 /* Output IT instructions. */
15503 void
15504 thumb2_asm_output_opcode (FILE * stream)
15506 char buff[5];
15507 int n;
15509 if (arm_condexec_mask)
15511 for (n = 0; n < arm_condexec_masklen; n++)
15512 buff[n] = (arm_condexec_mask & (1 << n)) ? 't' : 'e';
15513 buff[n] = 0;
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 */
15532 if (TARGET_THUMB1)
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 */
15561 if (TARGET_NEON)
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 */
15572 return FALSE;
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)
15613 if (TARGET_THUMB1)
15615 if (regno == STACK_POINTER_REGNUM)
15616 return STACK_REG;
15617 if (regno == CC_REGNUM)
15618 return CC_REG;
15619 if (regno < 8)
15620 return LO_REGS;
15621 return HI_REGS;
15624 if (TARGET_THUMB2 && regno < 8)
15625 return LO_REGS;
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;
15644 else
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;
15654 return FPA_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)
15663 rtx insn;
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. */
15681 if (value != 0)
15682 return value;
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)
15687 return 0;
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)
15692 return 0;
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)
15700 return 0;
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
15728 a constant integer
15730 then... */
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));
15745 break;
15749 if (value == 0)
15751 debug_rtx (addr);
15752 warning (0, "unable to compute real location of stacked parameter");
15753 value = 8; /* XXX magic hack */
15756 return value;
15759 #define def_mbuiltin(MASK, NAME, TYPE, CODE) \
15760 do \
15762 if ((MASK) & insn_flags) \
15763 lang_hooks.builtin_function ((NAME), (TYPE), (CODE), \
15764 BUILT_IN_MD, NULL, NULL_TREE); \
15766 while (0)
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. */
15905 static void
15906 arm_init_iwmmxt_builtins (void)
15908 const struct builtin_description * d;
15909 size_t i;
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);
15916 tree int_ftype_int
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,
15924 integer_type_node,
15925 endlink))));
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,
15930 endlink)));
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,
15935 endlink)));
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,
15940 endlink)));
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,
15945 endlink)));
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,
15951 integer_type_node,
15952 endlink))));
15953 tree int_ftype_v8qi
15954 = build_function_type (integer_type_node,
15955 tree_cons (NULL_TREE, V8QI_type_node,
15956 endlink));
15957 tree int_ftype_v4hi
15958 = build_function_type (integer_type_node,
15959 tree_cons (NULL_TREE, V4HI_type_node,
15960 endlink));
15961 tree int_ftype_v2si
15962 = build_function_type (integer_type_node,
15963 tree_cons (NULL_TREE, V2SI_type_node,
15964 endlink));
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,
15969 endlink)));
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,
15974 endlink)));
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,
15979 endlink)));
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,
15985 integer_type_node,
15986 endlink))));
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,
15992 integer_type_node,
15993 endlink))));
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,
15999 integer_type_node,
16000 endlink))));
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,
16006 endlink)));
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,
16011 endlink)));
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,
16016 endlink)));
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,
16021 endlink)));
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,
16027 endlink)));
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,
16033 endlink)));
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,
16038 endlink)));
16039 tree di_ftype_void
16040 = build_function_type (long_long_unsigned_type_node, endlink);
16041 tree di_ftype_v8qi
16042 = build_function_type (long_long_integer_type_node,
16043 tree_cons (NULL_TREE, V8QI_type_node,
16044 endlink));
16045 tree di_ftype_v4hi
16046 = build_function_type (long_long_integer_type_node,
16047 tree_cons (NULL_TREE, V4HI_type_node,
16048 endlink));
16049 tree di_ftype_v2si
16050 = build_function_type (long_long_integer_type_node,
16051 tree_cons (NULL_TREE, V2SI_type_node,
16052 endlink));
16053 tree v2si_ftype_v4hi
16054 = build_function_type (V2SI_type_node,
16055 tree_cons (NULL_TREE, V4HI_type_node,
16056 endlink));
16057 tree v4hi_ftype_v8qi
16058 = build_function_type (V4HI_type_node,
16059 tree_cons (NULL_TREE, V8QI_type_node,
16060 endlink));
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,
16068 V4HI_type_node,
16069 endlink))));
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,
16075 endlink)));
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,
16082 endlink)));
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,
16087 endlink)));
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,
16092 endlink)));
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,
16098 endlink)));
16100 /* Add all builtins that are more or less simple operations on two
16101 operands. */
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;
16107 tree type;
16109 if (d->name == 0)
16110 continue;
16112 mode = insn_data[d->icode].operand[1].mode;
16114 switch (mode)
16116 case V8QImode:
16117 type = v8qi_ftype_v8qi_v8qi;
16118 break;
16119 case V4HImode:
16120 type = v4hi_ftype_v4hi_v4hi;
16121 break;
16122 case V2SImode:
16123 type = v2si_ftype_v2si_v2si;
16124 break;
16125 case DImode:
16126 type = di_ftype_di_di;
16127 break;
16129 default:
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);
16228 static void
16229 arm_init_tls_builtins (void)
16231 tree ftype;
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 */
16242 typedef enum {
16243 T_V8QI = 0x0001,
16244 T_V4HI = 0x0002,
16245 T_V2SI = 0x0004,
16246 T_V2SF = 0x0008,
16247 /* LLVM LOCAL begin */
16248 T_V1DI = 0x0010,
16249 /* LLVM LOCAL end */
16250 T_V16QI = 0x0020,
16251 T_V8HI = 0x0040,
16252 T_V4SI = 0x0080,
16253 T_V4SF = 0x0100,
16254 T_V2DI = 0x0200,
16255 T_TI = 0x0400,
16256 T_EI = 0x0800,
16257 T_OI = 0x1000
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
16272 #define ti_UP T_TI
16273 #define ei_UP T_EI
16274 #define oi_UP T_OI
16276 #define UP(X) X##_UP
16278 #define T_MAX 13
16280 /* FIXME: Add other types of insn (loads & stores, etc.). */
16281 typedef enum {
16282 NEON_BINOP,
16283 NEON_TERNOP,
16284 NEON_UNOP,
16285 NEON_GETLANE,
16286 NEON_SETLANE,
16287 NEON_CREATE,
16288 NEON_DUP,
16289 NEON_DUPLANE,
16290 NEON_COMBINE,
16291 NEON_SPLIT,
16292 NEON_LANEMUL,
16293 NEON_LANEMULL,
16294 NEON_LANEMULH,
16295 NEON_LANEMAC,
16296 NEON_SCALARMUL,
16297 NEON_SCALARMULL,
16298 NEON_SCALARMULH,
16299 NEON_SCALARMAC,
16300 NEON_CONVERT,
16301 NEON_FIXCONV,
16302 NEON_SELECT,
16303 NEON_RESULTPAIR,
16304 NEON_REINTERP,
16305 NEON_VTBL,
16306 NEON_VTBX,
16307 NEON_LOAD1,
16308 NEON_LOAD1LANE,
16309 NEON_STORE1,
16310 NEON_STORE1LANE,
16311 NEON_LOADSTRUCT,
16312 NEON_LOADSTRUCTLANE,
16313 NEON_STORESTRUCT,
16314 NEON_STORESTRUCTLANE,
16315 NEON_LOGICBINOP,
16316 NEON_SHIFTINSERT,
16317 NEON_SHIFTIMM,
16318 NEON_SHIFTACC
16319 } neon_itype;
16321 typedef struct {
16322 const char *name;
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, \
16341 NEON_BUILTIN_##N
16342 #define VAR2(T, N, A, B) \
16343 #N, NEON_##T, UP (A) | UP (B), { CF (N, A), CF (N, B) }, 2, 0, \
16344 NEON_BUILTIN_##N
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, \
16348 NEON_BUILTIN_##N
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, \
16352 NEON_BUILTIN_##N
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, \
16356 NEON_BUILTIN_##N
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, \
16360 NEON_BUILTIN_##N
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, \
16365 NEON_BUILTIN_##N
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) \
16368 | UP (H), \
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, \
16371 NEON_BUILTIN_##N
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, \
16377 NEON_BUILTIN_##N
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, \
16383 NEON_BUILTIN_##N
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 */
16582 #undef CF
16583 #undef VAR1
16584 #undef VAR2
16585 #undef VAR3
16586 #undef VAR4
16587 #undef VAR5
16588 #undef VAR6
16589 #undef VAR7
16590 #undef VAR8
16591 #undef VAR9
16592 #undef VAR10
16594 static int
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. */
16601 static tree
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 */
16612 #ifdef ENABLE_LLVM
16613 /* Create a new builtin struct type containing NUMVECS fields (where NUMVECS
16614 is in the range from 1 to 4) of type VECTYPE. */
16615 static tree
16616 build_multivec_type (tree vectype, unsigned numvecs, const char *tag)
16618 tree record, name, fields, fld;
16619 char fldname[5];
16620 unsigned n;
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);
16627 fields = NULL;
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;
16636 fields = fld;
16639 TYPE_FIELDS (record) = fields;
16640 layout_type (record);
16641 return record;
16643 #endif /* ENABLE_LLVM */
16644 /* LLVM LOCAL end multi-vector types */
16646 static void
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 */
16656 #ifdef ENABLE_LLVM
16657 #define ti_TN V8QI2_type_node
16658 #define ei_TN V8QI3_type_node
16659 #define oi_TN V8QI4_type_node
16660 #else
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
16666 #endif
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 */
16686 #ifdef ENABLE_LLVM
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, \
16719 C##_TN, NULL)
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 */
16724 #ifdef ENABLE_LLVM
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)
16728 #else
16729 #define TYPE4_RESULTPAIR(A,B,C,D) TYPE4(A,B,C,D)
16730 #endif
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,
16761 TYPE_QUAL_CONST);
16762 tree const_intHI_node = build_qualified_type (neon_intHI_type_node,
16763 TYPE_QUAL_CONST);
16764 tree const_intSI_node = build_qualified_type (neon_intSI_type_node,
16765 TYPE_QUAL_CONST);
16766 tree const_intDI_node = build_qualified_type (neon_intDI_type_node,
16767 TYPE_QUAL_CONST);
16768 tree const_float_node = build_qualified_type (neon_float_type_node,
16769 TYPE_QUAL_CONST);
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 */
16811 #ifdef ENABLE_LLVM
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
16937 operand). */
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. */
17038 TYPE2 (v8qi, di);
17039 TYPE2 (v4hi, di);
17040 TYPE2 (v2si, di);
17041 TYPE2 (v2sf, di);
17042 TYPE2 (v1di, di);
17044 /* Duplicate an ARM register into lanes of a vector. */
17045 TYPE2 (v8qi, qi);
17046 TYPE2 (v4hi, hi);
17047 TYPE2 (v2si, si);
17048 TYPE2 (v2sf, sf);
17050 TYPE2 (v16qi, qi);
17051 TYPE2 (v8hi, hi);
17052 TYPE2 (v4si, si);
17053 TYPE2 (v4sf, sf);
17054 TYPE2 (v2di, di);
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,
17362 double-word. */
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,
17396 double-word. */
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,
17435 double-word. */
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++)
17774 int j;
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 */
17799 char namebuf[60];
17800 tree ftype = NULL;
17801 enum insn_code icode;
17802 enum machine_mode tmode, mode0, mode1, mode2, mode3;
17804 if ((d->bits & (1 << j)) == 0)
17805 continue;
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;
17815 switch (d->itype)
17817 case NEON_UNOP:
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);
17822 switch (tmode)
17824 case V8QImode:
17825 if (mode0 == V8QImode)
17826 ftype = v8qi_ftype_v8qi_si;
17827 else if (mode0 == V8HImode)
17828 ftype = v8qi_ftype_v8hi_si;
17829 break;
17831 case V4HImode:
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;
17838 break;
17840 case V2SImode:
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;
17847 break;
17849 case V2SFmode:
17850 if (mode0 == V2SFmode)
17851 ftype = v2sf_ftype_v2sf_si;
17852 break;
17854 /* LLVM LOCAL begin */
17855 case V1DImode:
17856 if (mode0 == V1DImode)
17857 ftype = v1di_ftype_v1di_si;
17858 else if (mode0 == V2SImode)
17859 ftype = v1di_ftype_v2si_si;
17860 break;
17861 /* LLVM LOCAL end */
17863 case V16QImode:
17864 if (mode0 == V16QImode)
17865 ftype = v16qi_ftype_v16qi_si;
17866 break;
17868 case V8HImode:
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;
17875 break;
17877 case V4SImode:
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;
17884 break;
17886 case V4SFmode:
17887 if (mode0 == V4SFmode)
17888 ftype = v4sf_ftype_v4sf_si;
17889 break;
17891 case V2DImode:
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;
17898 break;
17900 default:
17901 gcc_unreachable ();
17903 break;
17905 case NEON_BINOP:
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);
17912 switch (tmode)
17914 case V8QImode:
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;
17919 break;
17921 case V4HImode:
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;
17928 break;
17930 case V2SImode:
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;
17939 break;
17941 case V2SFmode:
17942 if (mode0 == V2SFmode && mode1 == V2SFmode)
17943 ftype = v2sf_ftype_v2sf_v2sf_si;
17944 break;
17946 /* LLVM LOCAL begin */
17947 case V1DImode:
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;
17952 break;
17953 /* LLVM LOCAL end */
17955 case V16QImode:
17956 if (mode0 == V16QImode && mode1 == V16QImode)
17957 ftype = v16qi_ftype_v16qi_v16qi_si;
17958 break;
17960 case V8HImode:
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;
17969 break;
17971 case V4SImode:
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;
17982 break;
17984 case V4SFmode:
17985 if (mode0 == V4SFmode && mode1 == V4SFmode)
17986 ftype = v4sf_ftype_v4sf_v4sf_si;
17987 break;
17989 case V2DImode:
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;
17998 break;
18000 default:
18001 gcc_unreachable ();
18003 break;
18005 case NEON_TERNOP:
18006 /* A ternary operation with three vector operands and a
18007 vector destination, plus an extra information
18008 word. */
18009 gcc_assert (valid_neon_mode (tmode) && valid_neon_mode (mode0)
18010 && valid_neon_mode (mode1)
18011 && valid_neon_mode (mode2)
18012 && mode3 == SImode);
18013 switch (tmode)
18015 case V8QImode:
18016 if (mode0 == V8QImode && mode1 == V8QImode
18017 && mode2 == V8QImode)
18018 ftype = v8qi_ftype_v8qi_v8qi_v8qi_si;
18019 break;
18021 case V4HImode:
18022 if (mode0 == V4HImode && mode1 == V4HImode
18023 && mode2 == V4HImode)
18024 ftype = v4hi_ftype_v4hi_v4hi_v4hi_si;
18025 break;
18027 case V2SImode:
18028 if (mode0 == V2SImode && mode1 == V2SImode
18029 && mode2 == V2SImode)
18030 ftype = v2si_ftype_v2si_v2si_v2si_si;
18031 break;
18033 case V2SFmode:
18034 if (mode0 == V2SFmode && mode1 == V2SFmode
18035 && mode2 == V2SFmode)
18036 ftype = v2sf_ftype_v2sf_v2sf_v2sf_si;
18037 break;
18039 case V16QImode:
18040 if (mode0 == V16QImode && mode1 == V16QImode
18041 && mode2 == V16QImode)
18042 ftype = v16qi_ftype_v16qi_v16qi_v16qi_si;
18043 break;
18045 case V8HImode:
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;
18052 break;
18054 case V4SImode:
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;
18061 break;
18063 case V4SFmode:
18064 if (mode0 == V4SFmode && mode1 == V4SFmode
18065 && mode2 == V4SFmode)
18066 ftype = v4sf_ftype_v4sf_v4sf_v4sf_si;
18067 break;
18069 case V2DImode:
18070 if (mode0 == V2DImode && mode1 == V2SImode
18071 && mode2 == V2SImode)
18072 ftype = v2di_ftype_v2di_v2si_v2si_si;
18073 break;
18075 default:
18076 gcc_unreachable ();
18078 break;
18080 case NEON_GETLANE:
18081 /* Vector lane extraction. */
18082 gcc_assert (valid_neon_mode (mode0) && mode1 == SImode
18083 && mode2 == SImode);
18084 switch (tmode)
18086 case QImode:
18087 if (mode0 == V8QImode)
18088 ftype = qi_ftype_v8qi_si_si;
18089 else if (mode0 == V16QImode)
18090 ftype = qi_ftype_v16qi_si_si;
18091 break;
18093 case HImode:
18094 if (mode0 == V4HImode)
18095 ftype = hi_ftype_v4hi_si_si;
18096 else if (mode0 == V8HImode)
18097 ftype = hi_ftype_v8hi_si_si;
18098 break;
18100 case SImode:
18101 if (mode0 == V2SImode)
18102 ftype = si_ftype_v2si_si_si;
18103 else if (mode0 == V4SImode)
18104 ftype = si_ftype_v4si_si_si;
18105 break;
18107 case SFmode:
18108 if (mode0 == V2SFmode)
18109 ftype = sf_ftype_v2sf_si_si;
18110 else if (mode0 == V4SFmode)
18111 ftype = sf_ftype_v4sf_si_si;
18112 break;
18114 /* LLVM LOCAL begin */
18115 case DImode:
18116 if (mode0 == V1DImode)
18117 ftype = di_ftype_v1di_si_si;
18118 else if (mode0 == V2DImode)
18119 ftype = di_ftype_v2di_si_si;
18120 break;
18121 /* LLVM LOCAL end */
18123 default:
18124 gcc_unreachable ();
18126 break;
18128 case NEON_SETLANE:
18130 /* Set lanes in vector. */
18131 gcc_assert (valid_neon_mode (mode1) && mode2 == SImode);
18132 switch (tmode)
18134 case V8QImode:
18135 if (mode0 == QImode && mode1 == V8QImode)
18136 ftype = v8qi_ftype_qi_v8qi_si;
18137 break;
18139 case V4HImode:
18140 if (mode0 == HImode && mode1 == V4HImode)
18141 ftype = v4hi_ftype_hi_v4hi_si;
18142 break;
18144 case V2SImode:
18145 if (mode0 == SImode && mode1 == V2SImode)
18146 ftype = v2si_ftype_si_v2si_si;
18147 break;
18149 case V2SFmode:
18150 if (mode0 == SFmode && mode1 == V2SFmode)
18151 ftype = v2sf_ftype_sf_v2sf_si;
18152 break;
18154 /* LLVM LOCAL begin */
18155 case V1DImode:
18156 if (mode0 == DImode && mode1 == V1DImode)
18157 ftype = v1di_ftype_di_v1di_si;
18158 break;
18159 /* LLVM LOCAL end */
18161 case V16QImode:
18162 if (mode0 == QImode && mode1 == V16QImode)
18163 ftype = v16qi_ftype_qi_v16qi_si;
18164 break;
18166 case V8HImode:
18167 if (mode0 == HImode && mode1 == V8HImode)
18168 ftype = v8hi_ftype_hi_v8hi_si;
18169 break;
18171 case V4SImode:
18172 if (mode0 == SImode && mode1 == V4SImode)
18173 ftype = v4si_ftype_si_v4si_si;
18174 break;
18176 case V4SFmode:
18177 if (mode0 == SFmode && mode1 == V4SFmode)
18178 ftype = v4sf_ftype_sf_v4sf_si;
18179 break;
18181 case V2DImode:
18182 if (mode0 == DImode && mode1 == V2DImode)
18183 ftype = v2di_ftype_di_v2di_si;
18184 break;
18186 default:
18187 gcc_unreachable ();
18190 break;
18192 case NEON_CREATE:
18193 gcc_assert (mode0 == DImode);
18194 /* Create vector from bit pattern. */
18195 switch (tmode)
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 ();
18206 break;
18208 case NEON_DUP:
18209 gcc_assert ((mode0 == DImode && tmode == V1DImode)
18210 || mode0 == GET_MODE_INNER (tmode));
18211 switch (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 ();
18227 break;
18229 case NEON_DUPLANE:
18230 gcc_assert (valid_neon_mode (mode0) && mode1 == SImode);
18231 switch (tmode)
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 ();
18249 break;
18251 case NEON_SHIFTIMM:
18252 gcc_assert (mode1 == SImode && mode2 == SImode);
18253 switch (tmode)
18255 case V8QImode:
18256 if (mode0 == V8QImode)
18257 ftype = v8qi_ftype_v8qi_si_si;
18258 else if (mode0 == V8HImode)
18259 ftype = v8qi_ftype_v8hi_si_si;
18260 break;
18262 case V4HImode:
18263 if (mode0 == V4HImode)
18264 ftype = v4hi_ftype_v4hi_si_si;
18265 else if (mode0 == V4SImode)
18266 ftype = v4hi_ftype_v4si_si_si;
18267 break;
18269 case V2SImode:
18270 if (mode0 == V2SImode)
18271 ftype = v2si_ftype_v2si_si_si;
18272 else if (mode0 == V2DImode)
18273 ftype = v2si_ftype_v2di_si_si;
18274 break;
18276 /* LLVM LOCAL begin */
18277 case V1DImode:
18278 if (mode0 == V1DImode)
18279 ftype = v1di_ftype_v1di_si_si;
18280 break;
18281 /* LLVM LOCAL end */
18283 case V16QImode:
18284 if (mode0 == V16QImode)
18285 ftype = v16qi_ftype_v16qi_si_si;
18286 break;
18288 case V8HImode:
18289 if (mode0 == V8HImode)
18290 ftype = v8hi_ftype_v8hi_si_si;
18291 else if (mode0 == V8QImode)
18292 ftype = v8hi_ftype_v8qi_si_si;
18293 break;
18295 case V4SImode:
18296 if (mode0 == V4SImode)
18297 ftype = v4si_ftype_v4si_si_si;
18298 else if (mode0 == V4HImode)
18299 ftype = v4si_ftype_v4hi_si_si;
18300 break;
18302 case V2DImode:
18303 if (mode0 == V2DImode)
18304 ftype = v2di_ftype_v2di_si_si;
18305 else if (mode0 == V2SImode)
18306 ftype = v2di_ftype_v2si_si_si;
18307 break;
18309 default: gcc_unreachable ();
18311 break;
18313 case NEON_SHIFTACC:
18314 gcc_assert (tmode == mode0 && mode0 == mode1 && mode2 == SImode
18315 && mode3 == SImode);
18316 switch (tmode)
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 ();
18332 break;
18334 case NEON_COMBINE:
18335 gcc_assert (valid_neon_mode (mode0) && valid_neon_mode (mode1));
18336 switch (tmode)
18338 case V16QImode:
18339 if (mode0 == V8QImode && mode1 == V8QImode)
18340 ftype = v16qi_ftype_v8qi_v8qi;
18341 break;
18343 case V8HImode:
18344 if (mode0 == V4HImode && mode1 == V4HImode)
18345 ftype = v8hi_ftype_v4hi_v4hi;
18346 break;
18348 case V4SImode:
18349 if (mode0 == V2SImode && mode1 == V2SImode)
18350 ftype = v4si_ftype_v2si_v2si;
18351 break;
18353 case V4SFmode:
18354 if (mode0 == V2SFmode && mode1 == V2SFmode)
18355 ftype = v4sf_ftype_v2sf_v2sf;
18356 break;
18358 /* LLVM LOCAL begin */
18359 case V2DImode:
18360 if (mode0 == V1DImode && mode1 == V1DImode)
18361 ftype = v2di_ftype_v1di_v1di;
18362 break;
18363 /* LLVM LOCAL end */
18365 default:
18366 gcc_unreachable ();
18368 break;
18370 case NEON_SPLIT:
18371 gcc_assert (valid_neon_mode (mode0));
18372 switch (tmode)
18374 case V8QImode:
18375 if (mode0 == V16QImode)
18376 ftype = v8qi_ftype_v16qi;
18377 break;
18379 case V4HImode:
18380 if (mode0 == V8HImode)
18381 ftype = v4hi_ftype_v8hi;
18382 break;
18384 case V2SImode:
18385 if (mode0 == V4SImode)
18386 ftype = v2si_ftype_v4si;
18387 break;
18389 case V2SFmode:
18390 if (mode0 == V4SFmode)
18391 ftype = v2sf_ftype_v4sf;
18392 break;
18394 /* LLVM LOCAL begin */
18395 case V1DImode:
18396 if (mode0 == V2DImode)
18397 ftype = v1di_ftype_v2di;
18398 break;
18399 /* LLVM LOCAL end */
18401 default:
18402 gcc_unreachable ();
18404 break;
18406 case NEON_CONVERT:
18407 gcc_assert (valid_neon_mode (mode0) && mode1 == SImode);
18408 switch (tmode)
18410 case V2SImode:
18411 if (mode0 == V2SFmode)
18412 ftype = v2si_ftype_v2sf_si;
18413 break;
18415 case V2SFmode:
18416 if (mode0 == V2SImode)
18417 ftype = v2sf_ftype_v2si_si;
18418 break;
18420 case V4SImode:
18421 if (mode0 == V4SFmode)
18422 ftype = v4si_ftype_v4sf_si;
18423 break;
18425 case V4SFmode:
18426 if (mode0 == V4SImode)
18427 ftype = v4sf_ftype_v4si_si;
18428 break;
18430 default: gcc_unreachable ();
18432 break;
18434 case NEON_FIXCONV:
18435 gcc_assert (valid_neon_mode (mode0) && mode1 == SImode
18436 && mode2 == SImode);
18437 switch (tmode)
18439 case V2SImode:
18440 if (mode0 == V2SFmode)
18441 ftype = v2si_ftype_v2sf_si_si;
18442 break;
18444 case V2SFmode:
18445 if (mode0 == V2SImode)
18446 ftype = v2sf_ftype_v2si_si_si;
18447 break;
18449 case V4SImode:
18450 if (mode0 == V4SFmode)
18451 ftype = v4si_ftype_v4sf_si_si;
18452 break;
18454 case V4SFmode:
18455 if (mode0 == V4SImode)
18456 ftype = v4sf_ftype_v4si_si_si;
18457 break;
18459 default:
18460 gcc_unreachable ();
18462 break;
18464 case NEON_LANEMUL:
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);
18469 switch (tmode)
18471 case V4HImode:
18472 if (mode0 == V4HImode && mode1 == V4HImode)
18473 ftype = v4hi_ftype_v4hi_v4hi_si_si;
18474 break;
18476 case V2SImode:
18477 if (mode0 == V2SImode && mode1 == V2SImode)
18478 ftype = v2si_ftype_v2si_v2si_si_si;
18479 break;
18481 case V2SFmode:
18482 if (mode0 == V2SFmode && mode1 == V2SFmode)
18483 ftype = v2sf_ftype_v2sf_v2sf_si_si;
18484 break;
18486 case V8HImode:
18487 if (mode0 == V8HImode && mode1 == V4HImode)
18488 ftype = v8hi_ftype_v8hi_v4hi_si_si;
18489 break;
18491 case V4SImode:
18492 if (mode0 == V4SImode && mode1 == V2SImode)
18493 ftype = v4si_ftype_v4si_v2si_si_si;
18494 break;
18496 case V4SFmode:
18497 if (mode0 == V4SFmode && mode1 == V2SFmode)
18498 ftype = v4sf_ftype_v4sf_v2sf_si_si;
18499 break;
18501 default:
18502 gcc_unreachable ();
18505 break;
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);
18512 switch (tmode)
18514 case V4SImode:
18515 if (mode0 == V4HImode && mode1 == V4HImode)
18516 ftype = v4si_ftype_v4hi_v4hi_si_si;
18517 break;
18519 case V2DImode:
18520 if (mode0 == V2SImode && mode1 == V2SImode)
18521 ftype = v2di_ftype_v2si_v2si_si_si;
18522 break;
18524 default:
18525 gcc_unreachable ();
18528 break;
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);
18535 switch (tmode)
18537 case V4SImode:
18538 if (mode0 == V4SImode && mode1 == V2SImode)
18539 ftype = v4si_ftype_v4si_v2si_si_si;
18540 break;
18542 case V8HImode:
18543 if (mode0 == V8HImode && mode1 == V4HImode)
18544 ftype = v8hi_ftype_v8hi_v4hi_si_si;
18545 break;
18547 case V2SImode:
18548 if (mode0 == V2SImode && mode1 == V2SImode)
18549 ftype = v2si_ftype_v2si_v2si_si_si;
18550 break;
18552 case V4HImode:
18553 if (mode0 == V4HImode && mode1 == V4HImode)
18554 ftype = v4hi_ftype_v4hi_v4hi_si_si;
18555 break;
18557 default:
18558 gcc_unreachable ();
18561 break;
18563 case NEON_LANEMAC:
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);
18570 switch (tmode)
18572 case V4HImode:
18573 if (mode0 == V4HImode && mode1 == V4HImode
18574 && mode2 == V4HImode)
18575 ftype = v4hi_ftype_v4hi_v4hi_v4hi_si_si;
18576 break;
18578 case V2SImode:
18579 if (mode0 == V2SImode && mode1 == V2SImode
18580 && mode2 == V2SImode)
18581 ftype = v2si_ftype_v2si_v2si_v2si_si_si;
18582 break;
18584 case V2SFmode:
18585 if (mode0 == V2SFmode && mode1 == V2SFmode
18586 && mode2 == V2SFmode)
18587 ftype = v2sf_ftype_v2sf_v2sf_v2sf_si_si;
18588 break;
18590 case V8HImode:
18591 if (mode0 == V8HImode && mode1 == V8HImode
18592 && mode2 == V4HImode)
18593 ftype = v8hi_ftype_v8hi_v8hi_v4hi_si_si;
18594 break;
18596 case V4SImode:
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;
18603 break;
18605 case V4SFmode:
18606 if (mode0 == V4SFmode && mode1 == V4SFmode
18607 && mode2 == V2SFmode)
18608 ftype = v4sf_ftype_v4sf_v4sf_v2sf_si_si;
18609 break;
18611 case V2DImode:
18612 if (mode0 == V2DImode && mode1 == V2SImode
18613 && mode2 == V2SImode)
18614 ftype = v2di_ftype_v2di_v2si_v2si_si_si;
18615 break;
18617 default:
18618 gcc_unreachable ();
18621 break;
18623 case NEON_SCALARMUL:
18624 switch (tmode)
18626 case V4HImode:
18627 if (mode0 == V4HImode && mode1 == HImode)
18628 ftype = v4hi_ftype_v4hi_hi_si;
18629 break;
18631 case V2SImode:
18632 if (mode0 == V2SImode && mode1 == SImode)
18633 ftype = v2si_ftype_v2si_si_si;
18634 break;
18636 case V2SFmode:
18637 if (mode0 == V2SFmode && mode1 == SFmode)
18638 ftype = v2sf_ftype_v2sf_sf_si;
18639 break;
18641 case V8HImode:
18642 if (mode0 == V8HImode && mode1 == HImode)
18643 ftype = v8hi_ftype_v8hi_hi_si;
18644 break;
18646 case V4SImode:
18647 if (mode0 == V4SImode && mode1 == SImode)
18648 ftype = v4si_ftype_v4si_si_si;
18649 break;
18651 case V4SFmode:
18652 if (mode0 == V4SFmode && mode1 == SFmode)
18653 ftype = v4sf_ftype_v4sf_sf_si;
18654 break;
18656 default:
18657 gcc_unreachable ();
18659 break;
18661 case NEON_SCALARMULL:
18662 switch (tmode)
18664 case V4SImode:
18665 if (mode0 == V4HImode && mode1 == HImode)
18666 ftype = v4si_ftype_v4hi_hi_si;
18667 break;
18669 case V2DImode:
18670 if (mode0 == V2SImode && mode1 == SImode)
18671 ftype = v2di_ftype_v2si_si_si;
18672 break;
18674 default:
18675 gcc_unreachable ();
18677 break;
18679 case NEON_SCALARMULH:
18681 switch (tmode)
18683 case V4SImode:
18684 if (mode0 == V4SImode && mode1 == SImode)
18685 ftype = v4si_ftype_v4si_si_si;
18686 break;
18688 case V8HImode:
18689 if (mode0 == V8HImode && mode1 == HImode)
18690 ftype = v8hi_ftype_v8hi_hi_si;
18691 break;
18693 case V2SImode:
18694 if (mode0 == V2SImode && mode1 == SImode)
18695 ftype = v2si_ftype_v2si_si_si;
18696 break;
18698 case V4HImode:
18699 if (mode0 == V4HImode && mode1 == HImode)
18700 ftype = v4hi_ftype_v4hi_hi_si;
18701 break;
18703 default:
18704 gcc_unreachable ();
18707 break;
18709 case NEON_SCALARMAC:
18711 gcc_assert (mode2 == GET_MODE_INNER (mode1));
18712 switch (tmode)
18714 case V4HImode:
18715 if (mode0 == V4HImode && mode1 == V4HImode)
18716 ftype = v4hi_ftype_v4hi_v4hi_hi_si;
18717 break;
18719 case V2SImode:
18720 if (mode0 == V2SImode && mode1 == V2SImode)
18721 ftype = v2si_ftype_v2si_v2si_si_si;
18722 break;
18724 case V2SFmode:
18725 if (mode0 == V2SFmode && mode1 == V2SFmode)
18726 ftype = v2sf_ftype_v2sf_v2sf_sf_si;
18727 break;
18729 case V8HImode:
18730 if (mode0 == V8HImode && mode1 == V8HImode)
18731 ftype = v8hi_ftype_v8hi_v8hi_hi_si;
18732 break;
18734 case V4SImode:
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;
18739 break;
18741 case V4SFmode:
18742 if (mode0 == V4SFmode && mode1 == V4SFmode)
18743 ftype = v4sf_ftype_v4sf_v4sf_sf_si;
18744 break;
18746 case V2DImode:
18747 if (mode0 == V2DImode && mode1 == V2SImode)
18748 ftype = v2di_ftype_v2di_v2si_si_si;
18749 break;
18751 default:
18752 gcc_unreachable ();
18755 break;
18757 case NEON_SELECT:
18758 gcc_assert (mode1 == mode2
18759 && (mode0 == mode1
18760 || (mode0 == V2SImode && mode1 == V2SFmode)
18761 || (mode0 == V4SImode && mode1 == V4SFmode)));
18762 switch (tmode)
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 ();
18778 break;
18780 case NEON_VTBL:
18782 gcc_assert (tmode == V8QImode && mode1 == V8QImode);
18783 switch (mode0)
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 ();
18792 break;
18794 case NEON_VTBX:
18796 gcc_assert (tmode == V8QImode && mode0 == V8QImode
18797 && mode2 == V8QImode);
18798 switch (mode1)
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 ();
18807 break;
18809 case NEON_RESULTPAIR:
18811 switch (mode0)
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 ();
18828 break;
18830 case NEON_REINTERP:
18832 /* We iterate over 5 doubleword types, then 5 quadword
18833 types. */
18834 int rhs = j % 5;
18835 switch (tmode)
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 ();
18852 break;
18854 case NEON_LOAD1:
18855 switch (tmode)
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 ();
18871 break;
18873 case NEON_LOAD1LANE:
18874 switch (tmode)
18876 case V8QImode:
18877 ftype = v8qi_ftype_const_qi_pointer_v8qi_si;
18878 break;
18879 case V4HImode:
18880 ftype = v4hi_ftype_const_hi_pointer_v4hi_si;
18881 break;
18882 case V2SImode:
18883 ftype = v2si_ftype_const_si_pointer_v2si_si;
18884 break;
18885 case V2SFmode:
18886 ftype = v2sf_ftype_const_sf_pointer_v2sf_si;
18887 break;
18888 /* LLVM LOCAL begin */
18889 case V1DImode:
18890 ftype = v1di_ftype_const_di_pointer_v1di_si;
18891 break;
18892 /* LLVM LOCAL end */
18893 case V16QImode:
18894 ftype = v16qi_ftype_const_qi_pointer_v16qi_si;
18895 break;
18896 case V8HImode:
18897 ftype = v8hi_ftype_const_hi_pointer_v8hi_si;
18898 break;
18899 case V4SImode:
18900 ftype = v4si_ftype_const_si_pointer_v4si_si;
18901 break;
18902 case V4SFmode:
18903 ftype = v4sf_ftype_const_sf_pointer_v4sf_si;
18904 break;
18905 case V2DImode:
18906 ftype = v2di_ftype_const_di_pointer_v2di_si;
18907 break;
18908 default:
18909 gcc_unreachable ();
18911 break;
18913 case NEON_STORE1:
18914 switch (mode0)
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 ();
18930 break;
18932 case NEON_STORE1LANE:
18933 switch (mode0)
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 ();
18949 break;
18951 case NEON_LOADSTRUCT:
18952 switch (tmode)
18954 case TImode:
18955 /* vld2 cases. */
18956 switch (1 << j)
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 ();
18967 break;
18969 case EImode:
18970 /* vld3 cases. */
18971 switch (1 << j)
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 ();
18982 break;
18984 case OImode:
18985 /* vld2q and vld4 cases. */
18986 switch (1 << j)
18988 /* vld2q 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;
18994 /* vld4 cases. */
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 ();
19005 break;
19007 case CImode:
19008 /* vld3q cases. */
19009 switch (1 << j)
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 ();
19017 break;
19019 case XImode:
19020 /* vld4q cases. */
19021 switch (1 << j)
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 ();
19029 break;
19031 default:
19032 gcc_unreachable ();
19034 break;
19036 case NEON_LOADSTRUCTLANE:
19037 switch (tmode)
19039 case TImode:
19040 /* vld2_lane cases. */
19041 switch (1 << j)
19043 case T_V8QI:
19044 ftype = ti_ftype_const_qi_pointer_ti_si;
19045 break;
19046 case T_V4HI:
19047 ftype = ti_ftype_const_hi_pointer_ti_si;
19048 break;
19049 case T_V2SI:
19050 ftype = ti_ftype_const_si_pointer_ti_si;
19051 break;
19052 case T_V2SF:
19053 ftype = ti_ftype_const_sf_pointer_ti_si;
19054 break;
19055 default:
19056 gcc_unreachable ();
19058 break;
19060 case EImode:
19061 /* vld3_lane cases. */
19062 switch (1 << j)
19064 case T_V8QI:
19065 ftype = ei_ftype_const_qi_pointer_ei_si;
19066 break;
19067 case T_V4HI:
19068 ftype = ei_ftype_const_hi_pointer_ei_si;
19069 break;
19070 case T_V2SI:
19071 ftype = ei_ftype_const_si_pointer_ei_si;
19072 break;
19073 case T_V2SF:
19074 ftype = ei_ftype_const_sf_pointer_ei_si;
19075 break;
19076 default:
19077 gcc_unreachable ();
19079 break;
19081 case OImode:
19082 /* vld2q_lane and vld4_lane cases. */
19083 switch (1 << j)
19085 /* vld2q_lane cases. */
19086 /* LLVM LOCAL begin multi-vector types */
19087 case T_V8HI:
19088 ftype = oiq_ftype_const_hi_pointer_oiq_si;
19089 break;
19090 case T_V4SI:
19091 ftype = oiq_ftype_const_si_pointer_oiq_si;
19092 break;
19093 case T_V4SF:
19094 ftype = oiq_ftype_const_sf_pointer_oiq_si;
19095 break;
19096 /* vld4_lane cases. */
19097 case T_V8QI:
19098 ftype = oi_ftype_const_qi_pointer_oi_si;
19099 break;
19100 case T_V4HI:
19101 ftype = oid_ftype_const_hi_pointer_oid_si;
19102 break;
19103 case T_V2SI:
19104 ftype = oid_ftype_const_si_pointer_oid_si;
19105 break;
19106 case T_V2SF:
19107 ftype = oid_ftype_const_sf_pointer_oid_si;
19108 break;
19109 /* LLVM LOCAL end multi-vector types */
19110 default:
19111 gcc_unreachable ();
19113 break;
19115 case CImode:
19116 /* vld3q_lane cases. */
19117 switch (1 << j)
19119 case T_V8HI:
19120 ftype = ci_ftype_const_hi_pointer_ci_si;
19121 break;
19122 case T_V4SI:
19123 ftype = ci_ftype_const_si_pointer_ci_si;
19124 break;
19125 case T_V4SF:
19126 ftype = ci_ftype_const_sf_pointer_ci_si;
19127 break;
19128 default:
19129 gcc_unreachable ();
19131 break;
19133 case XImode:
19134 /* vld4q_lane cases. */
19135 switch (1 << j)
19137 case T_V8HI:
19138 ftype = xi_ftype_const_hi_pointer_xi_si;
19139 break;
19140 case T_V4SI:
19141 ftype = xi_ftype_const_si_pointer_xi_si;
19142 break;
19143 case T_V4SF:
19144 ftype = xi_ftype_const_sf_pointer_xi_si;
19145 break;
19146 default:
19147 gcc_unreachable ();
19149 break;
19151 default:
19152 gcc_unreachable ();
19154 break;
19157 case NEON_STORESTRUCT:
19158 switch (mode0)
19160 case TImode:
19161 /* vst2 cases. */
19162 switch (1 << j)
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 ();
19173 break;
19175 case EImode:
19176 /* vst3 cases. */
19177 switch (1 << j)
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 ();
19188 break;
19190 case OImode:
19191 /* vst2q and vst4 cases. */
19192 switch (1 << j)
19194 /* vst2q 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;
19200 /* vst4 cases. */
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 ();
19211 break;
19213 case CImode:
19214 /* vst3q cases. */
19215 switch (1 << j)
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 ();
19223 break;
19225 case XImode:
19226 /* vst4q cases. */
19227 switch (1 << j)
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 ();
19235 break;
19237 default:
19238 gcc_unreachable ();
19240 break;
19242 case NEON_STORESTRUCTLANE:
19243 switch (mode0)
19245 case TImode:
19246 /* vst2_lane cases. */
19247 switch (1 << j)
19249 case T_V8QI:
19250 ftype = void_ftype_qi_pointer_ti_si;
19251 break;
19252 case T_V4HI:
19253 ftype = void_ftype_hi_pointer_ti_si;
19254 break;
19255 case T_V2SI:
19256 ftype = void_ftype_si_pointer_ti_si;
19257 break;
19258 case T_V2SF:
19259 ftype = void_ftype_sf_pointer_ti_si;
19260 break;
19261 default:
19262 gcc_unreachable ();
19264 break;
19266 case EImode:
19267 /* vst3_lane cases. */
19268 switch (1 << j)
19270 case T_V8QI:
19271 ftype = void_ftype_qi_pointer_ei_si;
19272 break;
19273 case T_V4HI:
19274 ftype = void_ftype_hi_pointer_ei_si;
19275 break;
19276 case T_V2SI:
19277 ftype = void_ftype_si_pointer_ei_si;
19278 break;
19279 case T_V2SF:
19280 ftype = void_ftype_sf_pointer_ei_si;
19281 break;
19282 default:
19283 gcc_unreachable ();
19285 break;
19287 case OImode:
19288 /* vst2q_lane and vst4_lane cases. */
19289 switch (1 << j)
19291 /* vst2q_lane cases. */
19292 /* LLVM LOCAL begin multi-vector types */
19293 case T_V8HI:
19294 ftype = void_ftype_hi_pointer_oiq_si;
19295 break;
19296 case T_V4SI:
19297 ftype = void_ftype_si_pointer_oiq_si;
19298 break;
19299 case T_V4SF:
19300 ftype = void_ftype_sf_pointer_oiq_si;
19301 break;
19302 /* vst4_lane cases. */
19303 case T_V8QI:
19304 ftype = void_ftype_qi_pointer_oi_si;
19305 break;
19306 case T_V4HI:
19307 ftype = void_ftype_hi_pointer_oid_si;
19308 break;
19309 case T_V2SI:
19310 ftype = void_ftype_si_pointer_oid_si;
19311 break;
19312 case T_V2SF:
19313 ftype = void_ftype_sf_pointer_oid_si;
19314 break;
19315 /* LLVM LOCAL end multi-vector types */
19316 default:
19317 gcc_unreachable ();
19319 break;
19321 case CImode:
19322 /* vst3q_lane cases. */
19323 switch (1 << j)
19325 case T_V8HI:
19326 ftype = void_ftype_hi_pointer_ci_si;
19327 break;
19328 case T_V4SI:
19329 ftype = void_ftype_si_pointer_ci_si;
19330 break;
19331 case T_V4SF:
19332 ftype = void_ftype_sf_pointer_ci_si;
19333 break;
19334 default:
19335 gcc_unreachable ();
19337 break;
19339 case XImode:
19340 /* vst4q_lane cases. */
19341 switch (1 << j)
19343 case T_V8HI:
19344 ftype = void_ftype_hi_pointer_xi_si;
19345 break;
19346 case T_V4SI:
19347 ftype = void_ftype_si_pointer_xi_si;
19348 break;
19349 case T_V4SF:
19350 ftype = void_ftype_sf_pointer_xi_si;
19351 break;
19352 default:
19353 gcc_unreachable ();
19355 break;
19357 default:
19358 gcc_unreachable ();
19360 break;
19362 default:
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,
19371 NULL, NULL_TREE);
19374 #undef qi_TN
19375 #undef hi_TN
19376 #undef si_TN
19377 #undef di_TN
19378 #undef ti_TN
19379 #undef ei_TN
19380 #undef oi_TN
19381 #undef ci_TN
19382 #undef xi_TN
19384 #undef sf_TN
19386 #undef v8qi_TN
19387 #undef v4hi_TN
19388 #undef v2si_TN
19389 #undef v2sf_TN
19391 #undef v16qi_TN
19392 #undef v8hi_TN
19393 #undef v4si_TN
19394 #undef v4sf_TN
19395 #undef v2di_TN
19397 #undef pv8qi_TN
19398 #undef pv4hi_TN
19399 #undef pv2si_TN
19400 #undef pv2sf_TN
19401 #undef pdi_TN
19403 #undef pv16qi_TN
19404 #undef pv8hi_TN
19405 #undef pv4si_TN
19406 #undef pv4sf_TN
19407 #undef pv2di_TN
19409 #undef void_TN
19411 #undef TYPE2
19412 #undef TYPE3
19413 #undef TYPE4
19414 #undef TYPE5
19415 #undef TYPE6
19418 static void
19419 arm_init_builtins (void)
19421 arm_init_tls_builtins ();
19423 if (TARGET_REALLY_IWMMXT)
19424 arm_init_iwmmxt_builtins ();
19426 if (TARGET_NEON)
19427 arm_init_neon_builtins ();
19428 /* APPLE LOCAL begin ARM darwin builtins */
19429 #ifdef SUBTARGET_INIT_BUILTINS
19430 SUBTARGET_INIT_BUILTINS;
19431 #endif
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. */
19440 static rtx
19441 safe_vector_operand (rtx x, enum machine_mode mode)
19443 if (x != const0_rtx)
19444 return x;
19445 x = gen_reg_rtx (mode);
19447 emit_insn (gen_iwmmxt_clrdi (mode == DImode ? x
19448 : gen_rtx_SUBREG (DImode, x, 0)));
19449 return x;
19452 /* Subroutine of arm_expand_builtin to take care of binop insns. */
19454 static rtx
19455 arm_expand_binop_builtin (enum insn_code icode,
19456 tree arglist, rtx target)
19458 rtx pat;
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);
19472 if (! target
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);
19485 if (! pat)
19486 return 0;
19487 emit_insn (pat);
19488 return target;
19491 /* Subroutine of arm_expand_builtin to take care of unop insns. */
19493 static rtx
19494 arm_expand_unop_builtin (enum insn_code icode,
19495 tree arglist, rtx target, int do_load)
19497 rtx pat;
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;
19503 if (! target
19504 || GET_MODE (target) != tmode
19505 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
19506 target = gen_reg_rtx (tmode);
19507 if (do_load)
19508 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
19509 else
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);
19519 if (! pat)
19520 return 0;
19521 emit_insn (pat);
19522 return target;
19525 /* APPLE LOCAL begin v7 support. Merge from Codesourcery */
19526 static int
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)
19535 return 0;
19536 else if (soughtcode < memb->base_fcode)
19537 return -1;
19538 else
19539 return 1;
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 *);
19548 enum insn_code
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;
19554 int idx;
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);
19563 if (itype)
19564 *itype = found->itype;
19566 /* LLVM LOCAL begin */
19567 if (neon_code)
19568 *neon_code = found->neon_code;
19569 /* LLVM LOCAL end */
19571 return found->codes[idx];
19574 typedef enum {
19575 NEON_ARG_COPY_TO_REG,
19576 NEON_ARG_CONSTANT,
19577 NEON_ARG_STOP
19578 } builtin_arg;
19580 #define NEON_MAX_BUILTIN_ARGS 5
19582 /* Expand a Neon builtin. */
19583 static rtx
19584 arm_expand_neon_args (rtx target, int icode, int have_retval,
19585 tree arglist, ...)
19587 va_list ap;
19588 rtx pat;
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];
19593 int argc = 0;
19595 if (have_retval
19596 && (!target
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);
19603 for (;;)
19605 builtin_arg thisarg = va_arg (ap, int);
19607 if (thisarg == NEON_ARG_STOP)
19608 break;
19609 else
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);
19617 switch (thisarg)
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]);
19624 break;
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");
19631 break;
19633 case NEON_ARG_STOP:
19634 gcc_unreachable ();
19637 argc++;
19641 va_end (ap);
19643 if (have_retval)
19644 switch (argc)
19646 case 1:
19647 pat = GEN_FCN (icode) (target, op[0]);
19648 break;
19650 case 2:
19651 pat = GEN_FCN (icode) (target, op[0], op[1]);
19652 break;
19654 case 3:
19655 pat = GEN_FCN (icode) (target, op[0], op[1], op[2]);
19656 break;
19658 case 4:
19659 pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]);
19660 break;
19662 case 5:
19663 pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]);
19664 break;
19666 default:
19667 gcc_unreachable ();
19669 else
19670 switch (argc)
19672 case 1:
19673 pat = GEN_FCN (icode) (op[0]);
19674 break;
19676 case 2:
19677 pat = GEN_FCN (icode) (op[0], op[1]);
19678 break;
19680 case 3:
19681 pat = GEN_FCN (icode) (op[0], op[1], op[2]);
19682 break;
19684 case 4:
19685 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
19686 break;
19688 case 5:
19689 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]);
19690 break;
19692 default:
19693 gcc_unreachable ();
19696 if (!pat)
19697 return 0;
19699 emit_insn (pat);
19701 return target;
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. */
19707 static rtx
19708 arm_expand_neon_builtin (rtx target, int fcode, tree arglist)
19710 neon_itype itype;
19711 /* LLVM LOCAL Added 0 argument to following call. */
19712 enum insn_code icode = locate_neon_builtin_icode (fcode, &itype, 0);
19714 switch (itype)
19716 case NEON_UNOP:
19717 case NEON_CONVERT:
19718 case NEON_DUPLANE:
19719 return arm_expand_neon_args (target, icode, 1, arglist,
19720 NEON_ARG_COPY_TO_REG, NEON_ARG_CONSTANT, NEON_ARG_STOP);
19722 case NEON_BINOP:
19723 case NEON_SETLANE:
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,
19731 NEON_ARG_STOP);
19733 case NEON_TERNOP:
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);
19738 case NEON_GETLANE:
19739 case NEON_FIXCONV:
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,
19743 NEON_ARG_STOP);
19745 case NEON_CREATE:
19746 return arm_expand_neon_args (target, icode, 1, arglist,
19747 NEON_ARG_COPY_TO_REG, NEON_ARG_STOP);
19749 case NEON_DUP:
19750 case NEON_SPLIT:
19751 case NEON_REINTERP:
19752 return arm_expand_neon_args (target, icode, 1, arglist,
19753 NEON_ARG_COPY_TO_REG, NEON_ARG_STOP);
19755 case NEON_COMBINE:
19756 case NEON_VTBL:
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,
19763 NEON_ARG_STOP);
19765 case NEON_LANEMUL:
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);
19772 case NEON_LANEMAC:
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);
19787 case NEON_SELECT:
19788 case NEON_VTBX:
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,
19791 NEON_ARG_STOP);
19793 case NEON_LOAD1:
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,
19802 NEON_ARG_STOP);
19804 case NEON_STORE1:
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,
19813 NEON_ARG_STOP);
19816 gcc_unreachable ();
19819 /* Emit code to reinterpret one Neon type as another, without altering bits. */
19820 void
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
19827 registers). */
19828 void
19829 neon_emit_pair_result_insn (enum machine_mode mode,
19830 rtx (*intfn) (rtx, rtx, rtx, rtx), rtx destaddr,
19831 rtx op1, rtx op2)
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. */
19849 void
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;
19854 unsigned int i, j;
19856 while (copied != done)
19858 for (i = 0; i < count; i++)
19860 int good = 1;
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]))
19865 good = 0;
19867 if (good)
19869 operands[opctr++] = dest[i];
19870 operands[opctr++] = src[i];
19871 copied |= 1 << 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. */
19886 static rtx
19887 arm_expand_builtin (tree exp,
19888 rtx target,
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);
19897 tree arg0;
19898 tree arg1;
19899 tree arg2;
19900 rtx op0;
19901 rtx op1;
19902 rtx op2;
19903 rtx pat;
19904 int fcode = DECL_FUNCTION_CODE (fndecl);
19905 size_t i;
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 */
19916 switch (fcode)
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);
19946 if (target == 0
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);
19951 if (! pat)
19952 return 0;
19953 emit_insn (pat);
19954 return target;
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");
19981 return const0_rtx;
19983 if (target == 0
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);
19988 if (! pat)
19989 return 0;
19990 emit_insn (pat);
19991 return target;
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));
19999 return 0;
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));
20006 return target;
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");
20024 return const0_rtx;
20026 if (target == 0
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);
20031 if (! pat)
20032 return 0;
20033 emit_insn (pat);
20034 return target;
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);
20081 if (target == 0
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);
20086 if (! pat)
20087 return 0;
20088 emit_insn (pat);
20089 return target;
20091 case ARM_BUILTIN_WZERO:
20092 target = gen_reg_rtx (DImode);
20093 emit_insn (gen_iwmmxt_clrdi (target));
20094 return target;
20096 case ARM_BUILTIN_THREAD_POINTER:
20097 return arm_load_tp (target);
20099 default:
20100 break;
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. */
20112 return NULL_RTX;
20115 /* Return the number (counting from 0) of
20116 the least significant set bit in MASK. */
20118 inline static int
20119 number_of_first_bit_set (unsigned mask)
20121 int bit;
20123 for (bit = 0;
20124 (mask & (1 << bit)) == 0;
20125 ++bit)
20126 continue;
20128 return bit;
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.
20146 static int
20147 handle_thumb_pushpop (FILE *f, unsigned long mask, int push, int *cfa_offset,
20148 unsigned long real_regs, bool emit)
20150 int regno;
20151 int lo_mask = mask & 0xFF;
20152 int pushed_words = 0;
20153 int bytes = 0;
20155 gcc_assert (mask);
20157 if (lo_mask == 0 && !push && (mask & (1 << PC_REGNUM)))
20159 /* Special case. Do not generate a POP PC statement here, do it in
20160 thumb_exit() */
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))
20172 fprintf (f, ", ");
20173 asm_fprintf (f, "%r", regno);
20176 fprintf (f, "}\n");
20179 bytes += 2;
20180 if (emit)
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)
20186 if (lo_mask & 1)
20188 if (emit)
20190 asm_fprintf (f, "%r", regno);
20192 if ((lo_mask & ~1) != 0)
20193 fprintf (f, ", ");
20196 pushed_words++;
20200 if (push && (mask & (1 << LR_REGNUM)))
20202 /* Catch pushing the LR. */
20203 if (emit)
20205 if (mask & 0xFF)
20206 fprintf (f, ", ");
20208 asm_fprintf (f, "%r", LR_REGNUM);
20211 pushed_words++;
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. */
20224 if (emit)
20225 fprintf (f, "}\n");
20227 bytes += handle_thumb_exit (f, -1, emit);
20229 return bytes;
20231 else if (emit)
20233 if (mask & 0xFF)
20234 fprintf (f, ", ");
20236 asm_fprintf (f, "%r", PC_REGNUM);
20240 if (emit)
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);
20251 pushed_words = 0;
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);
20259 return bytes;
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.
20270 static int
20271 handle_thumb_exit (FILE *f, int reg_containing_return_addr, bool emit)
20273 unsigned regs_available_for_popping;
20274 unsigned regs_to_pop;
20275 int pops_needed;
20276 unsigned available;
20277 unsigned required;
20278 int mode;
20279 int size;
20280 int restore_a4 = FALSE;
20281 int bytes = 0;
20283 /* Compute the registers we need to pop. */
20284 regs_to_pop = 0;
20285 pops_needed = 0;
20287 if (reg_containing_return_addr == -1)
20289 regs_to_pop |= 1 << LR_REGNUM;
20290 ++pops_needed;
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);
20297 pops_needed += 2;
20300 /* If there is nothing to pop then just emit the BX instruction and
20301 return. */
20302 if (pops_needed == 0)
20304 if (current_function_calls_eh_return)
20306 bytes += 2;
20307 if (emit)
20308 asm_fprintf (f, "\tadd\t%r, %r\n", SP_REGNUM, ARM_EH_STACKADJ_REGNUM);
20311 bytes += 2;
20312 if (emit)
20313 asm_fprintf (f, "\tbx\t%r\n", reg_containing_return_addr);
20315 return bytes;
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)
20326 bytes += 2;
20327 if (emit)
20328 asm_fprintf (f, "\tpop\t{%r}\n", PC_REGNUM);
20329 return bytes;
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)
20338 size = 12;
20339 else
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);
20349 else
20350 mode = DECL_MODE (DECL_RESULT (current_function_decl));
20352 size = GET_MODE_SIZE (mode);
20354 if (size == 0)
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));
20364 else
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))
20384 -- pops_needed;
20386 /* If we have any popping registers left over, remove them. */
20387 if (available > 0)
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)
20399 bytes += 2;
20400 if (emit)
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. */
20408 restore_a4 = TRUE;
20410 bytes += 2;
20411 if (emit)
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;
20420 --pops_needed;
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)
20445 int frame_pointer;
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. */
20451 bytes += 2;
20452 if (emit)
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)
20462 int stack_pointer;
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. */
20469 bytes += 2;
20470 if (emit)
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)) */
20481 else
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
20493 contained it. */
20494 if (regs_available_for_popping == 0 && pops_needed > 0)
20496 regs_available_for_popping |= 1 << reg_containing_return_addr;
20498 bytes += 2;
20499 if (emit)
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)
20510 int popped_into;
20511 int move_to;
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);
20521 bytes += 2;
20522 if (emit)
20523 asm_fprintf (f, "\tmov\t%r, %r\n", move_to, popped_into);
20525 regs_to_pop &= ~(1 << move_to);
20527 --pops_needed;
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)
20534 int popped_into;
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);
20541 bytes += 2;
20542 if (emit)
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. */
20551 if (restore_a4)
20553 if (reg_containing_return_addr != LR_REGNUM)
20555 bytes += 2;
20556 if (emit)
20557 asm_fprintf (f, "\tmov\t%r, %r\n", LR_REGNUM, LAST_ARG_REGNUM);
20558 reg_containing_return_addr = LR_REGNUM;
20561 bytes += 2;
20562 if (emit)
20563 asm_fprintf (f, "\tmov\t%r, %r\n", LAST_ARG_REGNUM, IP_REGNUM);
20566 if (current_function_calls_eh_return)
20568 bytes += 2;
20569 if (emit)
20570 asm_fprintf (f, "\tadd\t%r, %r\n", SP_REGNUM, ARM_EH_STACKADJ_REGNUM);
20573 /* Return to caller. */
20574 bytes += 2;
20575 if (emit)
20576 asm_fprintf (f, "\tbx\t%r\n", reg_containing_return_addr);
20577 return bytes;
20579 /* APPLE LOCAL end ARM compact switch tables */
20582 void
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;
20595 int i;
20597 if (val == 0) /* XXX */
20598 return 0;
20600 for (i = 0; i < 25; i++)
20601 if ((val & (mask << i)) == val)
20602 return 1;
20604 return 0;
20607 /* Returns nonzero if the current function contains,
20608 or might contain a far jump. */
20609 static int
20610 thumb_far_jump_used_p (void)
20612 /* LLVM LOCAL begin */
20613 #ifdef ENABLE_LLVM
20614 return 0;
20615 #else
20616 /* LLVM LOCAL end */
20617 rtx insn;
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)
20628 return 1;
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)
20659 return 0;
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;
20676 return 1;
20680 return 0;
20681 /* LLVM LOCAL */
20682 #endif
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))
20693 return TRUE;
20695 #ifdef ARM_PE
20696 return lookup_attribute ("interfacearm", DECL_ATTRIBUTES (func)) != NULL_TREE;
20697 #else
20698 return FALSE;
20699 #endif
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.
20709 static int
20710 handle_thumb_unexpanded_epilogue (bool emit)
20712 int regno;
20713 unsigned long live_regs_mask = 0;
20714 int high_regs_pushed = 0;
20715 int had_to_push_lr;
20716 int size;
20717 int bytes = 0;
20719 if (return_used_this_function)
20720 return bytes;
20722 if (IS_NAKED (arm_current_func_type ()))
20723 return bytes;
20725 /* APPLE LOCAL begin 6465387 exception handling interworking VFP save */
20726 if (current_function_has_nonlocal_label && arm_arch6)
20728 bytes += 4;
20729 if (emit)
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}
20749 mov r7, r9
20750 mov r6, r8
20751 push {r6, r7}
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;
20757 int next_hi_reg;
20759 /* The available low registers depend on the size of the value we are
20760 returning. */
20761 if (size <= 12)
20762 mask |= 1 << 3;
20763 if (size <= 8)
20764 mask |= 1 << 2;
20766 if (mask == 0)
20767 /* Oh dear! We have no low registers into which we can pop
20768 high registers! */
20769 internal_error
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))
20774 break;
20776 while (high_regs_pushed)
20778 /* Find lo register(s) into which the high register(s) can
20779 be popped. */
20780 for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
20782 if (mask & (1 << regno))
20783 high_regs_pushed--;
20784 if (high_regs_pushed == 0)
20785 break;
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))
20798 bytes += 2;
20799 if (emit)
20800 asm_fprintf (asm_out_file, "\tmov\t%r, %r\n", next_hi_reg,
20801 regno);
20803 for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++)
20804 if (live_regs_mask & (1 << next_hi_reg))
20805 break;
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);
20833 else
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)
20842 if (size > 12)
20844 /* We have no free low regs, so save one. */
20845 bytes += 2;
20846 if (emit)
20847 asm_fprintf (asm_out_file, "\tmov\t%r, %r\n", IP_REGNUM,
20848 LAST_ARG_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);
20855 if (size > 12)
20857 bytes += 4;
20858 if (emit)
20860 /* Move the return address to lr. */
20861 asm_fprintf (asm_out_file, "\tmov\t%r, %r\n", LR_REGNUM,
20862 LAST_ARG_REGNUM);
20863 /* Restore the low register. */
20864 asm_fprintf (asm_out_file, "\tmov\t%r, %r\n", LAST_ARG_REGNUM,
20865 IP_REGNUM);
20867 regno = LR_REGNUM;
20869 else
20870 regno = LAST_ARG_REGNUM;
20872 else
20873 regno = LR_REGNUM;
20875 /* Remove the argument registers that were pushed onto the stack. */
20876 bytes += 2;
20877 if (emit)
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);
20885 return bytes;
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);
20895 return "";
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;
20908 #endif
20909 return machine;
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)
20918 if (count != 0)
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. */
20926 void
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. */
20935 if (cfun)
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. */
20945 HOST_WIDE_INT
20946 thumb_compute_initial_elimination_offset (unsigned int from, unsigned int to)
20948 arm_stack_offsets *offsets;
20950 offsets = arm_get_frame_offsets ();
20952 switch (from)
20954 case ARG_POINTER_REGNUM:
20955 switch (to)
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 */
20968 default:
20969 gcc_unreachable ();
20971 break;
20973 case FRAME_POINTER_REGNUM:
20974 switch (to)
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 */
20984 default:
20985 gcc_unreachable ();
20987 break;
20989 default:
20990 gcc_unreachable ();
20995 /* Generate the rest of a function's prologue. */
20996 void
20997 /* APPLE LOCAL v7 support. Merge from mainline */
20998 thumb1_expand_prologue (void)
21000 rtx insn, dwarf;
21002 HOST_WIDE_INT amount;
21003 arm_stack_offsets *offsets;
21004 unsigned long func_type;
21005 int regno;
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))
21012 return;
21014 if (IS_INTERRUPT (func_type))
21016 error ("interrupt Service Routines cannot be coded in Thumb mode");
21017 return;
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,
21033 stack_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;
21046 if (amount)
21048 if (amount < 512)
21050 insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
21051 GEN_INT (- amount)));
21052 RTX_FRAME_RELATED_P (insn) = 1;
21054 else
21056 rtx reg;
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
21071 it now. */
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)))
21076 break;
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,
21098 -amount));
21099 RTX_FRAME_RELATED_P (dwarf) = 1;
21100 REG_NOTES (insn)
21101 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
21102 REG_NOTES (insn));
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));
21113 else
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,
21124 -amount));
21125 RTX_FRAME_RELATED_P (dwarf) = 1;
21126 REG_NOTES (insn)
21127 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
21128 REG_NOTES (insn));
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)));
21157 void
21158 /* APPLE LOCAL v7 support. Merge from mainline */
21159 thumb1_expand_epilogue (void)
21161 HOST_WIDE_INT amount;
21162 arm_stack_offsets *offsets;
21163 int regno;
21165 /* Naked functions don't have prologues. */
21166 if (IS_NAKED (arm_current_func_type ()))
21167 return;
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;
21181 if (fp_offset)
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));
21190 else
21192 emit_insn (gen_movsi (stack_pointer_rtx,
21193 hard_frame_pointer_rtx));
21196 else if (amount)
21197 /* APPLE LOCAL end ARM custom frame layout */
21199 if (amount < 512)
21200 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
21201 GEN_INT (amount)));
21202 else
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.
21236 static int
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;
21243 int regno;
21244 int bytes = 0;
21246 if (IS_NAKED (arm_current_func_type ()))
21247 return bytes;
21249 if (is_called_in_ARM_mode (current_function_decl))
21251 const char * name;
21253 gcc_assert (GET_CODE (DECL_RTL (current_function_decl)) == MEM);
21254 gcc_assert (GET_CODE (XEXP (DECL_RTL (current_function_decl), 0))
21255 == SYMBOL_REF);
21257 bytes += 8;
21259 if (emit)
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");
21279 #ifdef ARM_PE
21280 if (arm_dllexport_name_p (name))
21281 name = arm_strip_name_encoding (name);
21282 #endif
21283 asm_fprintf (f, "\t.globl %s%U%s\n", STUB_NAME, name);
21284 /* APPLE LOCAL begin ARM thumb_func <symbol_name> */
21285 if (TARGET_MACHO)
21286 asm_fprintf (f, "\t.thumb_func %s%U%s\n", STUB_NAME, name);
21287 else
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);
21302 if (emit)
21304 if (cfun->machine->uses_anonymous_args)
21306 int num_pushes;
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;
21314 regno++)
21315 asm_fprintf (f, "%r%s", regno,
21316 regno == LAST_ARG_REGNUM ? "" : ", ");
21318 fprintf (f, "}\n");
21320 else
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)
21348 unsigned offset;
21349 unsigned work_register;
21351 /* We have been asked to create a stack backtrace structure.
21352 The code looks like this:
21354 0 .align 2
21355 0 func:
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");
21374 bytes += 2;
21375 if (emit)
21376 asm_fprintf
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);
21388 if (l_mask)
21390 bytes += handle_thumb_pushpop (f, l_mask, 1, &cfa_offset, l_mask, emit);
21391 offset = bit_count (l_mask) * UNITS_PER_WORD;
21393 else
21394 offset = 0;
21396 bytes += 4;
21397 if (emit)
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,
21403 offset + 4);
21406 bytes += 8;
21407 if (emit)
21409 /* Make sure that the instruction fetching the PC is in the right place
21410 to calculate "start of backtrace creation code + 12". */
21411 if (l_mask)
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,
21415 offset + 12);
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,
21419 offset);
21421 else
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,
21426 offset);
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,
21429 offset + 12);
21433 bytes += 8;
21434 if (emit)
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,
21438 offset + 8);
21439 asm_fprintf (f, "\tadd\t%r, %r, #%d\n", work_register, SP_REGNUM,
21440 offset + 12);
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
21448 register. */
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))
21460 break;
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))
21476 bytes += 2;
21477 if (emit)
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;
21486 next_hi_reg --)
21487 if (live_regs_mask & (1 << next_hi_reg))
21488 break;
21490 else
21492 pushable_regs &= ~((1 << regno) - 1);
21493 break;
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),
21504 1, &cfa_offset,
21505 real_regs_mask | (1 << LR_REGNUM), emit);
21506 l_mask = 0;
21508 else
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)
21515 bytes += 4;
21516 if (emit)
21517 asm_fprintf (f, "\tblx ___save_vfp_d8_d15_regs\n");
21519 /* APPLE LOCAL end 6465387 exception handling interworking VFP save */
21520 return bytes;
21523 static void
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. */
21539 const char *
21540 thumb_load_double_from_address (rtx *operands)
21542 rtx addr;
21543 rtx base;
21544 rtx offset;
21545 rtx arg1;
21546 rtx arg2;
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))
21557 case REG:
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);
21565 else
21567 output_asm_insn ("ldr\t%0, %1", operands);
21568 output_asm_insn ("ldr\t%H0, %2", operands);
21570 break;
21572 case CONST:
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);
21578 break;
21580 case PLUS:
21581 arg1 = XEXP (addr, 0);
21582 arg2 = XEXP (addr, 1);
21584 if (CONSTANT_P (arg1))
21585 base = arg2, offset = arg1;
21586 else
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. */
21599 gcc_unreachable();
21600 /* APPLE LOCAL end ARM compact switch tables */
21602 else
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);
21615 else
21617 output_asm_insn ("ldr\t%0, %1", operands);
21618 output_asm_insn ("ldr\t%H0, %2", operands);
21621 break;
21623 case LABEL_REF:
21624 /* With no registers to worry about we can just load the value
21625 directly. */
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);
21630 break;
21632 default:
21633 gcc_unreachable ();
21636 return "";
21639 const char *
21640 thumb_output_move_mem_multiple (int n, rtx *operands)
21642 rtx tmp;
21644 switch (n)
21646 case 2:
21647 if (REGNO (operands[4]) > REGNO (operands[5]))
21649 tmp = operands[4];
21650 operands[4] = operands[5];
21651 operands[5] = tmp;
21653 output_asm_insn ("ldmia\t%1!, {%4, %5}", operands);
21654 output_asm_insn ("stmia\t%0!, {%4, %5}", operands);
21655 break;
21657 case 3:
21658 if (REGNO (operands[4]) > REGNO (operands[5]))
21660 tmp = operands[4];
21661 operands[4] = operands[5];
21662 operands[5] = tmp;
21664 if (REGNO (operands[5]) > REGNO (operands[6]))
21666 tmp = operands[5];
21667 operands[5] = operands[6];
21668 operands[6] = tmp;
21670 if (REGNO (operands[4]) > REGNO (operands[5]))
21672 tmp = operands[4];
21673 operands[4] = operands[5];
21674 operands[5] = tmp;
21677 output_asm_insn ("ldmia\t%1!, {%4, %5, %6}", operands);
21678 output_asm_insn ("stmia\t%0!, {%4, %5, %6}", operands);
21679 break;
21681 default:
21682 gcc_unreachable ();
21685 return "";
21688 /* Output a call-via instruction for thumb state. */
21689 const char *
21690 thumb_call_via_reg (rtx reg)
21692 int regno = REGNO (reg);
21693 rtx *labelp;
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;
21708 else
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);
21716 return "";
21719 /* Routines for generating rtl. */
21720 void
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;
21728 while (len >= 12)
21730 emit_insn (gen_movmem12b (out, in, out, in));
21731 len -= 12;
21734 if (len >= 8)
21736 emit_insn (gen_movmem8b (out, in, out, in));
21737 len -= 8;
21740 if (len >= 4)
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));
21745 len -= 4;
21746 offset += 4;
21749 if (len >= 2)
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)),
21755 reg));
21756 len -= 2;
21757 offset += 2;
21760 if (len)
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)),
21766 reg));
21770 void
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. */
21777 void
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'. */
21785 static int
21786 arm_get_strip_length (int c)
21788 switch (c)
21790 ARM_NAME_ENCODING_LENGTHS
21791 default: return 0;
21795 /* Return a pointer to a function's name with any
21796 and all prefix encodings stripped from it. */
21797 const char *
21798 arm_strip_name_encoding (const char *name)
21800 int skip;
21802 while ((skip = arm_get_strip_length (* name)))
21803 name += skip;
21805 return 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. */
21811 void
21812 arm_asm_output_labelref (FILE *stream, const char *name)
21814 int skip;
21815 int verbatim = 0;
21817 while ((skip = arm_get_strip_length (* name)))
21819 verbatim |= (*name == '*');
21820 name += skip;
21823 if (verbatim)
21824 fputs (name, stream);
21825 else
21826 asm_fprintf (stream, "%U%s", name);
21829 /* APPLE LOCAL begin v7 support. Merge from mainline */
21830 static void
21831 arm_file_start (void)
21833 int val;
21835 if (TARGET_UNIFIED_ASM)
21836 asm_fprintf (asm_out_file, "\t.syntax unified\n");
21838 if (TARGET_BPABI)
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);
21845 else
21846 asm_fprintf (asm_out_file, "\t.cpu %s\n",
21847 all_cores[arm_default_cpu].name);
21849 if (TARGET_SOFT_FLOAT)
21851 if (TARGET_VFP)
21852 fpu_name = "softvfp";
21853 else
21854 fpu_name = "softfpa";
21856 else
21858 int set_float_abi_attributes = 0;
21859 switch (arm_fpu_arch)
21861 case FPUTYPE_FPA:
21862 fpu_name = "fpa";
21863 break;
21864 case FPUTYPE_FPA_EMU2:
21865 fpu_name = "fpe2";
21866 break;
21867 case FPUTYPE_FPA_EMU3:
21868 fpu_name = "fpe3";
21869 break;
21870 case FPUTYPE_MAVERICK:
21871 fpu_name = "maverick";
21872 break;
21873 case FPUTYPE_VFP:
21874 fpu_name = "vfp";
21875 set_float_abi_attributes = 1;
21876 break;
21877 case FPUTYPE_VFP3:
21878 fpu_name = "vfp3";
21879 set_float_abi_attributes = 1;
21880 break;
21881 case FPUTYPE_NEON:
21882 fpu_name = "neon";
21883 set_float_abi_attributes = 1;
21884 break;
21885 default:
21886 abort();
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. */
21932 if (optimize_size)
21933 val = 4;
21934 else if (optimize >= 2)
21935 val = 2;
21936 else if (optimize)
21937 val = 1;
21938 else
21939 val = 6;
21940 asm_fprintf (asm_out_file, "\t.eabi_attribute 30, %d\n", val);
21942 /* APPLE LOCAL 6345234 begin place text sections together */
21943 #if TARGET_MACHO
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");
21955 else
21956 fprintf (asm_out_file,
21957 "\t.section __TEXT,__picsymbolstub4,symbol_stubs,none,16\n");
21959 #endif
21960 /* APPLE LOCAL 6345234 end place text sections together */
21961 default_file_start();
21964 /* APPLE LOCAL end v7 support. Merge from mainline */
21965 static void
21966 arm_file_end (void)
21968 int regno;
21970 if (! thumb_call_reg_needed)
21971 return;
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];
21981 if (label != 0)
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 */
21991 #if TARGET_MACHO
21992 static void
21993 arm_darwin_file_start (void)
21995 /* APPLE LOCAL v7 support. Merge from mainline */
21996 arm_file_start();
21997 darwin_file_start();
22000 static void
22001 arm_darwin_file_end (void)
22003 darwin_file_end ();
22004 arm_file_end ();
22006 #endif
22007 /* APPLE LOCAL end ARM asm file hooks */
22009 rtx aof_pic_label;
22011 #ifdef AOF_ASSEMBLER
22012 /* Special functions only needed when producing AOF syntax assembler. */
22014 struct pic_chain
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;
22026 int offset;
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);
22044 void
22045 aof_dump_pic_table (FILE *f)
22047 struct pic_chain * chain;
22049 if (aof_pic_chain == NULL)
22050 return;
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);
22061 fputs ("\n", f);
22065 int arm_text_section_count = 1;
22067 /* A get_unnamed_section callback for switching to the text section. */
22069 static void
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++);
22074 if (flag_pic)
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. */
22083 static void
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. */
22100 static void
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;
22110 void
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++);
22116 in_section = NULL;
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
22127 directive. */
22129 struct import
22131 struct import * next;
22132 const char * name;
22135 static struct import * imports_list = NULL;
22137 void
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)
22144 return;
22146 new = (struct import *) xmalloc (sizeof (struct import));
22147 new->next = imports_list;
22148 imports_list = new;
22149 new->name = name;
22152 void
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;
22162 return;
22167 int arm_main_function = 0;
22169 static void
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
22174 automagically. */
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);
22187 fputc ('\n', f);
22188 imports_list = imports_list->next;
22192 static void
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;
22200 static void
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);
22231 static void
22232 aof_file_end (void)
22234 if (flag_pic)
22235 aof_dump_pic_table (asm_out_file);
22236 arm_file_end ();
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
22248 simplification. */
22250 static void
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;
22258 #endif
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*/
22276 #if TARGET_MACHO
22277 /* Encode the standard darwin attributes, plus the longcall flag. */
22279 static void
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. */
22291 if (DECL_P (decl))
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);
22302 #endif
22303 /* APPLE LOCAL end ARM darwin section_info */
22305 static void
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. */
22319 static void
22320 arm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
22321 HOST_WIDE_INT delta,
22322 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
22323 tree function)
22325 /* APPLE LOCAL begin ARM 4620953 4745175 5920116 */
22326 static int thunk_label = 0;
22327 char label[256];
22328 char labelpc[256];
22329 int mi_delta = delta;
22330 const char *const mi_op = mi_delta < 0 ? "sub" : "add";
22331 int shift = 0;
22332 int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)
22333 ? 1 : 0);
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. */
22343 #if TARGET_MACHO
22344 if (TARGET_MACHO
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;
22352 else
22353 #endif
22354 function_name = XSTR (function_rtx, 0);
22356 if (mi_delta < 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);
22371 if (flag_pic)
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)
22378 = target + 1.
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);
22388 if (is_indirected)
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)
22396 shift += 2;
22397 else
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);
22403 shift += 8;
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);
22413 if (flag_pic)
22415 /* APPLE LOCAL 6361608 begin Thumb-2 longcall thunks */
22416 int pc_offset;
22417 /* If we're branching to a local Thumb routine, output:
22418 ".word .LTHUNKn-7-.LTHUNKPCn".
22419 Otherwise, output:
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
22426 mode has +8. */
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));
22430 else
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),
22435 tem,
22436 gen_rtx_SYMBOL_REF (Pmode,
22437 ggc_strdup (labelpc)));
22438 assemble_integer (tem, 4, BITS_PER_WORD, 1);
22440 else
22441 /* Output ".word .LTHUNKn". */
22442 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, function_name),
22443 4, BITS_PER_WORD, 1);
22445 else
22447 /* APPLE LOCAL begin 6297258 */
22448 if (TARGET_THUMB2)
22449 fputs ("\tb.w\t", file);
22450 else
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)
22465 int i;
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--;)
22481 rtx element;
22483 element = CONST_VECTOR_ELT (x, i);
22484 fprintf (file, pattern, INTVAL (element));
22487 return 1;
22490 const char *
22491 arm_output_load_gr (rtx *operands)
22493 rtx reg;
22494 rtx offset;
22495 rtx wcgr;
22496 rtx sum;
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];
22508 operands[0] = reg;
22509 output_asm_insn ("ldr%?\t%0, %1", operands);
22511 operands[0] = wcgr;
22512 operands[1] = reg;
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);
22516 return "";
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
22524 that way. */
22526 static void
22527 arm_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
22528 enum machine_mode mode ATTRIBUTE_UNUSED,
22529 tree type ATTRIBUTE_UNUSED,
22530 int *pretend_size,
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);
22570 rtx early_op;
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);
22581 op = XEXP (op, 1);
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
22586 operation. */
22587 if (GET_CODE (early_op) == REG)
22588 early_op = op;
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
22595 PRODUCER. */
22598 arm_no_early_alu_shift_value_dep (rtx producer, rtx consumer)
22600 rtx value = PATTERN (producer);
22601 rtx op = PATTERN (consumer);
22602 rtx early_op;
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);
22613 op = XEXP (op, 1);
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
22628 PRODUCER. */
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);
22645 op = XEXP (op, 1);
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);
22660 rtx mul_result;
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))
22673 return 0;
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. */
22690 static bool
22691 arm_promote_prototypes (tree t ATTRIBUTE_UNUSED)
22693 return !TARGET_AAPCS_BASED;
22697 /* AAPCS based ABIs use short enums by default. */
22699 static bool
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. */
22708 static bool
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. */
22717 static tree
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. */
22726 static bool
22727 arm_cxx_guard_mask_bit (void)
22729 return TARGET_AAPCS_BASED;
22733 /* The EABI specifies that all array cookies are 8 bytes long. */
22735 static tree
22736 arm_get_cookie_size (tree type)
22738 tree size;
22740 if (!TARGET_AAPCS_BASED)
22741 return default_cxx_get_cookie_size (type);
22743 size = build_int_cst (sizetype, 8);
22744 return size;
22748 /* The EABI says that array cookies should also contain the element size. */
22750 static bool
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. */
22760 static bool
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
22767 method. */
22769 static bool
22770 arm_cxx_key_method_may_be_inline (void)
22772 return !TARGET_AAPCS_BASED;
22775 static void
22776 arm_cxx_determine_class_data_visibility (tree decl)
22778 if (!TARGET_AAPCS_BASED)
22779 return;
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;
22786 else
22787 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
22788 DECL_VISIBILITY_SPECIFIED (decl) = 1;
22791 static bool
22792 arm_cxx_class_data_always_comdat (void)
22794 /* APPLE LOCAL begin ARM follow Darwin semantics on Darwin */
22795 #if TARGET_MACHO
22796 return false;
22797 #endif
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
22807 destructors. */
22809 static bool
22810 arm_cxx_use_aeabi_atexit (void)
22812 return TARGET_AAPCS_BASED;
22816 void
22817 arm_set_return_address (rtx source, rtx scratch)
22819 arm_stack_offsets *offsets;
22820 HOST_WIDE_INT delta;
22821 rtx addr;
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);
22828 else
22830 if (frame_pointer_needed)
22831 /* APPLE LOCAL ARM custom frame layout */
22832 addr = plus_constant(hard_frame_pointer_rtx, 4);
22833 else
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);
22841 if (delta >= 4096)
22843 emit_insn (gen_addsi3 (scratch, stack_pointer_rtx,
22844 GEN_INT (delta & ~4095)));
22845 addr = scratch;
22846 delta &= 4095;
22848 else
22849 addr = stack_pointer_rtx;
22851 addr = plus_constant (addr, delta);
22853 emit_move_insn (gen_frame_mem (Pmode, addr), source);
22858 void
22859 thumb_set_return_address (rtx source, rtx scratch)
22861 arm_stack_offsets *offsets;
22862 HOST_WIDE_INT delta;
22863 int reg;
22864 rtx addr;
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 */
22879 delta = 4;
22880 reg = THUMB_HARD_FRAME_POINTER_REGNUM;
22882 else
22884 /* APPLE LOCAL ARM custom frame layout */
22885 delta = offsets->outgoing_args - (offsets->saved_args + 4);
22886 reg = SP_REGNUM;
22888 /* Allow for the stack frame. */
22889 /* APPLE LOCAL v7 support. Merge from mainline */
22890 if (TARGET_THUMB1 && TARGET_BACKTRACE)
22891 delta -= 16;
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)
22898 || delta >= 1024)
22900 emit_insn (gen_movsi (scratch, GEN_INT (delta)));
22901 emit_insn (gen_addsi3 (scratch, scratch, stack_pointer_rtx));
22902 addr = scratch;
22904 else
22905 addr = plus_constant (addr, delta);
22907 emit_move_insn (gen_frame_mem (Pmode, addr), source);
22909 else
22910 emit_move_insn (gen_rtx_REG (Pmode, LR_REGNUM), source);
22913 /* Implements target hook vector_mode_supported_p. */
22914 bool
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))
22921 return true;
22923 /* APPLE LOCAL end v7 support. Merge from Codesourcery */
22924 if ((mode == V2SImode)
22925 || (mode == V4HImode)
22926 || (mode == V8QImode))
22927 return true;
22929 return false;
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. */
22958 unsigned int
22959 arm_dbx_register_number (unsigned int regno)
22961 if (regno < 16)
22962 return 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;
22976 else
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. */
22994 static rtx
22995 arm_dwarf_register_span(rtx rtl)
22997 unsigned regno;
22998 int nregs;
22999 int i;
23000 rtx p;
23002 regno = REGNO (rtl);
23003 if (!IS_VFP_REGNUM (regno))
23004 return NULL_RTX;
23006 /* The EABI defines two VFP register ranges:
23007 64-95: Legacy VFPv2 numbering for S0-S31 (obsolescent)
23008 256-287: D0-D31
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))
23014 return NULL_RTX;
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);
23022 return p;
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. */
23033 static void
23034 arm_unwind_emit_sequence (FILE * asm_out_file, rtx p)
23035 /* APPLE LOCAL end v7 support. Merge from mainline */
23037 int i;
23038 HOST_WIDE_INT offset;
23039 HOST_WIDE_INT nregs;
23040 int reg_size;
23041 unsigned reg;
23042 unsigned lastreg;
23043 rtx e;
23045 /* APPLE LOCAL begin v7 support. Merge from mainline */
23046 e = XVECEXP (p, 0, 0);
23047 if (GET_CODE (e) != SET)
23048 abort ();
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)
23056 abort ();
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));
23063 if (reg < 16)
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");
23070 offset -= 4;
23072 reg_size = 4;
23073 fprintf (asm_out_file, "\t.save {");
23075 else if (IS_VFP_REGNUM (reg))
23077 reg_size = 8;
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);
23085 return;
23087 else
23088 /* Unknown register type. */
23089 abort ();
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)
23094 abort ();
23096 /* APPLE LOCAL v7 support. Merge from mainline */
23097 /* Removed lines */
23098 offset = 0;
23099 lastreg = 0;
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)
23109 abort ();
23111 reg = REGNO (XEXP (e, 1));
23112 if (reg < lastreg)
23113 abort ();
23115 if (i != 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);
23121 else
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)))
23134 abort ();
23136 else if (i != 1
23137 || GET_CODE (e) != REG
23138 || REGNO (e) != SP_REGNUM)
23139 abort ();
23140 #endif
23142 fprintf (asm_out_file, "}\n");
23145 /* Emit unwind directives for a SET. */
23147 static void
23148 arm_unwind_emit_set (FILE * asm_out_file, rtx p)
23150 rtx e0;
23151 rtx e1;
23152 /* APPLE LOCAL v7 support. Merge from mainline */
23153 unsigned reg;
23155 e0 = XEXP (p, 0);
23156 e1 = XEXP (p, 1);
23157 switch (GET_CODE (e0))
23159 case MEM:
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)
23164 abort ();
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);
23170 else
23171 asm_fprintf(asm_out_file, "{%r}\n", REGNO (e1));
23172 break;
23174 case REG:
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)
23182 abort ();
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)
23197 abort ();
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)
23206 reg = REGNO (e1);
23207 asm_fprintf (asm_out_file, "\t.setfp %r, %r\n",
23208 HARD_FRAME_POINTER_REGNUM, reg);
23210 else
23211 abort ();
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. */
23231 reg = REGNO (e0);
23232 asm_fprintf (asm_out_file, "\t.unwind_raw 0, 0x%x @ vsp = r%d\n",
23233 reg + 0x90, reg);
23235 /* APPLE LOCAL end v7 support. Merge from mainline */
23236 else
23237 abort ();
23238 break;
23240 default:
23241 abort ();
23246 /* Emit unwind directives for the given insn. */
23248 static void
23249 arm_unwind_emit (FILE * asm_out_file, rtx insn)
23251 rtx pat;
23253 if (!ARM_EABI_UNWIND_TABLES)
23254 return;
23256 if (GET_CODE (insn) == NOTE || !RTX_FRAME_RELATED_P (insn))
23257 return;
23259 pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
23260 if (pat)
23261 pat = XEXP (pat, 0);
23262 else
23263 pat = PATTERN (insn);
23265 switch (GET_CODE (pat))
23267 case SET:
23268 arm_unwind_emit_set (asm_out_file, pat);
23269 break;
23271 case SEQUENCE:
23272 /* Store multiple. */
23273 /* APPLE LOCAL v7 support. Merge from mainline */
23274 arm_unwind_emit_sequence (asm_out_file, pat);
23275 break;
23277 default:
23278 abort();
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. */
23287 static bool
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);
23297 return TRUE;
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. */
23306 static void
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);
23312 switch (index)
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));
23320 break;
23321 default:
23322 gcc_unreachable ();
23327 /* APPLE LOCAL end v7 support. Merge from mainline */
23328 /* Output unwind directives for the start/end of a function. */
23330 void
23331 arm_output_fn_unwind (FILE * f, bool prologue)
23333 if (!ARM_EABI_UNWIND_TABLES)
23334 return;
23336 if (prologue)
23337 fputs ("\t.fnstart\n", f);
23338 else
23339 fputs ("\t.fnend\n", f);
23342 static bool
23343 arm_emit_tls_decoration (FILE *fp, rtx x)
23345 enum tls_reloc reloc;
23346 rtx val;
23348 val = XVECEXP (x, 0, 0);
23349 reloc = INTVAL (XVECEXP (x, 0, 1));
23351 output_addr_const (fp, val);
23353 switch (reloc)
23355 case TLS_GD32:
23356 fputs ("(tlsgd)", fp);
23357 break;
23358 case TLS_LDM32:
23359 fputs ("(tlsldm)", fp);
23360 break;
23361 case TLS_LDO32:
23362 fputs ("(tlsldo)", fp);
23363 break;
23364 case TLS_IE32:
23365 fputs ("(gottpoff)", fp);
23366 break;
23367 case TLS_LE32:
23368 fputs ("(tpoff)", fp);
23369 break;
23370 default:
23371 gcc_unreachable ();
23374 switch (reloc)
23376 case TLS_GD32:
23377 case TLS_LDM32:
23378 case TLS_IE32:
23379 fputs (" + (. - ", fp);
23380 output_addr_const (fp, XVECEXP (x, 0, 2));
23381 fputs (" - ", fp);
23382 output_addr_const (fp, XVECEXP (x, 0, 3));
23383 fputc (')', fp);
23384 break;
23385 default:
23386 break;
23389 return TRUE;
23392 bool
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)
23399 char label[256];
23400 int labelno = INTVAL (XVECEXP (x, 0, 0));
23402 ASM_GENERATE_INTERNAL_LABEL (label, "LPIC", labelno);
23403 assemble_name_raw (fp, label);
23405 return TRUE;
23407 else if (GET_CODE (x) == CONST_VECTOR)
23408 return arm_emit_vector_const (fp, x);
23410 return FALSE;
23413 /* APPLE LOCAL begin ARM darwin local binding */
23414 #if TARGET_MACHO
23415 /* Cross-module name binding. Darwin does not support overriding
23416 functions at dynamic-link time. */
23418 static bool
23419 arm_binds_local_p (tree decl)
23421 return default_binds_local_p_1 (decl,
23422 flag_apple_kext && lang_hooks.vtable_p (decl));
23424 #endif
23425 /* APPLE LOCAL end ARM darwin local binding */
23427 /* APPLE LOCAL begin ARM setjmp/longjmp interworking */
23428 static rtx
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. */
23442 #if TARGET_MACHO
23443 void
23444 reset_optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED)
23447 #endif
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. */
23455 void
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");
23475 if (flag_pic == 2)
23476 switch_to_section (darwin_sections[machopic_picsymbol_stub4_section]);
23477 else
23478 switch_to_section (darwin_sections[machopic_symbol_stub4_section]);
23480 fprintf (file, "\t.align 2\n");
23482 if (TARGET_THUMB)
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);
23489 label++;
23491 if (flag_pic == 2)
23492 fprintf (file, "L%d$scv:\tadd\tip, pc, ip\n", label);
23494 fprintf (file, "\tldr\tpc, [ip, #0]\n");
23496 if (flag_pic == 2)
23497 fprintf (file, "%s:\n\t.long\t%s - (L%d$scv + 8)\n",
23498 slp_label_name, lazy_ptr_name, label);
23499 else
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");
23509 #endif
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))
23518 return true;
23520 /* APPLE LOCAL end ARM MACH assembler */
23522 /* APPLE LOCAL begin ARM darwin optimization defaults */
23523 /* LLVM LOCAL fix warning on non-Darwin */
23524 void
23525 optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED)
23527 /* disable strict aliasing; breaks too much existing code. */
23528 #if TARGET_MACHO
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
23534 in darwin-c.c). */
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
23545 if (level > 1)
23546 flag_schedule_insns = 0;
23547 #endif
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;
23553 #endif
23555 #ifdef SUBTARGET_OPTIMIZATION_OPTIONS
23556 SUBTARGET_OPTIMIZATION_OPTIONS;
23557 #endif
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
23566 to be FP-based. */
23567 HOST_WIDE_INT
23568 arm_local_debug_offset (rtx var)
23570 int offset;
23571 int reg;
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)
23580 reg = REGNO (var);
23581 offset = 0;
23583 else
23585 return 0;
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);
23594 else
23595 return offset;
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);
23603 if (insn
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)
23609 return 2;
23610 /* APPLE LOCAL 7083296 Build without warnings. */
23611 if (XINT (PATTERN (insn), 1) == VUNSPEC_ALIGN8)
23612 return 3;
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. */
23624 const char *
23625 arm_output_shift(rtx * operands, int set_flags)
23627 char pattern[100];
23628 static const char flag_chars[3] = {'?', '.', '!'};
23629 const char *shift;
23630 HOST_WIDE_INT val;
23631 char c;
23633 c = flag_chars[set_flags];
23634 if (TARGET_UNIFIED_ASM)
23636 shift = shift_op(operands[3], &val);
23637 if (shift)
23639 if (val != -1)
23640 operands[2] = GEN_INT(val);
23641 sprintf (pattern, "%s%%%c\t%%0, %%1, %%2", shift, c);
23643 else
23644 sprintf (pattern, "mov%%%c\t%%0, %%1", c);
23646 else
23647 sprintf (pattern, "mov%%%c\t%%0, %%1%%S3", c);
23648 output_asm_insn (pattern, operands);
23649 return "";
23652 /* Output a Thumb-2 casesi instruction. */
23653 const char *
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))
23664 case QImode:
23665 return "tbb\t[%|pc, %0]";
23666 case HImode:
23667 return "tbh\t[%|pc, %0, lsl #1]";
23668 case SImode:
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 */
23674 default:
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). */
23687 typedef struct
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 }
23718 const char *
23719 arm_mangle_type (tree type)
23721 arm_mangle_map_entry *pos = arm_mangle_map;
23723 if (TREE_CODE (type) != VECTOR_TYPE)
23724 return NULL;
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;
23738 pos++;
23741 /* Use the default mangling for unrecognized (possibly user-defined)
23742 vector types. */
23743 return NULL;
23746 void
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";
23760 else
23762 pack = 1;
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",
23779 directive,
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",
23796 directive,
23797 CODE_LABEL_NUMBER (target_label), base_label_no);
23798 else
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;
23805 else
23806 vlen = vlen * size;
23807 while (vlen % pack != 0)
23809 asm_fprintf (file, "\t%s\t0 @ pad\n", directive);
23810 vlen += size;
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. */
23834 void
23835 arm_ifcvt_modify_multiple_tests (ce_if_block_t *ce_info ATTRIBUTE_UNUSED,
23836 basic_block bb ATTRIBUTE_UNUSED,
23837 rtx *p_true,
23838 rtx *p_false)
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;
23875 if (!TARGET_ARM)
23876 return;
23878 if (GET_CODE (*p_true) == AND)
23879 true_and_p = true;
23880 else if (GET_CODE (*p_true) == IOR)
23881 true_and_p = false;
23882 else
23883 return;
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;
23889 else
23890 return;
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))
23896 return;
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)
23902 return;
23904 if (GET_CODE (true_lhs) < NE || GET_CODE (true_lhs) > LTU
23905 || GET_CODE (true_rhs) < NE || GET_CODE (true_rhs) > LTU)
23906 *p_true = 0;
23907 else
23909 if (true_and_p)
23910 merged_code = and_codes [GET_CODE (true_lhs) - NE][GET_CODE (true_rhs) - NE];
23911 else
23912 merged_code = or_codes [GET_CODE (true_lhs) - NE][GET_CODE (true_rhs) - NE];
23913 if (merged_code == 0 || merged_code == 1)
23914 *p_true = 0;
23915 else
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)
23921 *p_false = 0;
23922 else
23924 if (false_and_p)
23925 merged_code = and_codes [GET_CODE (false_lhs) - NE][GET_CODE (false_rhs) - NE];
23926 else
23927 merged_code = or_codes [GET_CODE (false_lhs) - NE][GET_CODE (false_rhs) - NE];
23928 if (merged_code == 0 || merged_code == 1)
23929 *p_false = 0;
23930 else
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. */
23939 static tree
23940 arm_handle_ms_struct_attribute (tree *node, tree name,
23941 tree args ATTRIBUTE_UNUSED,
23942 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
23944 tree *type = NULL;
23945 if (DECL_P (*node))
23947 if (TREE_CODE (*node) == TYPE_DECL)
23948 type = &TREE_TYPE (*node);
23950 else
23951 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;
23967 return NULL_TREE;
23970 /* Handle a "gcc_struct" attribute; arguments as in struct
23971 attribute_spec.handler. */
23972 static tree
23973 arm_handle_gcc_struct_attribute (tree *node, tree name,
23974 tree args ATTRIBUTE_UNUSED,
23975 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
23977 tree *type = NULL;
23978 if (DECL_P (*node))
23980 if (TREE_CODE (*node) == TYPE_DECL)
23981 type = &TREE_TYPE (*node);
23983 else
23984 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;
24002 return NULL_TREE;
24005 static bool
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);
24018 int desired_align;
24020 if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)
24021 desired_align = TYPE_ALIGN (type);
24022 else
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);
24063 return min_align;
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
24071 offset. */
24072 void
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))
24083 rtx scratch;
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);
24090 return;
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
24102 offset. */
24103 void
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))
24114 rtx scratch;
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]);
24121 return;
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. */
24134 void
24135 arm_darwin_subtarget_conditional_register_usage (void)
24137 if (!(arm_arch6 && !darwin_reserve_r9_on_v6) && !arm_arch7a)
24138 fixed_regs[9] = 1;
24139 call_used_regs[9] = 1;
24141 if (TARGET_THUMB)
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. */
24154 static tree
24155 arm_md_asm_clobbers (tree outputs ATTRIBUTE_UNUSED,
24156 tree inputs ATTRIBUTE_UNUSED,
24157 tree clobbers)
24159 tree tail;
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);
24174 clobbers =
24175 tree_cons (NULL_TREE, build_string (strlen(regname), regname),
24176 clobbers);
24179 return clobbers;
24181 /* APPLE LOCAL end 6902792 Q register clobbers in inline asm */
24183 #include "gt-arm.h"