1 /* Subroutines used for code generation on the Synopsys DesignWare ARC cpu.
2 Copyright (C) 1994-2014 Free Software Foundation, Inc.
4 Sources derived from work done by Sankhya Technologies (www.sankhya.com) on
5 behalf of Synopsys Inc.
7 Position Independent Code support added,Code cleaned up,
8 Comments and Support For ARC700 instructions added by
9 Saurabh Verma (saurabh.verma@codito.com)
10 Ramana Radhakrishnan(ramana.radhakrishnan@codito.com)
12 Fixing ABI inconsistencies, optimizations for ARC600 / ARC700 pipelines,
13 profiling support added by Joern Rennecke <joern.rennecke@embecosm.com>
15 This file is part of GCC.
17 GCC is free software; you can redistribute it and/or modify
18 it under the terms of the GNU General Public License as published by
19 the Free Software Foundation; either version 3, or (at your option)
22 GCC is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU General Public License for more details.
27 You should have received a copy of the GNU General Public License
28 along with GCC; see the file COPYING3. If not see
29 <http://www.gnu.org/licenses/>. */
33 #include "coretypes.h"
37 #include "stor-layout.h"
38 #include "stringpool.h"
42 #include "hard-reg-set.h"
44 #include "insn-config.h"
45 #include "conditions.h"
46 #include "insn-flags.h"
58 #include "insn-attr.h"
63 #include "diagnostic.h"
64 #include "insn-codes.h"
65 #include "langhooks.h"
67 #include "tm-constrs.h"
68 #include "reload.h" /* For operands_match_p */
69 #include "dominance.h"
75 #include "cfgcleanup.h"
77 #include "basic-block.h"
79 #include "tree-pass.h"
81 #include "pass_manager.h"
86 /* Which cpu we're compiling for (A5, ARC600, ARC601, ARC700). */
87 static const char *arc_cpu_string
= "";
89 /* ??? Loads can handle any constant, stores can only handle small ones. */
90 /* OTOH, LIMMs cost extra, so their usefulness is limited. */
91 #define RTX_OK_FOR_OFFSET_P(MODE, X) \
92 (GET_CODE (X) == CONST_INT \
93 && SMALL_INT_RANGE (INTVAL (X), (GET_MODE_SIZE (MODE) - 1) & -4, \
94 (INTVAL (X) & (GET_MODE_SIZE (MODE) - 1) & 3 \
96 : -(-GET_MODE_SIZE (MODE) | -4) >> 1)))
98 #define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X, INDEX, STRICT) \
99 (GET_CODE (X) == PLUS \
100 && RTX_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
101 && ((INDEX && RTX_OK_FOR_INDEX_P (XEXP (X, 1), (STRICT)) \
102 && GET_MODE_SIZE ((MODE)) <= 4) \
103 || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
105 #define LEGITIMATE_SCALED_ADDRESS_P(MODE, X, STRICT) \
106 (GET_CODE (X) == PLUS \
107 && GET_CODE (XEXP (X, 0)) == MULT \
108 && RTX_OK_FOR_INDEX_P (XEXP (XEXP (X, 0), 0), (STRICT)) \
109 && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
110 && ((GET_MODE_SIZE (MODE) == 2 && INTVAL (XEXP (XEXP (X, 0), 1)) == 2) \
111 || (GET_MODE_SIZE (MODE) == 4 && INTVAL (XEXP (XEXP (X, 0), 1)) == 4)) \
112 && (RTX_OK_FOR_BASE_P (XEXP (X, 1), (STRICT)) \
113 || (flag_pic ? CONST_INT_P (XEXP (X, 1)) : CONSTANT_P (XEXP (X, 1)))))
115 #define LEGITIMATE_SMALL_DATA_ADDRESS_P(X) \
116 (GET_CODE (X) == PLUS \
117 && (REG_P (XEXP ((X), 0)) && REGNO (XEXP ((X), 0)) == SDATA_BASE_REGNUM) \
118 && ((GET_CODE (XEXP((X),1)) == SYMBOL_REF \
119 && SYMBOL_REF_SMALL_P (XEXP ((X), 1))) \
120 || (GET_CODE (XEXP ((X), 1)) == CONST \
121 && GET_CODE (XEXP (XEXP ((X), 1), 0)) == PLUS \
122 && GET_CODE (XEXP (XEXP (XEXP ((X), 1), 0), 0)) == SYMBOL_REF \
123 && SYMBOL_REF_SMALL_P (XEXP (XEXP (XEXP ((X), 1), 0), 0)) \
124 && GET_CODE (XEXP(XEXP (XEXP ((X), 1), 0), 1)) == CONST_INT)))
126 /* Array of valid operand punctuation characters. */
127 char arc_punct_chars
[256];
129 /* State used by arc_ccfsm_advance to implement conditional execution. */
130 struct GTY (()) arc_ccfsm
135 rtx_insn
*target_insn
;
139 #define arc_ccfsm_current cfun->machine->ccfsm_current
141 #define ARC_CCFSM_BRANCH_DELETED_P(STATE) \
142 ((STATE)->state == 1 || (STATE)->state == 2)
144 /* Indicate we're conditionalizing insns now. */
145 #define ARC_CCFSM_RECORD_BRANCH_DELETED(STATE) \
146 ((STATE)->state += 2)
148 #define ARC_CCFSM_COND_EXEC_P(STATE) \
149 ((STATE)->state == 3 || (STATE)->state == 4 || (STATE)->state == 5 \
150 || current_insn_predicate)
152 /* Check if INSN has a 16 bit opcode considering struct arc_ccfsm *STATE. */
153 #define CCFSM_ISCOMPACT(INSN,STATE) \
154 (ARC_CCFSM_COND_EXEC_P (STATE) \
155 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
156 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
157 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
159 /* Likewise, but also consider that INSN might be in a delay slot of JUMP. */
160 #define CCFSM_DBR_ISCOMPACT(INSN,JUMP,STATE) \
161 ((ARC_CCFSM_COND_EXEC_P (STATE) \
163 && INSN_ANNULLED_BRANCH_P (JUMP) \
164 && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (INSN)))) \
165 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
166 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
167 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
169 /* The maximum number of insns skipped which will be conditionalised if
171 /* When optimizing for speed:
172 Let p be the probability that the potentially skipped insns need to
173 be executed, pn the cost of a correctly predicted non-taken branch,
174 mt the cost of a mis/non-predicted taken branch,
175 mn mispredicted non-taken, pt correctly predicted taken ;
176 costs expressed in numbers of instructions like the ones considered
178 Unfortunately we don't have a measure of predictability - this
179 is linked to probability only in that in the no-eviction-scenario
180 there is a lower bound 1 - 2 * min (p, 1-p), and a somewhat larger
181 value that can be assumed *if* the distribution is perfectly random.
182 A predictability of 1 is perfectly plausible not matter what p is,
183 because the decision could be dependent on an invocation parameter
185 For large p, we want MAX_INSNS_SKIPPED == pn/(1-p) + mt - pn
186 For small p, we want MAX_INSNS_SKIPPED == pt
188 When optimizing for size:
189 We want to skip insn unless we could use 16 opcodes for the
190 non-conditionalized insn to balance the branch length or more.
191 Performance can be tie-breaker. */
192 /* If the potentially-skipped insns are likely to be executed, we'll
193 generally save one non-taken branch
195 this to be no less than the 1/p */
196 #define MAX_INSNS_SKIPPED 3
198 /* The values of unspec's first field. */
208 ARC_BUILTIN_NORM
= 3,
209 ARC_BUILTIN_NORMW
= 4,
210 ARC_BUILTIN_SWAP
= 5,
212 ARC_BUILTIN_DIVAW
= 7,
214 ARC_BUILTIN_MUL64
= 9,
215 ARC_BUILTIN_MULU64
= 10,
216 ARC_BUILTIN_RTIE
= 11,
217 ARC_BUILTIN_SYNC
= 12,
218 ARC_BUILTIN_CORE_READ
= 13,
219 ARC_BUILTIN_CORE_WRITE
= 14,
220 ARC_BUILTIN_FLAG
= 15,
223 ARC_BUILTIN_SLEEP
= 18,
224 ARC_BUILTIN_SWI
= 19,
225 ARC_BUILTIN_TRAP_S
= 20,
226 ARC_BUILTIN_UNIMP_S
= 21,
227 ARC_BUILTIN_ALIGNED
= 22,
229 /* Sentinel to mark start of simd builtins. */
230 ARC_SIMD_BUILTIN_BEGIN
= 1000,
232 ARC_SIMD_BUILTIN_VADDAW
= 1001,
233 ARC_SIMD_BUILTIN_VADDW
= 1002,
234 ARC_SIMD_BUILTIN_VAVB
= 1003,
235 ARC_SIMD_BUILTIN_VAVRB
= 1004,
236 ARC_SIMD_BUILTIN_VDIFAW
= 1005,
237 ARC_SIMD_BUILTIN_VDIFW
= 1006,
238 ARC_SIMD_BUILTIN_VMAXAW
= 1007,
239 ARC_SIMD_BUILTIN_VMAXW
= 1008,
240 ARC_SIMD_BUILTIN_VMINAW
= 1009,
241 ARC_SIMD_BUILTIN_VMINW
= 1010,
242 ARC_SIMD_BUILTIN_VMULAW
= 1011,
243 ARC_SIMD_BUILTIN_VMULFAW
= 1012,
244 ARC_SIMD_BUILTIN_VMULFW
= 1013,
245 ARC_SIMD_BUILTIN_VMULW
= 1014,
246 ARC_SIMD_BUILTIN_VSUBAW
= 1015,
247 ARC_SIMD_BUILTIN_VSUBW
= 1016,
248 ARC_SIMD_BUILTIN_VSUMMW
= 1017,
249 ARC_SIMD_BUILTIN_VAND
= 1018,
250 ARC_SIMD_BUILTIN_VANDAW
= 1019,
251 ARC_SIMD_BUILTIN_VBIC
= 1020,
252 ARC_SIMD_BUILTIN_VBICAW
= 1021,
253 ARC_SIMD_BUILTIN_VOR
= 1022,
254 ARC_SIMD_BUILTIN_VXOR
= 1023,
255 ARC_SIMD_BUILTIN_VXORAW
= 1024,
256 ARC_SIMD_BUILTIN_VEQW
= 1025,
257 ARC_SIMD_BUILTIN_VLEW
= 1026,
258 ARC_SIMD_BUILTIN_VLTW
= 1027,
259 ARC_SIMD_BUILTIN_VNEW
= 1028,
260 ARC_SIMD_BUILTIN_VMR1AW
= 1029,
261 ARC_SIMD_BUILTIN_VMR1W
= 1030,
262 ARC_SIMD_BUILTIN_VMR2AW
= 1031,
263 ARC_SIMD_BUILTIN_VMR2W
= 1032,
264 ARC_SIMD_BUILTIN_VMR3AW
= 1033,
265 ARC_SIMD_BUILTIN_VMR3W
= 1034,
266 ARC_SIMD_BUILTIN_VMR4AW
= 1035,
267 ARC_SIMD_BUILTIN_VMR4W
= 1036,
268 ARC_SIMD_BUILTIN_VMR5AW
= 1037,
269 ARC_SIMD_BUILTIN_VMR5W
= 1038,
270 ARC_SIMD_BUILTIN_VMR6AW
= 1039,
271 ARC_SIMD_BUILTIN_VMR6W
= 1040,
272 ARC_SIMD_BUILTIN_VMR7AW
= 1041,
273 ARC_SIMD_BUILTIN_VMR7W
= 1042,
274 ARC_SIMD_BUILTIN_VMRB
= 1043,
275 ARC_SIMD_BUILTIN_VH264F
= 1044,
276 ARC_SIMD_BUILTIN_VH264FT
= 1045,
277 ARC_SIMD_BUILTIN_VH264FW
= 1046,
278 ARC_SIMD_BUILTIN_VVC1F
= 1047,
279 ARC_SIMD_BUILTIN_VVC1FT
= 1048,
281 /* Va, Vb, rlimm instructions. */
282 ARC_SIMD_BUILTIN_VBADDW
= 1050,
283 ARC_SIMD_BUILTIN_VBMAXW
= 1051,
284 ARC_SIMD_BUILTIN_VBMINW
= 1052,
285 ARC_SIMD_BUILTIN_VBMULAW
= 1053,
286 ARC_SIMD_BUILTIN_VBMULFW
= 1054,
287 ARC_SIMD_BUILTIN_VBMULW
= 1055,
288 ARC_SIMD_BUILTIN_VBRSUBW
= 1056,
289 ARC_SIMD_BUILTIN_VBSUBW
= 1057,
291 /* Va, Vb, Ic instructions. */
292 ARC_SIMD_BUILTIN_VASRW
= 1060,
293 ARC_SIMD_BUILTIN_VSR8
= 1061,
294 ARC_SIMD_BUILTIN_VSR8AW
= 1062,
296 /* Va, Vb, u6 instructions. */
297 ARC_SIMD_BUILTIN_VASRRWi
= 1065,
298 ARC_SIMD_BUILTIN_VASRSRWi
= 1066,
299 ARC_SIMD_BUILTIN_VASRWi
= 1067,
300 ARC_SIMD_BUILTIN_VASRPWBi
= 1068,
301 ARC_SIMD_BUILTIN_VASRRPWBi
= 1069,
302 ARC_SIMD_BUILTIN_VSR8AWi
= 1070,
303 ARC_SIMD_BUILTIN_VSR8i
= 1071,
305 /* Va, Vb, u8 (simm) instructions. */
306 ARC_SIMD_BUILTIN_VMVAW
= 1075,
307 ARC_SIMD_BUILTIN_VMVW
= 1076,
308 ARC_SIMD_BUILTIN_VMVZW
= 1077,
309 ARC_SIMD_BUILTIN_VD6TAPF
= 1078,
311 /* Va, rlimm, u8 (simm) instructions. */
312 ARC_SIMD_BUILTIN_VMOVAW
= 1080,
313 ARC_SIMD_BUILTIN_VMOVW
= 1081,
314 ARC_SIMD_BUILTIN_VMOVZW
= 1082,
316 /* Va, Vb instructions. */
317 ARC_SIMD_BUILTIN_VABSAW
= 1085,
318 ARC_SIMD_BUILTIN_VABSW
= 1086,
319 ARC_SIMD_BUILTIN_VADDSUW
= 1087,
320 ARC_SIMD_BUILTIN_VSIGNW
= 1088,
321 ARC_SIMD_BUILTIN_VEXCH1
= 1089,
322 ARC_SIMD_BUILTIN_VEXCH2
= 1090,
323 ARC_SIMD_BUILTIN_VEXCH4
= 1091,
324 ARC_SIMD_BUILTIN_VUPBAW
= 1092,
325 ARC_SIMD_BUILTIN_VUPBW
= 1093,
326 ARC_SIMD_BUILTIN_VUPSBAW
= 1094,
327 ARC_SIMD_BUILTIN_VUPSBW
= 1095,
329 ARC_SIMD_BUILTIN_VDIRUN
= 1100,
330 ARC_SIMD_BUILTIN_VDORUN
= 1101,
331 ARC_SIMD_BUILTIN_VDIWR
= 1102,
332 ARC_SIMD_BUILTIN_VDOWR
= 1103,
334 ARC_SIMD_BUILTIN_VREC
= 1105,
335 ARC_SIMD_BUILTIN_VRUN
= 1106,
336 ARC_SIMD_BUILTIN_VRECRUN
= 1107,
337 ARC_SIMD_BUILTIN_VENDREC
= 1108,
339 ARC_SIMD_BUILTIN_VLD32WH
= 1110,
340 ARC_SIMD_BUILTIN_VLD32WL
= 1111,
341 ARC_SIMD_BUILTIN_VLD64
= 1112,
342 ARC_SIMD_BUILTIN_VLD32
= 1113,
343 ARC_SIMD_BUILTIN_VLD64W
= 1114,
344 ARC_SIMD_BUILTIN_VLD128
= 1115,
345 ARC_SIMD_BUILTIN_VST128
= 1116,
346 ARC_SIMD_BUILTIN_VST64
= 1117,
348 ARC_SIMD_BUILTIN_VST16_N
= 1120,
349 ARC_SIMD_BUILTIN_VST32_N
= 1121,
351 ARC_SIMD_BUILTIN_VINTI
= 1201,
356 /* A nop is needed between a 4 byte insn that sets the condition codes and
357 a branch that uses them (the same isn't true for an 8 byte insn that sets
358 the condition codes). Set by arc_ccfsm_advance. Used by
359 arc_print_operand. */
361 static int get_arc_condition_code (rtx
);
363 static tree
arc_handle_interrupt_attribute (tree
*, tree
, tree
, int, bool *);
365 /* Initialized arc_attribute_table to NULL since arc doesnot have any
366 machine specific supported attributes. */
367 const struct attribute_spec arc_attribute_table
[] =
369 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
370 type_handler, affects_type_identity } */
371 { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute
,
373 /* Function calls made to this symbol must be done indirectly, because
374 it may lie outside of the 21/25 bit addressing range of a normal function
376 { "long_call", 0, 0, false, true, true, NULL
, NULL
, false },
377 /* Whereas these functions are always known to reside within the 25 bit
378 addressing range of unconditionalized bl. */
379 { "medium_call", 0, 0, false, true, true, NULL
, NULL
, false },
380 /* And these functions are always known to reside within the 21 bit
381 addressing range of blcc. */
382 { "short_call", 0, 0, false, true, true, NULL
, NULL
, false },
383 { NULL
, 0, 0, false, false, false, NULL
, NULL
, false }
385 static int arc_comp_type_attributes (const_tree
, const_tree
);
386 static void arc_file_start (void);
387 static void arc_internal_label (FILE *, const char *, unsigned long);
388 static void arc_output_mi_thunk (FILE *, tree
, HOST_WIDE_INT
, HOST_WIDE_INT
,
390 static int arc_address_cost (rtx
, machine_mode
, addr_space_t
, bool);
391 static void arc_encode_section_info (tree decl
, rtx rtl
, int first
);
393 static void arc_init_builtins (void);
394 static rtx
arc_expand_builtin (tree
, rtx
, rtx
, machine_mode
, int);
396 static int branch_dest (rtx
);
398 static void arc_output_pic_addr_const (FILE *, rtx
, int);
399 void emit_pic_move (rtx
*, machine_mode
);
400 bool arc_legitimate_pic_operand_p (rtx
);
401 static bool arc_function_ok_for_sibcall (tree
, tree
);
402 static rtx
arc_function_value (const_tree
, const_tree
, bool);
403 const char * output_shift (rtx
*);
404 static void arc_reorg (void);
405 static bool arc_in_small_data_p (const_tree
);
407 static void arc_init_reg_tables (void);
408 static bool arc_return_in_memory (const_tree
, const_tree
);
409 static void arc_init_simd_builtins (void);
410 static bool arc_vector_mode_supported_p (machine_mode
);
412 static bool arc_can_use_doloop_p (const widest_int
&, const widest_int
&,
414 static const char *arc_invalid_within_doloop (const rtx_insn
*);
416 static void output_short_suffix (FILE *file
);
418 static bool arc_frame_pointer_required (void);
420 static bool arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT
,
422 enum by_pieces_operation op
,
425 /* Implements target hook vector_mode_supported_p. */
428 arc_vector_mode_supported_p (machine_mode mode
)
430 if (!TARGET_SIMD_SET
)
433 if ((mode
== V4SImode
)
434 || (mode
== V8HImode
))
441 /* TARGET_PRESERVE_RELOAD_P is still awaiting patch re-evaluation / review. */
442 static bool arc_preserve_reload_p (rtx in
) ATTRIBUTE_UNUSED
;
443 static rtx
arc_delegitimize_address (rtx
);
444 static bool arc_can_follow_jump (const rtx_insn
*follower
,
445 const rtx_insn
*followee
);
447 static rtx
frame_insn (rtx
);
448 static void arc_function_arg_advance (cumulative_args_t
, machine_mode
,
450 static rtx
arc_legitimize_address_0 (rtx
, rtx
, machine_mode mode
);
452 static void arc_finalize_pic (void);
454 /* initialize the GCC target structure. */
455 #undef TARGET_COMP_TYPE_ATTRIBUTES
456 #define TARGET_COMP_TYPE_ATTRIBUTES arc_comp_type_attributes
457 #undef TARGET_ASM_FILE_START
458 #define TARGET_ASM_FILE_START arc_file_start
459 #undef TARGET_ATTRIBUTE_TABLE
460 #define TARGET_ATTRIBUTE_TABLE arc_attribute_table
461 #undef TARGET_ASM_INTERNAL_LABEL
462 #define TARGET_ASM_INTERNAL_LABEL arc_internal_label
463 #undef TARGET_RTX_COSTS
464 #define TARGET_RTX_COSTS arc_rtx_costs
465 #undef TARGET_ADDRESS_COST
466 #define TARGET_ADDRESS_COST arc_address_cost
468 #undef TARGET_ENCODE_SECTION_INFO
469 #define TARGET_ENCODE_SECTION_INFO arc_encode_section_info
471 #undef TARGET_CANNOT_FORCE_CONST_MEM
472 #define TARGET_CANNOT_FORCE_CONST_MEM arc_cannot_force_const_mem
474 #undef TARGET_INIT_BUILTINS
475 #define TARGET_INIT_BUILTINS arc_init_builtins
477 #undef TARGET_EXPAND_BUILTIN
478 #define TARGET_EXPAND_BUILTIN arc_expand_builtin
480 #undef TARGET_ASM_OUTPUT_MI_THUNK
481 #define TARGET_ASM_OUTPUT_MI_THUNK arc_output_mi_thunk
483 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
484 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
486 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
487 #define TARGET_FUNCTION_OK_FOR_SIBCALL arc_function_ok_for_sibcall
489 #undef TARGET_MACHINE_DEPENDENT_REORG
490 #define TARGET_MACHINE_DEPENDENT_REORG arc_reorg
492 #undef TARGET_IN_SMALL_DATA_P
493 #define TARGET_IN_SMALL_DATA_P arc_in_small_data_p
495 #undef TARGET_PROMOTE_FUNCTION_MODE
496 #define TARGET_PROMOTE_FUNCTION_MODE \
497 default_promote_function_mode_always_promote
499 #undef TARGET_PROMOTE_PROTOTYPES
500 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
502 #undef TARGET_RETURN_IN_MEMORY
503 #define TARGET_RETURN_IN_MEMORY arc_return_in_memory
504 #undef TARGET_PASS_BY_REFERENCE
505 #define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
507 #undef TARGET_SETUP_INCOMING_VARARGS
508 #define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
510 #undef TARGET_ARG_PARTIAL_BYTES
511 #define TARGET_ARG_PARTIAL_BYTES arc_arg_partial_bytes
513 #undef TARGET_MUST_PASS_IN_STACK
514 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
516 #undef TARGET_FUNCTION_VALUE
517 #define TARGET_FUNCTION_VALUE arc_function_value
519 #undef TARGET_SCHED_ADJUST_PRIORITY
520 #define TARGET_SCHED_ADJUST_PRIORITY arc_sched_adjust_priority
522 #undef TARGET_VECTOR_MODE_SUPPORTED_P
523 #define TARGET_VECTOR_MODE_SUPPORTED_P arc_vector_mode_supported_p
525 #undef TARGET_CAN_USE_DOLOOP_P
526 #define TARGET_CAN_USE_DOLOOP_P arc_can_use_doloop_p
528 #undef TARGET_INVALID_WITHIN_DOLOOP
529 #define TARGET_INVALID_WITHIN_DOLOOP arc_invalid_within_doloop
531 #undef TARGET_PRESERVE_RELOAD_P
532 #define TARGET_PRESERVE_RELOAD_P arc_preserve_reload_p
534 #undef TARGET_CAN_FOLLOW_JUMP
535 #define TARGET_CAN_FOLLOW_JUMP arc_can_follow_jump
537 #undef TARGET_DELEGITIMIZE_ADDRESS
538 #define TARGET_DELEGITIMIZE_ADDRESS arc_delegitimize_address
540 #undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
541 #define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
542 arc_use_by_pieces_infrastructure_p
544 /* Usually, we will be able to scale anchor offsets.
545 When this fails, we want LEGITIMIZE_ADDRESS to kick in. */
546 #undef TARGET_MIN_ANCHOR_OFFSET
547 #define TARGET_MIN_ANCHOR_OFFSET (-1024)
548 #undef TARGET_MAX_ANCHOR_OFFSET
549 #define TARGET_MAX_ANCHOR_OFFSET (1020)
551 #undef TARGET_SECONDARY_RELOAD
552 #define TARGET_SECONDARY_RELOAD arc_secondary_reload
554 #define TARGET_OPTION_OVERRIDE arc_override_options
556 #define TARGET_CONDITIONAL_REGISTER_USAGE arc_conditional_register_usage
558 #define TARGET_TRAMPOLINE_INIT arc_initialize_trampoline
560 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS arc_trampoline_adjust_address
562 #define TARGET_CAN_ELIMINATE arc_can_eliminate
564 #define TARGET_FRAME_POINTER_REQUIRED arc_frame_pointer_required
566 #define TARGET_FUNCTION_ARG arc_function_arg
568 #define TARGET_FUNCTION_ARG_ADVANCE arc_function_arg_advance
570 #define TARGET_LEGITIMATE_CONSTANT_P arc_legitimate_constant_p
572 #define TARGET_LEGITIMATE_ADDRESS_P arc_legitimate_address_p
574 #define TARGET_MODE_DEPENDENT_ADDRESS_P arc_mode_dependent_address_p
576 #define TARGET_LEGITIMIZE_ADDRESS arc_legitimize_address
578 #define TARGET_ADJUST_INSN_LENGTH arc_adjust_insn_length
580 #define TARGET_INSN_LENGTH_PARAMETERS arc_insn_length_parameters
583 #define TARGET_LRA_P arc_lra_p
584 #define TARGET_REGISTER_PRIORITY arc_register_priority
585 /* Stores with scaled offsets have different displacement ranges. */
586 #define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
587 #define TARGET_SPILL_CLASS arc_spill_class
589 #include "target-def.h"
591 #undef TARGET_ASM_ALIGNED_HI_OP
592 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
593 #undef TARGET_ASM_ALIGNED_SI_OP
594 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
596 /* Try to keep the (mov:DF _, reg) as early as possible so
597 that the d<add/sub/mul>h-lr insns appear together and can
598 use the peephole2 pattern. */
601 arc_sched_adjust_priority (rtx_insn
*insn
, int priority
)
603 rtx set
= single_set (insn
);
605 && GET_MODE (SET_SRC(set
)) == DFmode
606 && GET_CODE (SET_SRC(set
)) == REG
)
608 /* Incrementing priority by 20 (empirically derived). */
609 return priority
+ 20;
616 arc_secondary_reload (bool in_p
, rtx x
, reg_class_t cl
, machine_mode
,
617 secondary_reload_info
*)
619 if (cl
== DOUBLE_REGS
)
622 /* The loop counter register can be stored, but not loaded directly. */
623 if ((cl
== LPCOUNT_REG
|| cl
== WRITABLE_CORE_REGS
)
624 && in_p
&& MEM_P (x
))
629 static unsigned arc_ifcvt (void);
633 const pass_data pass_data_arc_ifcvt
=
636 "arc_ifcvt", /* name */
637 OPTGROUP_NONE
, /* optinfo_flags */
638 TV_IFCVT2
, /* tv_id */
639 0, /* properties_required */
640 0, /* properties_provided */
641 0, /* properties_destroyed */
642 0, /* todo_flags_start */
643 TODO_df_finish
/* todo_flags_finish */
646 class pass_arc_ifcvt
: public rtl_opt_pass
649 pass_arc_ifcvt(gcc::context
*ctxt
)
650 : rtl_opt_pass(pass_data_arc_ifcvt
, ctxt
)
653 /* opt_pass methods: */
654 opt_pass
* clone () { return new pass_arc_ifcvt (m_ctxt
); }
655 virtual unsigned int execute (function
*) { return arc_ifcvt (); }
661 make_pass_arc_ifcvt (gcc::context
*ctxt
)
663 return new pass_arc_ifcvt (ctxt
);
666 static unsigned arc_predicate_delay_insns (void);
670 const pass_data pass_data_arc_predicate_delay_insns
=
673 "arc_predicate_delay_insns", /* name */
674 OPTGROUP_NONE
, /* optinfo_flags */
675 TV_IFCVT2
, /* tv_id */
676 0, /* properties_required */
677 0, /* properties_provided */
678 0, /* properties_destroyed */
679 0, /* todo_flags_start */
680 TODO_df_finish
/* todo_flags_finish */
683 class pass_arc_predicate_delay_insns
: public rtl_opt_pass
686 pass_arc_predicate_delay_insns(gcc::context
*ctxt
)
687 : rtl_opt_pass(pass_data_arc_predicate_delay_insns
, ctxt
)
690 /* opt_pass methods: */
691 virtual unsigned int execute (function
*)
693 return arc_predicate_delay_insns ();
700 make_pass_arc_predicate_delay_insns (gcc::context
*ctxt
)
702 return new pass_arc_predicate_delay_insns (ctxt
);
705 /* Called by OVERRIDE_OPTIONS to initialize various things. */
710 enum attr_tune tune_dflt
= TUNE_NONE
;
714 arc_cpu_string
= "A5";
716 else if (TARGET_ARC600
)
718 arc_cpu_string
= "ARC600";
719 tune_dflt
= TUNE_ARC600
;
721 else if (TARGET_ARC601
)
723 arc_cpu_string
= "ARC601";
724 tune_dflt
= TUNE_ARC600
;
726 else if (TARGET_ARC700
)
728 arc_cpu_string
= "ARC700";
729 tune_dflt
= TUNE_ARC700_4_2_STD
;
733 if (arc_tune
== TUNE_NONE
)
734 arc_tune
= tune_dflt
;
735 /* Note: arc_multcost is only used in rtx_cost if speed is true. */
736 if (arc_multcost
< 0)
739 case TUNE_ARC700_4_2_STD
:
741 max throughput (1 multiply + 4 other insns) / 5 cycles. */
742 arc_multcost
= COSTS_N_INSNS (4);
743 if (TARGET_NOMPY_SET
)
744 arc_multcost
= COSTS_N_INSNS (30);
746 case TUNE_ARC700_4_2_XMAC
:
748 max throughput (1 multiply + 2 other insns) / 3 cycles. */
749 arc_multcost
= COSTS_N_INSNS (3);
750 if (TARGET_NOMPY_SET
)
751 arc_multcost
= COSTS_N_INSNS (30);
754 if (TARGET_MUL64_SET
)
756 arc_multcost
= COSTS_N_INSNS (4);
761 arc_multcost
= COSTS_N_INSNS (30);
765 /* Support mul64 generation only for A5 and ARC600. */
766 if (TARGET_MUL64_SET
&& TARGET_ARC700
)
767 error ("-mmul64 not supported for ARC700");
769 /* MPY instructions valid only for ARC700. */
770 if (TARGET_NOMPY_SET
&& !TARGET_ARC700
)
771 error ("-mno-mpy supported only for ARC700");
773 /* mul/mac instructions only for ARC600. */
774 if (TARGET_MULMAC_32BY16_SET
&& !(TARGET_ARC600
|| TARGET_ARC601
))
775 error ("-mmul32x16 supported only for ARC600 or ARC601");
777 if (!TARGET_DPFP
&& TARGET_DPFP_DISABLE_LRSR
)
778 error ("-mno-dpfp-lrsr supported only with -mdpfp");
780 /* FPX-1. No fast and compact together. */
781 if ((TARGET_DPFP_FAST_SET
&& TARGET_DPFP_COMPACT_SET
)
782 || (TARGET_SPFP_FAST_SET
&& TARGET_SPFP_COMPACT_SET
))
783 error ("FPX fast and compact options cannot be specified together");
785 /* FPX-2. No fast-spfp for arc600 or arc601. */
786 if (TARGET_SPFP_FAST_SET
&& (TARGET_ARC600
|| TARGET_ARC601
))
787 error ("-mspfp_fast not available on ARC600 or ARC601");
789 /* FPX-3. No FPX extensions on pre-ARC600 cores. */
790 if ((TARGET_DPFP
|| TARGET_SPFP
)
791 && !(TARGET_ARC600
|| TARGET_ARC601
|| TARGET_ARC700
))
792 error ("FPX extensions not available on pre-ARC600 cores");
794 /* Warn for unimplemented PIC in pre-ARC700 cores, and disable flag_pic. */
795 if (flag_pic
&& !TARGET_ARC700
)
797 warning (DK_WARNING
, "PIC is not supported for %s. Generating non-PIC code only..", arc_cpu_string
);
801 arc_init_reg_tables ();
803 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
804 memset (arc_punct_chars
, 0, sizeof (arc_punct_chars
));
805 arc_punct_chars
['#'] = 1;
806 arc_punct_chars
['*'] = 1;
807 arc_punct_chars
['?'] = 1;
808 arc_punct_chars
['!'] = 1;
809 arc_punct_chars
['^'] = 1;
810 arc_punct_chars
['&'] = 1;
812 if (optimize
> 1 && !TARGET_NO_COND_EXEC
)
814 /* There are two target-independent ifcvt passes, and arc_reorg may do
815 one or more arc_ifcvt calls. */
816 opt_pass
*pass_arc_ifcvt_4
= make_pass_arc_ifcvt (g
);
817 struct register_pass_info arc_ifcvt4_info
818 = { pass_arc_ifcvt_4
, "dbr", 1, PASS_POS_INSERT_AFTER
};
819 struct register_pass_info arc_ifcvt5_info
820 = { pass_arc_ifcvt_4
->clone (), "shorten", 1, PASS_POS_INSERT_BEFORE
};
822 register_pass (&arc_ifcvt4_info
);
823 register_pass (&arc_ifcvt5_info
);
826 if (flag_delayed_branch
)
828 opt_pass
*pass_arc_predicate_delay_insns
829 = make_pass_arc_predicate_delay_insns (g
);
830 struct register_pass_info arc_predicate_delay_info
831 = { pass_arc_predicate_delay_insns
, "dbr", 1, PASS_POS_INSERT_AFTER
};
833 register_pass (&arc_predicate_delay_info
);
837 /* Check ARC options, generate derived target attributes. */
840 arc_override_options (void)
842 if (arc_cpu
== PROCESSOR_NONE
)
843 arc_cpu
= PROCESSOR_ARC700
;
845 if (arc_size_opt_level
== 3)
849 target_flags
|= MASK_NO_SDATA_SET
;
851 if (flag_no_common
== 255)
852 flag_no_common
= !TARGET_NO_SDATA_SET
;
854 /* TARGET_COMPACT_CASESI needs the "q" register class. */ \
855 if (TARGET_MIXED_CODE
)
858 TARGET_COMPACT_CASESI
= 0;
859 if (TARGET_COMPACT_CASESI
)
860 TARGET_CASE_VECTOR_PC_RELATIVE
= 1;
862 /* These need to be done at start up. It's convenient to do them here. */
866 /* The condition codes of the ARC, and the inverse function. */
867 /* For short branches, the "c" / "nc" names are not defined in the ARC
868 Programmers manual, so we have to use "lo" / "hs"" instead. */
869 static const char *arc_condition_codes
[] =
871 "al", 0, "eq", "ne", "p", "n", "lo", "hs", "v", "nv",
872 "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
875 enum arc_cc_code_index
877 ARC_CC_AL
, ARC_CC_EQ
= ARC_CC_AL
+2, ARC_CC_NE
, ARC_CC_P
, ARC_CC_N
,
878 ARC_CC_C
, ARC_CC_NC
, ARC_CC_V
, ARC_CC_NV
,
879 ARC_CC_GT
, ARC_CC_LE
, ARC_CC_GE
, ARC_CC_LT
, ARC_CC_HI
, ARC_CC_LS
, ARC_CC_PNZ
,
880 ARC_CC_LO
= ARC_CC_C
, ARC_CC_HS
= ARC_CC_NC
883 #define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
885 /* Returns the index of the ARC condition code string in
886 `arc_condition_codes'. COMPARISON should be an rtx like
887 `(eq (...) (...))'. */
890 get_arc_condition_code (rtx comparison
)
892 switch (GET_MODE (XEXP (comparison
, 0)))
895 case SImode
: /* For BRcc. */
896 switch (GET_CODE (comparison
))
898 case EQ
: return ARC_CC_EQ
;
899 case NE
: return ARC_CC_NE
;
900 case GT
: return ARC_CC_GT
;
901 case LE
: return ARC_CC_LE
;
902 case GE
: return ARC_CC_GE
;
903 case LT
: return ARC_CC_LT
;
904 case GTU
: return ARC_CC_HI
;
905 case LEU
: return ARC_CC_LS
;
906 case LTU
: return ARC_CC_LO
;
907 case GEU
: return ARC_CC_HS
;
908 default : gcc_unreachable ();
911 switch (GET_CODE (comparison
))
913 case EQ
: return ARC_CC_EQ
;
914 case NE
: return ARC_CC_NE
;
915 case GE
: return ARC_CC_P
;
916 case LT
: return ARC_CC_N
;
917 case GT
: return ARC_CC_PNZ
;
918 default : gcc_unreachable ();
921 switch (GET_CODE (comparison
))
923 case EQ
: return ARC_CC_EQ
;
924 case NE
: return ARC_CC_NE
;
925 default : gcc_unreachable ();
928 switch (GET_CODE (comparison
))
930 case LTU
: return ARC_CC_C
;
931 case GEU
: return ARC_CC_NC
;
932 default : gcc_unreachable ();
935 if (TARGET_ARGONAUT_SET
&& TARGET_SPFP
)
936 switch (GET_CODE (comparison
))
938 case GT
: return ARC_CC_N
;
939 case UNLE
: return ARC_CC_P
;
940 default : gcc_unreachable ();
943 switch (GET_CODE (comparison
))
945 case GT
: return ARC_CC_HI
;
946 case UNLE
: return ARC_CC_LS
;
947 default : gcc_unreachable ();
950 /* Same for FPX and non-FPX. */
951 switch (GET_CODE (comparison
))
953 case GE
: return ARC_CC_HS
;
954 case UNLT
: return ARC_CC_LO
;
955 default : gcc_unreachable ();
958 switch (GET_CODE (comparison
))
960 case UNEQ
: return ARC_CC_EQ
;
961 case LTGT
: return ARC_CC_NE
;
962 default : gcc_unreachable ();
965 switch (GET_CODE (comparison
))
967 case UNORDERED
: return ARC_CC_C
;
968 case ORDERED
: return ARC_CC_NC
;
969 default : gcc_unreachable ();
972 switch (GET_CODE (comparison
))
974 case EQ
: return ARC_CC_EQ
;
975 case NE
: return ARC_CC_NE
;
976 case UNORDERED
: return ARC_CC_C
;
977 case ORDERED
: return ARC_CC_NC
;
978 case LTGT
: return ARC_CC_HI
;
979 case UNEQ
: return ARC_CC_LS
;
980 default : gcc_unreachable ();
982 default : gcc_unreachable ();
988 /* Return true if COMPARISON has a short form that can accomodate OFFSET. */
991 arc_short_comparison_p (rtx comparison
, int offset
)
993 gcc_assert (ARC_CC_NC
== ARC_CC_HS
);
994 gcc_assert (ARC_CC_C
== ARC_CC_LO
);
995 switch (get_arc_condition_code (comparison
))
997 case ARC_CC_EQ
: case ARC_CC_NE
:
998 return offset
>= -512 && offset
<= 506;
999 case ARC_CC_GT
: case ARC_CC_LE
: case ARC_CC_GE
: case ARC_CC_LT
:
1000 case ARC_CC_HI
: case ARC_CC_LS
: case ARC_CC_LO
: case ARC_CC_HS
:
1001 return offset
>= -64 && offset
<= 58;
1007 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
1008 return the mode to be used for the comparison. */
1011 arc_select_cc_mode (enum rtx_code op
, rtx x
, rtx y
)
1013 machine_mode mode
= GET_MODE (x
);
1016 /* For an operation that sets the condition codes as a side-effect, the
1017 C and V flags is not set as for cmp, so we can only use comparisons where
1018 this doesn't matter. (For LT and GE we can use "mi" and "pl"
1020 /* ??? We could use "pnz" for greater than zero, however, we could then
1021 get into trouble because the comparison could not be reversed. */
1022 if (GET_MODE_CLASS (mode
) == MODE_INT
1024 && (op
== EQ
|| op
== NE
1025 || ((op
== LT
|| op
== GE
) && GET_MODE_SIZE (GET_MODE (x
)) <= 4)))
1028 /* add.f for if (a+b) */
1030 && GET_CODE (y
) == NEG
1031 && (op
== EQ
|| op
== NE
))
1034 /* Check if this is a test suitable for bxor.f . */
1035 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1036 && ((INTVAL (y
) - 1) & INTVAL (y
)) == 0
1040 /* Check if this is a test suitable for add / bmsk.f . */
1041 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1042 && GET_CODE (x
) == AND
&& CONST_INT_P ((x1
= XEXP (x
, 1)))
1043 && ((INTVAL (x1
) + 1) & INTVAL (x1
)) == 0
1044 && (~INTVAL (x1
) | INTVAL (y
)) < 0
1045 && (~INTVAL (x1
) | INTVAL (y
)) > -0x800)
1048 if (GET_MODE (x
) == SImode
&& (op
== LTU
|| op
== GEU
)
1049 && GET_CODE (x
) == PLUS
1050 && (rtx_equal_p (XEXP (x
, 0), y
) || rtx_equal_p (XEXP (x
, 1), y
)))
1053 if (TARGET_ARGONAUT_SET
1054 && ((mode
== SFmode
&& TARGET_SPFP
) || (mode
== DFmode
&& TARGET_DPFP
)))
1057 case EQ
: case NE
: case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1059 case LT
: case UNGE
: case GT
: case UNLE
:
1060 return CC_FP_GTmode
;
1061 case LE
: case UNGT
: case GE
: case UNLT
:
1062 return CC_FP_GEmode
;
1063 default: gcc_unreachable ();
1065 else if (GET_MODE_CLASS (mode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1068 case EQ
: case NE
: return CC_Zmode
;
1070 case GT
: case UNLE
: return CC_FP_GTmode
;
1072 case GE
: case UNLT
: return CC_FP_GEmode
;
1073 case UNEQ
: case LTGT
: return CC_FP_UNEQmode
;
1074 case ORDERED
: case UNORDERED
: return CC_FP_ORDmode
;
1075 default: gcc_unreachable ();
1081 /* Vectors to keep interesting information about registers where it can easily
1082 be got. We use to use the actual mode value as the bit number, but there
1083 is (or may be) more than 32 modes now. Instead we use two tables: one
1084 indexed by hard register number, and one indexed by mode. */
1086 /* The purpose of arc_mode_class is to shrink the range of modes so that
1087 they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
1088 mapped into one arc_mode_class mode. */
1090 enum arc_mode_class
{
1092 S_MODE
, D_MODE
, T_MODE
, O_MODE
,
1093 SF_MODE
, DF_MODE
, TF_MODE
, OF_MODE
,
1097 /* Modes for condition codes. */
1098 #define C_MODES (1 << (int) C_MODE)
1100 /* Modes for single-word and smaller quantities. */
1101 #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
1103 /* Modes for double-word and smaller quantities. */
1104 #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
1106 /* Mode for 8-byte DF values only. */
1107 #define DF_MODES (1 << DF_MODE)
1109 /* Modes for quad-word and smaller quantities. */
1110 #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
1112 /* Modes for 128-bit vectors. */
1113 #define V_MODES (1 << (int) V_MODE)
1115 /* Value is 1 if register/mode pair is acceptable on arc. */
1117 unsigned int arc_hard_regno_mode_ok
[] = {
1118 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1119 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1120 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, D_MODES
,
1121 D_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1123 /* ??? Leave these as S_MODES for now. */
1124 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1125 DF_MODES
, 0, DF_MODES
, 0, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1126 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1127 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, C_MODES
, S_MODES
,
1129 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1130 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1131 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1132 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1134 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1135 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1136 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1137 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1139 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1140 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
1143 unsigned int arc_mode_class
[NUM_MACHINE_MODES
];
1145 enum reg_class arc_regno_reg_class
[FIRST_PSEUDO_REGISTER
];
1148 arc_preferred_reload_class (rtx
, enum reg_class cl
)
1150 if ((cl
) == CHEAP_CORE_REGS
|| (cl
) == WRITABLE_CORE_REGS
)
1151 return GENERAL_REGS
;
1155 /* Initialize the arc_mode_class array. */
1158 arc_init_reg_tables (void)
1162 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
1164 machine_mode m
= (machine_mode
) i
;
1166 switch (GET_MODE_CLASS (m
))
1169 case MODE_PARTIAL_INT
:
1170 case MODE_COMPLEX_INT
:
1171 if (GET_MODE_SIZE (m
) <= 4)
1172 arc_mode_class
[i
] = 1 << (int) S_MODE
;
1173 else if (GET_MODE_SIZE (m
) == 8)
1174 arc_mode_class
[i
] = 1 << (int) D_MODE
;
1175 else if (GET_MODE_SIZE (m
) == 16)
1176 arc_mode_class
[i
] = 1 << (int) T_MODE
;
1177 else if (GET_MODE_SIZE (m
) == 32)
1178 arc_mode_class
[i
] = 1 << (int) O_MODE
;
1180 arc_mode_class
[i
] = 0;
1183 case MODE_COMPLEX_FLOAT
:
1184 if (GET_MODE_SIZE (m
) <= 4)
1185 arc_mode_class
[i
] = 1 << (int) SF_MODE
;
1186 else if (GET_MODE_SIZE (m
) == 8)
1187 arc_mode_class
[i
] = 1 << (int) DF_MODE
;
1188 else if (GET_MODE_SIZE (m
) == 16)
1189 arc_mode_class
[i
] = 1 << (int) TF_MODE
;
1190 else if (GET_MODE_SIZE (m
) == 32)
1191 arc_mode_class
[i
] = 1 << (int) OF_MODE
;
1193 arc_mode_class
[i
] = 0;
1195 case MODE_VECTOR_INT
:
1196 arc_mode_class
[i
] = (1<< (int) V_MODE
);
1200 /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
1201 we must explicitly check for them here. */
1202 if (i
== (int) CCmode
|| i
== (int) CC_ZNmode
|| i
== (int) CC_Zmode
1203 || i
== (int) CC_Cmode
1204 || i
== CC_FP_GTmode
|| i
== CC_FP_GEmode
|| i
== CC_FP_ORDmode
)
1205 arc_mode_class
[i
] = 1 << (int) C_MODE
;
1207 arc_mode_class
[i
] = 0;
1213 /* Core registers 56..59 are used for multiply extension options.
1214 The dsp option uses r56 and r57, these are then named acc1 and acc2.
1215 acc1 is the highpart, and acc2 the lowpart, so which register gets which
1216 number depends on endianness.
1217 The mul64 multiplier options use r57 for mlo, r58 for mmid and r59 for mhi.
1218 Because mlo / mhi form a 64 bit value, we use different gcc internal
1219 register numbers to make them form a register pair as the gcc internals
1220 know it. mmid gets number 57, if still available, and mlo / mhi get
1221 number 58 and 59, depending on endianness. We use DBX_REGISTER_NUMBER
1222 to map this back. */
1223 char rname56
[5] = "r56";
1224 char rname57
[5] = "r57";
1225 char rname58
[5] = "r58";
1226 char rname59
[5] = "r59";
1229 arc_conditional_register_usage (void)
1233 int fix_start
= 60, fix_end
= 55;
1235 if (TARGET_MUL64_SET
)
1240 /* We don't provide a name for mmed. In rtl / assembly resource lists,
1241 you are supposed to refer to it as mlo & mhi, e.g
1242 (zero_extract:SI (reg:DI 58) (const_int 32) (16)) .
1243 In an actual asm instruction, you are of course use mmed.
1244 The point of avoiding having a separate register for mmed is that
1245 this way, we don't have to carry clobbers of that reg around in every
1246 isntruction that modifies mlo and/or mhi. */
1247 strcpy (rname57
, "");
1248 strcpy (rname58
, TARGET_BIG_ENDIAN
? "mhi" : "mlo");
1249 strcpy (rname59
, TARGET_BIG_ENDIAN
? "mlo" : "mhi");
1251 if (TARGET_MULMAC_32BY16_SET
)
1254 fix_end
= fix_end
> 57 ? fix_end
: 57;
1255 strcpy (rname56
, TARGET_BIG_ENDIAN
? "acc1" : "acc2");
1256 strcpy (rname57
, TARGET_BIG_ENDIAN
? "acc2" : "acc1");
1258 for (regno
= fix_start
; regno
<= fix_end
; regno
++)
1260 if (!fixed_regs
[regno
])
1261 warning (0, "multiply option implies r%d is fixed", regno
);
1262 fixed_regs
[regno
] = call_used_regs
[regno
] = 1;
1266 reg_alloc_order
[2] = 12;
1267 reg_alloc_order
[3] = 13;
1268 reg_alloc_order
[4] = 14;
1269 reg_alloc_order
[5] = 15;
1270 reg_alloc_order
[6] = 1;
1271 reg_alloc_order
[7] = 0;
1272 reg_alloc_order
[8] = 4;
1273 reg_alloc_order
[9] = 5;
1274 reg_alloc_order
[10] = 6;
1275 reg_alloc_order
[11] = 7;
1276 reg_alloc_order
[12] = 8;
1277 reg_alloc_order
[13] = 9;
1278 reg_alloc_order
[14] = 10;
1279 reg_alloc_order
[15] = 11;
1281 if (TARGET_SIMD_SET
)
1284 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1285 reg_alloc_order
[i
] = i
;
1286 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1287 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1288 reg_alloc_order
[i
] = i
;
1290 /* For Arctangent-A5 / ARC600, lp_count may not be read in an instruction
1291 following immediately after another one setting it to a new value.
1292 There was some discussion on how to enforce scheduling constraints for
1293 processors with missing interlocks on the gcc mailing list:
1294 http://gcc.gnu.org/ml/gcc/2008-05/msg00021.html .
1295 However, we can't actually use this approach, because for ARC the
1296 delay slot scheduling pass is active, which runs after
1297 machine_dependent_reorg. */
1299 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1300 else if (!TARGET_ARC700
)
1301 fixed_regs
[LP_COUNT
] = 1;
1302 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
1303 if (!call_used_regs
[regno
])
1304 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], regno
);
1305 for (regno
= 32; regno
< 60; regno
++)
1306 if (!fixed_regs
[regno
])
1307 SET_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], regno
);
1310 for (regno
= 32; regno
<= 60; regno
++)
1311 CLEAR_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], regno
);
1313 /* If they have used -ffixed-lp_count, make sure it takes
1315 if (fixed_regs
[LP_COUNT
])
1317 CLEAR_HARD_REG_BIT (reg_class_contents
[LPCOUNT_REG
], LP_COUNT
);
1318 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1319 CLEAR_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], LP_COUNT
);
1321 /* Instead of taking out SF_MODE like below, forbid it outright. */
1322 arc_hard_regno_mode_ok
[60] = 0;
1325 arc_hard_regno_mode_ok
[60] = 1 << (int) S_MODE
;
1328 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1332 if (TARGET_Q_CLASS
&& ((i
<= 3) || ((i
>= 12) && (i
<= 15))))
1333 arc_regno_reg_class
[i
] = ARCOMPACT16_REGS
;
1335 arc_regno_reg_class
[i
] = GENERAL_REGS
;
1338 arc_regno_reg_class
[i
]
1340 ? (TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
)
1341 ? CHEAP_CORE_REGS
: ALL_CORE_REGS
)
1343 && TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
))
1344 ? CHEAP_CORE_REGS
: WRITABLE_CORE_REGS
));
1346 arc_regno_reg_class
[i
] = NO_REGS
;
1349 /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS has not been activated. */
1350 if (!TARGET_Q_CLASS
)
1352 CLEAR_HARD_REG_SET(reg_class_contents
[ARCOMPACT16_REGS
]);
1353 CLEAR_HARD_REG_SET(reg_class_contents
[AC16_BASE_REGS
]);
1356 gcc_assert (FIRST_PSEUDO_REGISTER
>= 144);
1358 /* Handle Special Registers. */
1359 arc_regno_reg_class
[29] = LINK_REGS
; /* ilink1 register. */
1360 arc_regno_reg_class
[30] = LINK_REGS
; /* ilink2 register. */
1361 arc_regno_reg_class
[31] = LINK_REGS
; /* blink register. */
1362 arc_regno_reg_class
[60] = LPCOUNT_REG
;
1363 arc_regno_reg_class
[61] = NO_REGS
; /* CC_REG: must be NO_REGS. */
1364 arc_regno_reg_class
[62] = GENERAL_REGS
;
1368 for (i
= 40; i
< 44; ++i
)
1370 arc_regno_reg_class
[i
] = DOUBLE_REGS
;
1372 /* Unless they want us to do 'mov d1, 0x00000000' make sure
1373 no attempt is made to use such a register as a destination
1374 operand in *movdf_insn. */
1375 if (!TARGET_ARGONAUT_SET
)
1377 /* Make sure no 'c', 'w', 'W', or 'Rac' constraint is
1378 interpreted to mean they can use D1 or D2 in their insn. */
1379 CLEAR_HARD_REG_BIT(reg_class_contents
[CHEAP_CORE_REGS
], i
);
1380 CLEAR_HARD_REG_BIT(reg_class_contents
[ALL_CORE_REGS
], i
);
1381 CLEAR_HARD_REG_BIT(reg_class_contents
[WRITABLE_CORE_REGS
], i
);
1382 CLEAR_HARD_REG_BIT(reg_class_contents
[MPY_WRITABLE_CORE_REGS
], i
);
1388 /* Disable all DOUBLE_REGISTER settings,
1389 if not generating DPFP code. */
1390 arc_regno_reg_class
[40] = ALL_REGS
;
1391 arc_regno_reg_class
[41] = ALL_REGS
;
1392 arc_regno_reg_class
[42] = ALL_REGS
;
1393 arc_regno_reg_class
[43] = ALL_REGS
;
1395 arc_hard_regno_mode_ok
[40] = 0;
1396 arc_hard_regno_mode_ok
[42] = 0;
1398 CLEAR_HARD_REG_SET(reg_class_contents
[DOUBLE_REGS
]);
1401 if (TARGET_SIMD_SET
)
1403 gcc_assert (ARC_FIRST_SIMD_VR_REG
== 64);
1404 gcc_assert (ARC_LAST_SIMD_VR_REG
== 127);
1406 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1407 arc_regno_reg_class
[i
] = SIMD_VR_REGS
;
1409 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_REG
== 128);
1410 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
== 128);
1411 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
== 136);
1412 gcc_assert (ARC_LAST_SIMD_DMA_CONFIG_REG
== 143);
1414 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1415 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1416 arc_regno_reg_class
[i
] = SIMD_DMA_CONFIG_REGS
;
1420 arc_regno_reg_class
[PROGRAM_COUNTER_REGNO
] = GENERAL_REGS
;
1423 /* Handle an "interrupt" attribute; arguments as in
1424 struct attribute_spec.handler. */
1427 arc_handle_interrupt_attribute (tree
*, tree name
, tree args
, int,
1432 tree value
= TREE_VALUE (args
);
1434 if (TREE_CODE (value
) != STRING_CST
)
1436 warning (OPT_Wattributes
,
1437 "argument of %qE attribute is not a string constant",
1439 *no_add_attrs
= true;
1441 else if (strcmp (TREE_STRING_POINTER (value
), "ilink1")
1442 && strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1444 warning (OPT_Wattributes
,
1445 "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
1447 *no_add_attrs
= true;
1452 /* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
1453 and two if they are nearly compatible (which causes a warning to be
1457 arc_comp_type_attributes (const_tree type1
,
1460 int l1
, l2
, m1
, m2
, s1
, s2
;
1462 /* Check for mismatch of non-default calling convention. */
1463 if (TREE_CODE (type1
) != FUNCTION_TYPE
)
1466 /* Check for mismatched call attributes. */
1467 l1
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1468 l2
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1469 m1
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1470 m2
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1471 s1
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1472 s2
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1474 /* Only bother to check if an attribute is defined. */
1475 if (l1
| l2
| m1
| m2
| s1
| s2
)
1477 /* If one type has an attribute, the other must have the same attribute. */
1478 if ((l1
!= l2
) || (m1
!= m2
) || (s1
!= s2
))
1481 /* Disallow mixed attributes. */
1482 if (l1
+ m1
+ s1
> 1)
1490 /* Set the default attributes for TYPE. */
1493 arc_set_default_type_attributes (tree type ATTRIBUTE_UNUSED
)
1498 /* Misc. utilities. */
1500 /* X and Y are two things to compare using CODE. Emit the compare insn and
1501 return the rtx for the cc reg in the proper mode. */
1504 gen_compare_reg (rtx comparison
, machine_mode omode
)
1506 enum rtx_code code
= GET_CODE (comparison
);
1507 rtx x
= XEXP (comparison
, 0);
1508 rtx y
= XEXP (comparison
, 1);
1510 machine_mode mode
, cmode
;
1513 cmode
= GET_MODE (x
);
1514 if (cmode
== VOIDmode
)
1515 cmode
= GET_MODE (y
);
1516 gcc_assert (cmode
== SImode
|| cmode
== SFmode
|| cmode
== DFmode
);
1517 if (cmode
== SImode
)
1519 if (!register_operand (x
, SImode
))
1521 if (register_operand (y
, SImode
))
1526 code
= swap_condition (code
);
1529 x
= copy_to_mode_reg (SImode
, x
);
1531 if (GET_CODE (y
) == SYMBOL_REF
&& flag_pic
)
1532 y
= copy_to_mode_reg (SImode
, y
);
1536 x
= force_reg (cmode
, x
);
1537 y
= force_reg (cmode
, y
);
1539 mode
= SELECT_CC_MODE (code
, x
, y
);
1541 cc_reg
= gen_rtx_REG (mode
, CC_REG
);
1543 /* ??? FIXME (x-y)==0, as done by both cmpsfpx_raw and
1544 cmpdfpx_raw, is not a correct comparison for floats:
1545 http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
1547 if (TARGET_ARGONAUT_SET
1548 && ((cmode
== SFmode
&& TARGET_SPFP
) || (cmode
== DFmode
&& TARGET_DPFP
)))
1552 case NE
: case EQ
: case LT
: case UNGE
: case LE
: case UNGT
:
1553 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1555 case GT
: case UNLE
: case GE
: case UNLT
:
1556 code
= swap_condition (code
);
1564 if (cmode
== SFmode
)
1566 emit_insn (gen_cmpsfpx_raw (x
, y
));
1570 /* Accepts Dx regs directly by insns. */
1571 emit_insn (gen_cmpdfpx_raw (x
, y
));
1574 if (mode
!= CC_FPXmode
)
1575 emit_insn (gen_rtx_SET (VOIDmode
, cc_reg
,
1576 gen_rtx_COMPARE (mode
,
1577 gen_rtx_REG (CC_FPXmode
, 61),
1580 else if (GET_MODE_CLASS (cmode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1582 rtx op0
= gen_rtx_REG (cmode
, 0);
1583 rtx op1
= gen_rtx_REG (cmode
, GET_MODE_SIZE (cmode
) / UNITS_PER_WORD
);
1587 case NE
: case EQ
: case GT
: case UNLE
: case GE
: case UNLT
:
1588 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1590 case LT
: case UNGE
: case LE
: case UNGT
:
1591 code
= swap_condition (code
);
1599 if (currently_expanding_to_rtl
)
1601 emit_move_insn (op0
, x
);
1602 emit_move_insn (op1
, y
);
1606 gcc_assert (rtx_equal_p (op0
, x
));
1607 gcc_assert (rtx_equal_p (op1
, y
));
1609 emit_insn (gen_cmp_float (cc_reg
, gen_rtx_COMPARE (mode
, op0
, op1
)));
1612 emit_insn (gen_rtx_SET (omode
, cc_reg
,
1613 gen_rtx_COMPARE (mode
, x
, y
)));
1614 return gen_rtx_fmt_ee (code
, omode
, cc_reg
, const0_rtx
);
1617 /* Return true if VALUE, a const_double, will fit in a limm (4 byte number).
1618 We assume the value can be either signed or unsigned. */
1621 arc_double_limm_p (rtx value
)
1623 HOST_WIDE_INT low
, high
;
1625 gcc_assert (GET_CODE (value
) == CONST_DOUBLE
);
1630 low
= CONST_DOUBLE_LOW (value
);
1631 high
= CONST_DOUBLE_HIGH (value
);
1633 if (low
& 0x80000000)
1635 return (((unsigned HOST_WIDE_INT
) low
<= 0xffffffff && high
== 0)
1636 || (((low
& - (unsigned HOST_WIDE_INT
) 0x80000000)
1637 == - (unsigned HOST_WIDE_INT
) 0x80000000)
1642 return (unsigned HOST_WIDE_INT
) low
<= 0x7fffffff && high
== 0;
1646 /* Do any needed setup for a variadic function. For the ARC, we must
1647 create a register parameter block, and then copy any anonymous arguments
1648 in registers to memory.
1650 CUM has not been updated for the last named argument which has type TYPE
1651 and mode MODE, and we rely on this fact. */
1654 arc_setup_incoming_varargs (cumulative_args_t args_so_far
,
1655 machine_mode mode
, tree type
,
1656 int *pretend_size
, int no_rtl
)
1659 CUMULATIVE_ARGS next_cum
;
1661 /* We must treat `__builtin_va_alist' as an anonymous arg. */
1663 next_cum
= *get_cumulative_args (args_so_far
);
1664 arc_function_arg_advance (pack_cumulative_args (&next_cum
), mode
, type
, 1);
1665 first_anon_arg
= next_cum
;
1667 if (first_anon_arg
< MAX_ARC_PARM_REGS
)
1669 /* First anonymous (unnamed) argument is in a reg. */
1671 /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
1672 int first_reg_offset
= first_anon_arg
;
1677 = gen_rtx_MEM (BLKmode
, plus_constant (Pmode
, arg_pointer_rtx
,
1678 FIRST_PARM_OFFSET (0)));
1679 move_block_from_reg (first_reg_offset
, regblock
,
1680 MAX_ARC_PARM_REGS
- first_reg_offset
);
1684 = ((MAX_ARC_PARM_REGS
- first_reg_offset
) * UNITS_PER_WORD
);
1688 /* Cost functions. */
1690 /* Provide the costs of an addressing mode that contains ADDR.
1691 If ADDR is not a valid address, its cost is irrelevant. */
1694 arc_address_cost (rtx addr
, machine_mode
, addr_space_t
, bool speed
)
1696 switch (GET_CODE (addr
))
1699 return speed
|| satisfies_constraint_Rcq (addr
) ? 0 : 1;
1700 case PRE_INC
: case PRE_DEC
: case POST_INC
: case POST_DEC
:
1701 case PRE_MODIFY
: case POST_MODIFY
:
1707 /* Most likely needs a LIMM. */
1708 return COSTS_N_INSNS (1);
1712 register rtx plus0
= XEXP (addr
, 0);
1713 register rtx plus1
= XEXP (addr
, 1);
1715 if (GET_CODE (plus0
) != REG
1716 && (GET_CODE (plus0
) != MULT
1717 || !CONST_INT_P (XEXP (plus0
, 1))
1718 || (INTVAL (XEXP (plus0
, 1)) != 2
1719 && INTVAL (XEXP (plus0
, 1)) != 4)))
1722 switch (GET_CODE (plus1
))
1725 return (!RTX_OK_FOR_OFFSET_P (SImode
, plus1
)
1729 : (satisfies_constraint_Rcq (plus0
)
1730 && satisfies_constraint_O (plus1
))
1734 return (speed
< 1 ? 0
1735 : (satisfies_constraint_Rcq (plus0
)
1736 && satisfies_constraint_Rcq (plus1
))
1741 return COSTS_N_INSNS (1);
1754 /* Emit instruction X with the frame related bit set. */
1760 RTX_FRAME_RELATED_P (x
) = 1;
1764 /* Emit a frame insn to move SRC to DST. */
1767 frame_move (rtx dst
, rtx src
)
1769 return frame_insn (gen_rtx_SET (VOIDmode
, dst
, src
));
1772 /* Like frame_move, but add a REG_INC note for REG if ADDR contains an
1773 auto increment address, or is zero. */
1776 frame_move_inc (rtx dst
, rtx src
, rtx reg
, rtx addr
)
1778 rtx insn
= frame_move (dst
, src
);
1781 || GET_CODE (addr
) == PRE_DEC
|| GET_CODE (addr
) == POST_INC
1782 || GET_CODE (addr
) == PRE_MODIFY
|| GET_CODE (addr
) == POST_MODIFY
)
1783 add_reg_note (insn
, REG_INC
, reg
);
1787 /* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
1790 frame_add (rtx reg
, HOST_WIDE_INT offset
)
1792 gcc_assert ((offset
& 0x3) == 0);
1795 return frame_move (reg
, plus_constant (Pmode
, reg
, offset
));
1798 /* Emit a frame insn which adjusts stack pointer by OFFSET. */
1801 frame_stack_add (HOST_WIDE_INT offset
)
1803 return frame_add (stack_pointer_rtx
, offset
);
1806 /* Traditionally, we push saved registers first in the prologue,
1807 then we allocate the rest of the frame - and reverse in the epilogue.
1808 This has still its merits for ease of debugging, or saving code size
1809 or even execution time if the stack frame is so large that some accesses
1810 can't be encoded anymore with offsets in the instruction code when using
1812 Also, it would be a good starting point if we got instructions to help
1813 with register save/restore.
1815 However, often stack frames are small, and the pushing / popping has
1817 - the stack modification prevents a lot of scheduling.
1818 - frame allocation / deallocation needs extra instructions.
1819 - unless we know that we compile ARC700 user code, we need to put
1820 a memory barrier after frame allocation / before deallocation to
1821 prevent interrupts clobbering our data in the frame.
1822 In particular, we don't have any such guarantees for library functions,
1823 which tend to, on the other hand, to have small frames.
1825 Thus, for small frames, we'd like to use a different scheme:
1826 - The frame is allocated in full with the first prologue instruction,
1827 and deallocated in full with the last epilogue instruction.
1828 Thus, the instructions in-betwen can be freely scheduled.
1829 - If the function has no outgoing arguments on the stack, we can allocate
1830 one register save slot at the top of the stack. This register can then
1831 be saved simultanously with frame allocation, and restored with
1833 This register can be picked depending on scheduling considerations,
1834 although same though should go into having some set of registers
1835 to be potentially lingering after a call, and others to be available
1836 immediately - i.e. in the absence of interprocedual optimization, we
1837 can use an ABI-like convention for register allocation to reduce
1838 stalls after function return. */
1839 /* Function prologue/epilogue handlers. */
1841 /* ARCompact stack frames look like:
1843 Before call After call
1844 high +-----------------------+ +-----------------------+
1845 mem | reg parm save area | | reg parm save area |
1846 | only created for | | only created for |
1847 | variable arg fns | | variable arg fns |
1848 AP +-----------------------+ +-----------------------+
1849 | return addr register | | return addr register |
1850 | (if required) | | (if required) |
1851 +-----------------------+ +-----------------------+
1853 | reg save area | | reg save area |
1855 +-----------------------+ +-----------------------+
1856 | frame pointer | | frame pointer |
1857 | (if required) | | (if required) |
1858 FP +-----------------------+ +-----------------------+
1860 | local/temp variables | | local/temp variables |
1862 +-----------------------+ +-----------------------+
1864 | arguments on stack | | arguments on stack |
1866 SP +-----------------------+ +-----------------------+
1867 | reg parm save area |
1868 | only created for |
1869 | variable arg fns |
1870 AP +-----------------------+
1871 | return addr register |
1873 +-----------------------+
1877 +-----------------------+
1880 FP +-----------------------+
1882 | local/temp variables |
1884 +-----------------------+
1886 | arguments on stack |
1888 mem SP +-----------------------+
1891 1) The "reg parm save area" does not exist for non variable argument fns.
1892 The "reg parm save area" can be eliminated completely if we created our
1893 own va-arc.h, but that has tradeoffs as well (so it's not done). */
1895 /* Structure to be filled in by arc_compute_frame_size with register
1896 save masks, and offsets for the current function. */
1897 struct GTY (()) arc_frame_info
1899 unsigned int total_size
; /* # bytes that the entire frame takes up. */
1900 unsigned int extra_size
; /* # bytes of extra stuff. */
1901 unsigned int pretend_size
; /* # bytes we push and pretend caller did. */
1902 unsigned int args_size
; /* # bytes that outgoing arguments take up. */
1903 unsigned int reg_size
; /* # bytes needed to store regs. */
1904 unsigned int var_size
; /* # bytes that variables take up. */
1905 unsigned int reg_offset
; /* Offset from new sp to store regs. */
1906 unsigned int gmask
; /* Mask of saved gp registers. */
1907 int initialized
; /* Nonzero if frame size already calculated. */
1908 short millicode_start_reg
;
1909 short millicode_end_reg
;
1910 bool save_return_addr
;
1913 /* Defining data structures for per-function information. */
1915 typedef struct GTY (()) machine_function
1917 enum arc_function_type fn_type
;
1918 struct arc_frame_info frame_info
;
1919 /* To keep track of unalignment caused by short insns. */
1921 int force_short_suffix
; /* Used when disgorging return delay slot insns. */
1922 const char *size_reason
;
1923 struct arc_ccfsm ccfsm_current
;
1924 /* Map from uid to ccfsm state during branch shortening. */
1925 rtx ccfsm_current_insn
;
1926 char arc_reorg_started
;
1927 char prescan_initialized
;
1930 /* Type of function DECL.
1932 The result is cached. To reset the cache at the end of a function,
1933 call with DECL = NULL_TREE. */
1935 enum arc_function_type
1936 arc_compute_function_type (struct function
*fun
)
1938 tree decl
= fun
->decl
;
1940 enum arc_function_type fn_type
= fun
->machine
->fn_type
;
1942 if (fn_type
!= ARC_FUNCTION_UNKNOWN
)
1945 /* Assume we have a normal function (not an interrupt handler). */
1946 fn_type
= ARC_FUNCTION_NORMAL
;
1948 /* Now see if this is an interrupt handler. */
1949 for (a
= DECL_ATTRIBUTES (decl
);
1953 tree name
= TREE_PURPOSE (a
), args
= TREE_VALUE (a
);
1955 if (name
== get_identifier ("interrupt")
1956 && list_length (args
) == 1
1957 && TREE_CODE (TREE_VALUE (args
)) == STRING_CST
)
1959 tree value
= TREE_VALUE (args
);
1961 if (!strcmp (TREE_STRING_POINTER (value
), "ilink1"))
1962 fn_type
= ARC_FUNCTION_ILINK1
;
1963 else if (!strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1964 fn_type
= ARC_FUNCTION_ILINK2
;
1971 return fun
->machine
->fn_type
= fn_type
;
1974 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
1975 #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
1977 /* Tell prologue and epilogue if register REGNO should be saved / restored.
1978 The return address and frame pointer are treated separately.
1979 Don't consider them here.
1980 Addition for pic: The gp register needs to be saved if the current
1981 function changes it to access gotoff variables.
1982 FIXME: This will not be needed if we used some arbitrary register
1985 #define MUST_SAVE_REGISTER(regno, interrupt_p) \
1986 (((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
1987 && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p))) \
1988 || (flag_pic && crtl->uses_pic_offset_table \
1989 && regno == PIC_OFFSET_TABLE_REGNUM) )
1991 #define MUST_SAVE_RETURN_ADDR \
1992 (cfun->machine->frame_info.save_return_addr)
1994 /* Return non-zero if there are registers to be saved or loaded using
1995 millicode thunks. We can only use consecutive sequences starting
1996 with r13, and not going beyond r25.
1997 GMASK is a bitmask of registers to save. This function sets
1998 FRAME->millicod_start_reg .. FRAME->millicode_end_reg to the range
1999 of registers to be saved / restored with a millicode call. */
2002 arc_compute_millicode_save_restore_regs (unsigned int gmask
,
2003 struct arc_frame_info
*frame
)
2007 int start_reg
= 13, end_reg
= 25;
2009 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1L << regno
));)
2011 end_reg
= regno
- 1;
2012 /* There is no point in using millicode thunks if we don't save/restore
2013 at least three registers. For non-leaf functions we also have the
2015 if (regno
- start_reg
>= 3 - (crtl
->is_leaf
== 0))
2017 frame
->millicode_start_reg
= 13;
2018 frame
->millicode_end_reg
= regno
- 1;
2024 /* Return the bytes needed to compute the frame pointer from the current
2027 SIZE is the size needed for local variables. */
2030 arc_compute_frame_size (int size
) /* size = # of var. bytes allocated. */
2033 unsigned int total_size
, var_size
, args_size
, pretend_size
, extra_size
;
2034 unsigned int reg_size
, reg_offset
;
2036 enum arc_function_type fn_type
;
2038 struct arc_frame_info
*frame_info
= &cfun
->machine
->frame_info
;
2040 size
= ARC_STACK_ALIGN (size
);
2042 /* 1) Size of locals and temporaries */
2045 /* 2) Size of outgoing arguments */
2046 args_size
= crtl
->outgoing_args_size
;
2048 /* 3) Calculate space needed for saved registers.
2049 ??? We ignore the extension registers for now. */
2051 /* See if this is an interrupt handler. Call used registers must be saved
2056 fn_type
= arc_compute_function_type (cfun
);
2057 interrupt_p
= ARC_INTERRUPT_P (fn_type
);
2059 for (regno
= 0; regno
<= 31; regno
++)
2061 if (MUST_SAVE_REGISTER (regno
, interrupt_p
))
2063 reg_size
+= UNITS_PER_WORD
;
2064 gmask
|= 1 << regno
;
2068 /* 4) Space for back trace data structure.
2069 <return addr reg size> (if required) + <fp size> (if required). */
2070 frame_info
->save_return_addr
2071 = (!crtl
->is_leaf
|| df_regs_ever_live_p (RETURN_ADDR_REGNUM
));
2072 /* Saving blink reg in case of leaf function for millicode thunk calls. */
2073 if (optimize_size
&& !TARGET_NO_MILLICODE_THUNK_SET
)
2075 if (arc_compute_millicode_save_restore_regs (gmask
, frame_info
))
2076 frame_info
->save_return_addr
= true;
2080 if (MUST_SAVE_RETURN_ADDR
)
2082 if (frame_pointer_needed
)
2085 /* 5) Space for variable arguments passed in registers */
2086 pretend_size
= crtl
->args
.pretend_args_size
;
2088 /* Ensure everything before the locals is aligned appropriately. */
2090 unsigned int extra_plus_reg_size
;
2091 unsigned int extra_plus_reg_size_aligned
;
2093 extra_plus_reg_size
= extra_size
+ reg_size
;
2094 extra_plus_reg_size_aligned
= ARC_STACK_ALIGN(extra_plus_reg_size
);
2095 reg_size
= extra_plus_reg_size_aligned
- extra_size
;
2098 /* Compute total frame size. */
2099 total_size
= var_size
+ args_size
+ extra_size
+ pretend_size
+ reg_size
;
2101 total_size
= ARC_STACK_ALIGN (total_size
);
2103 /* Compute offset of register save area from stack pointer:
2104 A5 Frame: pretend_size <blink> reg_size <fp> var_size args_size <--sp
2106 reg_offset
= (total_size
- (pretend_size
+ reg_size
+ extra_size
)
2107 + (frame_pointer_needed
? 4 : 0));
2109 /* Save computed information. */
2110 frame_info
->total_size
= total_size
;
2111 frame_info
->extra_size
= extra_size
;
2112 frame_info
->pretend_size
= pretend_size
;
2113 frame_info
->var_size
= var_size
;
2114 frame_info
->args_size
= args_size
;
2115 frame_info
->reg_size
= reg_size
;
2116 frame_info
->reg_offset
= reg_offset
;
2117 frame_info
->gmask
= gmask
;
2118 frame_info
->initialized
= reload_completed
;
2120 /* Ok, we're done. */
2124 /* Common code to save/restore registers. */
2125 /* BASE_REG is the base register to use for addressing and to adjust.
2126 GMASK is a bitmask of general purpose registers to save/restore.
2127 epilogue_p 0: prologue 1:epilogue 2:epilogue, sibling thunk
2128 If *FIRST_OFFSET is non-zero, add it first to BASE_REG - preferably
2129 using a pre-modify for the first memory access. *FIRST_OFFSET is then
2133 arc_save_restore (rtx base_reg
,
2134 unsigned int gmask
, int epilogue_p
, int *first_offset
)
2136 unsigned int offset
= 0;
2138 struct arc_frame_info
*frame
= &cfun
->machine
->frame_info
;
2139 rtx sibthunk_insn
= NULL_RTX
;
2143 /* Millicode thunks implementation:
2144 Generates calls to millicodes for registers starting from r13 to r25
2145 Present Limitations:
2146 - Only one range supported. The remaining regs will have the ordinary
2147 st and ld instructions for store and loads. Hence a gmask asking
2148 to store r13-14, r16-r25 will only generate calls to store and
2149 load r13 to r14 while store and load insns will be generated for
2150 r16 to r25 in the prologue and epilogue respectively.
2152 - Presently library only supports register ranges starting from r13.
2154 if (epilogue_p
== 2 || frame
->millicode_end_reg
> 14)
2156 int start_call
= frame
->millicode_start_reg
;
2157 int end_call
= frame
->millicode_end_reg
;
2158 int n_regs
= end_call
- start_call
+ 1;
2159 int i
= 0, r
, off
= 0;
2161 rtx ret_addr
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2165 /* "reg_size" won't be more than 127 . */
2166 gcc_assert (epilogue_p
|| abs (*first_offset
) <= 127);
2167 frame_add (base_reg
, *first_offset
);
2170 insn
= gen_rtx_PARALLEL
2171 (VOIDmode
, rtvec_alloc ((epilogue_p
== 2) + n_regs
+ 1));
2172 if (epilogue_p
== 2)
2175 XVECEXP (insn
, 0, n_regs
) = gen_rtx_CLOBBER (VOIDmode
, ret_addr
);
2176 for (r
= start_call
; r
<= end_call
; r
++, off
+= UNITS_PER_WORD
, i
++)
2178 rtx reg
= gen_rtx_REG (SImode
, r
);
2180 = gen_frame_mem (SImode
, plus_constant (Pmode
, base_reg
, off
));
2183 XVECEXP (insn
, 0, i
) = gen_rtx_SET (VOIDmode
, reg
, mem
);
2185 XVECEXP (insn
, 0, i
) = gen_rtx_SET (VOIDmode
, mem
, reg
);
2186 gmask
= gmask
& ~(1L << r
);
2188 if (epilogue_p
== 2)
2189 sibthunk_insn
= insn
;
2195 for (regno
= 0; regno
<= 31; regno
++)
2197 if ((gmask
& (1L << regno
)) != 0)
2199 rtx reg
= gen_rtx_REG (SImode
, regno
);
2204 gcc_assert (!offset
);
2205 addr
= plus_constant (Pmode
, base_reg
, *first_offset
);
2206 addr
= gen_rtx_PRE_MODIFY (Pmode
, base_reg
, addr
);
2211 gcc_assert (SMALL_INT (offset
));
2212 addr
= plus_constant (Pmode
, base_reg
, offset
);
2214 mem
= gen_frame_mem (SImode
, addr
);
2216 frame_move_inc (reg
, mem
, base_reg
, addr
);
2218 frame_move_inc (mem
, reg
, base_reg
, addr
);
2219 offset
+= UNITS_PER_WORD
;
2225 rtx r12
= gen_rtx_REG (Pmode
, 12);
2227 frame_insn (gen_rtx_SET (VOIDmode
, r12
, GEN_INT (offset
)));
2228 XVECEXP (sibthunk_insn
, 0, 0) = ret_rtx
;
2229 XVECEXP (sibthunk_insn
, 0, 1)
2230 = gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
2231 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, r12
));
2232 sibthunk_insn
= emit_jump_insn (sibthunk_insn
);
2233 RTX_FRAME_RELATED_P (sibthunk_insn
) = 1;
2235 } /* arc_save_restore */
2238 int arc_return_address_regs
[4]
2239 = {0, RETURN_ADDR_REGNUM
, ILINK1_REGNUM
, ILINK2_REGNUM
};
2241 /* Set up the stack and frame pointer (if desired) for the function. */
2244 arc_expand_prologue (void)
2246 int size
= get_frame_size ();
2247 unsigned int gmask
= cfun
->machine
->frame_info
.gmask
;
2248 /* unsigned int frame_pointer_offset;*/
2249 unsigned int frame_size_to_allocate
;
2250 /* (FIXME: The first store will use a PRE_MODIFY; this will usually be r13.
2251 Change the stack layout so that we rather store a high register with the
2252 PRE_MODIFY, thus enabling more short insn generation.) */
2253 int first_offset
= 0;
2255 size
= ARC_STACK_ALIGN (size
);
2257 /* Compute/get total frame size. */
2258 size
= (!cfun
->machine
->frame_info
.initialized
2259 ? arc_compute_frame_size (size
)
2260 : cfun
->machine
->frame_info
.total_size
);
2262 if (flag_stack_usage_info
)
2263 current_function_static_stack_size
= size
;
2265 /* Keep track of frame size to be allocated. */
2266 frame_size_to_allocate
= size
;
2268 /* These cases shouldn't happen. Catch them now. */
2269 gcc_assert (!(size
== 0 && gmask
));
2271 /* Allocate space for register arguments if this is a variadic function. */
2272 if (cfun
->machine
->frame_info
.pretend_size
!= 0)
2274 /* Ensure pretend_size is maximum of 8 * word_size. */
2275 gcc_assert (cfun
->machine
->frame_info
.pretend_size
<= 32);
2277 frame_stack_add (-(HOST_WIDE_INT
)cfun
->machine
->frame_info
.pretend_size
);
2278 frame_size_to_allocate
-= cfun
->machine
->frame_info
.pretend_size
;
2281 /* The home-grown ABI says link register is saved first. */
2282 if (MUST_SAVE_RETURN_ADDR
)
2284 rtx ra
= gen_rtx_REG (SImode
, RETURN_ADDR_REGNUM
);
2285 rtx mem
= gen_frame_mem (Pmode
, gen_rtx_PRE_DEC (Pmode
, stack_pointer_rtx
));
2287 frame_move_inc (mem
, ra
, stack_pointer_rtx
, 0);
2288 frame_size_to_allocate
-= UNITS_PER_WORD
;
2290 } /* MUST_SAVE_RETURN_ADDR */
2292 /* Save any needed call-saved regs (and call-used if this is an
2293 interrupt handler) for ARCompact ISA. */
2294 if (cfun
->machine
->frame_info
.reg_size
)
2296 first_offset
= -cfun
->machine
->frame_info
.reg_size
;
2297 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
2298 arc_save_restore (stack_pointer_rtx
, gmask
, 0, &first_offset
);
2299 frame_size_to_allocate
-= cfun
->machine
->frame_info
.reg_size
;
2303 /* Save frame pointer if needed. */
2304 if (frame_pointer_needed
)
2306 rtx addr
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
2307 GEN_INT (-UNITS_PER_WORD
+ first_offset
));
2308 rtx mem
= gen_frame_mem (Pmode
, gen_rtx_PRE_MODIFY (Pmode
,
2311 frame_move_inc (mem
, frame_pointer_rtx
, stack_pointer_rtx
, 0);
2312 frame_size_to_allocate
-= UNITS_PER_WORD
;
2314 frame_move (frame_pointer_rtx
, stack_pointer_rtx
);
2317 /* ??? We don't handle the case where the saved regs are more than 252
2318 bytes away from sp. This can be handled by decrementing sp once, saving
2319 the regs, and then decrementing it again. The epilogue doesn't have this
2320 problem as the `ld' insn takes reg+limm values (though it would be more
2321 efficient to avoid reg+limm). */
2323 frame_size_to_allocate
-= first_offset
;
2324 /* Allocate the stack frame. */
2325 if (frame_size_to_allocate
> 0)
2326 frame_stack_add ((HOST_WIDE_INT
) 0 - frame_size_to_allocate
);
2328 /* Setup the gp register, if needed. */
2329 if (crtl
->uses_pic_offset_table
)
2330 arc_finalize_pic ();
2333 /* Do any necessary cleanup after a function to restore stack, frame,
2337 arc_expand_epilogue (int sibcall_p
)
2339 int size
= get_frame_size ();
2340 enum arc_function_type fn_type
= arc_compute_function_type (cfun
);
2342 size
= ARC_STACK_ALIGN (size
);
2343 size
= (!cfun
->machine
->frame_info
.initialized
2344 ? arc_compute_frame_size (size
)
2345 : cfun
->machine
->frame_info
.total_size
);
2347 unsigned int pretend_size
= cfun
->machine
->frame_info
.pretend_size
;
2348 unsigned int frame_size
;
2349 unsigned int size_to_deallocate
;
2351 int can_trust_sp_p
= !cfun
->calls_alloca
;
2352 int first_offset
= 0;
2353 int millicode_p
= cfun
->machine
->frame_info
.millicode_end_reg
> 0;
2355 size_to_deallocate
= size
;
2357 frame_size
= size
- (pretend_size
+
2358 cfun
->machine
->frame_info
.reg_size
+
2359 cfun
->machine
->frame_info
.extra_size
);
2361 /* ??? There are lots of optimizations that can be done here.
2362 EG: Use fp to restore regs if it's closer.
2363 Maybe in time we'll do them all. For now, always restore regs from
2364 sp, but don't restore sp if we don't have to. */
2366 if (!can_trust_sp_p
)
2367 gcc_assert (frame_pointer_needed
);
2369 /* Restore stack pointer to the beginning of saved register area for
2373 if (frame_pointer_needed
)
2374 frame_move (stack_pointer_rtx
, frame_pointer_rtx
);
2376 first_offset
= frame_size
;
2377 size_to_deallocate
-= frame_size
;
2379 else if (!can_trust_sp_p
)
2380 frame_stack_add (-frame_size
);
2383 /* Restore any saved registers. */
2384 if (frame_pointer_needed
)
2386 rtx addr
= gen_rtx_POST_INC (Pmode
, stack_pointer_rtx
);
2388 frame_move_inc (frame_pointer_rtx
, gen_frame_mem (Pmode
, addr
),
2389 stack_pointer_rtx
, 0);
2390 size_to_deallocate
-= UNITS_PER_WORD
;
2393 /* Load blink after the calls to thunk calls in case of optimize size. */
2396 int sibthunk_p
= (!sibcall_p
2397 && fn_type
== ARC_FUNCTION_NORMAL
2398 && !cfun
->machine
->frame_info
.pretend_size
);
2400 gcc_assert (!(cfun
->machine
->frame_info
.gmask
2401 & (FRAME_POINTER_MASK
| RETURN_ADDR_MASK
)));
2402 arc_save_restore (stack_pointer_rtx
,
2403 cfun
->machine
->frame_info
.gmask
,
2404 1 + sibthunk_p
, &first_offset
);
2408 /* If we are to restore registers, and first_offset would require
2409 a limm to be encoded in a PRE_MODIFY, yet we can add it with a
2410 fast add to the stack pointer, do this now. */
2411 if ((!SMALL_INT (first_offset
)
2412 && cfun
->machine
->frame_info
.gmask
2413 && ((TARGET_ARC700
&& !optimize_size
)
2414 ? first_offset
<= 0x800
2415 : satisfies_constraint_C2a (GEN_INT (first_offset
))))
2416 /* Also do this if we have both gprs and return
2417 address to restore, and they both would need a LIMM. */
2418 || (MUST_SAVE_RETURN_ADDR
2419 && !SMALL_INT ((cfun
->machine
->frame_info
.reg_size
+ first_offset
) >> 2)
2420 && cfun
->machine
->frame_info
.gmask
))
2422 frame_stack_add (first_offset
);
2425 if (MUST_SAVE_RETURN_ADDR
)
2427 rtx ra
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2428 int ra_offs
= cfun
->machine
->frame_info
.reg_size
+ first_offset
;
2429 rtx addr
= plus_constant (Pmode
, stack_pointer_rtx
, ra_offs
);
2431 /* If the load of blink would need a LIMM, but we can add
2432 the offset quickly to sp, do the latter. */
2433 if (!SMALL_INT (ra_offs
>> 2)
2434 && !cfun
->machine
->frame_info
.gmask
2435 && ((TARGET_ARC700
&& !optimize_size
)
2437 : satisfies_constraint_C2a (GEN_INT (ra_offs
))))
2439 size_to_deallocate
-= ra_offs
- first_offset
;
2441 frame_stack_add (ra_offs
);
2443 addr
= stack_pointer_rtx
;
2445 /* See if we can combine the load of the return address with the
2446 final stack adjustment.
2447 We need a separate load if there are still registers to
2448 restore. We also want a separate load if the combined insn
2449 would need a limm, but a separate load doesn't. */
2451 && !cfun
->machine
->frame_info
.gmask
2452 && (SMALL_INT (ra_offs
) || !SMALL_INT (ra_offs
>> 2)))
2454 addr
= gen_rtx_PRE_MODIFY (Pmode
, stack_pointer_rtx
, addr
);
2456 size_to_deallocate
-= cfun
->machine
->frame_info
.reg_size
;
2458 else if (!ra_offs
&& size_to_deallocate
== UNITS_PER_WORD
)
2460 addr
= gen_rtx_POST_INC (Pmode
, addr
);
2461 size_to_deallocate
= 0;
2463 frame_move_inc (ra
, gen_frame_mem (Pmode
, addr
), stack_pointer_rtx
, addr
);
2468 if (cfun
->machine
->frame_info
.reg_size
)
2469 arc_save_restore (stack_pointer_rtx
,
2470 /* The zeroing of these two bits is unnecessary, but leave this in for clarity. */
2471 cfun
->machine
->frame_info
.gmask
2472 & ~(FRAME_POINTER_MASK
| RETURN_ADDR_MASK
), 1, &first_offset
);
2476 /* The rest of this function does the following:
2477 ARCompact : handle epilogue_delay, restore sp (phase-2), return
2480 /* Keep track of how much of the stack pointer we've restored.
2481 It makes the following a lot more readable. */
2482 size_to_deallocate
+= first_offset
;
2483 restored
= size
- size_to_deallocate
;
2485 if (size
> restored
)
2486 frame_stack_add (size
- restored
);
2487 /* Emit the return instruction. */
2488 if (sibcall_p
== FALSE
)
2489 emit_jump_insn (gen_simple_return ());
2491 if (!TARGET_EPILOGUE_CFI
)
2495 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
2496 RTX_FRAME_RELATED_P (insn
) = 0;
2500 /* Return the offset relative to the stack pointer where the return address
2501 is stored, or -1 if it is not stored. */
2504 arc_return_slot_offset ()
2506 struct arc_frame_info
*afi
= &cfun
->machine
->frame_info
;
2508 return (afi
->save_return_addr
2509 ? afi
->total_size
- afi
->pretend_size
- afi
->extra_size
: -1);
2514 /* Emit special PIC prologues and epilogues. */
2515 /* If the function has any GOTOFF relocations, then the GOTBASE
2516 register has to be setup in the prologue
2517 The instruction needed at the function start for setting up the
2520 ----------------------------------------------------------
2521 The rtl to be emitted for this should be:
2524 (const (unspec (symref _DYNAMIC) 3)))
2525 ---------------------------------------------------------- */
2528 arc_finalize_pic (void)
2531 rtx baseptr_rtx
= gen_rtx_REG (Pmode
, PIC_OFFSET_TABLE_REGNUM
);
2533 if (crtl
->uses_pic_offset_table
== 0)
2536 gcc_assert (flag_pic
!= 0);
2538 pat
= gen_rtx_SYMBOL_REF (Pmode
, "_DYNAMIC");
2539 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, pat
), ARC_UNSPEC_GOT
);
2540 pat
= gen_rtx_CONST (Pmode
, pat
);
2542 pat
= gen_rtx_SET (VOIDmode
, baseptr_rtx
, pat
);
2547 /* !TARGET_BARREL_SHIFTER support. */
2548 /* Emit a shift insn to set OP0 to OP1 shifted by OP2; CODE specifies what
2552 emit_shift (enum rtx_code code
, rtx op0
, rtx op1
, rtx op2
)
2554 rtx shift
= gen_rtx_fmt_ee (code
, SImode
, op1
, op2
);
2556 = ((shift4_operator (shift
, SImode
) ? gen_shift_si3
: gen_shift_si3_loop
)
2557 (op0
, op1
, op2
, shift
));
2561 /* Output the assembler code for doing a shift.
2562 We go to a bit of trouble to generate efficient code as the ARC601 only has
2563 single bit shifts. This is taken from the h8300 port. We only have one
2564 mode of shifting and can't access individual bytes like the h8300 can, so
2565 this is greatly simplified (at the expense of not generating hyper-
2568 This function is not used if the variable shift insns are present. */
2570 /* FIXME: This probably can be done using a define_split in arc.md.
2571 Alternately, generate rtx rather than output instructions. */
2574 output_shift (rtx
*operands
)
2576 /* static int loopend_lab;*/
2577 rtx shift
= operands
[3];
2578 machine_mode mode
= GET_MODE (shift
);
2579 enum rtx_code code
= GET_CODE (shift
);
2580 const char *shift_one
;
2582 gcc_assert (mode
== SImode
);
2586 case ASHIFT
: shift_one
= "add %0,%1,%1"; break;
2587 case ASHIFTRT
: shift_one
= "asr %0,%1"; break;
2588 case LSHIFTRT
: shift_one
= "lsr %0,%1"; break;
2589 default: gcc_unreachable ();
2592 if (GET_CODE (operands
[2]) != CONST_INT
)
2594 output_asm_insn ("and.f lp_count,%2, 0x1f", operands
);
2601 n
= INTVAL (operands
[2]);
2603 /* Only consider the lower 5 bits of the shift count. */
2606 /* First see if we can do them inline. */
2607 /* ??? We could get better scheduling & shorter code (using short insns)
2608 by using splitters. Alas, that'd be even more verbose. */
2609 if (code
== ASHIFT
&& n
<= 9 && n
> 2
2610 && dest_reg_operand (operands
[4], SImode
))
2612 output_asm_insn ("mov %4,0\n\tadd3 %0,%4,%1", operands
);
2613 for (n
-=3 ; n
>= 3; n
-= 3)
2614 output_asm_insn ("add3 %0,%4,%0", operands
);
2616 output_asm_insn ("add2 %0,%4,%0", operands
);
2618 output_asm_insn ("add %0,%0,%0", operands
);
2624 output_asm_insn (shift_one
, operands
);
2625 operands
[1] = operands
[0];
2628 /* See if we can use a rotate/and. */
2629 else if (n
== BITS_PER_WORD
- 1)
2634 output_asm_insn ("and %0,%1,1\n\tror %0,%0", operands
);
2637 /* The ARC doesn't have a rol insn. Use something else. */
2638 output_asm_insn ("add.f 0,%1,%1\n\tsbc %0,%0,%0", operands
);
2641 /* The ARC doesn't have a rol insn. Use something else. */
2642 output_asm_insn ("add.f 0,%1,%1\n\trlc %0,0", operands
);
2648 else if (n
== BITS_PER_WORD
- 2 && dest_reg_operand (operands
[4], SImode
))
2653 output_asm_insn ("and %0,%1,3\n\tror %0,%0\n\tror %0,%0", operands
);
2656 #if 1 /* Need some scheduling comparisons. */
2657 output_asm_insn ("add.f %4,%1,%1\n\tsbc %0,%0,%0\n\t"
2658 "add.f 0,%4,%4\n\trlc %0,%0", operands
);
2660 output_asm_insn ("add.f %4,%1,%1\n\tbxor %0,%4,31\n\t"
2661 "sbc.f %0,%0,%4\n\trlc %0,%0", operands
);
2666 output_asm_insn ("add.f %4,%1,%1\n\trlc %0,0\n\t"
2667 "add.f 0,%4,%4\n\trlc %0,%0", operands
);
2669 output_asm_insn ("add.f %0,%1,%1\n\trlc.f %0,0\n\t"
2670 "and %0,%0,1\n\trlc %0,%0", operands
);
2677 else if (n
== BITS_PER_WORD
- 3 && code
== ASHIFT
)
2678 output_asm_insn ("and %0,%1,7\n\tror %0,%0\n\tror %0,%0\n\tror %0,%0",
2683 operands
[2] = GEN_INT (n
);
2684 output_asm_insn ("mov.f lp_count, %2", operands
);
2688 output_asm_insn ("lpnz\t2f", operands
);
2689 output_asm_insn (shift_one
, operands
);
2690 output_asm_insn ("nop", operands
);
2691 fprintf (asm_out_file
, "2:\t%s end single insn loop\n",
2700 /* Nested function support. */
2702 /* Directly store VALUE into memory object BLOCK at OFFSET. */
2705 emit_store_direct (rtx block
, int offset
, int value
)
2707 emit_insn (gen_store_direct (adjust_address (block
, SImode
, offset
),
2709 gen_int_mode (value
, SImode
))));
2712 /* Emit RTL insns to initialize the variable parts of a trampoline.
2713 FNADDR is an RTX for the address of the function's pure code.
2714 CXT is an RTX for the static chain value for the function. */
2715 /* With potentially multiple shared objects loaded, and multiple stacks
2716 present for multiple thereds where trampolines might reside, a simple
2717 range check will likely not suffice for the profiler to tell if a callee
2718 is a trampoline. We a speedier check by making the trampoline start at
2719 an address that is not 4-byte aligned.
2720 A trampoline looks like this:
2724 ld_s r12,[pcl,12] 0xd403
2725 ld r11,[pcl,12] 0x170c 700b
2729 The fastest trampoline to execute for trampolines within +-8KB of CTX
2732 j [limm] 0x20200f80 limm
2733 and that would also be faster to write to the stack by computing the offset
2734 from CTX to TRAMP at compile time. However, it would really be better to
2735 get rid of the high cost of cache invalidation when generating trampolines,
2736 which requires that the code part of trampolines stays constant, and
2738 - making sure that no executable code but trampolines is on the stack,
2739 no icache entries linger for the area of the stack from when before the
2740 stack was allocated, and allocating trampolines in trampoline-only
2743 - allocate trampolines fram a special pool of pre-allocated trampolines. */
2746 arc_initialize_trampoline (rtx tramp
, tree fndecl
, rtx cxt
)
2748 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2750 emit_store_direct (tramp
, 0, TARGET_BIG_ENDIAN
? 0x78e0d403 : 0xd40378e0);
2751 emit_store_direct (tramp
, 4, TARGET_BIG_ENDIAN
? 0x170c700b : 0x700b170c);
2752 emit_store_direct (tramp
, 8, TARGET_BIG_ENDIAN
? 0x7c0078e0 : 0x78e07c00);
2753 emit_move_insn (adjust_address (tramp
, SImode
, 12), fnaddr
);
2754 emit_move_insn (adjust_address (tramp
, SImode
, 16), cxt
);
2755 emit_insn (gen_flush_icache (adjust_address (tramp
, SImode
, 0)));
2758 /* Allow the profiler to easily distinguish trampolines from normal
2762 arc_trampoline_adjust_address (rtx addr
)
2764 return plus_constant (Pmode
, addr
, 2);
2767 /* This is set briefly to 1 when we output a ".as" address modifer, and then
2768 reset when we output the scaled address. */
2769 static int output_scaled
= 0;
2771 /* Print operand X (an rtx) in assembler syntax to file FILE.
2772 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2773 For `%' followed by punctuation, CODE is the punctuation and X is null. */
2774 /* In final.c:output_asm_insn:
2777 'c' : constant address if CONSTANT_ADDRESS_P
2783 '#': condbranch delay slot suffix
2784 '*': jump delay slot suffix
2785 '?' : nonjump-insn suffix for conditional execution or short instruction
2786 '!' : jump / call suffix for conditional execution or short instruction
2787 '`': fold constant inside unary o-perator, re-recognize, and emit.
2792 'B': Branch comparison operand - suppress sda reference
2793 'H': Most significant word
2794 'L': Least significant word
2795 'A': ASCII decimal representation of floating point value
2796 'U': Load/store update or scaling indicator
2797 'V': cache bypass indicator for volatile
2802 'o': original symbol - no @ prepending. */
2805 arc_print_operand (FILE *file
, rtx x
, int code
)
2810 if (GET_CODE (x
) == CONST_INT
)
2811 fprintf (file
, "%d",exact_log2(INTVAL (x
) + 1) - 1 );
2813 output_operand_lossage ("invalid operand to %%Z code");
2818 if (GET_CODE (x
) == CONST_INT
)
2819 fprintf (file
, "%d",exact_log2(INTVAL (x
)) );
2821 output_operand_lossage ("invalid operand to %%z code");
2826 if (GET_CODE (x
) == CONST_INT
)
2827 fprintf (file
, "%d",exact_log2(~INTVAL (x
)) );
2829 output_operand_lossage ("invalid operand to %%M code");
2834 /* Conditional branches depending on condition codes.
2835 Note that this is only for branches that were known to depend on
2836 condition codes before delay slot scheduling;
2837 out-of-range brcc / bbit expansions should use '*'.
2838 This distinction is important because of the different
2839 allowable delay slot insns and the output of the delay suffix
2840 for TARGET_AT_DBR_COND_EXEC. */
2842 /* Unconditional branches / branches not depending on condition codes.
2843 This could also be a CALL_INSN.
2844 Output the appropriate delay slot suffix. */
2845 if (final_sequence
&& final_sequence
->len () != 1)
2847 rtx_insn
*jump
= final_sequence
->insn (0);
2848 rtx_insn
*delay
= final_sequence
->insn (1);
2850 /* For TARGET_PAD_RETURN we might have grabbed the delay insn. */
2851 if (delay
->deleted ())
2853 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
2854 fputs (INSN_FROM_TARGET_P (delay
) ? ".d"
2855 : TARGET_AT_DBR_CONDEXEC
&& code
== '#' ? ".d"
2856 : get_attr_type (jump
) == TYPE_RETURN
&& code
== '#' ? ""
2863 case '?' : /* with leading "." */
2864 case '!' : /* without leading "." */
2865 /* This insn can be conditionally executed. See if the ccfsm machinery
2866 says it should be conditionalized.
2867 If it shouldn't, we'll check the compact attribute if this insn
2868 has a short variant, which may be used depending on code size and
2869 alignment considerations. */
2870 if (current_insn_predicate
)
2871 arc_ccfsm_current
.cc
2872 = get_arc_condition_code (current_insn_predicate
);
2873 if (ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
))
2875 /* Is this insn in a delay slot sequence? */
2876 if (!final_sequence
|| XVECLEN (final_sequence
, 0) < 2
2877 || current_insn_predicate
2878 || CALL_P (final_sequence
->insn (0))
2879 || simplejump_p (final_sequence
->insn (0)))
2881 /* This insn isn't in a delay slot sequence, or conditionalized
2882 independently of its position in a delay slot. */
2883 fprintf (file
, "%s%s",
2884 code
== '?' ? "." : "",
2885 arc_condition_codes
[arc_ccfsm_current
.cc
]);
2886 /* If this is a jump, there are still short variants. However,
2887 only beq_s / bne_s have the same offset range as b_s,
2888 and the only short conditional returns are jeq_s and jne_s. */
2890 && (arc_ccfsm_current
.cc
== ARC_CC_EQ
2891 || arc_ccfsm_current
.cc
== ARC_CC_NE
2892 || 0 /* FIXME: check if branch in 7 bit range. */))
2893 output_short_suffix (file
);
2895 else if (code
== '!') /* Jump with delay slot. */
2896 fputs (arc_condition_codes
[arc_ccfsm_current
.cc
], file
);
2897 else /* An Instruction in a delay slot of a jump or call. */
2899 rtx jump
= XVECEXP (final_sequence
, 0, 0);
2900 rtx insn
= XVECEXP (final_sequence
, 0, 1);
2902 /* If the insn is annulled and is from the target path, we need
2903 to inverse the condition test. */
2904 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
2906 if (INSN_FROM_TARGET_P (insn
))
2907 fprintf (file
, "%s%s",
2908 code
== '?' ? "." : "",
2909 arc_condition_codes
[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current
.cc
)]);
2911 fprintf (file
, "%s%s",
2912 code
== '?' ? "." : "",
2913 arc_condition_codes
[arc_ccfsm_current
.cc
]);
2914 if (arc_ccfsm_current
.state
== 5)
2915 arc_ccfsm_current
.state
= 0;
2918 /* This insn is executed for either path, so don't
2919 conditionalize it at all. */
2920 output_short_suffix (file
);
2925 output_short_suffix (file
);
2928 /* FIXME: fold constant inside unary operator, re-recognize, and emit. */
2931 fputs (arc_condition_codes
[get_arc_condition_code (x
)], file
);
2934 fputs (arc_condition_codes
[ARC_INVERSE_CONDITION_CODE
2935 (get_arc_condition_code (x
))],
2939 /* Write second word of DImode or DFmode reference,
2940 register or memory. */
2941 if (GET_CODE (x
) == REG
)
2942 fputs (reg_names
[REGNO (x
)+1], file
);
2943 else if (GET_CODE (x
) == MEM
)
2947 /* Handle possible auto-increment. For PRE_INC / PRE_DEC /
2948 PRE_MODIFY, we will have handled the first word already;
2949 For POST_INC / POST_DEC / POST_MODIFY, the access to the
2950 first word will be done later. In either case, the access
2951 to the first word will do the modify, and we only have
2952 to add an offset of four here. */
2953 if (GET_CODE (XEXP (x
, 0)) == PRE_INC
2954 || GET_CODE (XEXP (x
, 0)) == PRE_DEC
2955 || GET_CODE (XEXP (x
, 0)) == PRE_MODIFY
2956 || GET_CODE (XEXP (x
, 0)) == POST_INC
2957 || GET_CODE (XEXP (x
, 0)) == POST_DEC
2958 || GET_CODE (XEXP (x
, 0)) == POST_MODIFY
)
2959 output_address (plus_constant (Pmode
, XEXP (XEXP (x
, 0), 0), 4));
2960 else if (output_scaled
)
2962 rtx addr
= XEXP (x
, 0);
2963 int size
= GET_MODE_SIZE (GET_MODE (x
));
2965 output_address (plus_constant (Pmode
, XEXP (addr
, 0),
2966 ((INTVAL (XEXP (addr
, 1)) + 4)
2967 >> (size
== 2 ? 1 : 2))));
2971 output_address (plus_constant (Pmode
, XEXP (x
, 0), 4));
2975 output_operand_lossage ("invalid operand to %%R code");
2978 /* FIXME: remove %S option. */
2980 case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
2983 output_addr_const (file
, x
);
2989 if (GET_CODE (x
) == REG
)
2991 /* L = least significant word, H = most significant word. */
2992 if ((WORDS_BIG_ENDIAN
!= 0) ^ (code
== 'L'))
2993 fputs (reg_names
[REGNO (x
)], file
);
2995 fputs (reg_names
[REGNO (x
)+1], file
);
2997 else if (GET_CODE (x
) == CONST_INT
2998 || GET_CODE (x
) == CONST_DOUBLE
)
3002 split_double (x
, &first
, &second
);
3004 if((WORDS_BIG_ENDIAN
) == 0)
3005 fprintf (file
, "0x%08" PRIx64
,
3006 code
== 'L' ? INTVAL (first
) : INTVAL (second
));
3008 fprintf (file
, "0x%08" PRIx64
,
3009 code
== 'L' ? INTVAL (second
) : INTVAL (first
));
3014 output_operand_lossage ("invalid operand to %%H/%%L code");
3020 gcc_assert (GET_CODE (x
) == CONST_DOUBLE
3021 && GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
);
3023 real_to_decimal (str
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (str
), 0, 1);
3024 fprintf (file
, "%s", str
);
3028 /* Output a load/store with update indicator if appropriate. */
3029 if (GET_CODE (x
) == MEM
)
3031 rtx addr
= XEXP (x
, 0);
3032 switch (GET_CODE (addr
))
3034 case PRE_INC
: case PRE_DEC
: case PRE_MODIFY
:
3035 fputs (".a", file
); break;
3036 case POST_INC
: case POST_DEC
: case POST_MODIFY
:
3037 fputs (".ab", file
); break;
3039 /* Are we using a scaled index? */
3040 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3041 fputs (".as", file
);
3042 /* Can we use a scaled offset? */
3043 else if (CONST_INT_P (XEXP (addr
, 1))
3044 && GET_MODE_SIZE (GET_MODE (x
)) > 1
3045 && (!(INTVAL (XEXP (addr
, 1))
3046 & (GET_MODE_SIZE (GET_MODE (x
)) - 1) & 3))
3047 /* Does it make a difference? */
3048 && !SMALL_INT_RANGE(INTVAL (XEXP (addr
, 1)),
3049 GET_MODE_SIZE (GET_MODE (x
)) - 2, 0))
3051 fputs (".as", file
);
3058 gcc_assert (CONSTANT_P (addr
)); break;
3062 output_operand_lossage ("invalid operand to %%U code");
3065 /* Output cache bypass indicator for a load/store insn. Volatile memory
3066 refs are defined to use the cache bypass mechanism. */
3067 if (GET_CODE (x
) == MEM
)
3069 if (MEM_VOLATILE_P (x
) && !TARGET_VOLATILE_CACHE_SET
)
3070 fputs (".di", file
);
3073 output_operand_lossage ("invalid operand to %%V code");
3078 /* Do nothing special. */
3081 fputs (reg_names
[REGNO (x
)]+1, file
);
3084 /* This punctuation character is needed because label references are
3085 printed in the output template using %l. This is a front end
3086 character, and when we want to emit a '@' before it, we have to use
3092 /* Output an operator. */
3093 switch (GET_CODE (x
))
3095 case PLUS
: fputs ("add", file
); return;
3096 case SS_PLUS
: fputs ("adds", file
); return;
3097 case AND
: fputs ("and", file
); return;
3098 case IOR
: fputs ("or", file
); return;
3099 case XOR
: fputs ("xor", file
); return;
3100 case MINUS
: fputs ("sub", file
); return;
3101 case SS_MINUS
: fputs ("subs", file
); return;
3102 case ASHIFT
: fputs ("asl", file
); return;
3103 case ASHIFTRT
: fputs ("asr", file
); return;
3104 case LSHIFTRT
: fputs ("lsr", file
); return;
3105 case ROTATERT
: fputs ("ror", file
); return;
3106 case MULT
: fputs ("mpy", file
); return;
3107 case ABS
: fputs ("abs", file
); return; /* Unconditional. */
3108 case NEG
: fputs ("neg", file
); return;
3109 case SS_NEG
: fputs ("negs", file
); return;
3110 case NOT
: fputs ("not", file
); return; /* Unconditional. */
3112 fputs ("ext", file
); /* bmsk allows predication. */
3114 case SIGN_EXTEND
: /* Unconditional. */
3115 fputs ("sex", file
);
3117 switch (GET_MODE (XEXP (x
, 0)))
3119 case QImode
: fputs ("b", file
); return;
3120 case HImode
: fputs ("w", file
); return;
3125 if (GET_MODE (x
) != HImode
)
3127 fputs ("sat16", file
);
3130 output_operand_lossage ("invalid operand to %%O code"); return;
3132 if (GET_CODE (x
) == SYMBOL_REF
)
3134 assemble_name (file
, XSTR (x
, 0));
3139 if (TARGET_ANNOTATE_ALIGN
&& cfun
->machine
->size_reason
)
3140 fprintf (file
, "; unalign: %d", cfun
->machine
->unalign
);
3144 output_operand_lossage ("invalid operand output code");
3147 switch (GET_CODE (x
))
3150 fputs (reg_names
[REGNO (x
)], file
);
3154 rtx addr
= XEXP (x
, 0);
3155 int size
= GET_MODE_SIZE (GET_MODE (x
));
3159 switch (GET_CODE (addr
))
3161 case PRE_INC
: case POST_INC
:
3162 output_address (plus_constant (Pmode
, XEXP (addr
, 0), size
)); break;
3163 case PRE_DEC
: case POST_DEC
:
3164 output_address (plus_constant (Pmode
, XEXP (addr
, 0), -size
));
3166 case PRE_MODIFY
: case POST_MODIFY
:
3167 output_address (XEXP (addr
, 1)); break;
3171 output_address (plus_constant (Pmode
, XEXP (addr
, 0),
3172 (INTVAL (XEXP (addr
, 1))
3173 >> (size
== 2 ? 1 : 2))));
3177 output_address (addr
);
3180 if (flag_pic
&& CONSTANT_ADDRESS_P (addr
))
3181 arc_output_pic_addr_const (file
, addr
, code
);
3183 output_address (addr
);
3190 /* We handle SFmode constants here as output_addr_const doesn't. */
3191 if (GET_MODE (x
) == SFmode
)
3196 REAL_VALUE_FROM_CONST_DOUBLE (d
, x
);
3197 REAL_VALUE_TO_TARGET_SINGLE (d
, l
);
3198 fprintf (file
, "0x%08lx", l
);
3201 /* Fall through. Let output_addr_const deal with it. */
3204 arc_output_pic_addr_const (file
, x
, code
);
3207 /* FIXME: Dirty way to handle @var@sda+const. Shd be handled
3208 with asm_output_symbol_ref */
3209 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == PLUS
)
3212 output_addr_const (file
, XEXP (x
, 0));
3213 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (XEXP (x
, 0)))
3214 fprintf (file
, "@sda");
3216 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
3217 || INTVAL (XEXP (x
, 1)) >= 0)
3218 fprintf (file
, "+");
3219 output_addr_const (file
, XEXP (x
, 1));
3222 output_addr_const (file
, x
);
3224 if (GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (x
))
3225 fprintf (file
, "@sda");
3230 /* Print a memory address as an operand to reference that memory location. */
3233 arc_print_operand_address (FILE *file
, rtx addr
)
3235 register rtx base
, index
= 0;
3237 switch (GET_CODE (addr
))
3240 fputs (reg_names
[REGNO (addr
)], file
);
3243 output_addr_const (file
, addr
);
3244 if (SYMBOL_REF_SMALL_P (addr
))
3245 fprintf (file
, "@sda");
3248 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3249 index
= XEXP (XEXP (addr
, 0), 0), base
= XEXP (addr
, 1);
3250 else if (CONST_INT_P (XEXP (addr
, 0)))
3251 index
= XEXP (addr
, 0), base
= XEXP (addr
, 1);
3253 base
= XEXP (addr
, 0), index
= XEXP (addr
, 1);
3255 gcc_assert (OBJECT_P (base
));
3256 arc_print_operand_address (file
, base
);
3257 if (CONSTANT_P (base
) && CONST_INT_P (index
))
3261 gcc_assert (OBJECT_P (index
));
3262 arc_print_operand_address (file
, index
);
3266 rtx c
= XEXP (addr
, 0);
3268 gcc_assert (GET_CODE (XEXP (c
, 0)) == SYMBOL_REF
);
3269 gcc_assert (GET_CODE (XEXP (c
, 1)) == CONST_INT
);
3271 output_address(XEXP(addr
,0));
3277 /* We shouldn't get here as we've lost the mode of the memory object
3278 (which says how much to inc/dec by. */
3283 arc_output_pic_addr_const (file
, addr
, 0);
3285 output_addr_const (file
, addr
);
3290 /* Called via walk_stores. DATA points to a hash table we can use to
3291 establish a unique SYMBOL_REF for each counter, which corresponds to
3292 a caller-callee pair.
3293 X is a store which we want to examine for an UNSPEC_PROF, which
3294 would be an address loaded into a register, or directly used in a MEM.
3295 If we found an UNSPEC_PROF, if we encounter a new counter the first time,
3296 write out a description and a data allocation for a 32 bit counter.
3297 Also, fill in the appropriate symbol_ref into each UNSPEC_PROF instance. */
3300 write_profile_sections (rtx dest ATTRIBUTE_UNUSED
, rtx x
, void *data
)
3303 htab_t htab
= (htab_t
) data
;
3306 if (GET_CODE (x
) != SET
)
3308 srcp
= &SET_SRC (x
);
3310 srcp
= &XEXP (*srcp
, 0);
3311 else if (MEM_P (SET_DEST (x
)))
3312 srcp
= &XEXP (SET_DEST (x
), 0);
3314 if (GET_CODE (src
) != CONST
)
3316 src
= XEXP (src
, 0);
3317 if (GET_CODE (src
) != UNSPEC
|| XINT (src
, 1) != UNSPEC_PROF
)
3320 gcc_assert (XVECLEN (src
, 0) == 3);
3321 if (!htab_elements (htab
))
3323 output_asm_insn (".section .__arc_profile_desc, \"a\"\n"
3325 &XVECEXP (src
, 0, 0));
3327 slot
= (rtx
*) htab_find_slot (htab
, src
, INSERT
);
3328 if (*slot
== HTAB_EMPTY_ENTRY
)
3330 static int count_nr
;
3335 sprintf (buf
, "__prof_count%d", count_nr
++);
3336 count
= gen_rtx_SYMBOL_REF (Pmode
, xstrdup (buf
));
3337 XVECEXP (src
, 0, 2) = count
;
3338 output_asm_insn (".section\t.__arc_profile_desc, \"a\"\n"
3340 "\t.section\t.__arc_profile_counters, \"aw\"\n"
3341 "\t.type\t%o2, @object\n"
3344 &XVECEXP (src
, 0, 0));
3348 *srcp
= XVECEXP (*slot
, 0, 2);
3351 /* Hash function for UNSPEC_PROF htab. Use both the caller's name and
3352 the callee's name (if known). */
3355 unspec_prof_hash (const void *x
)
3357 const_rtx u
= (const_rtx
) x
;
3358 const_rtx s1
= XVECEXP (u
, 0, 1);
3360 return (htab_hash_string (XSTR (XVECEXP (u
, 0, 0), 0))
3361 ^ (s1
->code
== SYMBOL_REF
? htab_hash_string (XSTR (s1
, 0)) : 0));
3364 /* Equality function for UNSPEC_PROF htab. Two pieces of UNSPEC_PROF rtl
3365 shall refer to the same counter if both caller name and callee rtl
3369 unspec_prof_htab_eq (const void *x
, const void *y
)
3371 const_rtx u0
= (const_rtx
) x
;
3372 const_rtx u1
= (const_rtx
) y
;
3373 const_rtx s01
= XVECEXP (u0
, 0, 1);
3374 const_rtx s11
= XVECEXP (u1
, 0, 1);
3376 return (!strcmp (XSTR (XVECEXP (u0
, 0, 0), 0),
3377 XSTR (XVECEXP (u1
, 0, 0), 0))
3378 && rtx_equal_p (s01
, s11
));
3381 /* Conditional execution support.
3383 This is based on the ARM port but for now is much simpler.
3385 A finite state machine takes care of noticing whether or not instructions
3386 can be conditionally executed, and thus decrease execution time and code
3387 size by deleting branch instructions. The fsm is controlled by
3388 arc_ccfsm_advance (called by arc_final_prescan_insn), and controls the
3389 actions of PRINT_OPERAND. The patterns in the .md file for the branch
3390 insns also have a hand in this. */
3391 /* The way we leave dealing with non-anulled or annull-false delay slot
3392 insns to the consumer is awkward. */
3394 /* The state of the fsm controlling condition codes are:
3395 0: normal, do nothing special
3396 1: don't output this insn
3397 2: don't output this insn
3398 3: make insns conditional
3399 4: make insns conditional
3400 5: make insn conditional (only for outputting anulled delay slot insns)
3402 special value for cfun->machine->uid_ccfsm_state:
3403 6: return with but one insn before it since function start / call
3405 State transitions (state->state by whom, under what condition):
3406 0 -> 1 arc_ccfsm_advance, if insn is a conditional branch skipping over
3408 0 -> 2 arc_ccfsm_advance, if insn is a conditional branch followed
3409 by zero or more non-jump insns and an unconditional branch with
3410 the same target label as the condbranch.
3411 1 -> 3 branch patterns, after having not output the conditional branch
3412 2 -> 4 branch patterns, after having not output the conditional branch
3413 0 -> 5 branch patterns, for anulled delay slot insn.
3414 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL, if the `target' label is reached
3415 (the target label has CODE_LABEL_NUMBER equal to
3416 arc_ccfsm_target_label).
3417 4 -> 0 arc_ccfsm_advance, if `target' unconditional branch is reached
3418 3 -> 1 arc_ccfsm_advance, finding an 'else' jump skipping over some insns.
3419 5 -> 0 when outputting the delay slot insn
3421 If the jump clobbers the conditions then we use states 2 and 4.
3423 A similar thing can be done with conditional return insns.
3425 We also handle separating branches from sets of the condition code.
3426 This is done here because knowledge of the ccfsm state is required,
3427 we may not be outputting the branch. */
3429 /* arc_final_prescan_insn calls arc_ccfsm_advance to adjust arc_ccfsm_current,
3430 before letting final output INSN. */
3433 arc_ccfsm_advance (rtx_insn
*insn
, struct arc_ccfsm
*state
)
3435 /* BODY will hold the body of INSN. */
3438 /* This will be 1 if trying to repeat the trick (ie: do the `else' part of
3439 an if/then/else), and things need to be reversed. */
3442 /* If we start with a return insn, we only succeed if we find another one. */
3443 int seeking_return
= 0;
3445 /* START_INSN will hold the insn from where we start looking. This is the
3446 first insn after the following code_label if REVERSE is true. */
3447 rtx_insn
*start_insn
= insn
;
3449 /* Type of the jump_insn. Brcc insns don't affect ccfsm changes,
3450 since they don't rely on a cmp preceding the. */
3451 enum attr_type jump_insn_type
;
3453 /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
3454 We can't do this in macro FINAL_PRESCAN_INSN because its called from
3455 final_scan_insn which has `optimize' as a local. */
3456 if (optimize
< 2 || TARGET_NO_COND_EXEC
)
3459 /* Ignore notes and labels. */
3462 body
= PATTERN (insn
);
3463 /* If in state 4, check if the target branch is reached, in order to
3464 change back to state 0. */
3465 if (state
->state
== 4)
3467 if (insn
== state
->target_insn
)
3469 state
->target_insn
= NULL
;
3475 /* If in state 3, it is possible to repeat the trick, if this insn is an
3476 unconditional branch to a label, and immediately following this branch
3477 is the previous target label which is only used once, and the label this
3478 branch jumps to is not too far off. Or in other words "we've done the
3479 `then' part, see if we can do the `else' part." */
3480 if (state
->state
== 3)
3482 if (simplejump_p (insn
))
3484 start_insn
= next_nonnote_insn (start_insn
);
3485 if (GET_CODE (start_insn
) == BARRIER
)
3487 /* ??? Isn't this always a barrier? */
3488 start_insn
= next_nonnote_insn (start_insn
);
3490 if (GET_CODE (start_insn
) == CODE_LABEL
3491 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3492 && LABEL_NUSES (start_insn
) == 1)
3497 else if (GET_CODE (body
) == SIMPLE_RETURN
)
3499 start_insn
= next_nonnote_insn (start_insn
);
3500 if (GET_CODE (start_insn
) == BARRIER
)
3501 start_insn
= next_nonnote_insn (start_insn
);
3502 if (GET_CODE (start_insn
) == CODE_LABEL
3503 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3504 && LABEL_NUSES (start_insn
) == 1)
3516 if (GET_CODE (insn
) != JUMP_INSN
3517 || GET_CODE (PATTERN (insn
)) == ADDR_VEC
3518 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
3521 /* We can't predicate BRCC or loop ends.
3522 Also, when generating PIC code, and considering a medium range call,
3523 we can't predicate the call. */
3524 jump_insn_type
= get_attr_type (insn
);
3525 if (jump_insn_type
== TYPE_BRCC
3526 || jump_insn_type
== TYPE_BRCC_NO_DELAY_SLOT
3527 || jump_insn_type
== TYPE_LOOP_END
3528 || (jump_insn_type
== TYPE_CALL
&& !get_attr_predicable (insn
)))
3531 /* This jump might be paralleled with a clobber of the condition codes,
3532 the jump should always come first. */
3533 if (GET_CODE (body
) == PARALLEL
&& XVECLEN (body
, 0) > 0)
3534 body
= XVECEXP (body
, 0, 0);
3537 || (GET_CODE (body
) == SET
&& GET_CODE (SET_DEST (body
)) == PC
3538 && GET_CODE (SET_SRC (body
)) == IF_THEN_ELSE
))
3540 int insns_skipped
= 0, fail
= FALSE
, succeed
= FALSE
;
3541 /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
3542 int then_not_else
= TRUE
;
3543 /* Nonzero if next insn must be the target label. */
3544 int next_must_be_target_label_p
;
3545 rtx_insn
*this_insn
= start_insn
;
3548 /* Register the insn jumped to. */
3551 if (!seeking_return
)
3552 label
= XEXP (SET_SRC (body
), 0);
3554 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == LABEL_REF
)
3555 label
= XEXP (XEXP (SET_SRC (body
), 1), 0);
3556 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == LABEL_REF
)
3558 label
= XEXP (XEXP (SET_SRC (body
), 2), 0);
3559 then_not_else
= FALSE
;
3561 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == SIMPLE_RETURN
)
3563 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == SIMPLE_RETURN
)
3566 then_not_else
= FALSE
;
3571 /* If this is a non-annulled branch with a delay slot, there is
3572 no need to conditionalize the delay slot. */
3573 if (NEXT_INSN (PREV_INSN (insn
)) != insn
3574 && state
->state
== 0 && !INSN_ANNULLED_BRANCH_P (insn
))
3576 this_insn
= NEXT_INSN (this_insn
);
3577 gcc_assert (NEXT_INSN (NEXT_INSN (PREV_INSN (start_insn
)))
3578 == NEXT_INSN (this_insn
));
3580 /* See how many insns this branch skips, and what kind of insns. If all
3581 insns are okay, and the label or unconditional branch to the same
3582 label is not too far away, succeed. */
3583 for (insns_skipped
= 0, next_must_be_target_label_p
= FALSE
;
3584 !fail
&& !succeed
&& insns_skipped
< MAX_INSNS_SKIPPED
;
3589 this_insn
= next_nonnote_insn (this_insn
);
3593 if (next_must_be_target_label_p
)
3595 if (GET_CODE (this_insn
) == BARRIER
)
3597 if (GET_CODE (this_insn
) == CODE_LABEL
3598 && this_insn
== label
)
3608 scanbody
= PATTERN (this_insn
);
3610 switch (GET_CODE (this_insn
))
3613 /* Succeed if it is the target label, otherwise fail since
3614 control falls in from somewhere else. */
3615 if (this_insn
== label
)
3625 /* Succeed if the following insn is the target label.
3627 If return insns are used then the last insn in a function
3628 will be a barrier. */
3629 next_must_be_target_label_p
= TRUE
;
3633 /* Can handle a call insn if there are no insns after it.
3634 IE: The next "insn" is the target label. We don't have to
3635 worry about delay slots as such insns are SEQUENCE's inside
3636 INSN's. ??? It is possible to handle such insns though. */
3637 if (get_attr_cond (this_insn
) == COND_CANUSE
)
3638 next_must_be_target_label_p
= TRUE
;
3644 /* If this is an unconditional branch to the same label, succeed.
3645 If it is to another label, do nothing. If it is conditional,
3647 /* ??? Probably, the test for the SET and the PC are
3650 if (GET_CODE (scanbody
) == SET
3651 && GET_CODE (SET_DEST (scanbody
)) == PC
)
3653 if (GET_CODE (SET_SRC (scanbody
)) == LABEL_REF
3654 && XEXP (SET_SRC (scanbody
), 0) == label
&& !reverse
)
3659 else if (GET_CODE (SET_SRC (scanbody
)) == IF_THEN_ELSE
)
3661 else if (get_attr_cond (this_insn
) != COND_CANUSE
)
3664 else if (GET_CODE (scanbody
) == SIMPLE_RETURN
3670 else if (GET_CODE (scanbody
) == PARALLEL
)
3672 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3678 /* We can only do this with insns that can use the condition
3679 codes (and don't set them). */
3680 if (GET_CODE (scanbody
) == SET
3681 || GET_CODE (scanbody
) == PARALLEL
)
3683 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3686 /* We can't handle other insns like sequences. */
3698 if ((!seeking_return
) && (state
->state
== 1 || reverse
))
3699 state
->target_label
= CODE_LABEL_NUMBER (label
);
3700 else if (seeking_return
|| state
->state
== 2)
3702 while (this_insn
&& GET_CODE (PATTERN (this_insn
)) == USE
)
3704 this_insn
= next_nonnote_insn (this_insn
);
3706 gcc_assert (!this_insn
||
3707 (GET_CODE (this_insn
) != BARRIER
3708 && GET_CODE (this_insn
) != CODE_LABEL
));
3712 /* Oh dear! we ran off the end, give up. */
3713 extract_insn_cached (insn
);
3715 state
->target_insn
= NULL
;
3718 state
->target_insn
= this_insn
;
3723 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
3727 state
->cond
= XEXP (SET_SRC (body
), 0);
3728 state
->cc
= get_arc_condition_code (XEXP (SET_SRC (body
), 0));
3731 if (reverse
|| then_not_else
)
3732 state
->cc
= ARC_INVERSE_CONDITION_CODE (state
->cc
);
3735 /* Restore recog_operand. Getting the attributes of other insns can
3736 destroy this array, but final.c assumes that it remains intact
3737 across this call; since the insn has been recognized already we
3738 call insn_extract direct. */
3739 extract_insn_cached (insn
);
3743 /* Record that we are currently outputting label NUM with prefix PREFIX.
3744 It it's the label we're looking for, reset the ccfsm machinery.
3746 Called from ASM_OUTPUT_INTERNAL_LABEL. */
3749 arc_ccfsm_at_label (const char *prefix
, int num
, struct arc_ccfsm
*state
)
3751 if (state
->state
== 3 && state
->target_label
== num
3752 && !strcmp (prefix
, "L"))
3755 state
->target_insn
= NULL
;
3759 /* We are considering a conditional branch with the condition COND.
3760 Check if we want to conditionalize a delay slot insn, and if so modify
3761 the ccfsm state accordingly.
3762 REVERSE says branch will branch when the condition is false. */
3764 arc_ccfsm_record_condition (rtx cond
, bool reverse
, rtx_insn
*jump
,
3765 struct arc_ccfsm
*state
)
3767 rtx_insn
*seq_insn
= NEXT_INSN (PREV_INSN (jump
));
3769 state
= &arc_ccfsm_current
;
3771 gcc_assert (state
->state
== 0);
3772 if (seq_insn
!= jump
)
3774 rtx insn
= XVECEXP (PATTERN (seq_insn
), 0, 1);
3776 if (!as_a
<rtx_insn
*> (insn
)->deleted ()
3777 && INSN_ANNULLED_BRANCH_P (jump
)
3778 && (TARGET_AT_DBR_CONDEXEC
|| INSN_FROM_TARGET_P (insn
)))
3781 state
->cc
= get_arc_condition_code (cond
);
3783 arc_ccfsm_current
.cc
3784 = ARC_INVERSE_CONDITION_CODE (state
->cc
);
3785 rtx pat
= PATTERN (insn
);
3786 if (GET_CODE (pat
) == COND_EXEC
)
3787 gcc_assert ((INSN_FROM_TARGET_P (insn
)
3788 ? ARC_INVERSE_CONDITION_CODE (state
->cc
) : state
->cc
)
3789 == get_arc_condition_code (XEXP (pat
, 0)));
3796 /* Update *STATE as we would when we emit INSN. */
3799 arc_ccfsm_post_advance (rtx_insn
*insn
, struct arc_ccfsm
*state
)
3801 enum attr_type type
;
3804 arc_ccfsm_at_label ("L", CODE_LABEL_NUMBER (insn
), state
);
3805 else if (JUMP_P (insn
)
3806 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
3807 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
3808 && ((type
= get_attr_type (insn
)) == TYPE_BRANCH
3809 || (type
== TYPE_UNCOND_BRANCH
3810 /* ??? Maybe should also handle TYPE_RETURN here,
3811 but we don't have a testcase for that. */
3812 && ARC_CCFSM_BRANCH_DELETED_P (state
))))
3814 if (ARC_CCFSM_BRANCH_DELETED_P (state
))
3815 ARC_CCFSM_RECORD_BRANCH_DELETED (state
);
3818 rtx src
= SET_SRC (PATTERN (insn
));
3819 arc_ccfsm_record_condition (XEXP (src
, 0), XEXP (src
, 1) == pc_rtx
,
3823 else if (arc_ccfsm_current
.state
== 5)
3824 arc_ccfsm_current
.state
= 0;
3827 /* Return true if the current insn, which is a conditional branch, is to be
3831 arc_ccfsm_branch_deleted_p (void)
3833 return ARC_CCFSM_BRANCH_DELETED_P (&arc_ccfsm_current
);
3836 /* Record a branch isn't output because subsequent insns can be
3840 arc_ccfsm_record_branch_deleted (void)
3842 ARC_CCFSM_RECORD_BRANCH_DELETED (&arc_ccfsm_current
);
3845 /* During insn output, indicate if the current insn is predicated. */
3848 arc_ccfsm_cond_exec_p (void)
3850 return (cfun
->machine
->prescan_initialized
3851 && ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
));
3854 /* Like next_active_insn, but return NULL if we find an ADDR_(DIFF_)VEC,
3855 and look inside SEQUENCEs. */
3858 arc_next_active_insn (rtx_insn
*insn
, struct arc_ccfsm
*statep
)
3865 arc_ccfsm_post_advance (insn
, statep
);
3866 insn
= NEXT_INSN (insn
);
3867 if (!insn
|| BARRIER_P (insn
))
3870 arc_ccfsm_advance (insn
, statep
);
3872 while (NOTE_P (insn
)
3873 || (cfun
->machine
->arc_reorg_started
3874 && LABEL_P (insn
) && !label_to_alignment (insn
))
3875 || (NONJUMP_INSN_P (insn
)
3876 && (GET_CODE (PATTERN (insn
)) == USE
3877 || GET_CODE (PATTERN (insn
)) == CLOBBER
)));
3878 if (!LABEL_P (insn
))
3880 gcc_assert (INSN_P (insn
));
3881 pat
= PATTERN (insn
);
3882 if (GET_CODE (pat
) == ADDR_VEC
|| GET_CODE (pat
) == ADDR_DIFF_VEC
)
3884 if (GET_CODE (pat
) == SEQUENCE
)
3885 return as_a
<rtx_insn
*> (XVECEXP (pat
, 0, 0));
3890 /* When deciding if an insn should be output short, we want to know something
3891 about the following insns:
3892 - if another insn follows which we know we can output as a short insn
3893 before an alignment-sensitive point, we can output this insn short:
3894 the decision about the eventual alignment can be postponed.
3895 - if a to-be-aligned label comes next, we should output this insn such
3896 as to get / preserve 4-byte alignment.
3897 - if a likely branch without delay slot insn, or a call with an immediately
3898 following short insn comes next, we should out output this insn such as to
3899 get / preserve 2 mod 4 unalignment.
3900 - do the same for a not completely unlikely branch with a short insn
3901 following before any other branch / label.
3902 - in order to decide if we are actually looking at a branch, we need to
3903 call arc_ccfsm_advance.
3904 - in order to decide if we are looking at a short insn, we should know
3905 if it is conditionalized. To a first order of approximation this is
3906 the case if the state from arc_ccfsm_advance from before this insn
3907 indicates the insn is conditionalized. However, a further refinement
3908 could be to not conditionalize an insn if the destination register(s)
3909 is/are dead in the non-executed case. */
3910 /* Return non-zero if INSN should be output as a short insn. UNALIGN is
3911 zero if the current insn is aligned to a 4-byte-boundary, two otherwise.
3912 If CHECK_ATTR is greater than 0, check the iscompact attribute first. */
3915 arc_verify_short (rtx_insn
*insn
, int, int check_attr
)
3917 enum attr_iscompact iscompact
;
3918 struct machine_function
*machine
;
3922 iscompact
= get_attr_iscompact (insn
);
3923 if (iscompact
== ISCOMPACT_FALSE
)
3926 machine
= cfun
->machine
;
3928 if (machine
->force_short_suffix
>= 0)
3929 return machine
->force_short_suffix
;
3931 return (get_attr_length (insn
) & 2) != 0;
3934 /* When outputting an instruction (alternative) that can potentially be short,
3935 output the short suffix if the insn is in fact short, and update
3936 cfun->machine->unalign accordingly. */
3939 output_short_suffix (FILE *file
)
3941 rtx_insn
*insn
= current_output_insn
;
3943 if (arc_verify_short (insn
, cfun
->machine
->unalign
, 1))
3945 fprintf (file
, "_s");
3946 cfun
->machine
->unalign
^= 2;
3948 /* Restore recog_operand. */
3949 extract_insn_cached (insn
);
3952 /* Implement FINAL_PRESCAN_INSN. */
3955 arc_final_prescan_insn (rtx_insn
*insn
, rtx
*opvec ATTRIBUTE_UNUSED
,
3956 int noperands ATTRIBUTE_UNUSED
)
3958 if (TARGET_DUMPISIZE
)
3959 fprintf (asm_out_file
, "\n; at %04x\n", INSN_ADDRESSES (INSN_UID (insn
)));
3961 /* Output a nop if necessary to prevent a hazard.
3962 Don't do this for delay slots: inserting a nop would
3963 alter semantics, and the only time we would find a hazard is for a
3964 call function result - and in that case, the hazard is spurious to
3966 if (PREV_INSN (insn
)
3967 && PREV_INSN (NEXT_INSN (insn
)) == insn
3968 && arc_hazard (prev_real_insn (insn
), insn
))
3970 current_output_insn
=
3971 emit_insn_before (gen_nop (), NEXT_INSN (PREV_INSN (insn
)));
3972 final_scan_insn (current_output_insn
, asm_out_file
, optimize
, 1, NULL
);
3973 current_output_insn
= insn
;
3975 /* Restore extraction data which might have been clobbered by arc_hazard. */
3976 extract_constrain_insn_cached (insn
);
3978 if (!cfun
->machine
->prescan_initialized
)
3980 /* Clear lingering state from branch shortening. */
3981 memset (&arc_ccfsm_current
, 0, sizeof arc_ccfsm_current
);
3982 cfun
->machine
->prescan_initialized
= 1;
3984 arc_ccfsm_advance (insn
, &arc_ccfsm_current
);
3986 cfun
->machine
->size_reason
= 0;
3989 /* Given FROM and TO register numbers, say whether this elimination is allowed.
3990 Frame pointer elimination is automatically handled.
3992 All eliminations are permissible. If we need a frame
3993 pointer, we must eliminate ARG_POINTER_REGNUM into
3994 FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */
3997 arc_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
3999 return to
== FRAME_POINTER_REGNUM
|| !arc_frame_pointer_required ();
4002 /* Define the offset between two registers, one to be eliminated, and
4003 the other its replacement, at the start of a routine. */
4006 arc_initial_elimination_offset (int from
, int to
)
4008 if (! cfun
->machine
->frame_info
.initialized
)
4009 arc_compute_frame_size (get_frame_size ());
4011 if (from
== ARG_POINTER_REGNUM
&& to
== FRAME_POINTER_REGNUM
)
4013 return (cfun
->machine
->frame_info
.extra_size
4014 + cfun
->machine
->frame_info
.reg_size
);
4017 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
4019 return (cfun
->machine
->frame_info
.total_size
4020 - cfun
->machine
->frame_info
.pretend_size
);
4023 if ((from
== FRAME_POINTER_REGNUM
) && (to
== STACK_POINTER_REGNUM
))
4025 return (cfun
->machine
->frame_info
.total_size
4026 - (cfun
->machine
->frame_info
.pretend_size
4027 + cfun
->machine
->frame_info
.extra_size
4028 + cfun
->machine
->frame_info
.reg_size
));
4035 arc_frame_pointer_required (void)
4037 return cfun
->calls_alloca
;
4041 /* Return the destination address of a branch. */
4044 branch_dest (rtx branch
)
4046 rtx pat
= PATTERN (branch
);
4047 rtx dest
= (GET_CODE (pat
) == PARALLEL
4048 ? SET_SRC (XVECEXP (pat
, 0, 0)) : SET_SRC (pat
));
4051 if (GET_CODE (dest
) == IF_THEN_ELSE
)
4052 dest
= XEXP (dest
, XEXP (dest
, 1) == pc_rtx
? 2 : 1);
4054 dest
= XEXP (dest
, 0);
4055 dest_uid
= INSN_UID (dest
);
4057 return INSN_ADDRESSES (dest_uid
);
4061 /* Implement TARGET_ENCODE_SECTION_INFO hook. */
4064 arc_encode_section_info (tree decl
, rtx rtl
, int first
)
4066 /* For sdata, SYMBOL_FLAG_LOCAL and SYMBOL_FLAG_FUNCTION.
4067 This clears machine specific flags, so has to come first. */
4068 default_encode_section_info (decl
, rtl
, first
);
4070 /* Check if it is a function, and whether it has the
4071 [long/medium/short]_call attribute specified. */
4072 if (TREE_CODE (decl
) == FUNCTION_DECL
)
4074 rtx symbol
= XEXP (rtl
, 0);
4075 int flags
= SYMBOL_REF_FLAGS (symbol
);
4077 tree attr
= (TREE_TYPE (decl
) != error_mark_node
4078 ? TYPE_ATTRIBUTES (TREE_TYPE (decl
)) : NULL_TREE
);
4079 tree long_call_attr
= lookup_attribute ("long_call", attr
);
4080 tree medium_call_attr
= lookup_attribute ("medium_call", attr
);
4081 tree short_call_attr
= lookup_attribute ("short_call", attr
);
4083 if (long_call_attr
!= NULL_TREE
)
4084 flags
|= SYMBOL_FLAG_LONG_CALL
;
4085 else if (medium_call_attr
!= NULL_TREE
)
4086 flags
|= SYMBOL_FLAG_MEDIUM_CALL
;
4087 else if (short_call_attr
!= NULL_TREE
)
4088 flags
|= SYMBOL_FLAG_SHORT_CALL
;
4090 SYMBOL_REF_FLAGS (symbol
) = flags
;
4094 /* This is how to output a definition of an internal numbered label where
4095 PREFIX is the class of label and NUM is the number within the class. */
4097 static void arc_internal_label (FILE *stream
, const char *prefix
, unsigned long labelno
)
4100 arc_ccfsm_at_label (prefix
, labelno
, &arc_ccfsm_current
);
4101 default_internal_label (stream
, prefix
, labelno
);
4104 /* Set the cpu type and print out other fancy things,
4105 at the top of the file. */
4107 static void arc_file_start (void)
4109 default_file_start ();
4110 fprintf (asm_out_file
, "\t.cpu %s\n", arc_cpu_string
);
4113 /* Cost functions. */
4115 /* Compute a (partial) cost for rtx X. Return true if the complete
4116 cost has been computed, and false if subexpressions should be
4117 scanned. In either case, *TOTAL contains the cost result. */
4120 arc_rtx_costs (rtx x
, int code
, int outer_code
, int opno ATTRIBUTE_UNUSED
,
4121 int *total
, bool speed
)
4125 /* Small integers are as cheap as registers. */
4128 bool nolimm
= false; /* Can we do without long immediate? */
4129 bool fast
= false; /* Is the result available immediately? */
4130 bool condexec
= false; /* Does this allow conditiobnal execution? */
4131 bool compact
= false; /* Is a 16 bit opcode available? */
4132 /* CONDEXEC also implies that we can have an unconditional
4133 3-address operation. */
4135 nolimm
= compact
= condexec
= false;
4136 if (UNSIGNED_INT6 (INTVAL (x
)))
4137 nolimm
= condexec
= compact
= true;
4140 if (SMALL_INT (INTVAL (x
)))
4141 nolimm
= fast
= true;
4144 case AND
: /* bclr, bmsk, ext[bw] */
4145 if (satisfies_constraint_Ccp (x
) /* bclr */
4146 || satisfies_constraint_C1p (x
) /* bmsk */)
4147 nolimm
= fast
= condexec
= compact
= true;
4149 case IOR
: /* bset */
4150 if (satisfies_constraint_C0p (x
)) /* bset */
4151 nolimm
= fast
= condexec
= compact
= true;
4154 if (satisfies_constraint_C0p (x
)) /* bxor */
4155 nolimm
= fast
= condexec
= true;
4158 if (satisfies_constraint_Crr (x
)) /* ror b,u6 */
4164 /* FIXME: Add target options to attach a small cost if
4165 condexec / compact is not true. */
4174 /* 4 byte values can be fetched as immediate constants -
4175 let's give that the cost of an extra insn. */
4179 *total
= COSTS_N_INSNS (1);
4188 *total
= COSTS_N_INSNS (1);
4191 /* FIXME: correct the order of high,low */
4192 split_double (x
, &high
, &low
);
4193 *total
= COSTS_N_INSNS (!SMALL_INT (INTVAL (high
))
4194 + !SMALL_INT (INTVAL (low
)));
4198 /* Encourage synth_mult to find a synthetic multiply when reasonable.
4199 If we need more than 12 insns to do a multiply, then go out-of-line,
4200 since the call overhead will be < 10% of the cost of the multiply. */
4204 if (TARGET_BARREL_SHIFTER
)
4206 /* If we want to shift a constant, we need a LIMM. */
4207 /* ??? when the optimizers want to know if a constant should be
4208 hoisted, they ask for the cost of the constant. OUTER_CODE is
4209 insufficient context for shifts since we don't know which operand
4210 we are looking at. */
4211 if (CONSTANT_P (XEXP (x
, 0)))
4213 *total
+= (COSTS_N_INSNS (2)
4214 + rtx_cost (XEXP (x
, 1), (enum rtx_code
) code
, 0, speed
));
4217 *total
= COSTS_N_INSNS (1);
4219 else if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4220 *total
= COSTS_N_INSNS (16);
4223 *total
= COSTS_N_INSNS (INTVAL (XEXP ((x
), 1)));
4224 /* ??? want_to_gcse_p can throw negative shift counts at us,
4225 and then panics when it gets a negative cost as result.
4226 Seen for gcc.c-torture/compile/20020710-1.c -Os . */
4235 *total
= COSTS_N_INSNS(30);
4237 *total
= COSTS_N_INSNS(1);
4241 if ((TARGET_DPFP
&& GET_MODE (x
) == DFmode
))
4242 *total
= COSTS_N_INSNS (1);
4244 *total
= arc_multcost
;
4245 /* We do not want synth_mult sequences when optimizing
4247 else if (TARGET_MUL64_SET
|| (TARGET_ARC700
&& !TARGET_NOMPY_SET
))
4248 *total
= COSTS_N_INSNS (1);
4250 *total
= COSTS_N_INSNS (2);
4253 if (GET_CODE (XEXP (x
, 0)) == MULT
4254 && _2_4_8_operand (XEXP (XEXP (x
, 0), 1), VOIDmode
))
4256 *total
+= (rtx_cost (XEXP (x
, 1), PLUS
, 0, speed
)
4257 + rtx_cost (XEXP (XEXP (x
, 0), 0), PLUS
, 1, speed
));
4262 if (GET_CODE (XEXP (x
, 1)) == MULT
4263 && _2_4_8_operand (XEXP (XEXP (x
, 1), 1), VOIDmode
))
4265 *total
+= (rtx_cost (XEXP (x
, 0), PLUS
, 0, speed
)
4266 + rtx_cost (XEXP (XEXP (x
, 1), 0), PLUS
, 1, speed
));
4272 rtx op0
= XEXP (x
, 0);
4273 rtx op1
= XEXP (x
, 1);
4275 if (GET_CODE (op0
) == ZERO_EXTRACT
&& op1
== const0_rtx
4276 && XEXP (op0
, 1) == const1_rtx
)
4278 /* btst / bbit0 / bbit1:
4279 Small integers and registers are free; everything else can
4280 be put in a register. */
4281 *total
= (rtx_cost (XEXP (op0
, 0), SET
, 1, speed
)
4282 + rtx_cost (XEXP (op0
, 2), SET
, 1, speed
));
4285 if (GET_CODE (op0
) == AND
&& op1
== const0_rtx
4286 && satisfies_constraint_C1p (XEXP (op0
, 1)))
4289 *total
= rtx_cost (XEXP (op0
, 0), SET
, 1, speed
);
4293 if (GET_CODE (op1
) == NEG
)
4295 /* op0 might be constant, the inside of op1 is rather
4296 unlikely to be so. So swapping the operands might lower
4298 *total
= (rtx_cost (op0
, PLUS
, 1, speed
)
4299 + rtx_cost (XEXP (op1
, 0), PLUS
, 0, speed
));
4304 if (outer_code
== IF_THEN_ELSE
4305 && GET_CODE (XEXP (x
, 0)) == ZERO_EXTRACT
4306 && XEXP (x
, 1) == const0_rtx
4307 && XEXP (XEXP (x
, 0), 1) == const1_rtx
)
4309 /* btst / bbit0 / bbit1:
4310 Small integers and registers are free; everything else can
4311 be put in a register. */
4312 rtx op0
= XEXP (x
, 0);
4314 *total
= (rtx_cost (XEXP (op0
, 0), SET
, 1, speed
)
4315 + rtx_cost (XEXP (op0
, 2), SET
, 1, speed
));
4319 /* scc_insn expands into two insns. */
4320 case GTU
: case GEU
: case LEU
:
4321 if (GET_MODE (x
) == SImode
)
4322 *total
+= COSTS_N_INSNS (1);
4324 case LTU
: /* might use adc. */
4325 if (GET_MODE (x
) == SImode
)
4326 *total
+= COSTS_N_INSNS (1) - 1;
4333 /* Return true if ADDR is an address that needs to be expressed as an
4334 explicit sum of pcl + offset. */
4337 arc_legitimate_pc_offset_p (rtx addr
)
4339 if (GET_CODE (addr
) != CONST
)
4341 addr
= XEXP (addr
, 0);
4342 if (GET_CODE (addr
) == PLUS
)
4344 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4346 addr
= XEXP (addr
, 0);
4348 return (GET_CODE (addr
) == UNSPEC
4349 && XVECLEN (addr
, 0) == 1
4350 && XINT (addr
, 1) == ARC_UNSPEC_GOT
4351 && GET_CODE (XVECEXP (addr
, 0, 0)) == SYMBOL_REF
);
4354 /* Return true if ADDR is a valid pic address.
4355 A valid pic address on arc should look like
4356 const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT)) */
4359 arc_legitimate_pic_addr_p (rtx addr
)
4361 if (GET_CODE (addr
) == LABEL_REF
)
4363 if (GET_CODE (addr
) != CONST
)
4366 addr
= XEXP (addr
, 0);
4369 if (GET_CODE (addr
) == PLUS
)
4371 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4373 addr
= XEXP (addr
, 0);
4376 if (GET_CODE (addr
) != UNSPEC
4377 || XVECLEN (addr
, 0) != 1)
4380 /* Must be @GOT or @GOTOFF. */
4381 if (XINT (addr
, 1) != ARC_UNSPEC_GOT
4382 && XINT (addr
, 1) != ARC_UNSPEC_GOTOFF
)
4385 if (GET_CODE (XVECEXP (addr
, 0, 0)) != SYMBOL_REF
4386 && GET_CODE (XVECEXP (addr
, 0, 0)) != LABEL_REF
)
4394 /* Return true if OP contains a symbol reference. */
4397 symbolic_reference_mentioned_p (rtx op
)
4399 register const char *fmt
;
4402 if (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == LABEL_REF
)
4405 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4406 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4412 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4413 if (symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
)))
4417 else if (fmt
[i
] == 'e' && symbolic_reference_mentioned_p (XEXP (op
, i
)))
4424 /* Return true if OP contains a SYMBOL_REF that is not wrapped in an unspec.
4425 If SKIP_LOCAL is true, skip symbols that bind locally.
4426 This is used further down in this file, and, without SKIP_LOCAL,
4427 in the addsi3 / subsi3 expanders when generating PIC code. */
4430 arc_raw_symbolic_reference_mentioned_p (rtx op
, bool skip_local
)
4432 register const char *fmt
;
4435 if (GET_CODE(op
) == UNSPEC
)
4438 if (GET_CODE (op
) == SYMBOL_REF
)
4440 tree decl
= SYMBOL_REF_DECL (op
);
4441 return !skip_local
|| !decl
|| !default_binds_local_p (decl
);
4444 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4445 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4451 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4452 if (arc_raw_symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
),
4457 else if (fmt
[i
] == 'e'
4458 && arc_raw_symbolic_reference_mentioned_p (XEXP (op
, i
),
4466 /* Legitimize a pic address reference in ORIG.
4467 The return value is the legitimated address.
4468 If OLDX is non-zero, it is the target to assign the address to first. */
4471 arc_legitimize_pic_address (rtx orig
, rtx oldx
)
4480 if (GET_CODE (addr
) == LABEL_REF
)
4482 else if (GET_CODE (addr
) == SYMBOL_REF
4483 && (CONSTANT_POOL_ADDRESS_P (addr
)
4484 || SYMBOL_REF_LOCAL_P (addr
)))
4486 /* This symbol may be referenced via a displacement from the PIC
4487 base address (@GOTOFF). */
4489 /* FIXME: if we had a way to emit pc-relative adds that don't
4490 create a GOT entry, we could do without the use of the gp register. */
4491 crtl
->uses_pic_offset_table
= 1;
4492 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOTOFF
);
4493 pat
= gen_rtx_CONST (Pmode
, pat
);
4494 pat
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, pat
);
4497 oldx
= gen_reg_rtx (Pmode
);
4501 emit_move_insn (oldx
, pat
);
4506 else if (GET_CODE (addr
) == SYMBOL_REF
)
4508 /* This symbol must be referenced via a load from the
4509 Global Offset Table (@GOTPC). */
4511 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOT
);
4512 pat
= gen_rtx_CONST (Pmode
, pat
);
4513 pat
= gen_const_mem (Pmode
, pat
);
4516 oldx
= gen_reg_rtx (Pmode
);
4518 emit_move_insn (oldx
, pat
);
4523 if (GET_CODE (addr
) == CONST
)
4525 addr
= XEXP (addr
, 0);
4526 if (GET_CODE (addr
) == UNSPEC
)
4528 /* Check that the unspec is one of the ones we generate? */
4531 gcc_assert (GET_CODE (addr
) == PLUS
);
4534 if (GET_CODE (addr
) == PLUS
)
4536 rtx op0
= XEXP (addr
, 0), op1
= XEXP (addr
, 1);
4538 /* Check first to see if this is a constant offset from a @GOTOFF
4539 symbol reference. */
4540 if ((GET_CODE (op0
) == LABEL_REF
4541 || (GET_CODE (op0
) == SYMBOL_REF
4542 && (CONSTANT_POOL_ADDRESS_P (op0
)
4543 || SYMBOL_REF_LOCAL_P (op0
))))
4544 && GET_CODE (op1
) == CONST_INT
)
4546 /* FIXME: like above, could do without gp reference. */
4547 crtl
->uses_pic_offset_table
= 1;
4549 = gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, op0
), ARC_UNSPEC_GOTOFF
);
4550 pat
= gen_rtx_PLUS (Pmode
, pat
, op1
);
4551 pat
= gen_rtx_CONST (Pmode
, pat
);
4552 pat
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, pat
);
4556 emit_move_insn (oldx
, pat
);
4562 base
= arc_legitimize_pic_address (XEXP (addr
, 0), oldx
);
4563 pat
= arc_legitimize_pic_address (XEXP (addr
, 1),
4564 base
== oldx
? NULL_RTX
: oldx
);
4566 if (GET_CODE (pat
) == CONST_INT
)
4567 pat
= plus_constant (Pmode
, base
, INTVAL (pat
));
4570 if (GET_CODE (pat
) == PLUS
&& CONSTANT_P (XEXP (pat
, 1)))
4572 base
= gen_rtx_PLUS (Pmode
, base
, XEXP (pat
, 0));
4573 pat
= XEXP (pat
, 1);
4575 pat
= gen_rtx_PLUS (Pmode
, base
, pat
);
4584 /* Output address constant X to FILE, taking PIC into account. */
4587 arc_output_pic_addr_const (FILE * file
, rtx x
, int code
)
4592 switch (GET_CODE (x
))
4602 output_addr_const (file
, x
);
4604 /* Local functions do not get references through the PLT. */
4605 if (code
== 'P' && ! SYMBOL_REF_LOCAL_P (x
))
4606 fputs ("@plt", file
);
4610 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (XEXP (x
, 0)));
4611 assemble_name (file
, buf
);
4615 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (x
));
4616 assemble_name (file
, buf
);
4620 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
));
4624 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4628 if (GET_MODE (x
) == VOIDmode
)
4630 /* We can use %d if the number is one word and positive. */
4631 if (CONST_DOUBLE_HIGH (x
))
4632 fprintf (file
, HOST_WIDE_INT_PRINT_DOUBLE_HEX
,
4633 CONST_DOUBLE_HIGH (x
), CONST_DOUBLE_LOW (x
));
4634 else if (CONST_DOUBLE_LOW (x
) < 0)
4635 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, CONST_DOUBLE_LOW (x
));
4637 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, CONST_DOUBLE_LOW (x
));
4640 /* We can't handle floating point constants;
4641 PRINT_OPERAND must handle them. */
4642 output_operand_lossage ("floating constant misused");
4646 /* FIXME: Not needed here. */
4647 /* Some assemblers need integer constants to appear last (eg masm). */
4648 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
4650 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4651 fprintf (file
, "+");
4652 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4654 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
4656 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4657 if (INTVAL (XEXP (x
, 1)) >= 0)
4658 fprintf (file
, "+");
4659 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4666 /* Avoid outputting things like x-x or x+5-x,
4667 since some assemblers can't handle that. */
4668 x
= simplify_subtraction (x
);
4669 if (GET_CODE (x
) != MINUS
)
4672 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4673 fprintf (file
, "-");
4674 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
4675 && INTVAL (XEXP (x
, 1)) < 0)
4677 fprintf (file
, "(");
4678 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4679 fprintf (file
, ")");
4682 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4687 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4692 gcc_assert (XVECLEN (x
, 0) == 1);
4693 if (XINT (x
, 1) == ARC_UNSPEC_GOT
)
4694 fputs ("pcl,", file
);
4695 arc_output_pic_addr_const (file
, XVECEXP (x
, 0, 0), code
);
4696 switch (XINT (x
, 1))
4698 case ARC_UNSPEC_GOT
:
4699 fputs ("@gotpc", file
);
4701 case ARC_UNSPEC_GOTOFF
:
4702 fputs ("@gotoff", file
);
4704 case ARC_UNSPEC_PLT
:
4705 fputs ("@plt", file
);
4708 output_operand_lossage ("invalid UNSPEC as operand: %d", XINT (x
,1));
4714 output_operand_lossage ("invalid expression as operand");
4718 #define SYMBOLIC_CONST(X) \
4719 (GET_CODE (X) == SYMBOL_REF \
4720 || GET_CODE (X) == LABEL_REF \
4721 || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
4723 /* Emit insns to move operands[1] into operands[0]. */
4726 emit_pic_move (rtx
*operands
, machine_mode
)
4728 rtx temp
= reload_in_progress
? operands
[0] : gen_reg_rtx (Pmode
);
4730 if (GET_CODE (operands
[0]) == MEM
&& SYMBOLIC_CONST (operands
[1]))
4731 operands
[1] = force_reg (Pmode
, operands
[1]);
4733 operands
[1] = arc_legitimize_pic_address (operands
[1], temp
);
4737 /* The function returning the number of words, at the beginning of an
4738 argument, must be put in registers. The returned value must be
4739 zero for arguments that are passed entirely in registers or that
4740 are entirely pushed on the stack.
4742 On some machines, certain arguments must be passed partially in
4743 registers and partially in memory. On these machines, typically
4744 the first N words of arguments are passed in registers, and the
4745 rest on the stack. If a multi-word argument (a `double' or a
4746 structure) crosses that boundary, its first few words must be
4747 passed in registers and the rest must be pushed. This function
4748 tells the compiler when this occurs, and how many of the words
4749 should go in registers.
4751 `FUNCTION_ARG' for these arguments should return the first register
4752 to be used by the caller for this argument; likewise
4753 `FUNCTION_INCOMING_ARG', for the called function.
4755 The function is used to implement macro FUNCTION_ARG_PARTIAL_NREGS. */
4757 /* If REGNO is the least arg reg available then what is the total number of arg
4759 #define GPR_REST_ARG_REGS(REGNO) \
4760 ((REGNO) <= MAX_ARC_PARM_REGS ? MAX_ARC_PARM_REGS - (REGNO) : 0 )
4762 /* Since arc parm regs are contiguous. */
4763 #define ARC_NEXT_ARG_REG(REGNO) ( (REGNO) + 1 )
4765 /* Implement TARGET_ARG_PARTIAL_BYTES. */
4768 arc_arg_partial_bytes (cumulative_args_t cum_v
, machine_mode mode
,
4769 tree type
, bool named ATTRIBUTE_UNUSED
)
4771 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4772 int bytes
= (mode
== BLKmode
4773 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
4774 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
4778 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
4779 ret
= GPR_REST_ARG_REGS (arg_num
);
4781 /* ICEd at function.c:2361, and ret is copied to data->partial */
4782 ret
= (ret
>= words
? 0 : ret
* UNITS_PER_WORD
);
4789 /* This function is used to control a function argument is passed in a
4790 register, and which register.
4792 The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes
4793 (in a way defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE)
4794 all of the previous arguments so far passed in registers; MODE, the
4795 machine mode of the argument; TYPE, the data type of the argument
4796 as a tree node or 0 if that is not known (which happens for C
4797 support library functions); and NAMED, which is 1 for an ordinary
4798 argument and 0 for nameless arguments that correspond to `...' in
4799 the called function's prototype.
4801 The returned value should either be a `reg' RTX for the hard
4802 register in which to pass the argument, or zero to pass the
4803 argument on the stack.
4805 For machines like the Vax and 68000, where normally all arguments
4806 are pushed, zero suffices as a definition.
4808 The usual way to make the ANSI library `stdarg.h' work on a machine
4809 where some arguments are usually passed in registers, is to cause
4810 nameless arguments to be passed on the stack instead. This is done
4811 by making the function return 0 whenever NAMED is 0.
4813 You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the
4814 definition of this function to determine if this argument is of a
4815 type that must be passed in the stack. If `REG_PARM_STACK_SPACE'
4816 is not defined and the function returns non-zero for such an
4817 argument, the compiler will abort. If `REG_PARM_STACK_SPACE' is
4818 defined, the argument will be computed in the stack and then loaded
4821 The function is used to implement macro FUNCTION_ARG. */
4822 /* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers
4823 and the rest are pushed. */
4826 arc_function_arg (cumulative_args_t cum_v
, machine_mode mode
,
4827 const_tree type ATTRIBUTE_UNUSED
, bool named ATTRIBUTE_UNUSED
)
4829 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4832 const char *debstr ATTRIBUTE_UNUSED
;
4834 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
4835 /* Return a marker for use in the call instruction. */
4836 if (mode
== VOIDmode
)
4841 else if (GPR_REST_ARG_REGS (arg_num
) > 0)
4843 ret
= gen_rtx_REG (mode
, arg_num
);
4844 debstr
= reg_names
[arg_num
];
4854 /* The function to update the summarizer variable *CUM to advance past
4855 an argument in the argument list. The values MODE, TYPE and NAMED
4856 describe that argument. Once this is done, the variable *CUM is
4857 suitable for analyzing the *following* argument with
4858 `FUNCTION_ARG', etc.
4860 This function need not do anything if the argument in question was
4861 passed on the stack. The compiler knows how to track the amount of
4862 stack space used for arguments without any special help.
4864 The function is used to implement macro FUNCTION_ARG_ADVANCE. */
4865 /* For the ARC: the cum set here is passed on to function_arg where we
4866 look at its value and say which reg to use. Strategy: advance the
4867 regnumber here till we run out of arg regs, then set *cum to last
4868 reg. In function_arg, since *cum > last arg reg we would return 0
4869 and thus the arg will end up on the stack. For straddling args of
4870 course function_arg_partial_nregs will come into play. */
4873 arc_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
,
4874 const_tree type
, bool named ATTRIBUTE_UNUSED
)
4876 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4877 int bytes
= (mode
== BLKmode
4878 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
4879 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
4883 *cum
= ROUND_ADVANCE_CUM (*cum
, mode
, type
);
4884 for (i
= 0; i
< words
; i
++)
4885 *cum
= ARC_NEXT_ARG_REG (*cum
);
4889 /* Define how to find the value returned by a function.
4890 VALTYPE is the data type of the value (as a tree).
4891 If the precise function being called is known, FN_DECL_OR_TYPE is its
4892 FUNCTION_DECL; otherwise, FN_DECL_OR_TYPE is its type. */
4895 arc_function_value (const_tree valtype
,
4896 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
4897 bool outgoing ATTRIBUTE_UNUSED
)
4899 machine_mode mode
= TYPE_MODE (valtype
);
4900 int unsignedp ATTRIBUTE_UNUSED
;
4902 unsignedp
= TYPE_UNSIGNED (valtype
);
4903 if (INTEGRAL_TYPE_P (valtype
) || TREE_CODE (valtype
) == OFFSET_TYPE
)
4904 PROMOTE_MODE (mode
, unsignedp
, valtype
);
4905 return gen_rtx_REG (mode
, 0);
4908 /* Returns the return address that is used by builtin_return_address. */
4911 arc_return_addr_rtx (int count
, ATTRIBUTE_UNUSED rtx frame
)
4916 return get_hard_reg_initial_val (Pmode
, RETURN_ADDR_REGNUM
);
4919 /* Nonzero if the constant value X is a legitimate general operand
4920 when generating PIC code. It is given that flag_pic is on and
4921 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
4924 arc_legitimate_pic_operand_p (rtx x
)
4926 return !arc_raw_symbolic_reference_mentioned_p (x
, true);
4929 /* Determine if a given RTX is a valid constant. We already know this
4930 satisfies CONSTANT_P. */
4933 arc_legitimate_constant_p (machine_mode
, rtx x
)
4938 switch (GET_CODE (x
))
4943 if (GET_CODE (x
) == PLUS
)
4945 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4950 /* Only some unspecs are valid as "constants". */
4951 if (GET_CODE (x
) == UNSPEC
)
4952 switch (XINT (x
, 1))
4954 case ARC_UNSPEC_PLT
:
4955 case ARC_UNSPEC_GOTOFF
:
4956 case ARC_UNSPEC_GOT
:
4964 /* We must have drilled down to a symbol. */
4965 if (arc_raw_symbolic_reference_mentioned_p (x
, false))
4979 /* Otherwise we handle everything else in the move patterns. */
4984 arc_legitimate_address_p (machine_mode mode
, rtx x
, bool strict
)
4986 if (RTX_OK_FOR_BASE_P (x
, strict
))
4988 if (LEGITIMATE_OFFSET_ADDRESS_P (mode
, x
, TARGET_INDEXED_LOADS
, strict
))
4990 if (LEGITIMATE_SCALED_ADDRESS_P (mode
, x
, strict
))
4992 if (LEGITIMATE_SMALL_DATA_ADDRESS_P (x
))
4994 if (GET_CODE (x
) == CONST_INT
&& LARGE_INT (INTVAL (x
)))
4996 if ((GET_MODE_SIZE (mode
) != 16)
4997 && (GET_CODE (x
) == SYMBOL_REF
4998 || GET_CODE (x
) == LABEL_REF
4999 || GET_CODE (x
) == CONST
))
5001 if (!flag_pic
|| arc_legitimate_pic_addr_p (x
))
5004 if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == PRE_INC
5005 || GET_CODE (x
) == POST_DEC
|| GET_CODE (x
) == POST_INC
)
5006 && RTX_OK_FOR_BASE_P (XEXP (x
, 0), strict
))
5008 /* We're restricted here by the `st' insn. */
5009 if ((GET_CODE (x
) == PRE_MODIFY
|| GET_CODE (x
) == POST_MODIFY
)
5010 && GET_CODE (XEXP ((x
), 1)) == PLUS
5011 && rtx_equal_p (XEXP ((x
), 0), XEXP (XEXP (x
, 1), 0))
5012 && LEGITIMATE_OFFSET_ADDRESS_P (QImode
, XEXP (x
, 1),
5013 TARGET_AUTO_MODIFY_REG
, strict
))
5018 /* Return true iff ADDR (a legitimate address expression)
5019 has an effect that depends on the machine mode it is used for. */
5022 arc_mode_dependent_address_p (const_rtx addr
, addr_space_t
)
5024 /* SYMBOL_REF is not mode dependent: it is either a small data reference,
5025 which is valid for loads and stores, or a limm offset, which is valid for
5027 /* Scaled indices are scaled by the access mode; likewise for scaled
5028 offsets, which are needed for maximum offset stores. */
5029 if (GET_CODE (addr
) == PLUS
5030 && (GET_CODE (XEXP ((addr
), 0)) == MULT
5031 || (CONST_INT_P (XEXP ((addr
), 1))
5032 && !SMALL_INT (INTVAL (XEXP ((addr
), 1))))))
5037 /* Determine if it's legal to put X into the constant pool. */
5040 arc_cannot_force_const_mem (machine_mode mode
, rtx x
)
5042 return !arc_legitimate_constant_p (mode
, x
);
5046 /* Generic function to define a builtin. */
5047 #define def_mbuiltin(MASK, NAME, TYPE, CODE) \
5051 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE); \
5057 arc_init_builtins (void)
5059 tree endlink
= void_list_node
;
5061 tree void_ftype_void
5062 = build_function_type (void_type_node
,
5066 = build_function_type (integer_type_node
,
5067 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
5069 tree pcvoid_type_node
5070 = build_pointer_type (build_qualified_type (void_type_node
, TYPE_QUAL_CONST
));
5071 tree int_ftype_pcvoid_int
5072 = build_function_type (integer_type_node
,
5073 tree_cons (NULL_TREE
, pcvoid_type_node
,
5074 tree_cons (NULL_TREE
, integer_type_node
,
5077 tree int_ftype_short_int
5078 = build_function_type (integer_type_node
,
5079 tree_cons (NULL_TREE
, short_integer_type_node
, endlink
));
5081 tree void_ftype_int_int
5082 = build_function_type (void_type_node
,
5083 tree_cons (NULL_TREE
, integer_type_node
,
5084 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5085 tree void_ftype_usint_usint
5086 = build_function_type (void_type_node
,
5087 tree_cons (NULL_TREE
, long_unsigned_type_node
,
5088 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
)));
5090 tree int_ftype_int_int
5091 = build_function_type (integer_type_node
,
5092 tree_cons (NULL_TREE
, integer_type_node
,
5093 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5095 tree usint_ftype_usint
5096 = build_function_type (long_unsigned_type_node
,
5097 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5099 tree void_ftype_usint
5100 = build_function_type (void_type_node
,
5101 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5103 /* Add the builtins. */
5104 def_mbuiltin (1,"__builtin_arc_nop", void_ftype_void
, ARC_BUILTIN_NOP
);
5105 def_mbuiltin (TARGET_NORM
, "__builtin_arc_norm", int_ftype_int
, ARC_BUILTIN_NORM
);
5106 def_mbuiltin (TARGET_NORM
, "__builtin_arc_normw", int_ftype_short_int
, ARC_BUILTIN_NORMW
);
5107 def_mbuiltin (TARGET_SWAP
, "__builtin_arc_swap", int_ftype_int
, ARC_BUILTIN_SWAP
);
5108 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mul64", void_ftype_int_int
, ARC_BUILTIN_MUL64
);
5109 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mulu64", void_ftype_usint_usint
, ARC_BUILTIN_MULU64
);
5110 def_mbuiltin (1,"__builtin_arc_rtie", void_ftype_void
, ARC_BUILTIN_RTIE
);
5111 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_sync", void_ftype_void
, ARC_BUILTIN_SYNC
);
5112 def_mbuiltin ((TARGET_EA_SET
),"__builtin_arc_divaw", int_ftype_int_int
, ARC_BUILTIN_DIVAW
);
5113 def_mbuiltin (1,"__builtin_arc_brk", void_ftype_void
, ARC_BUILTIN_BRK
);
5114 def_mbuiltin (1,"__builtin_arc_flag", void_ftype_usint
, ARC_BUILTIN_FLAG
);
5115 def_mbuiltin (1,"__builtin_arc_sleep", void_ftype_usint
, ARC_BUILTIN_SLEEP
);
5116 def_mbuiltin (1,"__builtin_arc_swi", void_ftype_void
, ARC_BUILTIN_SWI
);
5117 def_mbuiltin (1,"__builtin_arc_core_read", usint_ftype_usint
, ARC_BUILTIN_CORE_READ
);
5118 def_mbuiltin (1,"__builtin_arc_core_write", void_ftype_usint_usint
, ARC_BUILTIN_CORE_WRITE
);
5119 def_mbuiltin (1,"__builtin_arc_lr", usint_ftype_usint
, ARC_BUILTIN_LR
);
5120 def_mbuiltin (1,"__builtin_arc_sr", void_ftype_usint_usint
, ARC_BUILTIN_SR
);
5121 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_trap_s", void_ftype_usint
, ARC_BUILTIN_TRAP_S
);
5122 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_unimp_s", void_ftype_void
, ARC_BUILTIN_UNIMP_S
);
5123 def_mbuiltin (1,"__builtin_arc_aligned", int_ftype_pcvoid_int
, ARC_BUILTIN_ALIGNED
);
5125 if (TARGET_SIMD_SET
)
5126 arc_init_simd_builtins ();
5129 static rtx
arc_expand_simd_builtin (tree
, rtx
, rtx
, machine_mode
, int);
5131 /* Expand an expression EXP that calls a built-in function,
5132 with result going to TARGET if that's convenient
5133 (and in mode MODE if that's convenient).
5134 SUBTARGET may be used as the target for computing one of EXP's operands.
5135 IGNORE is nonzero if the value is to be ignored. */
5138 arc_expand_builtin (tree exp
,
5144 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
5149 int fcode
= DECL_FUNCTION_CODE (fndecl
);
5154 if (fcode
> ARC_SIMD_BUILTIN_BEGIN
&& fcode
< ARC_SIMD_BUILTIN_END
)
5155 return arc_expand_simd_builtin (exp
, target
, subtarget
, mode
, ignore
);
5159 case ARC_BUILTIN_NOP
:
5160 emit_insn (gen_nop ());
5163 case ARC_BUILTIN_NORM
:
5164 icode
= CODE_FOR_clrsbsi2
;
5165 arg0
= CALL_EXPR_ARG (exp
, 0);
5166 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5167 mode0
= insn_data
[icode
].operand
[1].mode
;
5168 target
= gen_reg_rtx (SImode
);
5170 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5171 op0
= copy_to_mode_reg (mode0
, op0
);
5173 emit_insn (gen_clrsbsi2 (target
, op0
));
5176 case ARC_BUILTIN_NORMW
:
5178 /* FIXME : This should all be HImode, not SImode. */
5179 icode
= CODE_FOR_normw
;
5180 arg0
= CALL_EXPR_ARG (exp
, 0);
5181 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5182 mode0
= insn_data
[icode
].operand
[1].mode
;
5183 target
= gen_reg_rtx (SImode
);
5185 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5186 op0
= copy_to_mode_reg (mode0
, convert_to_mode (mode0
, op0
,0));
5188 emit_insn (gen_normw (target
, op0
));
5191 case ARC_BUILTIN_MUL64
:
5192 icode
= CODE_FOR_mul64
;
5193 arg0
= CALL_EXPR_ARG (exp
, 0);
5194 arg1
= CALL_EXPR_ARG (exp
, 1);
5195 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5196 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5198 mode0
= insn_data
[icode
].operand
[0].mode
;
5199 mode1
= insn_data
[icode
].operand
[1].mode
;
5201 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5202 op0
= copy_to_mode_reg (mode0
, op0
);
5204 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5205 op1
= copy_to_mode_reg (mode1
, op1
);
5207 emit_insn (gen_mul64 (op0
,op1
));
5210 case ARC_BUILTIN_MULU64
:
5211 icode
= CODE_FOR_mulu64
;
5212 arg0
= CALL_EXPR_ARG (exp
, 0);
5213 arg1
= CALL_EXPR_ARG (exp
, 1);
5214 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5215 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5217 mode0
= insn_data
[icode
].operand
[0].mode
;
5218 mode1
= insn_data
[icode
].operand
[1].mode
;
5220 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5221 op0
= copy_to_mode_reg (mode0
, op0
);
5223 if (! (*insn_data
[icode
].operand
[0].predicate
) (op1
, mode1
))
5224 op1
= copy_to_mode_reg (mode1
, op1
);
5226 emit_insn (gen_mulu64 (op0
,op1
));
5229 case ARC_BUILTIN_RTIE
:
5230 icode
= CODE_FOR_rtie
;
5231 emit_insn (gen_rtie (const1_rtx
));
5234 case ARC_BUILTIN_SYNC
:
5235 icode
= CODE_FOR_sync
;
5236 emit_insn (gen_sync (const1_rtx
));
5239 case ARC_BUILTIN_SWAP
:
5240 icode
= CODE_FOR_swap
;
5241 arg0
= CALL_EXPR_ARG (exp
, 0);
5242 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5243 mode0
= insn_data
[icode
].operand
[1].mode
;
5244 target
= gen_reg_rtx (SImode
);
5246 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5247 op0
= copy_to_mode_reg (mode0
, op0
);
5249 emit_insn (gen_swap (target
, op0
));
5252 case ARC_BUILTIN_DIVAW
:
5253 icode
= CODE_FOR_divaw
;
5254 arg0
= CALL_EXPR_ARG (exp
, 0);
5255 arg1
= CALL_EXPR_ARG (exp
, 1);
5257 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5258 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5259 target
= gen_reg_rtx (SImode
);
5261 mode0
= insn_data
[icode
].operand
[0].mode
;
5262 mode1
= insn_data
[icode
].operand
[1].mode
;
5264 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5265 op0
= copy_to_mode_reg (mode0
, op0
);
5267 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5268 op1
= copy_to_mode_reg (mode1
, op1
);
5270 emit_insn (gen_divaw (target
, op0
, op1
));
5273 case ARC_BUILTIN_BRK
:
5274 icode
= CODE_FOR_brk
;
5275 emit_insn (gen_brk (const1_rtx
));
5278 case ARC_BUILTIN_SLEEP
:
5279 icode
= CODE_FOR_sleep
;
5280 arg0
= CALL_EXPR_ARG (exp
, 0);
5284 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5285 mode0
= insn_data
[icode
].operand
[1].mode
;
5287 emit_insn (gen_sleep (op0
));
5290 case ARC_BUILTIN_SWI
:
5291 icode
= CODE_FOR_swi
;
5292 emit_insn (gen_swi (const1_rtx
));
5295 case ARC_BUILTIN_FLAG
:
5296 icode
= CODE_FOR_flag
;
5297 arg0
= CALL_EXPR_ARG (exp
, 0);
5298 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5299 mode0
= insn_data
[icode
].operand
[0].mode
;
5301 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5302 op0
= copy_to_mode_reg (mode0
, op0
);
5304 emit_insn (gen_flag (op0
));
5307 case ARC_BUILTIN_CORE_READ
:
5308 icode
= CODE_FOR_core_read
;
5309 arg0
= CALL_EXPR_ARG (exp
, 0);
5310 target
= gen_reg_rtx (SImode
);
5314 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5315 mode0
= insn_data
[icode
].operand
[1].mode
;
5317 emit_insn (gen_core_read (target
, op0
));
5320 case ARC_BUILTIN_CORE_WRITE
:
5321 icode
= CODE_FOR_core_write
;
5322 arg0
= CALL_EXPR_ARG (exp
, 0);
5323 arg1
= CALL_EXPR_ARG (exp
, 1);
5327 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5328 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5330 mode0
= insn_data
[icode
].operand
[0].mode
;
5331 mode1
= insn_data
[icode
].operand
[1].mode
;
5333 emit_insn (gen_core_write (op0
, op1
));
5336 case ARC_BUILTIN_LR
:
5337 icode
= CODE_FOR_lr
;
5338 arg0
= CALL_EXPR_ARG (exp
, 0);
5339 target
= gen_reg_rtx (SImode
);
5343 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5344 mode0
= insn_data
[icode
].operand
[1].mode
;
5346 emit_insn (gen_lr (target
, op0
));
5349 case ARC_BUILTIN_SR
:
5350 icode
= CODE_FOR_sr
;
5351 arg0
= CALL_EXPR_ARG (exp
, 0);
5352 arg1
= CALL_EXPR_ARG (exp
, 1);
5356 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5357 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5359 mode0
= insn_data
[icode
].operand
[0].mode
;
5360 mode1
= insn_data
[icode
].operand
[1].mode
;
5362 emit_insn (gen_sr (op0
, op1
));
5365 case ARC_BUILTIN_TRAP_S
:
5366 icode
= CODE_FOR_trap_s
;
5367 arg0
= CALL_EXPR_ARG (exp
, 0);
5371 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5372 mode0
= insn_data
[icode
].operand
[1].mode
;
5374 /* We don't give an error for non-cost values here because
5375 we still want to allow things to be fixed up by later inlining /
5376 constant folding / dead code elimination. */
5377 if (CONST_INT_P (op0
) && !satisfies_constraint_L (op0
))
5379 /* Keep this message in sync with the one in arc.md:trap_s,
5380 because *.md files don't get scanned by exgettext. */
5381 error ("operand to trap_s should be an unsigned 6-bit value");
5383 emit_insn (gen_trap_s (op0
));
5386 case ARC_BUILTIN_UNIMP_S
:
5387 icode
= CODE_FOR_unimp_s
;
5388 emit_insn (gen_unimp_s (const1_rtx
));
5391 case ARC_BUILTIN_ALIGNED
:
5392 /* __builtin_arc_aligned (void* val, int alignval) */
5393 arg0
= CALL_EXPR_ARG (exp
, 0);
5394 arg1
= CALL_EXPR_ARG (exp
, 1);
5396 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5397 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5398 target
= gen_reg_rtx (SImode
);
5400 if (!CONST_INT_P (op1
))
5402 /* If we can't fold the alignment to a constant integer
5403 whilst optimizing, this is probably a user error. */
5405 warning (0, "__builtin_arc_aligned with non-constant alignment");
5409 HOST_WIDE_INT alignTest
= INTVAL (op1
);
5410 /* Check alignTest is positive, and a power of two. */
5411 if (alignTest
<= 0 || alignTest
!= (alignTest
& -alignTest
))
5413 error ("invalid alignment value for __builtin_arc_aligned");
5417 if (CONST_INT_P (op0
))
5419 HOST_WIDE_INT pnt
= INTVAL (op0
);
5421 if ((pnt
& (alignTest
- 1)) == 0)
5426 unsigned align
= get_pointer_alignment (arg0
);
5427 unsigned numBits
= alignTest
* BITS_PER_UNIT
;
5429 if (align
&& align
>= numBits
)
5431 /* Another attempt to ascertain alignment. Check the type
5432 we are pointing to. */
5433 if (POINTER_TYPE_P (TREE_TYPE (arg0
))
5434 && TYPE_ALIGN (TREE_TYPE (TREE_TYPE (arg0
))) >= numBits
)
5439 /* Default to false. */
5446 /* @@@ Should really do something sensible here. */
5450 /* Returns true if the operands[opno] is a valid compile-time constant to be
5451 used as register number in the code for builtins. Else it flags an error
5452 and returns false. */
5455 check_if_valid_regno_const (rtx
*operands
, int opno
)
5458 switch (GET_CODE (operands
[opno
]))
5465 error ("register number must be a compile-time constant. Try giving higher optimization levels");
5471 /* Check that after all the constant folding, whether the operand to
5472 __builtin_arc_sleep is an unsigned int of 6 bits. If not, flag an error. */
5475 check_if_valid_sleep_operand (rtx
*operands
, int opno
)
5477 switch (GET_CODE (operands
[opno
]))
5481 if( UNSIGNED_INT6 (INTVAL (operands
[opno
])))
5484 fatal_error("operand for sleep instruction must be an unsigned 6 bit compile-time constant");
5490 /* Return true if it is ok to make a tail-call to DECL. */
5493 arc_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED
,
5494 tree exp ATTRIBUTE_UNUSED
)
5496 /* Never tailcall from an ISR routine - it needs a special exit sequence. */
5497 if (ARC_INTERRUPT_P (arc_compute_function_type (cfun
)))
5500 /* Everything else is ok. */
5504 /* Output code to add DELTA to the first argument, and then jump
5505 to FUNCTION. Used for C++ multiple inheritance. */
5508 arc_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
5509 HOST_WIDE_INT delta
,
5510 HOST_WIDE_INT vcall_offset
,
5513 int mi_delta
= delta
;
5514 const char *const mi_op
= mi_delta
< 0 ? "sub" : "add";
5517 = aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
) ? 1 : 0;
5521 mi_delta
= - mi_delta
;
5523 /* Add DELTA. When possible use a plain add, otherwise load it into
5524 a register first. */
5526 while (mi_delta
!= 0)
5528 if ((mi_delta
& (3 << shift
)) == 0)
5532 asm_fprintf (file
, "\t%s\t%s, %s, %d\n",
5533 mi_op
, reg_names
[this_regno
], reg_names
[this_regno
],
5534 mi_delta
& (0xff << shift
));
5535 mi_delta
&= ~(0xff << shift
);
5540 /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
5541 if (vcall_offset
!= 0)
5543 /* ld r12,[this] --> temp = *this
5544 add r12,r12,vcall_offset --> temp = *(*this + vcall_offset)
5546 add this,this,r12 --> this+ = *(*this + vcall_offset) */
5547 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5548 ARC_TEMP_SCRATCH_REG
, reg_names
[this_regno
]);
5549 asm_fprintf (file
, "\tadd\t%s, %s, " HOST_WIDE_INT_PRINT_DEC
"\n",
5550 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
, vcall_offset
);
5551 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5552 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
);
5553 asm_fprintf (file
, "\tadd\t%s, %s, %s\n", reg_names
[this_regno
],
5554 reg_names
[this_regno
], ARC_TEMP_SCRATCH_REG
);
5557 fnaddr
= XEXP (DECL_RTL (function
), 0);
5559 if (arc_is_longcall_p (fnaddr
))
5560 fputs ("\tj\t", file
);
5562 fputs ("\tb\t", file
);
5563 assemble_name (file
, XSTR (fnaddr
, 0));
5567 /* Return true if a 32 bit "long_call" should be generated for
5568 this calling SYM_REF. We generate a long_call if the function:
5570 a. has an __attribute__((long call))
5571 or b. the -mlong-calls command line switch has been specified
5573 However we do not generate a long call if the function has an
5574 __attribute__ ((short_call)) or __attribute__ ((medium_call))
5576 This function will be called by C fragments contained in the machine
5577 description file. */
5580 arc_is_longcall_p (rtx sym_ref
)
5582 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5585 return (SYMBOL_REF_LONG_CALL_P (sym_ref
)
5586 || (TARGET_LONG_CALLS_SET
5587 && !SYMBOL_REF_SHORT_CALL_P (sym_ref
)
5588 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
5592 /* Likewise for short calls. */
5595 arc_is_shortcall_p (rtx sym_ref
)
5597 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5600 return (SYMBOL_REF_SHORT_CALL_P (sym_ref
)
5601 || (!TARGET_LONG_CALLS_SET
&& !TARGET_MEDIUM_CALLS
5602 && !SYMBOL_REF_LONG_CALL_P (sym_ref
)
5603 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
5607 /* Emit profiling code for calling CALLEE. Return true if a special
5608 call pattern needs to be generated. */
5611 arc_profile_call (rtx callee
)
5613 rtx from
= XEXP (DECL_RTL (current_function_decl
), 0);
5615 if (TARGET_UCB_MCOUNT
)
5616 /* Profiling is done by instrumenting the callee. */
5619 if (CONSTANT_P (callee
))
5622 = gen_rtx_CONST (Pmode
,
5623 gen_rtx_UNSPEC (Pmode
,
5624 gen_rtvec (3, from
, callee
,
5625 CONST0_RTX (Pmode
)),
5627 rtx counter
= gen_rtx_MEM (SImode
, count_ptr
);
5628 /* ??? The increment would better be done atomically, but as there is
5629 no proper hardware support, that would be too expensive. */
5630 emit_move_insn (counter
,
5631 force_reg (SImode
, plus_constant (SImode
, counter
, 1)));
5637 = gen_rtx_CONST (Pmode
,
5638 gen_rtx_UNSPEC (Pmode
,
5639 gen_rtvec (3, from
, CONST0_RTX (Pmode
),
5640 CONST0_RTX (Pmode
)),
5642 emit_move_insn (gen_rtx_REG (Pmode
, 8), count_list_ptr
);
5643 emit_move_insn (gen_rtx_REG (Pmode
, 9), callee
);
5648 /* Worker function for TARGET_RETURN_IN_MEMORY. */
5651 arc_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
5653 if (AGGREGATE_TYPE_P (type
) || TREE_ADDRESSABLE (type
))
5657 HOST_WIDE_INT size
= int_size_in_bytes (type
);
5658 return (size
== -1 || size
> 8);
5663 /* This was in rtlanal.c, and can go in there when we decide we want
5664 to submit the change for inclusion in the GCC tree. */
5665 /* Like note_stores, but allow the callback to have side effects on the rtl
5666 (like the note_stores of yore):
5667 Call FUN on each register or MEM that is stored into or clobbered by X.
5668 (X would be the pattern of an insn). DATA is an arbitrary pointer,
5669 ignored by note_stores, but passed to FUN.
5670 FUN may alter parts of the RTL.
5672 FUN receives three arguments:
5673 1. the REG, MEM, CC0 or PC being stored in or clobbered,
5674 2. the SET or CLOBBER rtx that does the store,
5675 3. the pointer DATA provided to note_stores.
5677 If the item being stored in or clobbered is a SUBREG of a hard register,
5678 the SUBREG will be passed. */
5680 /* For now. */ static
5682 walk_stores (rtx x
, void (*fun
) (rtx
, rtx
, void *), void *data
)
5686 if (GET_CODE (x
) == COND_EXEC
)
5687 x
= COND_EXEC_CODE (x
);
5689 if (GET_CODE (x
) == SET
|| GET_CODE (x
) == CLOBBER
)
5691 rtx dest
= SET_DEST (x
);
5693 while ((GET_CODE (dest
) == SUBREG
5694 && (!REG_P (SUBREG_REG (dest
))
5695 || REGNO (SUBREG_REG (dest
)) >= FIRST_PSEUDO_REGISTER
))
5696 || GET_CODE (dest
) == ZERO_EXTRACT
5697 || GET_CODE (dest
) == STRICT_LOW_PART
)
5698 dest
= XEXP (dest
, 0);
5700 /* If we have a PARALLEL, SET_DEST is a list of EXPR_LIST expressions,
5701 each of whose first operand is a register. */
5702 if (GET_CODE (dest
) == PARALLEL
)
5704 for (i
= XVECLEN (dest
, 0) - 1; i
>= 0; i
--)
5705 if (XEXP (XVECEXP (dest
, 0, i
), 0) != 0)
5706 (*fun
) (XEXP (XVECEXP (dest
, 0, i
), 0), x
, data
);
5709 (*fun
) (dest
, x
, data
);
5712 else if (GET_CODE (x
) == PARALLEL
)
5713 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
5714 walk_stores (XVECEXP (x
, 0, i
), fun
, data
);
5718 arc_pass_by_reference (cumulative_args_t ca_v ATTRIBUTE_UNUSED
,
5719 machine_mode mode ATTRIBUTE_UNUSED
,
5721 bool named ATTRIBUTE_UNUSED
)
5724 && (TREE_CODE (TYPE_SIZE (type
)) != INTEGER_CST
5725 || TREE_ADDRESSABLE (type
)));
5728 /* Implement TARGET_CAN_USE_DOLOOP_P. */
5731 arc_can_use_doloop_p (const widest_int
&iterations
, const widest_int
&,
5732 unsigned int loop_depth
, bool entered_at_top
)
5736 /* Setting up the loop with two sr instructions costs 6 cycles. */
5739 && wi::gtu_p (iterations
, 0)
5740 && wi::leu_p (iterations
, flag_pic
? 6 : 3))
5745 /* NULL if INSN insn is valid within a low-overhead loop.
5746 Otherwise return why doloop cannot be applied. */
5749 arc_invalid_within_doloop (const rtx_insn
*insn
)
5752 return "Function call in the loop.";
5756 static int arc_reorg_in_progress
= 0;
5758 /* ARC's machince specific reorg function. */
5769 cfun
->machine
->arc_reorg_started
= 1;
5770 arc_reorg_in_progress
= 1;
5772 /* Emit special sections for profiling. */
5775 section
*save_text_section
;
5777 int size
= get_max_uid () >> 4;
5778 htab_t htab
= htab_create (size
, unspec_prof_hash
, unspec_prof_htab_eq
,
5781 save_text_section
= in_section
;
5782 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5783 if (NONJUMP_INSN_P (insn
))
5784 walk_stores (PATTERN (insn
), write_profile_sections
, htab
);
5785 if (htab_elements (htab
))
5787 switch_to_section (save_text_section
);
5791 /* Link up loop ends with their loop start. */
5793 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5794 if (GET_CODE (insn
) == JUMP_INSN
5795 && recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
5798 = as_a
<rtx_insn
*> (XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 1), 0));
5799 rtx num
= GEN_INT (CODE_LABEL_NUMBER (top_label
));
5800 rtx_insn
*lp
, *prev
= prev_nonnote_insn (top_label
);
5801 rtx_insn
*lp_simple
= NULL
;
5802 rtx_insn
*next
= NULL
;
5803 rtx op0
= XEXP (XVECEXP (PATTERN (insn
), 0, 1), 0);
5804 HOST_WIDE_INT loop_end_id
5805 = -INTVAL (XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0));
5809 (lp
&& NONJUMP_INSN_P (lp
)
5810 && recog_memoized (lp
) != CODE_FOR_doloop_begin_i
);
5811 lp
= prev_nonnote_insn (lp
))
5813 if (!lp
|| !NONJUMP_INSN_P (lp
)
5814 || dead_or_set_regno_p (lp
, LP_COUNT
))
5816 for (prev
= next
= insn
, lp
= NULL
; prev
|| next
;)
5820 if (NONJUMP_INSN_P (prev
)
5821 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
5822 && (INTVAL (XEXP (XVECEXP (PATTERN (prev
), 0, 5), 0))
5828 else if (LABEL_P (prev
))
5830 prev
= prev_nonnote_insn (prev
);
5834 if (NONJUMP_INSN_P (next
)
5835 && recog_memoized (next
) == CODE_FOR_doloop_begin_i
5836 && (INTVAL (XEXP (XVECEXP (PATTERN (next
), 0, 5), 0))
5842 next
= next_nonnote_insn (next
);
5849 if (lp
&& !dead_or_set_regno_p (lp
, LP_COUNT
))
5851 rtx begin_cnt
= XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0);
5852 if (INTVAL (XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0)))
5853 /* The loop end insn has been duplicated. That can happen
5854 when there is a conditional block at the very end of
5857 /* If Register allocation failed to allocate to the right
5858 register, There is no point into teaching reload to
5859 fix this up with reloads, as that would cost more
5860 than using an ordinary core register with the
5861 doloop_fallback pattern. */
5862 if ((true_regnum (op0
) != LP_COUNT
|| !REG_P (begin_cnt
))
5863 /* Likewise, if the loop setup is evidently inside the loop,
5865 || (!lp_simple
&& lp
!= next
&& !seen_label
))
5870 /* It is common that the optimizers copy the loop count from
5871 another register, and doloop_begin_i is stuck with the
5872 source of the move. Making doloop_begin_i only accept "l"
5873 is nonsentical, as this then makes reload evict the pseudo
5874 used for the loop end. The underlying cause is that the
5875 optimizers don't understand that the register allocation for
5876 doloop_begin_i should be treated as part of the loop.
5877 Try to work around this problem by verifying the previous
5879 if (true_regnum (begin_cnt
) != LP_COUNT
)
5884 for (mov
= prev_nonnote_insn (lp
); mov
;
5885 mov
= prev_nonnote_insn (mov
))
5887 if (!NONJUMP_INSN_P (mov
))
5889 else if ((set
= single_set (mov
))
5890 && rtx_equal_p (SET_SRC (set
), begin_cnt
)
5891 && rtx_equal_p (SET_DEST (set
), op0
))
5896 XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0) = op0
;
5897 note
= find_regno_note (lp
, REG_DEAD
, REGNO (begin_cnt
));
5899 remove_note (lp
, note
);
5907 XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0) = num
;
5908 XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0) = num
;
5910 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const2_rtx
;
5911 else if (!lp_simple
)
5912 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const1_rtx
;
5913 else if (prev
!= lp
)
5916 add_insn_after (lp
, prev
, NULL
);
5920 XEXP (XVECEXP (PATTERN (lp
), 0, 7), 0)
5921 = gen_rtx_LABEL_REF (Pmode
, top_label
);
5922 add_reg_note (lp
, REG_LABEL_OPERAND
, top_label
);
5923 LABEL_NUSES (top_label
)++;
5925 /* We can avoid tedious loop start / end setting for empty loops
5926 be merely setting the loop count to its final value. */
5927 if (next_active_insn (top_label
) == insn
)
5930 = gen_rtx_SET (VOIDmode
,
5931 XEXP (XVECEXP (PATTERN (lp
), 0, 3), 0),
5934 rtx_insn
*lc_set_insn
= emit_insn_before (lc_set
, insn
);
5939 /* If the loop is non-empty with zero length, we can't make it
5940 a zero-overhead loop. That can happen for empty asms. */
5945 for (scan
= top_label
;
5946 (scan
&& scan
!= insn
5947 && (!NONJUMP_INSN_P (scan
) || !get_attr_length (scan
)));
5948 scan
= NEXT_INSN (scan
));
5958 /* Sometimes the loop optimizer makes a complete hash of the
5959 loop. If it were only that the loop is not entered at the
5960 top, we could fix this up by setting LP_START with SR .
5961 However, if we can't find the loop begin were it should be,
5962 chances are that it does not even dominate the loop, but is
5963 inside the loop instead. Using SR there would kill
5965 We use the doloop_fallback pattern here, which executes
5966 in two cycles on the ARC700 when predicted correctly. */
5970 rtx op3
= XEXP (XVECEXP (PATTERN (insn
), 0, 5), 0);
5972 emit_insn_before (gen_move_insn (op3
, op0
), insn
);
5974 = gen_doloop_fallback_m (op3
, JUMP_LABEL (insn
), op0
);
5977 XVEC (PATTERN (insn
), 0)
5978 = gen_rtvec (2, XVECEXP (PATTERN (insn
), 0, 0),
5979 XVECEXP (PATTERN (insn
), 0, 1));
5980 INSN_CODE (insn
) = -1;
5985 /* FIXME: should anticipate ccfsm action, generate special patterns for
5986 to-be-deleted branches that have no delay slot and have at least the
5987 length of the size increase forced on other insns that are conditionalized.
5988 This can also have an insn_list inside that enumerates insns which are
5989 not actually conditionalized because the destinations are dead in the
5991 Could also tag branches that we want to be unaligned if they get no delay
5992 slot, or even ones that we don't want to do delay slot sheduling for
5993 because we can unalign them.
5995 However, there are cases when conditional execution is only possible after
5996 delay slot scheduling:
5998 - If a delay slot is filled with a nocond/set insn from above, the previous
5999 basic block can become elegible for conditional execution.
6000 - If a delay slot is filled with a nocond insn from the fall-through path,
6001 the branch with that delay slot can become eligble for conditional
6002 execution (however, with the same sort of data flow analysis that dbr
6003 does, we could have figured out before that we don't need to
6004 conditionalize this insn.)
6005 - If a delay slot insn is filled with an insn from the target, the
6006 target label gets its uses decremented (even deleted if falling to zero),
6007 thus possibly creating more condexec opportunities there.
6008 Therefore, we should still be prepared to apply condexec optimization on
6009 non-prepared branches if the size increase of conditionalized insns is no
6010 more than the size saved from eliminating the branch. An invocation option
6011 could also be used to reserve a bit of extra size for condbranches so that
6012 this'll work more often (could also test in arc_reorg if the block is
6013 'close enough' to be eligible for condexec to make this likely, and
6014 estimate required size increase). */
6015 /* Generate BRcc insns, by combining cmp and Bcc insns wherever possible. */
6016 if (TARGET_NO_BRCC_SET
)
6021 init_insn_lengths();
6024 if (optimize
> 1 && !TARGET_NO_COND_EXEC
)
6027 unsigned int flags
= pass_data_arc_ifcvt
.todo_flags_finish
;
6028 df_finish_pass ((flags
& TODO_df_verify
) != 0);
6031 /* Call shorten_branches to calculate the insn lengths. */
6032 shorten_branches (get_insns());
6033 cfun
->machine
->ccfsm_current_insn
= NULL_RTX
;
6035 if (!INSN_ADDRESSES_SET_P())
6036 fatal_error ("Insn addresses not set after shorten_branches");
6038 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
6041 enum attr_type insn_type
;
6043 /* If a non-jump insn (or a casesi jump table), continue. */
6044 if (GET_CODE (insn
) != JUMP_INSN
||
6045 GET_CODE (PATTERN (insn
)) == ADDR_VEC
6046 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
6049 /* If we already have a brcc, note if it is suitable for brcc_s.
6050 Be a bit generous with the brcc_s range so that we can take
6051 advantage of any code shortening from delay slot scheduling. */
6052 if (recog_memoized (insn
) == CODE_FOR_cbranchsi4_scratch
)
6054 rtx pat
= PATTERN (insn
);
6055 rtx op
= XEXP (SET_SRC (XVECEXP (pat
, 0, 0)), 0);
6056 rtx
*ccp
= &XEXP (XVECEXP (pat
, 0, 1), 0);
6058 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6059 if ((offset
>= -140 && offset
< 140)
6060 && rtx_equal_p (XEXP (op
, 1), const0_rtx
)
6061 && compact_register_operand (XEXP (op
, 0), VOIDmode
)
6062 && equality_comparison_operator (op
, VOIDmode
))
6063 PUT_MODE (*ccp
, CC_Zmode
);
6064 else if (GET_MODE (*ccp
) == CC_Zmode
)
6065 PUT_MODE (*ccp
, CC_ZNmode
);
6068 if ((insn_type
= get_attr_type (insn
)) == TYPE_BRCC
6069 || insn_type
== TYPE_BRCC_NO_DELAY_SLOT
)
6072 /* OK. so we have a jump insn. */
6073 /* We need to check that it is a bcc. */
6074 /* Bcc => set (pc) (if_then_else ) */
6075 pattern
= PATTERN (insn
);
6076 if (GET_CODE (pattern
) != SET
6077 || GET_CODE (SET_SRC (pattern
)) != IF_THEN_ELSE
6078 || ANY_RETURN_P (XEXP (SET_SRC (pattern
), 1)))
6081 /* Now check if the jump is beyond the s9 range. */
6082 if (CROSSING_JUMP_P (insn
))
6084 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6086 if(offset
> 253 || offset
< -254)
6089 pc_target
= SET_SRC (pattern
);
6091 /* Now go back and search for the set cc insn. */
6093 label
= XEXP (pc_target
, 1);
6097 rtx_insn
*scan
, *link_insn
= NULL
;
6099 for (scan
= PREV_INSN (insn
);
6100 scan
&& GET_CODE (scan
) != CODE_LABEL
;
6101 scan
= PREV_INSN (scan
))
6103 if (! INSN_P (scan
))
6105 pat
= PATTERN (scan
);
6106 if (GET_CODE (pat
) == SET
6107 && cc_register (SET_DEST (pat
), VOIDmode
))
6116 /* Check if this is a data dependency. */
6118 rtx op
, cc_clob_rtx
, op0
, op1
, brcc_insn
, note
;
6121 /* Ok this is the set cc. copy args here. */
6122 op
= XEXP (pc_target
, 0);
6124 op0
= cmp0
= XEXP (SET_SRC (pat
), 0);
6125 op1
= cmp1
= XEXP (SET_SRC (pat
), 1);
6126 if (GET_CODE (op0
) == ZERO_EXTRACT
6127 && XEXP (op0
, 1) == const1_rtx
6128 && (GET_CODE (op
) == EQ
6129 || GET_CODE (op
) == NE
))
6131 /* btst / b{eq,ne} -> bbit{0,1} */
6132 op0
= XEXP (cmp0
, 0);
6133 op1
= XEXP (cmp0
, 2);
6135 else if (!register_operand (op0
, VOIDmode
)
6136 || !general_operand (op1
, VOIDmode
))
6138 /* Be careful not to break what cmpsfpx_raw is
6139 trying to create for checking equality of
6140 single-precision floats. */
6141 else if (TARGET_SPFP
6142 && GET_MODE (op0
) == SFmode
6143 && GET_MODE (op1
) == SFmode
)
6146 /* None of the two cmp operands should be set between the
6147 cmp and the branch. */
6148 if (reg_set_between_p (op0
, link_insn
, insn
))
6151 if (reg_set_between_p (op1
, link_insn
, insn
))
6154 /* Since the MODE check does not work, check that this is
6155 CC reg's last set location before insn, and also no
6156 instruction between the cmp and branch uses the
6158 if ((reg_set_between_p (SET_DEST (pat
), link_insn
, insn
))
6159 || (reg_used_between_p (SET_DEST (pat
), link_insn
, insn
)))
6162 /* CC reg should be dead after insn. */
6163 if (!find_regno_note (insn
, REG_DEAD
, CC_REG
))
6166 op
= gen_rtx_fmt_ee (GET_CODE (op
),
6167 GET_MODE (op
), cmp0
, cmp1
);
6168 /* If we create a LIMM where there was none before,
6169 we only benefit if we can avoid a scheduling bubble
6170 for the ARC600. Otherwise, we'd only forgo chances
6171 at short insn generation, and risk out-of-range
6173 if (!brcc_nolimm_operator (op
, VOIDmode
)
6174 && !long_immediate_operand (op1
, VOIDmode
)
6176 || next_active_insn (link_insn
) != insn
))
6179 /* Emit bbit / brcc (or brcc_s if possible).
6180 CC_Zmode indicates that brcc_s is possible. */
6183 cc_clob_rtx
= gen_rtx_REG (CC_ZNmode
, CC_REG
);
6184 else if ((offset
>= -140 && offset
< 140)
6185 && rtx_equal_p (op1
, const0_rtx
)
6186 && compact_register_operand (op0
, VOIDmode
)
6187 && (GET_CODE (op
) == EQ
6188 || GET_CODE (op
) == NE
))
6189 cc_clob_rtx
= gen_rtx_REG (CC_Zmode
, CC_REG
);
6191 cc_clob_rtx
= gen_rtx_REG (CCmode
, CC_REG
);
6194 = gen_rtx_IF_THEN_ELSE (VOIDmode
, op
, label
, pc_rtx
);
6195 brcc_insn
= gen_rtx_SET (VOIDmode
, pc_rtx
, brcc_insn
);
6196 cc_clob_rtx
= gen_rtx_CLOBBER (VOIDmode
, cc_clob_rtx
);
6199 (VOIDmode
, gen_rtvec (2, brcc_insn
, cc_clob_rtx
));
6200 brcc_insn
= emit_jump_insn_before (brcc_insn
, insn
);
6202 JUMP_LABEL (brcc_insn
) = JUMP_LABEL (insn
);
6203 note
= find_reg_note (insn
, REG_BR_PROB
, 0);
6206 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6207 REG_NOTES (brcc_insn
) = note
;
6209 note
= find_reg_note (link_insn
, REG_DEAD
, op0
);
6212 remove_note (link_insn
, note
);
6213 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6214 REG_NOTES (brcc_insn
) = note
;
6216 note
= find_reg_note (link_insn
, REG_DEAD
, op1
);
6219 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6220 REG_NOTES (brcc_insn
) = note
;
6225 /* Delete the bcc insn. */
6226 set_insn_deleted (insn
);
6228 /* Delete the cmp insn. */
6229 set_insn_deleted (link_insn
);
6234 /* Clear out insn_addresses. */
6235 INSN_ADDRESSES_FREE ();
6239 if (INSN_ADDRESSES_SET_P())
6240 fatal_error ("insn addresses not freed");
6242 arc_reorg_in_progress
= 0;
6245 /* Check if the operands are valid for BRcc.d generation
6246 Valid Brcc.d patterns are
6250 For cc={GT, LE, GTU, LEU}, u6=63 can not be allowed,
6251 since they are encoded by the assembler as {GE, LT, HS, LS} 64, which
6252 does not have a delay slot
6254 Assumed precondition: Second operand is either a register or a u6 value. */
6257 valid_brcc_with_delay_p (rtx
*operands
)
6259 if (optimize_size
&& GET_MODE (operands
[4]) == CC_Zmode
)
6261 return brcc_nolimm_operator (operands
[0], VOIDmode
);
6264 /* ??? Hack. This should no really be here. See PR32143. */
6266 arc_decl_anon_ns_mem_p (const_tree decl
)
6270 if (decl
== NULL_TREE
|| decl
== error_mark_node
)
6272 if (TREE_CODE (decl
) == NAMESPACE_DECL
6273 && DECL_NAME (decl
) == NULL_TREE
)
6275 /* Classes and namespaces inside anonymous namespaces have
6276 TREE_PUBLIC == 0, so we can shortcut the search. */
6277 else if (TYPE_P (decl
))
6278 return (TREE_PUBLIC (TYPE_NAME (decl
)) == 0);
6279 else if (TREE_CODE (decl
) == NAMESPACE_DECL
)
6280 return (TREE_PUBLIC (decl
) == 0);
6282 decl
= DECL_CONTEXT (decl
);
6286 /* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
6287 access DECL using %gp_rel(...)($gp). */
6290 arc_in_small_data_p (const_tree decl
)
6294 if (TREE_CODE (decl
) == STRING_CST
|| TREE_CODE (decl
) == FUNCTION_DECL
)
6298 /* We don't yet generate small-data references for -mabicalls. See related
6299 -G handling in override_options. */
6300 if (TARGET_NO_SDATA_SET
)
6303 if (TREE_CODE (decl
) == VAR_DECL
&& DECL_SECTION_NAME (decl
) != 0)
6307 /* Reject anything that isn't in a known small-data section. */
6308 name
= DECL_SECTION_NAME (decl
);
6309 if (strcmp (name
, ".sdata") != 0 && strcmp (name
, ".sbss") != 0)
6312 /* If a symbol is defined externally, the assembler will use the
6313 usual -G rules when deciding how to implement macros. */
6314 if (!DECL_EXTERNAL (decl
))
6317 /* Only global variables go into sdata section for now. */
6320 /* Don't put constants into the small data section: we want them
6321 to be in ROM rather than RAM. */
6322 if (TREE_CODE (decl
) != VAR_DECL
)
6325 if (TREE_READONLY (decl
)
6326 && !TREE_SIDE_EFFECTS (decl
)
6327 && (!DECL_INITIAL (decl
) || TREE_CONSTANT (DECL_INITIAL (decl
))))
6330 /* TREE_PUBLIC might change after the first call, because of the patch
6332 if (default_binds_local_p_1 (decl
, 1)
6333 || arc_decl_anon_ns_mem_p (decl
))
6336 /* To ensure -mvolatile-cache works
6337 ld.di does not have a gp-relative variant. */
6338 if (TREE_THIS_VOLATILE (decl
))
6342 /* Disable sdata references to weak variables. */
6343 if (DECL_WEAK (decl
))
6346 size
= int_size_in_bytes (TREE_TYPE (decl
));
6348 /* if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) */
6351 /* Allow only <=4B long data types into sdata. */
6352 return (size
> 0 && size
<= 4);
6355 /* Return true if X is a small data address that can be rewritten
6359 arc_rewrite_small_data_p (const_rtx x
)
6361 if (GET_CODE (x
) == CONST
)
6364 if (GET_CODE (x
) == PLUS
)
6366 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
6370 return (GET_CODE (x
) == SYMBOL_REF
6371 && SYMBOL_REF_SMALL_P(x
));
6374 /* If possible, rewrite OP so that it refers to small data using
6375 explicit relocations. */
6378 arc_rewrite_small_data (rtx op
)
6380 op
= copy_insn (op
);
6381 subrtx_ptr_iterator::array_type array
;
6382 FOR_EACH_SUBRTX_PTR (iter
, array
, &op
, ALL
)
6385 if (arc_rewrite_small_data_p (*loc
))
6387 gcc_assert (SDATA_BASE_REGNUM
== PIC_OFFSET_TABLE_REGNUM
);
6388 *loc
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, *loc
);
6391 if (GET_CODE (op
) == MEM
&& &XEXP (op
, 0) == loc
)
6393 else if (GET_CODE (op
) == MEM
6394 && GET_CODE (XEXP (op
, 0)) == PLUS
6395 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == MULT
)
6396 *loc
= force_reg (Pmode
, *loc
);
6400 iter
.skip_subrtxes ();
6402 else if (GET_CODE (*loc
) == PLUS
6403 && rtx_equal_p (XEXP (*loc
, 0), pic_offset_table_rtx
))
6404 iter
.skip_subrtxes ();
6409 /* Return true if OP refers to small data symbols directly, not through
6413 small_data_pattern (rtx op
, machine_mode
)
6415 if (GET_CODE (op
) == SEQUENCE
)
6417 subrtx_iterator::array_type array
;
6418 FOR_EACH_SUBRTX (iter
, array
, op
, ALL
)
6420 const_rtx x
= *iter
;
6421 if (GET_CODE (x
) == PLUS
6422 && rtx_equal_p (XEXP (x
, 0), pic_offset_table_rtx
))
6423 iter
.skip_subrtxes ();
6424 else if (arc_rewrite_small_data_p (x
))
6430 /* Return true if OP is an acceptable memory operand for ARCompact
6431 16-bit gp-relative load instructions.
6432 op shd look like : [r26, symref@sda]
6433 i.e. (mem (plus (reg 26) (symref with smalldata flag set))
6435 /* volatile cache option still to be handled. */
6438 compact_sda_memory_operand (rtx op
, machine_mode mode
)
6443 /* Eliminate non-memory operations. */
6444 if (GET_CODE (op
) != MEM
)
6447 if (mode
== VOIDmode
)
6448 mode
= GET_MODE (op
);
6450 size
= GET_MODE_SIZE (mode
);
6452 /* dword operations really put out 2 instructions, so eliminate them. */
6453 if (size
> UNITS_PER_WORD
)
6456 /* Decode the address now. */
6457 addr
= XEXP (op
, 0);
6459 return LEGITIMATE_SMALL_DATA_ADDRESS_P (addr
);
6462 /* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */
6465 arc_asm_output_aligned_decl_local (FILE * stream
, tree decl
, const char * name
,
6466 unsigned HOST_WIDE_INT size
,
6467 unsigned HOST_WIDE_INT align
,
6468 unsigned HOST_WIDE_INT globalize_p
)
6470 int in_small_data
= arc_in_small_data_p (decl
);
6473 switch_to_section (get_named_section (NULL
, ".sbss", 0));
6474 /* named_section (0,".sbss",0); */
6476 switch_to_section (bss_section
);
6479 (*targetm
.asm_out
.globalize_label
) (stream
, name
);
6481 ASM_OUTPUT_ALIGN (stream
, floor_log2 ((align
) / BITS_PER_UNIT
));
6482 ASM_OUTPUT_TYPE_DIRECTIVE (stream
, name
, "object");
6483 ASM_OUTPUT_SIZE_DIRECTIVE (stream
, name
, size
);
6484 ASM_OUTPUT_LABEL (stream
, name
);
6487 ASM_OUTPUT_SKIP (stream
, size
);
6523 /* SIMD builtins support. */
6524 enum simd_insn_args_type
{
6547 struct builtin_description
6549 enum simd_insn_args_type args_type
;
6550 const enum insn_code icode
;
6551 const char * const name
;
6552 const enum arc_builtins code
;
6555 static const struct builtin_description arc_simd_builtin_desc_list
[] =
6557 /* VVV builtins go first. */
6558 #define SIMD_BUILTIN(type, code, string, builtin) \
6559 { type,CODE_FOR_##code, "__builtin_arc_" string, \
6560 ARC_SIMD_BUILTIN_##builtin },
6562 SIMD_BUILTIN (Va_Vb_Vc
, vaddaw_insn
, "vaddaw", VADDAW
)
6563 SIMD_BUILTIN (Va_Vb_Vc
, vaddw_insn
, "vaddw", VADDW
)
6564 SIMD_BUILTIN (Va_Vb_Vc
, vavb_insn
, "vavb", VAVB
)
6565 SIMD_BUILTIN (Va_Vb_Vc
, vavrb_insn
, "vavrb", VAVRB
)
6566 SIMD_BUILTIN (Va_Vb_Vc
, vdifaw_insn
, "vdifaw", VDIFAW
)
6567 SIMD_BUILTIN (Va_Vb_Vc
, vdifw_insn
, "vdifw", VDIFW
)
6568 SIMD_BUILTIN (Va_Vb_Vc
, vmaxaw_insn
, "vmaxaw", VMAXAW
)
6569 SIMD_BUILTIN (Va_Vb_Vc
, vmaxw_insn
, "vmaxw", VMAXW
)
6570 SIMD_BUILTIN (Va_Vb_Vc
, vminaw_insn
, "vminaw", VMINAW
)
6571 SIMD_BUILTIN (Va_Vb_Vc
, vminw_insn
, "vminw", VMINW
)
6572 SIMD_BUILTIN (Va_Vb_Vc
, vmulaw_insn
, "vmulaw", VMULAW
)
6573 SIMD_BUILTIN (Va_Vb_Vc
, vmulfaw_insn
, "vmulfaw", VMULFAW
)
6574 SIMD_BUILTIN (Va_Vb_Vc
, vmulfw_insn
, "vmulfw", VMULFW
)
6575 SIMD_BUILTIN (Va_Vb_Vc
, vmulw_insn
, "vmulw", VMULW
)
6576 SIMD_BUILTIN (Va_Vb_Vc
, vsubaw_insn
, "vsubaw", VSUBAW
)
6577 SIMD_BUILTIN (Va_Vb_Vc
, vsubw_insn
, "vsubw", VSUBW
)
6578 SIMD_BUILTIN (Va_Vb_Vc
, vsummw_insn
, "vsummw", VSUMMW
)
6579 SIMD_BUILTIN (Va_Vb_Vc
, vand_insn
, "vand", VAND
)
6580 SIMD_BUILTIN (Va_Vb_Vc
, vandaw_insn
, "vandaw", VANDAW
)
6581 SIMD_BUILTIN (Va_Vb_Vc
, vbic_insn
, "vbic", VBIC
)
6582 SIMD_BUILTIN (Va_Vb_Vc
, vbicaw_insn
, "vbicaw", VBICAW
)
6583 SIMD_BUILTIN (Va_Vb_Vc
, vor_insn
, "vor", VOR
)
6584 SIMD_BUILTIN (Va_Vb_Vc
, vxor_insn
, "vxor", VXOR
)
6585 SIMD_BUILTIN (Va_Vb_Vc
, vxoraw_insn
, "vxoraw", VXORAW
)
6586 SIMD_BUILTIN (Va_Vb_Vc
, veqw_insn
, "veqw", VEQW
)
6587 SIMD_BUILTIN (Va_Vb_Vc
, vlew_insn
, "vlew", VLEW
)
6588 SIMD_BUILTIN (Va_Vb_Vc
, vltw_insn
, "vltw", VLTW
)
6589 SIMD_BUILTIN (Va_Vb_Vc
, vnew_insn
, "vnew", VNEW
)
6590 SIMD_BUILTIN (Va_Vb_Vc
, vmr1aw_insn
, "vmr1aw", VMR1AW
)
6591 SIMD_BUILTIN (Va_Vb_Vc
, vmr1w_insn
, "vmr1w", VMR1W
)
6592 SIMD_BUILTIN (Va_Vb_Vc
, vmr2aw_insn
, "vmr2aw", VMR2AW
)
6593 SIMD_BUILTIN (Va_Vb_Vc
, vmr2w_insn
, "vmr2w", VMR2W
)
6594 SIMD_BUILTIN (Va_Vb_Vc
, vmr3aw_insn
, "vmr3aw", VMR3AW
)
6595 SIMD_BUILTIN (Va_Vb_Vc
, vmr3w_insn
, "vmr3w", VMR3W
)
6596 SIMD_BUILTIN (Va_Vb_Vc
, vmr4aw_insn
, "vmr4aw", VMR4AW
)
6597 SIMD_BUILTIN (Va_Vb_Vc
, vmr4w_insn
, "vmr4w", VMR4W
)
6598 SIMD_BUILTIN (Va_Vb_Vc
, vmr5aw_insn
, "vmr5aw", VMR5AW
)
6599 SIMD_BUILTIN (Va_Vb_Vc
, vmr5w_insn
, "vmr5w", VMR5W
)
6600 SIMD_BUILTIN (Va_Vb_Vc
, vmr6aw_insn
, "vmr6aw", VMR6AW
)
6601 SIMD_BUILTIN (Va_Vb_Vc
, vmr6w_insn
, "vmr6w", VMR6W
)
6602 SIMD_BUILTIN (Va_Vb_Vc
, vmr7aw_insn
, "vmr7aw", VMR7AW
)
6603 SIMD_BUILTIN (Va_Vb_Vc
, vmr7w_insn
, "vmr7w", VMR7W
)
6604 SIMD_BUILTIN (Va_Vb_Vc
, vmrb_insn
, "vmrb", VMRB
)
6605 SIMD_BUILTIN (Va_Vb_Vc
, vh264f_insn
, "vh264f", VH264F
)
6606 SIMD_BUILTIN (Va_Vb_Vc
, vh264ft_insn
, "vh264ft", VH264FT
)
6607 SIMD_BUILTIN (Va_Vb_Vc
, vh264fw_insn
, "vh264fw", VH264FW
)
6608 SIMD_BUILTIN (Va_Vb_Vc
, vvc1f_insn
, "vvc1f", VVC1F
)
6609 SIMD_BUILTIN (Va_Vb_Vc
, vvc1ft_insn
, "vvc1ft", VVC1FT
)
6611 SIMD_BUILTIN (Va_Vb_rlimm
, vbaddw_insn
, "vbaddw", VBADDW
)
6612 SIMD_BUILTIN (Va_Vb_rlimm
, vbmaxw_insn
, "vbmaxw", VBMAXW
)
6613 SIMD_BUILTIN (Va_Vb_rlimm
, vbminw_insn
, "vbminw", VBMINW
)
6614 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulaw_insn
, "vbmulaw", VBMULAW
)
6615 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulfw_insn
, "vbmulfw", VBMULFW
)
6616 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulw_insn
, "vbmulw", VBMULW
)
6617 SIMD_BUILTIN (Va_Vb_rlimm
, vbrsubw_insn
, "vbrsubw", VBRSUBW
)
6618 SIMD_BUILTIN (Va_Vb_rlimm
, vbsubw_insn
, "vbsubw", VBSUBW
)
6620 /* Va, Vb, Ic instructions. */
6621 SIMD_BUILTIN (Va_Vb_Ic
, vasrw_insn
, "vasrw", VASRW
)
6622 SIMD_BUILTIN (Va_Vb_Ic
, vsr8_insn
, "vsr8", VSR8
)
6623 SIMD_BUILTIN (Va_Vb_Ic
, vsr8aw_insn
, "vsr8aw", VSR8AW
)
6625 /* Va, Vb, u6 instructions. */
6626 SIMD_BUILTIN (Va_Vb_u6
, vasrrwi_insn
, "vasrrwi", VASRRWi
)
6627 SIMD_BUILTIN (Va_Vb_u6
, vasrsrwi_insn
, "vasrsrwi", VASRSRWi
)
6628 SIMD_BUILTIN (Va_Vb_u6
, vasrwi_insn
, "vasrwi", VASRWi
)
6629 SIMD_BUILTIN (Va_Vb_u6
, vasrpwbi_insn
, "vasrpwbi", VASRPWBi
)
6630 SIMD_BUILTIN (Va_Vb_u6
, vasrrpwbi_insn
,"vasrrpwbi", VASRRPWBi
)
6631 SIMD_BUILTIN (Va_Vb_u6
, vsr8awi_insn
, "vsr8awi", VSR8AWi
)
6632 SIMD_BUILTIN (Va_Vb_u6
, vsr8i_insn
, "vsr8i", VSR8i
)
6634 /* Va, Vb, u8 (simm) instructions. */
6635 SIMD_BUILTIN (Va_Vb_u8
, vmvaw_insn
, "vmvaw", VMVAW
)
6636 SIMD_BUILTIN (Va_Vb_u8
, vmvw_insn
, "vmvw", VMVW
)
6637 SIMD_BUILTIN (Va_Vb_u8
, vmvzw_insn
, "vmvzw", VMVZW
)
6638 SIMD_BUILTIN (Va_Vb_u8
, vd6tapf_insn
, "vd6tapf", VD6TAPF
)
6640 /* Va, rlimm, u8 (simm) instructions. */
6641 SIMD_BUILTIN (Va_rlimm_u8
, vmovaw_insn
, "vmovaw", VMOVAW
)
6642 SIMD_BUILTIN (Va_rlimm_u8
, vmovw_insn
, "vmovw", VMOVW
)
6643 SIMD_BUILTIN (Va_rlimm_u8
, vmovzw_insn
, "vmovzw", VMOVZW
)
6645 /* Va, Vb instructions. */
6646 SIMD_BUILTIN (Va_Vb
, vabsaw_insn
, "vabsaw", VABSAW
)
6647 SIMD_BUILTIN (Va_Vb
, vabsw_insn
, "vabsw", VABSW
)
6648 SIMD_BUILTIN (Va_Vb
, vaddsuw_insn
, "vaddsuw", VADDSUW
)
6649 SIMD_BUILTIN (Va_Vb
, vsignw_insn
, "vsignw", VSIGNW
)
6650 SIMD_BUILTIN (Va_Vb
, vexch1_insn
, "vexch1", VEXCH1
)
6651 SIMD_BUILTIN (Va_Vb
, vexch2_insn
, "vexch2", VEXCH2
)
6652 SIMD_BUILTIN (Va_Vb
, vexch4_insn
, "vexch4", VEXCH4
)
6653 SIMD_BUILTIN (Va_Vb
, vupbaw_insn
, "vupbaw", VUPBAW
)
6654 SIMD_BUILTIN (Va_Vb
, vupbw_insn
, "vupbw", VUPBW
)
6655 SIMD_BUILTIN (Va_Vb
, vupsbaw_insn
, "vupsbaw", VUPSBAW
)
6656 SIMD_BUILTIN (Va_Vb
, vupsbw_insn
, "vupsbw", VUPSBW
)
6658 /* DIb, rlimm, rlimm instructions. */
6659 SIMD_BUILTIN (Da_rlimm_rlimm
, vdirun_insn
, "vdirun", VDIRUN
)
6660 SIMD_BUILTIN (Da_rlimm_rlimm
, vdorun_insn
, "vdorun", VDORUN
)
6662 /* DIb, limm, rlimm instructions. */
6663 SIMD_BUILTIN (Da_u3_rlimm
, vdiwr_insn
, "vdiwr", VDIWR
)
6664 SIMD_BUILTIN (Da_u3_rlimm
, vdowr_insn
, "vdowr", VDOWR
)
6666 /* rlimm instructions. */
6667 SIMD_BUILTIN (void_rlimm
, vrec_insn
, "vrec", VREC
)
6668 SIMD_BUILTIN (void_rlimm
, vrun_insn
, "vrun", VRUN
)
6669 SIMD_BUILTIN (void_rlimm
, vrecrun_insn
, "vrecrun", VRECRUN
)
6670 SIMD_BUILTIN (void_rlimm
, vendrec_insn
, "vendrec", VENDREC
)
6672 /* Va, [Ib,u8] instructions. */
6673 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wh_insn
, "vld32wh", VLD32WH
)
6674 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wl_insn
, "vld32wl", VLD32WL
)
6675 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld64_insn
, "vld64", VLD64
)
6676 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32_insn
, "vld32", VLD32
)
6678 SIMD_BUILTIN (Va_Ib_u8
, vld64w_insn
, "vld64w", VLD64W
)
6679 SIMD_BUILTIN (Va_Ib_u8
, vld128_insn
, "vld128", VLD128
)
6680 SIMD_BUILTIN (void_Va_Ib_u8
, vst128_insn
, "vst128", VST128
)
6681 SIMD_BUILTIN (void_Va_Ib_u8
, vst64_insn
, "vst64", VST64
)
6683 /* Va, [Ib, u8] instructions. */
6684 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst16_n_insn
, "vst16_n", VST16_N
)
6685 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst32_n_insn
, "vst32_n", VST32_N
)
6687 SIMD_BUILTIN (void_u6
, vinti_insn
, "vinti", VINTI
)
6691 arc_init_simd_builtins (void)
6694 tree endlink
= void_list_node
;
6695 tree V8HI_type_node
= build_vector_type_for_mode (intHI_type_node
, V8HImode
);
6697 tree v8hi_ftype_v8hi_v8hi
6698 = build_function_type (V8HI_type_node
,
6699 tree_cons (NULL_TREE
, V8HI_type_node
,
6700 tree_cons (NULL_TREE
, V8HI_type_node
,
6702 tree v8hi_ftype_v8hi_int
6703 = build_function_type (V8HI_type_node
,
6704 tree_cons (NULL_TREE
, V8HI_type_node
,
6705 tree_cons (NULL_TREE
, integer_type_node
,
6708 tree v8hi_ftype_v8hi_int_int
6709 = build_function_type (V8HI_type_node
,
6710 tree_cons (NULL_TREE
, V8HI_type_node
,
6711 tree_cons (NULL_TREE
, integer_type_node
,
6712 tree_cons (NULL_TREE
,
6716 tree void_ftype_v8hi_int_int
6717 = build_function_type (void_type_node
,
6718 tree_cons (NULL_TREE
, V8HI_type_node
,
6719 tree_cons (NULL_TREE
, integer_type_node
,
6720 tree_cons (NULL_TREE
,
6724 tree void_ftype_v8hi_int_int_int
6725 = (build_function_type
6727 tree_cons (NULL_TREE
, V8HI_type_node
,
6728 tree_cons (NULL_TREE
, integer_type_node
,
6729 tree_cons (NULL_TREE
, integer_type_node
,
6730 tree_cons (NULL_TREE
,
6734 tree v8hi_ftype_int_int
6735 = build_function_type (V8HI_type_node
,
6736 tree_cons (NULL_TREE
, integer_type_node
,
6737 tree_cons (NULL_TREE
, integer_type_node
,
6740 tree void_ftype_int_int
6741 = build_function_type (void_type_node
,
6742 tree_cons (NULL_TREE
, integer_type_node
,
6743 tree_cons (NULL_TREE
, integer_type_node
,
6747 = build_function_type (void_type_node
,
6748 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
6750 tree v8hi_ftype_v8hi
6751 = build_function_type (V8HI_type_node
, tree_cons (NULL_TREE
, V8HI_type_node
,
6754 /* These asserts have been introduced to ensure that the order of builtins
6755 does not get messed up, else the initialization goes wrong. */
6756 gcc_assert (arc_simd_builtin_desc_list
[0].args_type
== Va_Vb_Vc
);
6757 for (i
=0; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Vc
; i
++)
6758 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6759 v8hi_ftype_v8hi_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
6761 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
);
6762 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
; i
++)
6763 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6764 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6766 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
);
6767 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
; i
++)
6768 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6769 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6771 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
);
6772 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
; i
++)
6773 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6774 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6776 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
);
6777 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
; i
++)
6778 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6779 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6781 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
);
6782 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
; i
++)
6783 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6784 v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6786 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
);
6787 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
; i
++)
6788 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6789 v8hi_ftype_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
6791 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
);
6792 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
; i
++)
6793 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6794 void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6796 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
);
6797 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
; i
++)
6798 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6799 void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6801 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
);
6802 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
; i
++)
6803 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6804 void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
6806 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
);
6807 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
; i
++)
6808 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6809 v8hi_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6811 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
);
6812 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
; i
++)
6813 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6814 v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6816 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
);
6817 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
; i
++)
6818 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6819 void_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6821 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
);
6822 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
; i
++)
6823 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6824 void_ftype_v8hi_int_int_int
,
6825 arc_simd_builtin_desc_list
[i
].code
);
6827 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_u6
);
6828 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_u6
; i
++)
6829 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6830 void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
6832 gcc_assert(i
== ARRAY_SIZE (arc_simd_builtin_desc_list
));
6835 /* Helper function of arc_expand_builtin; has the same parameters,
6836 except that EXP is now known to be a call to a simd builtin. */
6839 arc_expand_simd_builtin (tree exp
,
6841 rtx subtarget ATTRIBUTE_UNUSED
,
6842 machine_mode mode ATTRIBUTE_UNUSED
,
6843 int ignore ATTRIBUTE_UNUSED
)
6845 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
6857 int fcode
= DECL_FUNCTION_CODE (fndecl
);
6864 const struct builtin_description
* d
;
6866 for (i
= 0, d
= arc_simd_builtin_desc_list
;
6867 i
< ARRAY_SIZE (arc_simd_builtin_desc_list
); i
++, d
++)
6868 if (d
->code
== (const enum arc_builtins
) fcode
)
6871 /* We must get an entry here. */
6872 gcc_assert (i
< ARRAY_SIZE (arc_simd_builtin_desc_list
));
6874 switch (d
->args_type
)
6878 arg0
= CALL_EXPR_ARG (exp
, 0);
6879 arg1
= CALL_EXPR_ARG (exp
, 1);
6880 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6881 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6883 target
= gen_reg_rtx (V8HImode
);
6884 mode0
= insn_data
[icode
].operand
[1].mode
;
6885 mode1
= insn_data
[icode
].operand
[2].mode
;
6887 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6888 op0
= copy_to_mode_reg (mode0
, op0
);
6890 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6891 op1
= copy_to_mode_reg (mode1
, op1
);
6893 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6903 arg0
= CALL_EXPR_ARG (exp
, 0);
6904 arg1
= CALL_EXPR_ARG (exp
, 1);
6905 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6906 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6908 target
= gen_reg_rtx (V8HImode
);
6909 mode0
= insn_data
[icode
].operand
[1].mode
;
6910 mode1
= insn_data
[icode
].operand
[2].mode
;
6912 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6913 op0
= copy_to_mode_reg (mode0
, op0
);
6915 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
)
6916 || (d
->args_type
== Va_Vb_u6
&& !UNSIGNED_INT6 (INTVAL (op1
)))
6917 || (d
->args_type
== Va_Vb_u8
&& !UNSIGNED_INT8 (INTVAL (op1
))))
6918 error ("operand 2 of %s instruction should be an unsigned %d-bit value",
6920 (d
->args_type
== Va_Vb_u6
)? 6: 8);
6922 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6931 arg0
= CALL_EXPR_ARG (exp
, 0);
6932 arg1
= CALL_EXPR_ARG (exp
, 1);
6933 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6934 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6936 target
= gen_reg_rtx (V8HImode
);
6937 mode0
= insn_data
[icode
].operand
[1].mode
;
6938 mode1
= insn_data
[icode
].operand
[2].mode
;
6940 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6941 op0
= copy_to_mode_reg (mode0
, op0
);
6943 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6944 || !(UNSIGNED_INT8 (INTVAL (op1
))))
6945 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
6948 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6957 arg0
= CALL_EXPR_ARG (exp
, 0);
6958 arg1
= CALL_EXPR_ARG (exp
, 1);
6959 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6960 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6961 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
6963 target
= gen_reg_rtx (V8HImode
);
6964 mode0
= insn_data
[icode
].operand
[1].mode
;
6965 mode1
= insn_data
[icode
].operand
[2].mode
;
6967 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6968 op0
= copy_to_mode_reg (mode0
, op0
);
6970 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6971 || !(UNSIGNED_INT3 (INTVAL (op1
))))
6972 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
6975 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
6984 arg0
= CALL_EXPR_ARG (exp
, 0);
6985 arg1
= CALL_EXPR_ARG (exp
, 1);
6986 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6987 op1
= expand_expr (arg1
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6989 target
= gen_reg_rtx (V8HImode
);
6990 mode0
= insn_data
[icode
].operand
[1].mode
;
6991 mode1
= insn_data
[icode
].operand
[2].mode
;
6993 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6994 op0
= copy_to_mode_reg (mode0
, op0
);
6996 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6997 op1
= copy_to_mode_reg (mode1
, op1
);
6999 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7008 arg0
= CALL_EXPR_ARG (exp
, 0);
7009 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7011 target
= gen_reg_rtx (V8HImode
);
7012 mode0
= insn_data
[icode
].operand
[1].mode
;
7014 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7015 op0
= copy_to_mode_reg (mode0
, op0
);
7017 pat
= GEN_FCN (icode
) (target
, op0
);
7024 case Da_rlimm_rlimm
:
7026 arg0
= CALL_EXPR_ARG (exp
, 0);
7027 arg1
= CALL_EXPR_ARG (exp
, 1);
7028 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7029 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7032 if (icode
== CODE_FOR_vdirun_insn
)
7033 target
= gen_rtx_REG (SImode
, 131);
7034 else if (icode
== CODE_FOR_vdorun_insn
)
7035 target
= gen_rtx_REG (SImode
, 139);
7039 mode0
= insn_data
[icode
].operand
[1].mode
;
7040 mode1
= insn_data
[icode
].operand
[2].mode
;
7042 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7043 op0
= copy_to_mode_reg (mode0
, op0
);
7045 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7046 op1
= copy_to_mode_reg (mode1
, op1
);
7049 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7058 arg0
= CALL_EXPR_ARG (exp
, 0);
7059 arg1
= CALL_EXPR_ARG (exp
, 1);
7060 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7061 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7064 if (! (GET_CODE (op0
) == CONST_INT
)
7065 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7066 error ("operand 1 of %s instruction should be an unsigned 3-bit value (DR0-DR7)",
7069 mode1
= insn_data
[icode
].operand
[1].mode
;
7071 if (icode
== CODE_FOR_vdiwr_insn
)
7072 target
= gen_rtx_REG (SImode
,
7073 ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
+ INTVAL (op0
));
7074 else if (icode
== CODE_FOR_vdowr_insn
)
7075 target
= gen_rtx_REG (SImode
,
7076 ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
+ INTVAL (op0
));
7080 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7081 op1
= copy_to_mode_reg (mode1
, op1
);
7083 pat
= GEN_FCN (icode
) (target
, op1
);
7092 arg0
= CALL_EXPR_ARG (exp
, 0);
7096 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7097 mode0
= insn_data
[icode
].operand
[0].mode
;
7099 /* op0 should be u6. */
7100 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
)
7101 || !(UNSIGNED_INT6 (INTVAL (op0
))))
7102 error ("operand of %s instruction should be an unsigned 6-bit value",
7105 pat
= GEN_FCN (icode
) (op0
);
7114 arg0
= CALL_EXPR_ARG (exp
, 0);
7118 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7119 mode0
= insn_data
[icode
].operand
[0].mode
;
7121 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7122 op0
= copy_to_mode_reg (mode0
, op0
);
7124 pat
= GEN_FCN (icode
) (op0
);
7135 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7136 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7137 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7139 src_vreg
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7140 op0
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* [I]0-7 */
7141 op1
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7142 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7144 /* target <- src vreg */
7145 emit_insn (gen_move_insn (target
, src_vreg
));
7147 /* target <- vec_concat: target, mem(Ib, u8) */
7148 mode0
= insn_data
[icode
].operand
[3].mode
;
7149 mode1
= insn_data
[icode
].operand
[1].mode
;
7151 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op0
, mode0
))
7152 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7153 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7156 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7157 || !(UNSIGNED_INT8 (INTVAL (op1
))))
7158 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7161 pat
= GEN_FCN (icode
) (target
, op1
, op2
, op0
);
7171 arg0
= CALL_EXPR_ARG (exp
, 0); /* src vreg */
7172 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7173 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7175 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7176 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* I[0-7] */
7177 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7178 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
); /* Vdest */
7180 mode0
= insn_data
[icode
].operand
[0].mode
;
7181 mode1
= insn_data
[icode
].operand
[1].mode
;
7182 mode2
= insn_data
[icode
].operand
[2].mode
;
7183 mode3
= insn_data
[icode
].operand
[3].mode
;
7185 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7186 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7187 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7190 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7191 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7192 error ("operand 3 of %s instruction should be an unsigned 8-bit value",
7195 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7196 op3
= copy_to_mode_reg (mode3
, op3
);
7198 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
);
7207 arg0
= CALL_EXPR_ARG (exp
, 0); /* dest vreg */
7208 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7210 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7211 op1
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* I[0-7] */
7212 op2
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7214 /* target <- src vreg */
7215 target
= gen_reg_rtx (V8HImode
);
7217 /* target <- vec_concat: target, mem(Ib, u8) */
7218 mode0
= insn_data
[icode
].operand
[1].mode
;
7219 mode1
= insn_data
[icode
].operand
[2].mode
;
7220 mode2
= insn_data
[icode
].operand
[3].mode
;
7222 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7223 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7224 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7227 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op2
, mode2
))
7228 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7229 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7232 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
7239 case void_Va_u3_Ib_u8
:
7241 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7242 arg1
= CALL_EXPR_ARG (exp
, 1); /* u3 */
7243 arg2
= CALL_EXPR_ARG (exp
, 2); /* [I]0-7 */
7244 arg3
= CALL_EXPR_ARG (exp
, 3); /* u8 */
7246 op0
= expand_expr (arg3
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7247 op1
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR */
7248 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* [I]0-7 */
7249 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);/* vreg to be stored */
7250 op4
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* vreg 0-7 subreg no. */
7252 mode0
= insn_data
[icode
].operand
[0].mode
;
7253 mode2
= insn_data
[icode
].operand
[2].mode
;
7254 mode3
= insn_data
[icode
].operand
[3].mode
;
7255 mode4
= insn_data
[icode
].operand
[4].mode
;
7257 /* Do some correctness checks for the operands. */
7258 if ( (!(*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7259 || !(UNSIGNED_INT8 (INTVAL (op0
))))
7260 error ("operand 4 of %s instruction should be an unsigned 8-bit value (0-255)",
7263 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7264 || !(UNSIGNED_INT3 (INTVAL (op2
))))
7265 error ("operand 3 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7268 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7269 op3
= copy_to_mode_reg (mode3
, op3
);
7271 if ( (!(*insn_data
[icode
].operand
[4].predicate
) (op4
, mode4
))
7272 || !(UNSIGNED_INT3 (INTVAL (op4
))))
7273 error ("operand 2 of %s instruction should be an unsigned 3-bit value (subreg 0-7)",
7275 else if (icode
== CODE_FOR_vst32_n_insn
7276 && ((INTVAL(op4
) % 2 ) != 0))
7277 error ("operand 2 of %s instruction should be an even 3-bit value (subreg 0,2,4,6)",
7280 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
, op4
);
7294 arc_preserve_reload_p (rtx in
)
7296 return (GET_CODE (in
) == PLUS
7297 && RTX_OK_FOR_BASE_P (XEXP (in
, 0), true)
7298 && CONST_INT_P (XEXP (in
, 1))
7299 && !((INTVAL (XEXP (in
, 1)) & 511)));
7303 arc_register_move_cost (machine_mode
,
7304 enum reg_class from_class
, enum reg_class to_class
)
7306 /* The ARC600 has no bypass for extension registers, hence a nop might be
7307 needed to be inserted after a write so that reads are safe. */
7310 if (to_class
== MPY_WRITABLE_CORE_REGS
)
7312 /* Instructions modifying LP_COUNT need 4 additional cycles before
7313 the register will actually contain the value. */
7314 else if (to_class
== LPCOUNT_REG
)
7316 else if (to_class
== WRITABLE_CORE_REGS
)
7320 /* The ARC700 stalls for 3 cycles when *reading* from lp_count. */
7322 && (from_class
== LPCOUNT_REG
|| from_class
== ALL_CORE_REGS
7323 || from_class
== WRITABLE_CORE_REGS
))
7326 /* Force an attempt to 'mov Dy,Dx' to spill. */
7327 if (TARGET_ARC700
&& TARGET_DPFP
7328 && from_class
== DOUBLE_REGS
&& to_class
== DOUBLE_REGS
)
7334 /* Emit code for an addsi3 instruction with OPERANDS.
7335 COND_P indicates if this will use conditional execution.
7336 Return the length of the instruction.
7337 If OUTPUT_P is false, don't actually output the instruction, just return
7340 arc_output_addsi (rtx
*operands
, bool cond_p
, bool output_p
)
7344 int match
= operands_match_p (operands
[0], operands
[1]);
7345 int match2
= operands_match_p (operands
[0], operands
[2]);
7346 int intval
= (REG_P (operands
[2]) ? 1
7347 : CONST_INT_P (operands
[2]) ? INTVAL (operands
[2]) : 0xbadc057);
7348 int neg_intval
= -intval
;
7349 int short_0
= satisfies_constraint_Rcq (operands
[0]);
7350 int short_p
= (!cond_p
&& short_0
&& satisfies_constraint_Rcq (operands
[1]));
7353 #define ADDSI_OUTPUT1(FORMAT) do {\
7355 output_asm_insn (FORMAT, operands);\
7358 #define ADDSI_OUTPUT(LIST) do {\
7361 ADDSI_OUTPUT1 (format);\
7365 /* First try to emit a 16 bit insn. */
7368 /* If we are actually about to output this insn, don't try a 16 bit
7369 variant if we already decided that we don't want that
7370 (I.e. we upsized this insn to align some following insn.)
7371 E.g. add_s r0,sp,70 is 16 bit, but add r0,sp,70 requires a LIMM -
7372 but add1 r0,sp,35 doesn't. */
7373 && (!output_p
|| (get_attr_length (current_output_insn
) & 2)))
7376 && (REG_P (operands
[2])
7377 ? (match
|| satisfies_constraint_Rcq (operands
[2]))
7378 : (unsigned) intval
<= (match
? 127 : 7)))
7379 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7380 if (short_0
&& REG_P (operands
[1]) && match2
)
7381 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7382 if ((short_0
|| REGNO (operands
[0]) == STACK_POINTER_REGNUM
)
7383 && REGNO (operands
[1]) == STACK_POINTER_REGNUM
&& !(intval
& ~124))
7384 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7386 if ((short_p
&& (unsigned) neg_intval
<= (match
? 31 : 7))
7387 || (REGNO (operands
[0]) == STACK_POINTER_REGNUM
7388 && match
&& !(neg_intval
& ~124)))
7389 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7392 /* Now try to emit a 32 bit insn without long immediate. */
7394 if (!match
&& match2
&& REG_P (operands
[1]))
7395 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7396 if (match
|| !cond_p
)
7398 int limit
= (match
&& !cond_p
) ? 0x7ff : 0x3f;
7399 int range_factor
= neg_intval
& intval
;
7402 if (intval
== -1 << 31)
7403 ADDSI_OUTPUT1 ("bxor%? %0,%1,31");
7405 /* If we can use a straight add / sub instead of a {add,sub}[123] of
7406 same size, do, so - the insn latency is lower. */
7407 /* -0x800 is a 12-bit constant for add /add3 / sub / sub3, but
7409 if ((intval
>= 0 && intval
<= limit
)
7410 || (intval
== -0x800 && limit
== 0x7ff))
7411 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7412 else if ((intval
< 0 && neg_intval
<= limit
)
7413 || (intval
== 0x800 && limit
== 0x7ff))
7414 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7415 shift
= range_factor
>= 8 ? 3 : (range_factor
>> 1);
7416 gcc_assert (shift
== 0 || shift
== 1 || shift
== 2 || shift
== 3);
7417 gcc_assert ((((1 << shift
) - 1) & intval
) == 0);
7418 if (((intval
< 0 && intval
!= -0x4000)
7419 /* sub[123] is slower than add_s / sub, only use it if it
7420 avoids a long immediate. */
7421 && neg_intval
<= limit
<< shift
)
7422 || (intval
== 0x4000 && limit
== 0x7ff))
7423 ADDSI_OUTPUT ((format
, "sub%d%%? %%0,%%1,%d",
7424 shift
, neg_intval
>> shift
));
7425 else if ((intval
>= 0 && intval
<= limit
<< shift
)
7426 || (intval
== -0x4000 && limit
== 0x7ff))
7427 ADDSI_OUTPUT ((format
, "add%d%%? %%0,%%1,%d", shift
, intval
>> shift
));
7429 /* Try to emit a 16 bit opcode with long immediate. */
7431 if (short_p
&& match
)
7432 ADDSI_OUTPUT1 ("add%? %0,%1,%S2");
7434 /* We have to use a 32 bit opcode, and with a long immediate. */
7436 ADDSI_OUTPUT1 (intval
< 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%S2");
7439 /* Emit code for an commutative_cond_exec instruction with OPERANDS.
7440 Return the length of the instruction.
7441 If OUTPUT_P is false, don't actually output the instruction, just return
7444 arc_output_commutative_cond_exec (rtx
*operands
, bool output_p
)
7446 enum rtx_code commutative_op
= GET_CODE (operands
[3]);
7447 const char *pat
= NULL
;
7449 /* Canonical rtl should not have a constant in the first operand position. */
7450 gcc_assert (!CONSTANT_P (operands
[1]));
7452 switch (commutative_op
)
7455 if (satisfies_constraint_C1p (operands
[2]))
7456 pat
= "bmsk%? %0,%1,%Z2";
7457 else if (satisfies_constraint_Ccp (operands
[2]))
7458 pat
= "bclr%? %0,%1,%M2";
7459 else if (satisfies_constraint_CnL (operands
[2]))
7460 pat
= "bic%? %0,%1,%n2-1";
7463 if (satisfies_constraint_C0p (operands
[2]))
7464 pat
= "bset%? %0,%1,%z2";
7467 if (satisfies_constraint_C0p (operands
[2]))
7468 pat
= "bxor%? %0,%1,%z2";
7471 return arc_output_addsi (operands
, true, output_p
);
7475 output_asm_insn (pat
? pat
: "%O3.%d5 %0,%1,%2", operands
);
7476 if (pat
|| REG_P (operands
[2]) || satisfies_constraint_L (operands
[2]))
7481 /* Helper function of arc_expand_movmem. ADDR points to a chunk of memory.
7482 Emit code and return an potentially modified address such that offsets
7483 up to SIZE are can be added to yield a legitimate address.
7484 if REUSE is set, ADDR is a register that may be modified. */
7487 force_offsettable (rtx addr
, HOST_WIDE_INT size
, bool reuse
)
7490 rtx offs
= const0_rtx
;
7492 if (GET_CODE (base
) == PLUS
)
7494 offs
= XEXP (base
, 1);
7495 base
= XEXP (base
, 0);
7498 || (REGNO (base
) != STACK_POINTER_REGNUM
7499 && REGNO_PTR_FRAME_P (REGNO (addr
)))
7500 || !CONST_INT_P (offs
) || !SMALL_INT (INTVAL (offs
))
7501 || !SMALL_INT (INTVAL (offs
) + size
))
7504 emit_insn (gen_add2_insn (addr
, offs
));
7506 addr
= copy_to_mode_reg (Pmode
, addr
);
7511 /* Like move_by_pieces, but take account of load latency,
7512 and actual offset ranges.
7513 Return true on success. */
7516 arc_expand_movmem (rtx
*operands
)
7518 rtx dst
= operands
[0];
7519 rtx src
= operands
[1];
7520 rtx dst_addr
, src_addr
;
7522 int align
= INTVAL (operands
[3]);
7529 if (!CONST_INT_P (operands
[2]))
7531 size
= INTVAL (operands
[2]);
7532 /* move_by_pieces_ninsns is static, so we can't use it. */
7534 n_pieces
= (size
+ 2) / 4U + (size
& 1);
7535 else if (align
== 2)
7536 n_pieces
= (size
+ 1) / 2U;
7539 if (n_pieces
>= (unsigned int) (optimize_size
? 3 : 15))
7543 dst_addr
= force_offsettable (XEXP (operands
[0], 0), size
, 0);
7544 src_addr
= force_offsettable (XEXP (operands
[1], 0), size
, 0);
7545 store
[0] = store
[1] = NULL_RTX
;
7546 tmpx
[0] = tmpx
[1] = NULL_RTX
;
7547 for (i
= 0; size
> 0; i
^= 1, size
-= piece
)
7553 piece
= size
& -size
;
7554 mode
= smallest_mode_for_size (piece
* BITS_PER_UNIT
, MODE_INT
);
7555 /* If we don't re-use temporaries, the scheduler gets carried away,
7556 and the register pressure gets unnecessarily high. */
7557 if (0 && tmpx
[i
] && GET_MODE (tmpx
[i
]) == mode
)
7560 tmpx
[i
] = tmp
= gen_reg_rtx (mode
);
7561 dst_addr
= force_offsettable (dst_addr
, piece
, 1);
7562 src_addr
= force_offsettable (src_addr
, piece
, 1);
7564 emit_insn (store
[i
]);
7565 emit_move_insn (tmp
, change_address (src
, mode
, src_addr
));
7566 store
[i
] = gen_move_insn (change_address (dst
, mode
, dst_addr
), tmp
);
7567 dst_addr
= plus_constant (Pmode
, dst_addr
, piece
);
7568 src_addr
= plus_constant (Pmode
, src_addr
, piece
);
7571 emit_insn (store
[i
]);
7573 emit_insn (store
[i
^1]);
7577 /* Prepare operands for move in MODE. Return true iff the move has
7581 prepare_move_operands (rtx
*operands
, machine_mode mode
)
7583 /* We used to do this only for MODE_INT Modes, but addresses to floating
7584 point variables may well be in the small data section. */
7587 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[0], Pmode
))
7588 operands
[0] = arc_rewrite_small_data (operands
[0]);
7589 else if (mode
== SImode
&& flag_pic
&& SYMBOLIC_CONST (operands
[1]))
7591 emit_pic_move (operands
, SImode
);
7593 /* Disable any REG_EQUALs associated with the symref
7594 otherwise the optimization pass undoes the work done
7595 here and references the variable directly. */
7597 else if (GET_CODE (operands
[0]) != MEM
7598 && !TARGET_NO_SDATA_SET
7599 && small_data_pattern (operands
[1], Pmode
))
7601 /* This is to take care of address calculations involving sdata
7603 operands
[1] = arc_rewrite_small_data (operands
[1]);
7605 emit_insn (gen_rtx_SET (mode
, operands
[0],operands
[1]));
7606 /* ??? This note is useless, since it only restates the set itself.
7607 We should rather use the original SYMBOL_REF. However, there is
7608 the problem that we are lying to the compiler about these
7609 SYMBOL_REFs to start with. symbol@sda should be encoded specially
7610 so that we can tell it apart from an actual symbol. */
7611 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7613 /* Take care of the REG_EQUAL note that will be attached to mark the
7614 output reg equal to the initial symbol_ref after this code is
7616 emit_move_insn (operands
[0], operands
[0]);
7621 if (MEM_P (operands
[0])
7622 && !(reload_in_progress
|| reload_completed
))
7624 operands
[1] = force_reg (mode
, operands
[1]);
7625 if (!move_dest_operand (operands
[0], mode
))
7627 rtx addr
= copy_to_mode_reg (Pmode
, XEXP (operands
[0], 0));
7628 /* This is like change_address_1 (operands[0], mode, 0, 1) ,
7629 except that we can't use that function because it is static. */
7630 rtx pat
= change_address (operands
[0], mode
, addr
);
7631 MEM_COPY_ATTRIBUTES (pat
, operands
[0]);
7634 if (!cse_not_expected
)
7636 rtx pat
= XEXP (operands
[0], 0);
7638 pat
= arc_legitimize_address_0 (pat
, pat
, mode
);
7641 pat
= change_address (operands
[0], mode
, pat
);
7642 MEM_COPY_ATTRIBUTES (pat
, operands
[0]);
7648 if (MEM_P (operands
[1]) && !cse_not_expected
)
7650 rtx pat
= XEXP (operands
[1], 0);
7652 pat
= arc_legitimize_address_0 (pat
, pat
, mode
);
7655 pat
= change_address (operands
[1], mode
, pat
);
7656 MEM_COPY_ATTRIBUTES (pat
, operands
[1]);
7664 /* Prepare OPERANDS for an extension using CODE to OMODE.
7665 Return true iff the move has been emitted. */
7668 prepare_extend_operands (rtx
*operands
, enum rtx_code code
,
7671 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[1], Pmode
))
7673 /* This is to take care of address calculations involving sdata
7676 = gen_rtx_fmt_e (code
, omode
, arc_rewrite_small_data (operands
[1]));
7677 emit_insn (gen_rtx_SET (omode
, operands
[0], operands
[1]));
7678 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7680 /* Take care of the REG_EQUAL note that will be attached to mark the
7681 output reg equal to the initial extension after this code is
7683 emit_move_insn (operands
[0], operands
[0]);
7689 /* Output a library call to a function called FNAME that has been arranged
7690 to be local to any dso. */
7693 arc_output_libcall (const char *fname
)
7695 unsigned len
= strlen (fname
);
7696 static char buf
[64];
7698 gcc_assert (len
< sizeof buf
- 35);
7699 if (TARGET_LONG_CALLS_SET
7700 || (TARGET_MEDIUM_CALLS
&& arc_ccfsm_cond_exec_p ()))
7703 sprintf (buf
, "add r12,pcl,@%s-(.&-4)\n\tjl%%!%%* [r12]", fname
);
7705 sprintf (buf
, "jl%%! @%s", fname
);
7708 sprintf (buf
, "bl%%!%%* @%s", fname
);
7712 /* Return the SImode highpart of the DImode value IN. */
7715 disi_highpart (rtx in
)
7717 return simplify_gen_subreg (SImode
, in
, DImode
, TARGET_BIG_ENDIAN
? 0 : 4);
7720 /* Return length adjustment for INSN.
7722 A write to a core reg greater or equal to 32 must not be immediately
7723 followed by a use. Anticipate the length requirement to insert a nop
7724 between PRED and SUCC to prevent a hazard. */
7727 arc600_corereg_hazard (rtx_insn
*pred
, rtx_insn
*succ
)
7731 /* If SUCC is a doloop_end_i with a preceding label, we must output a nop
7732 in front of SUCC anyway, so there will be separation between PRED and
7734 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
7735 && LABEL_P (prev_nonnote_insn (succ
)))
7737 if (recog_memoized (succ
) == CODE_FOR_doloop_begin_i
)
7739 if (GET_CODE (PATTERN (pred
)) == SEQUENCE
)
7740 pred
= as_a
<rtx_sequence
*> (PATTERN (pred
))->insn (1);
7741 if (GET_CODE (PATTERN (succ
)) == SEQUENCE
)
7742 succ
= as_a
<rtx_sequence
*> (PATTERN (succ
))->insn (0);
7743 if (recog_memoized (pred
) == CODE_FOR_mulsi_600
7744 || recog_memoized (pred
) == CODE_FOR_umul_600
7745 || recog_memoized (pred
) == CODE_FOR_mac_600
7746 || recog_memoized (pred
) == CODE_FOR_mul64_600
7747 || recog_memoized (pred
) == CODE_FOR_mac64_600
7748 || recog_memoized (pred
) == CODE_FOR_umul64_600
7749 || recog_memoized (pred
) == CODE_FOR_umac64_600
)
7751 subrtx_iterator::array_type array
;
7752 FOR_EACH_SUBRTX (iter
, array
, PATTERN (pred
), NONCONST
)
7754 const_rtx x
= *iter
;
7755 switch (GET_CODE (x
))
7757 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
7760 /* This is also fine for PRE/POST_MODIFY, because they
7764 rtx dest
= XEXP (x
, 0);
7765 /* Check if this sets a an extension register. N.B. we use 61 for the
7766 condition codes, which is definitely not an extension register. */
7767 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61
7768 /* Check if the same register is used by the PAT. */
7769 && (refers_to_regno_p
7771 REGNO (dest
) + (GET_MODE_SIZE (GET_MODE (dest
)) + 3) / 4U,
7772 PATTERN (succ
), 0)))
7779 A write to a core reg greater or equal to 32 must not be immediately
7780 followed by a use. Anticipate the length requirement to insert a nop
7781 between PRED and SUCC to prevent a hazard. */
7784 arc_hazard (rtx_insn
*pred
, rtx_insn
*succ
)
7788 if (!pred
|| !INSN_P (pred
) || !succ
|| !INSN_P (succ
))
7790 /* We might have a CALL to a non-returning function before a loop end.
7791 ??? Although the manual says that's OK (the target is outside the loop,
7792 and the loop counter unused there), the assembler barfs on this, so we
7793 must instert a nop before such a call too. */
7794 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
7795 && (JUMP_P (pred
) || CALL_P (pred
)
7796 || GET_CODE (PATTERN (pred
)) == SEQUENCE
))
7798 return arc600_corereg_hazard (pred
, succ
);
7801 /* Return length adjustment for INSN. */
7804 arc_adjust_insn_length (rtx_insn
*insn
, int len
, bool)
7808 /* We already handle sequences by ignoring the delay sequence flag. */
7809 if (GET_CODE (PATTERN (insn
)) == SEQUENCE
)
7812 /* It is impossible to jump to the very end of a Zero-Overhead Loop, as
7813 the ZOL mechanism only triggers when advancing to the end address,
7814 so if there's a label at the end of a ZOL, we need to insert a nop.
7815 The ARC600 ZOL also has extra restrictions on jumps at the end of a
7817 if (recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
7819 rtx_insn
*prev
= prev_nonnote_insn (insn
);
7821 return ((LABEL_P (prev
)
7824 || CALL_P (prev
) /* Could be a noreturn call. */
7825 || (NONJUMP_INSN_P (prev
)
7826 && GET_CODE (PATTERN (prev
)) == SEQUENCE
))))
7830 /* Check for return with but one preceding insn since function
7832 if (TARGET_PAD_RETURN
7834 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
7835 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
7836 && get_attr_type (insn
) == TYPE_RETURN
)
7838 rtx_insn
*prev
= prev_active_insn (insn
);
7840 if (!prev
|| !(prev
= prev_active_insn (prev
))
7841 || ((NONJUMP_INSN_P (prev
)
7842 && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
7843 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
7845 : CALL_ATTR (prev
, NON_SIBCALL
)))
7850 rtx_insn
*succ
= next_real_insn (insn
);
7852 /* One the ARC600, a write to an extension register must be separated
7854 if (succ
&& INSN_P (succ
))
7855 len
+= arc600_corereg_hazard (insn
, succ
);
7858 /* Restore extracted operands - otherwise splitters like the addsi3_mixed one
7860 extract_constrain_insn_cached (insn
);
7865 /* Values for length_sensitive. */
7869 ARC_LS_25
, // 25 bit offset, B
7870 ARC_LS_21
, // 21 bit offset, Bcc
7871 ARC_LS_U13
,// 13 bit unsigned offset, LP
7872 ARC_LS_10
, // 10 bit offset, B_s, Beq_s, Bne_s
7873 ARC_LS_9
, // 9 bit offset, BRcc
7874 ARC_LS_8
, // 8 bit offset, BRcc_s
7875 ARC_LS_U7
, // 7 bit unsigned offset, LPcc
7876 ARC_LS_7
// 7 bit offset, Bcc_s
7879 /* While the infrastructure patch is waiting for review, duplicate the
7880 struct definitions, to allow this file to compile. */
7885 /* Cost as a branch / call target or call return address. */
7887 int fallthrough_cost
;
7890 /* 0 for not length sensitive, 1 for largest offset range,
7891 * 2 for next smaller etc. */
7892 unsigned length_sensitive
: 8;
7894 } insn_length_variant_t
;
7896 typedef struct insn_length_parameters_s
7901 int (*get_variants
) (rtx_insn
*, int, bool, bool, insn_length_variant_t
*);
7902 } insn_length_parameters_t
;
7905 arc_insn_length_parameters (insn_length_parameters_t
*ilp
) ATTRIBUTE_UNUSED
;
7909 arc_get_insn_variants (rtx_insn
*insn
, int len
, bool, bool target_p
,
7910 insn_length_variant_t
*ilv
)
7912 if (!NONDEBUG_INSN_P (insn
))
7914 enum attr_type type
;
7915 /* shorten_branches doesn't take optimize_size into account yet for the
7916 get_variants mechanism, so turn this off for now. */
7919 if (rtx_sequence
*pat
= dyn_cast
<rtx_sequence
*> (PATTERN (insn
)))
7921 /* The interaction of a short delay slot insn with a short branch is
7922 too weird for shorten_branches to piece together, so describe the
7925 if (TARGET_UPSIZE_DBR
7926 && get_attr_length (pat
->insn (1)) <= 2
7927 && (((type
= get_attr_type (inner
= pat
->insn (0)))
7928 == TYPE_UNCOND_BRANCH
)
7929 || type
== TYPE_BRANCH
)
7930 && get_attr_delay_slot_filled (inner
) == DELAY_SLOT_FILLED_YES
)
7933 = arc_get_insn_variants (inner
, get_attr_length (inner
), true,
7935 /* The short variant gets split into a higher-cost aligned
7936 and a lower cost unaligned variant. */
7937 gcc_assert (n_variants
);
7938 gcc_assert (ilv
[1].length_sensitive
== ARC_LS_7
7939 || ilv
[1].length_sensitive
== ARC_LS_10
);
7940 gcc_assert (ilv
[1].align_set
== 3);
7942 ilv
[0].align_set
= 1;
7943 ilv
[0].branch_cost
+= 1;
7944 ilv
[1].align_set
= 2;
7946 for (int i
= 0; i
< n_variants
; i
++)
7948 /* In case an instruction with aligned size is wanted, and
7949 the short variants are unavailable / too expensive, add
7950 versions of long branch + long delay slot. */
7951 for (int i
= 2, end
= n_variants
; i
< end
; i
++, n_variants
++)
7953 ilv
[n_variants
] = ilv
[i
];
7954 ilv
[n_variants
].length
+= 2;
7960 insn_length_variant_t
*first_ilv
= ilv
;
7961 type
= get_attr_type (insn
);
7963 = (get_attr_delay_slot_filled (insn
) == DELAY_SLOT_FILLED_YES
);
7964 int branch_align_cost
= delay_filled
? 0 : 1;
7965 int branch_unalign_cost
= delay_filled
? 0 : TARGET_UNALIGN_BRANCH
? 0 : 1;
7966 /* If the previous instruction is an sfunc call, this insn is always
7967 a target, even though the middle-end is unaware of this. */
7968 bool force_target
= false;
7969 rtx_insn
*prev
= prev_active_insn (insn
);
7970 if (prev
&& arc_next_active_insn (prev
, 0) == insn
7971 && ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
7972 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
7974 : (CALL_ATTR (prev
, NON_SIBCALL
)
7975 && NEXT_INSN (PREV_INSN (prev
)) == prev
)))
7976 force_target
= true;
7981 /* Short BRCC only comes in no-delay-slot version, and without limm */
7986 ilv
->branch_cost
= 1;
7987 ilv
->enabled
= (len
== 2);
7988 ilv
->length_sensitive
= ARC_LS_8
;
7992 case TYPE_BRCC_NO_DELAY_SLOT
:
7993 /* doloop_fallback* patterns are TYPE_BRCC_NO_DELAY_SLOT for
7994 (delay slot) scheduling purposes, but they are longer. */
7995 if (GET_CODE (PATTERN (insn
)) == PARALLEL
7996 && GET_CODE (XVECEXP (PATTERN (insn
), 0, 1)) == SET
)
7998 /* Standard BRCC: 4 bytes, or 8 bytes with limm. */
7999 ilv
->length
= ((type
== TYPE_BRCC
) ? 4 : 8);
8001 ilv
->branch_cost
= branch_align_cost
;
8002 ilv
->enabled
= (len
<= ilv
->length
);
8003 ilv
->length_sensitive
= ARC_LS_9
;
8004 if ((target_p
|| force_target
)
8005 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8011 ilv
->target_cost
= 1;
8012 ilv
->branch_cost
= branch_unalign_cost
;
8017 op
= XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 0);
8020 if (GET_CODE (op0
) == ZERO_EXTRACT
8021 && satisfies_constraint_L (XEXP (op0
, 2)))
8022 op0
= XEXP (op0
, 0);
8023 if (satisfies_constraint_Rcq (op0
))
8025 ilv
->length
= ((type
== TYPE_BRCC
) ? 6 : 10);
8027 ilv
->branch_cost
= 1 + branch_align_cost
;
8028 ilv
->fallthrough_cost
= 1;
8029 ilv
->enabled
= true;
8030 ilv
->length_sensitive
= ARC_LS_21
;
8031 if (!delay_filled
&& TARGET_UNALIGN_BRANCH
)
8037 ilv
->branch_cost
= 1 + branch_unalign_cost
;
8041 ilv
->length
= ((type
== TYPE_BRCC
) ? 8 : 12);
8043 ilv
->branch_cost
= 1 + branch_align_cost
;
8044 ilv
->fallthrough_cost
= 1;
8045 ilv
->enabled
= true;
8046 ilv
->length_sensitive
= ARC_LS_21
;
8047 if ((target_p
|| force_target
)
8048 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8054 ilv
->target_cost
= 1;
8055 ilv
->branch_cost
= 1 + branch_unalign_cost
;
8063 case TYPE_CALL_NO_DELAY_SLOT
:
8068 ilv
->length_sensitive
8069 = GET_CODE (PATTERN (insn
)) == COND_EXEC
? ARC_LS_21
: ARC_LS_25
;
8072 ilv
->fallthrough_cost
= branch_align_cost
;
8073 ilv
->enabled
= true;
8074 if ((target_p
|| force_target
)
8075 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8081 ilv
->target_cost
= 1;
8082 ilv
->fallthrough_cost
= branch_unalign_cost
;
8086 case TYPE_UNCOND_BRANCH
:
8087 /* Strictly speaking, this should be ARC_LS_10 for equality comparisons,
8088 but that makes no difference at the moment. */
8089 ilv
->length_sensitive
= ARC_LS_7
;
8090 ilv
[1].length_sensitive
= ARC_LS_25
;
8093 ilv
->length_sensitive
= ARC_LS_10
;
8094 ilv
[1].length_sensitive
= ARC_LS_21
;
8098 ilv
->branch_cost
= branch_align_cost
;
8099 ilv
->enabled
= (len
== ilv
->length
);
8103 ilv
->branch_cost
= branch_align_cost
;
8104 ilv
->enabled
= true;
8105 if ((target_p
|| force_target
)
8106 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8112 ilv
->target_cost
= 1;
8113 ilv
->branch_cost
= branch_unalign_cost
;
8120 /* For every short insn, there is generally also a long insn.
8121 trap_s is an exception. */
8122 if ((len
& 2) == 0 || recog_memoized (insn
) == CODE_FOR_trap_s
)
8129 ilv
->length
= len
+ 2;
8131 if (target_p
|| force_target
)
8137 ilv
->target_cost
= 1;
8141 /* If the previous instruction is an sfunc call, this insn is always
8142 a target, even though the middle-end is unaware of this.
8143 Therefore, if we have a call predecessor, transfer the target cost
8144 to the fallthrough and branch costs. */
8147 for (insn_length_variant_t
*p
= first_ilv
; p
< ilv
; p
++)
8149 p
->fallthrough_cost
+= p
->target_cost
;
8150 p
->branch_cost
+= p
->target_cost
;
8155 return ilv
- first_ilv
;
8159 arc_insn_length_parameters (insn_length_parameters_t
*ilp
)
8161 ilp
->align_unit_log
= 1;
8162 ilp
->align_base_log
= 1;
8163 ilp
->max_variants
= 7;
8164 ilp
->get_variants
= arc_get_insn_variants
;
8167 /* Return a copy of COND from *STATEP, inverted if that is indicated by the
8168 CC field of *STATEP. */
8171 arc_get_ccfsm_cond (struct arc_ccfsm
*statep
, bool reverse
)
8173 rtx cond
= statep
->cond
;
8174 int raw_cc
= get_arc_condition_code (cond
);
8176 raw_cc
= ARC_INVERSE_CONDITION_CODE (raw_cc
);
8178 if (statep
->cc
== raw_cc
)
8179 return copy_rtx (cond
);
8181 gcc_assert (ARC_INVERSE_CONDITION_CODE (raw_cc
) == statep
->cc
);
8183 machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
8184 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
8185 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
8186 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
8188 return gen_rtx_fmt_ee (code
, GET_MODE (cond
),
8189 copy_rtx (XEXP (cond
, 0)), copy_rtx (XEXP (cond
, 1)));
8192 /* Return version of PAT conditionalized with COND, which is part of INSN.
8193 ANNULLED indicates if INSN is an annulled delay-slot insn.
8194 Register further changes if necessary. */
8196 conditionalize_nonjump (rtx pat
, rtx cond
, rtx insn
, bool annulled
)
8198 /* For commutative operators, we generally prefer to have
8199 the first source match the destination. */
8200 if (GET_CODE (pat
) == SET
)
8202 rtx src
= SET_SRC (pat
);
8204 if (COMMUTATIVE_P (src
))
8206 rtx src0
= XEXP (src
, 0);
8207 rtx src1
= XEXP (src
, 1);
8208 rtx dst
= SET_DEST (pat
);
8210 if (rtx_equal_p (src1
, dst
) && !rtx_equal_p (src0
, dst
)
8211 /* Leave add_n alone - the canonical form is to
8212 have the complex summand first. */
8214 pat
= gen_rtx_SET (VOIDmode
, dst
,
8215 gen_rtx_fmt_ee (GET_CODE (src
), GET_MODE (src
),
8220 /* dwarf2out.c:dwarf2out_frame_debug_expr doesn't know
8221 what to do with COND_EXEC. */
8222 if (RTX_FRAME_RELATED_P (insn
))
8224 /* If this is the delay slot insn of an anulled branch,
8225 dwarf2out.c:scan_trace understands the anulling semantics
8226 without the COND_EXEC. */
8227 gcc_assert (annulled
);
8228 rtx note
= alloc_reg_note (REG_FRAME_RELATED_EXPR
, pat
,
8230 validate_change (insn
, ®_NOTES (insn
), note
, 1);
8232 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
8236 /* Use the ccfsm machinery to do if conversion. */
8241 struct arc_ccfsm
*statep
= &cfun
->machine
->ccfsm_current
;
8242 basic_block merge_bb
= 0;
8244 memset (statep
, 0, sizeof *statep
);
8245 for (rtx_insn
*insn
= get_insns (); insn
; insn
= next_insn (insn
))
8247 arc_ccfsm_advance (insn
, statep
);
8249 switch (statep
->state
)
8257 /* Deleted branch. */
8258 gcc_assert (!merge_bb
);
8259 merge_bb
= BLOCK_FOR_INSN (insn
);
8261 = BLOCK_FOR_INSN (NEXT_INSN (NEXT_INSN (PREV_INSN (insn
))));
8262 arc_ccfsm_post_advance (insn
, statep
);
8263 gcc_assert (!IN_RANGE (statep
->state
, 1, 2));
8264 rtx_insn
*seq
= NEXT_INSN (PREV_INSN (insn
));
8267 rtx slot
= XVECEXP (PATTERN (seq
), 0, 1);
8268 rtx pat
= PATTERN (slot
);
8269 if (INSN_ANNULLED_BRANCH_P (insn
))
8272 = arc_get_ccfsm_cond (statep
, INSN_FROM_TARGET_P (slot
));
8273 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
8275 if (!validate_change (seq
, &PATTERN (seq
), pat
, 0))
8277 PUT_CODE (slot
, NOTE
);
8278 NOTE_KIND (slot
) = NOTE_INSN_DELETED
;
8279 if (merge_bb
&& succ_bb
)
8280 merge_blocks (merge_bb
, succ_bb
);
8282 else if (merge_bb
&& succ_bb
)
8284 set_insn_deleted (insn
);
8285 merge_blocks (merge_bb
, succ_bb
);
8289 PUT_CODE (insn
, NOTE
);
8290 NOTE_KIND (insn
) = NOTE_INSN_DELETED
;
8296 && statep
->target_label
== CODE_LABEL_NUMBER (insn
))
8298 arc_ccfsm_post_advance (insn
, statep
);
8299 basic_block succ_bb
= BLOCK_FOR_INSN (insn
);
8300 if (merge_bb
&& succ_bb
)
8301 merge_blocks (merge_bb
, succ_bb
);
8302 else if (--LABEL_NUSES (insn
) == 0)
8304 const char *name
= LABEL_NAME (insn
);
8305 PUT_CODE (insn
, NOTE
);
8306 NOTE_KIND (insn
) = NOTE_INSN_DELETED_LABEL
;
8307 NOTE_DELETED_LABEL_NAME (insn
) = name
;
8314 if (!NONDEBUG_INSN_P (insn
))
8317 /* Conditionalized insn. */
8319 rtx_insn
*prev
, *pprev
;
8320 rtx
*patp
, pat
, cond
;
8321 bool annulled
; annulled
= false;
8323 /* If this is a delay slot insn in a non-annulled branch,
8324 don't conditionalize it. N.B., this should be fine for
8325 conditional return too. However, don't do this for
8326 unconditional branches, as these would be encountered when
8327 processing an 'else' part. */
8328 prev
= PREV_INSN (insn
);
8329 pprev
= PREV_INSN (prev
);
8330 if (pprev
&& NEXT_INSN (NEXT_INSN (pprev
)) == NEXT_INSN (insn
)
8331 && JUMP_P (prev
) && get_attr_cond (prev
) == COND_USE
)
8333 if (!INSN_ANNULLED_BRANCH_P (prev
))
8338 patp
= &PATTERN (insn
);
8340 cond
= arc_get_ccfsm_cond (statep
, INSN_FROM_TARGET_P (insn
));
8341 if (NONJUMP_INSN_P (insn
) || CALL_P (insn
))
8343 /* ??? don't conditionalize if all side effects are dead
8344 in the not-execute case. */
8346 pat
= conditionalize_nonjump (pat
, cond
, insn
, annulled
);
8348 else if (simplejump_p (insn
))
8350 patp
= &SET_SRC (pat
);
8351 pat
= gen_rtx_IF_THEN_ELSE (VOIDmode
, cond
, *patp
, pc_rtx
);
8353 else if (JUMP_P (insn
) && ANY_RETURN_P (PATTERN (insn
)))
8355 pat
= gen_rtx_IF_THEN_ELSE (VOIDmode
, cond
, pat
, pc_rtx
);
8356 pat
= gen_rtx_SET (VOIDmode
, pc_rtx
, pat
);
8360 validate_change (insn
, patp
, pat
, 1);
8361 if (!apply_change_group ())
8365 rtx_insn
*next
= next_nonnote_insn (insn
);
8366 if (GET_CODE (next
) == BARRIER
)
8368 if (statep
->state
== 3)
8375 arc_ccfsm_post_advance (insn
, statep
);
8380 /* Find annulled delay insns and convert them to use the appropriate predicate.
8381 This allows branch shortening to size up these insns properly. */
8384 arc_predicate_delay_insns (void)
8386 for (rtx_insn
*insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
8388 rtx pat
, jump
, dlay
, src
, cond
, *patp
;
8391 if (!NONJUMP_INSN_P (insn
)
8392 || GET_CODE (pat
= PATTERN (insn
)) != SEQUENCE
)
8394 jump
= XVECEXP (pat
, 0, 0);
8395 dlay
= XVECEXP (pat
, 0, 1);
8396 if (!JUMP_P (jump
) || !INSN_ANNULLED_BRANCH_P (jump
))
8398 /* If the branch insn does the annulling, leave the delay insn alone. */
8399 if (!TARGET_AT_DBR_CONDEXEC
&& !INSN_FROM_TARGET_P (dlay
))
8401 /* ??? Could also leave DLAY un-conditionalized if its target is dead
8402 on the other path. */
8403 gcc_assert (GET_CODE (PATTERN (jump
)) == SET
);
8404 gcc_assert (SET_DEST (PATTERN (jump
)) == pc_rtx
);
8405 src
= SET_SRC (PATTERN (jump
));
8406 gcc_assert (GET_CODE (src
) == IF_THEN_ELSE
);
8407 cond
= XEXP (src
, 0);
8408 if (XEXP (src
, 2) == pc_rtx
)
8410 else if (XEXP (src
, 1) == pc_rtx
)
8414 if (reverse
!= !INSN_FROM_TARGET_P (dlay
))
8416 machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
8417 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
8418 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
8419 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
8421 cond
= gen_rtx_fmt_ee (code
, GET_MODE (cond
),
8422 copy_rtx (XEXP (cond
, 0)),
8423 copy_rtx (XEXP (cond
, 1)));
8426 cond
= copy_rtx (cond
);
8427 patp
= &PATTERN (dlay
);
8429 pat
= conditionalize_nonjump (pat
, cond
, dlay
, true);
8430 validate_change (dlay
, patp
, pat
, 1);
8431 if (!apply_change_group ())
8437 /* For ARC600: If a write to a core reg >=32 appears in a delay slot
8438 (other than of a forward brcc), it creates a hazard when there is a read
8439 of the same register at the branch target. We can't know what is at the
8440 branch target of calls, and for branches, we don't really know before the
8441 end of delay slot scheduling, either. Not only can individual instruction
8442 be hoisted out into a delay slot, a basic block can also be emptied this
8443 way, and branch and/or fall through targets be redirected. Hence we don't
8444 want such writes in a delay slot. */
8446 /* Return nonzreo iff INSN writes to an extension core register. */
8449 arc_write_ext_corereg (rtx insn
)
8451 subrtx_iterator::array_type array
;
8452 FOR_EACH_SUBRTX (iter
, array
, PATTERN (insn
), NONCONST
)
8454 const_rtx x
= *iter
;
8455 switch (GET_CODE (x
))
8457 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
8460 /* This is also fine for PRE/POST_MODIFY, because they
8464 const_rtx dest
= XEXP (x
, 0);
8465 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61)
8471 /* This is like the hook, but returns NULL when it can't / won't generate
8472 a legitimate address. */
8475 arc_legitimize_address_0 (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
8480 if (flag_pic
&& SYMBOLIC_CONST (x
))
8481 (x
) = arc_legitimize_pic_address (x
, 0);
8483 if (GET_CODE (addr
) == CONST
)
8484 addr
= XEXP (addr
, 0);
8485 if (GET_CODE (addr
) == PLUS
8486 && CONST_INT_P (XEXP (addr
, 1))
8487 && ((GET_CODE (XEXP (addr
, 0)) == SYMBOL_REF
8488 && !SYMBOL_REF_FUNCTION_P (XEXP (addr
, 0)))
8489 || (REG_P (XEXP (addr
, 0))
8490 && (INTVAL (XEXP (addr
, 1)) & 252))))
8492 HOST_WIDE_INT offs
, upper
;
8493 int size
= GET_MODE_SIZE (mode
);
8495 offs
= INTVAL (XEXP (addr
, 1));
8496 upper
= (offs
+ 256 * size
) & ~511 * size
;
8497 inner
= plus_constant (Pmode
, XEXP (addr
, 0), upper
);
8498 #if 0 /* ??? this produces worse code for EEMBC idctrn01 */
8499 if (GET_CODE (x
) == CONST
)
8500 inner
= gen_rtx_CONST (Pmode
, inner
);
8502 addr
= plus_constant (Pmode
, force_reg (Pmode
, inner
), offs
- upper
);
8505 else if (GET_CODE (addr
) == SYMBOL_REF
&& !SYMBOL_REF_FUNCTION_P (addr
))
8506 x
= force_reg (Pmode
, x
);
8507 if (memory_address_p ((machine_mode
) mode
, x
))
8513 arc_legitimize_address (rtx orig_x
, rtx oldx
, machine_mode mode
)
8515 rtx new_x
= arc_legitimize_address_0 (orig_x
, oldx
, mode
);
8523 arc_delegitimize_address_0 (rtx x
)
8527 if (GET_CODE (x
) == CONST
&& GET_CODE (u
= XEXP (x
, 0)) == UNSPEC
)
8529 if (XINT (u
, 1) == ARC_UNSPEC_GOT
)
8530 return XVECEXP (u
, 0, 0);
8532 else if (GET_CODE (x
) == PLUS
8533 && ((REG_P (gp
= XEXP (x
, 0))
8534 && REGNO (gp
) == PIC_OFFSET_TABLE_REGNUM
)
8535 || (GET_CODE (gp
) == CONST
8536 && GET_CODE (u
= XEXP (gp
, 0)) == UNSPEC
8537 && XINT (u
, 1) == ARC_UNSPEC_GOT
8538 && GET_CODE (XVECEXP (u
, 0, 0)) == SYMBOL_REF
8539 && !strcmp (XSTR (XVECEXP (u
, 0, 0), 0), "_DYNAMIC")))
8540 && GET_CODE (XEXP (x
, 1)) == CONST
8541 && GET_CODE (u
= XEXP (XEXP (x
, 1), 0)) == UNSPEC
8542 && XINT (u
, 1) == ARC_UNSPEC_GOTOFF
)
8543 return XVECEXP (u
, 0, 0);
8544 else if (GET_CODE (x
) == PLUS
&& GET_CODE (XEXP (x
, 0)) == PLUS
8545 && ((REG_P (gp
= XEXP (XEXP (x
, 0), 1))
8546 && REGNO (gp
) == PIC_OFFSET_TABLE_REGNUM
)
8547 || (GET_CODE (gp
) == CONST
8548 && GET_CODE (u
= XEXP (gp
, 0)) == UNSPEC
8549 && XINT (u
, 1) == ARC_UNSPEC_GOT
8550 && GET_CODE (XVECEXP (u
, 0, 0)) == SYMBOL_REF
8551 && !strcmp (XSTR (XVECEXP (u
, 0, 0), 0), "_DYNAMIC")))
8552 && GET_CODE (XEXP (x
, 1)) == CONST
8553 && GET_CODE (u
= XEXP (XEXP (x
, 1), 0)) == UNSPEC
8554 && XINT (u
, 1) == ARC_UNSPEC_GOTOFF
)
8555 return gen_rtx_PLUS (GET_MODE (x
), XEXP (XEXP (x
, 0), 0),
8557 else if (GET_CODE (x
) == PLUS
8558 && (u
= arc_delegitimize_address_0 (XEXP (x
, 1))))
8559 return gen_rtx_PLUS (GET_MODE (x
), XEXP (x
, 0), u
);
8564 arc_delegitimize_address (rtx x
)
8566 rtx orig_x
= x
= delegitimize_mem_from_attrs (x
);
8567 if (GET_CODE (x
) == MEM
)
8569 x
= arc_delegitimize_address_0 (x
);
8573 x
= replace_equiv_address_nv (orig_x
, x
);
8579 /* Return a REG rtx for acc1. N.B. the gcc-internal representation may
8580 differ from the hardware register number in order to allow the generic
8581 code to correctly split the concatenation of acc1 and acc2. */
8586 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 56: 57);
8589 /* Return a REG rtx for acc2. N.B. the gcc-internal representation may
8590 differ from the hardware register number in order to allow the generic
8591 code to correctly split the concatenation of acc1 and acc2. */
8596 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 57: 56);
8599 /* Return a REG rtx for mlo. N.B. the gcc-internal representation may
8600 differ from the hardware register number in order to allow the generic
8601 code to correctly split the concatenation of mhi and mlo. */
8606 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 59: 58);
8609 /* Return a REG rtx for mhi. N.B. the gcc-internal representation may
8610 differ from the hardware register number in order to allow the generic
8611 code to correctly split the concatenation of mhi and mlo. */
8616 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 58: 59);
8619 /* FIXME: a parameter should be added, and code added to final.c,
8620 to reproduce this functionality in shorten_branches. */
8622 /* Return nonzero iff BRANCH should be unaligned if possible by upsizing
8623 a previous instruction. */
8625 arc_unalign_branch_p (rtx branch
)
8629 if (!TARGET_UNALIGN_BRANCH
)
8631 /* Do not do this if we have a filled delay slot. */
8632 if (get_attr_delay_slot_filled (branch
) == DELAY_SLOT_FILLED_YES
8633 && !NEXT_INSN (branch
)->deleted ())
8635 note
= find_reg_note (branch
, REG_BR_PROB
, 0);
8637 || (arc_unalign_prob_threshold
&& !br_prob_note_reliable_p (note
))
8638 || INTVAL (XEXP (note
, 0)) < arc_unalign_prob_threshold
);
8642 /* When estimating sizes during arc_reorg, when optimizing for speed, there
8643 are three reasons why we need to consider branches to be length 6:
8644 - annull-false delay slot insns are implemented using conditional execution,
8645 thus preventing short insn formation where used.
8646 - for ARC600: annul-true delay slot insns are implemented where possible
8647 using conditional execution, preventing short insn formation where used.
8648 - for ARC700: likely or somewhat likely taken branches are made long and
8649 unaligned if possible to avoid branch penalty. */
8652 arc_branch_size_unknown_p (void)
8654 return !optimize_size
&& arc_reorg_in_progress
;
8657 /* We are about to output a return insn. Add padding if necessary to avoid
8658 a mispredict. A return could happen immediately after the function
8659 start, but after a call we know that there will be at least a blink
8663 arc_pad_return (void)
8665 rtx_insn
*insn
= current_output_insn
;
8666 rtx_insn
*prev
= prev_active_insn (insn
);
8671 fputs ("\tnop_s\n", asm_out_file
);
8672 cfun
->machine
->unalign
^= 2;
8675 /* If PREV is a sequence, we know it must be a branch / jump or a tailcall,
8676 because after a call, we'd have to restore blink first. */
8677 else if (GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8681 want_long
= (get_attr_length (prev
) == 2);
8682 prev
= prev_active_insn (prev
);
8685 || ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8686 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
8688 : CALL_ATTR (prev
, NON_SIBCALL
)))
8691 cfun
->machine
->size_reason
8692 = "call/return and return/return must be 6 bytes apart to avoid mispredict";
8693 else if (TARGET_UNALIGN_BRANCH
&& cfun
->machine
->unalign
)
8695 cfun
->machine
->size_reason
8696 = "Long unaligned jump avoids non-delay slot penalty";
8699 /* Disgorge delay insn, if there is any, and it may be moved. */
8701 /* ??? Annulled would be OK if we can and do conditionalize
8702 the delay slot insn accordingly. */
8703 && !INSN_ANNULLED_BRANCH_P (insn
)
8704 && (get_attr_cond (insn
) != COND_USE
8705 || !reg_set_p (gen_rtx_REG (CCmode
, CC_REG
),
8706 XVECEXP (final_sequence
, 0, 1))))
8708 prev
= as_a
<rtx_insn
*> (XVECEXP (final_sequence
, 0, 1));
8709 gcc_assert (!prev_real_insn (insn
)
8710 || !arc_hazard (prev_real_insn (insn
), prev
));
8711 cfun
->machine
->force_short_suffix
= !want_long
;
8712 rtx save_pred
= current_insn_predicate
;
8713 final_scan_insn (prev
, asm_out_file
, optimize
, 1, NULL
);
8714 cfun
->machine
->force_short_suffix
= -1;
8715 prev
->set_deleted ();
8716 current_output_insn
= insn
;
8717 current_insn_predicate
= save_pred
;
8720 fputs ("\tnop\n", asm_out_file
);
8723 fputs ("\tnop_s\n", asm_out_file
);
8724 cfun
->machine
->unalign
^= 2;
8730 /* The usual; we set up our machine_function data. */
8732 static struct machine_function
*
8733 arc_init_machine_status (void)
8735 struct machine_function
*machine
;
8736 machine
= ggc_cleared_alloc
<machine_function
> ();
8737 machine
->fn_type
= ARC_FUNCTION_UNKNOWN
;
8738 machine
->force_short_suffix
= -1;
8743 /* Implements INIT_EXPANDERS. We just set up to call the above
8747 arc_init_expanders (void)
8749 init_machine_status
= arc_init_machine_status
;
8752 /* Check if OP is a proper parallel of a millicode call pattern. OFFSET
8753 indicates a number of elements to ignore - that allows to have a
8754 sibcall pattern that starts with (return). LOAD_P is zero for store
8755 multiple (for prologues), and one for load multiples (for epilogues),
8756 and two for load multiples where no final clobber of blink is required.
8757 We also skip the first load / store element since this is supposed to
8758 be checked in the instruction pattern. */
8761 arc_check_millicode (rtx op
, int offset
, int load_p
)
8763 int len
= XVECLEN (op
, 0) - offset
;
8768 if (len
< 2 || len
> 13)
8774 rtx elt
= XVECEXP (op
, 0, --len
);
8776 if (GET_CODE (elt
) != CLOBBER
8777 || !REG_P (XEXP (elt
, 0))
8778 || REGNO (XEXP (elt
, 0)) != RETURN_ADDR_REGNUM
8779 || len
< 3 || len
> 13)
8782 for (i
= 1; i
< len
; i
++)
8784 rtx elt
= XVECEXP (op
, 0, i
+ offset
);
8787 if (GET_CODE (elt
) != SET
)
8789 mem
= XEXP (elt
, load_p
);
8790 reg
= XEXP (elt
, 1-load_p
);
8791 if (!REG_P (reg
) || REGNO (reg
) != 13U+i
|| !MEM_P (mem
))
8793 addr
= XEXP (mem
, 0);
8794 if (GET_CODE (addr
) != PLUS
8795 || !rtx_equal_p (stack_pointer_rtx
, XEXP (addr
, 0))
8796 || !CONST_INT_P (XEXP (addr
, 1)) || INTVAL (XEXP (addr
, 1)) != i
*4)
8802 /* Accessor functions for cfun->machine->unalign. */
8805 arc_get_unalign (void)
8807 return cfun
->machine
->unalign
;
8811 arc_clear_unalign (void)
8814 cfun
->machine
->unalign
= 0;
8818 arc_toggle_unalign (void)
8820 cfun
->machine
->unalign
^= 2;
8823 /* Operands 0..2 are the operands of a addsi which uses a 12 bit
8824 constant in operand 2, but which would require a LIMM because of
8826 operands 3 and 4 are new SET_SRCs for operands 0. */
8829 split_addsi (rtx
*operands
)
8831 int val
= INTVAL (operands
[2]);
8833 /* Try for two short insns first. Lengths being equal, we prefer
8834 expansions with shorter register lifetimes. */
8835 if (val
> 127 && val
<= 255
8836 && satisfies_constraint_Rcq (operands
[0]))
8838 operands
[3] = operands
[2];
8839 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
8843 operands
[3] = operands
[1];
8844 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[2]);
8848 /* Operands 0..2 are the operands of a subsi which uses a 12 bit
8849 constant in operand 1, but which would require a LIMM because of
8851 operands 3 and 4 are new SET_SRCs for operands 0. */
8854 split_subsi (rtx
*operands
)
8856 int val
= INTVAL (operands
[1]);
8858 /* Try for two short insns first. Lengths being equal, we prefer
8859 expansions with shorter register lifetimes. */
8860 if (satisfies_constraint_Rcq (operands
[0])
8861 && satisfies_constraint_Rcq (operands
[2]))
8863 if (val
>= -31 && val
<= 127)
8865 operands
[3] = gen_rtx_NEG (SImode
, operands
[2]);
8866 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
8869 else if (val
>= 0 && val
< 255)
8871 operands
[3] = operands
[1];
8872 operands
[4] = gen_rtx_MINUS (SImode
, operands
[0], operands
[2]);
8876 /* If the destination is not an ARCompact16 register, we might
8877 still have a chance to make a short insn if the source is;
8878 we need to start with a reg-reg move for this. */
8879 operands
[3] = operands
[2];
8880 operands
[4] = gen_rtx_MINUS (SImode
, operands
[1], operands
[0]);
8883 /* Handle DOUBLE_REGS uses.
8884 Operand 0: destination register
8885 Operand 1: source register */
8888 arc_process_double_reg_moves (rtx
*operands
)
8890 rtx dest
= operands
[0];
8891 rtx src
= operands
[1];
8894 enum usesDxState
{ none
, srcDx
, destDx
, maxDx
};
8895 enum usesDxState state
= none
;
8897 if (refers_to_regno_p (40, 44, src
, 0))
8899 if (refers_to_regno_p (40, 44, dest
, 0))
8901 /* Via arc_register_move_cost, we should never see D,D moves. */
8902 gcc_assert (state
== none
);
8913 /* Without the LR insn, we need to split this into a
8914 sequence of insns which will use the DEXCLx and DADDHxy
8915 insns to be able to read the Dx register in question. */
8916 if (TARGET_DPFP_DISABLE_LRSR
)
8918 /* gen *movdf_insn_nolrsr */
8919 rtx set
= gen_rtx_SET (VOIDmode
, dest
, src
);
8920 rtx use1
= gen_rtx_USE (VOIDmode
, const1_rtx
);
8921 emit_insn (gen_rtx_PARALLEL (VOIDmode
, gen_rtvec (2, set
, use1
)));
8925 /* When we have 'mov D, r' or 'mov D, D' then get the target
8926 register pair for use with LR insn. */
8927 rtx destHigh
= simplify_gen_subreg(SImode
, dest
, DFmode
, 4);
8928 rtx destLow
= simplify_gen_subreg(SImode
, dest
, DFmode
, 0);
8930 /* Produce the two LR insns to get the high and low parts. */
8931 emit_insn (gen_rtx_SET (VOIDmode
,
8933 gen_rtx_UNSPEC_VOLATILE (Pmode
, gen_rtvec (1, src
),
8935 emit_insn (gen_rtx_SET (VOIDmode
,
8937 gen_rtx_UNSPEC_VOLATILE (Pmode
, gen_rtvec (1, src
),
8941 else if (state
== destDx
)
8943 /* When we have 'mov r, D' or 'mov D, D' and we have access to the
8944 LR insn get the target register pair. */
8945 rtx srcHigh
= simplify_gen_subreg(SImode
, src
, DFmode
, 4);
8946 rtx srcLow
= simplify_gen_subreg(SImode
, src
, DFmode
, 0);
8948 emit_insn (gen_rtx_UNSPEC_VOLATILE (Pmode
,
8949 gen_rtvec (3, dest
, srcHigh
, srcLow
),
8950 VUNSPEC_DEXCL_NORES
));
8961 /* operands 0..1 are the operands of a 64 bit move instruction.
8962 split it into two moves with operands 2/3 and 4/5. */
8965 arc_split_move (rtx
*operands
)
8967 machine_mode mode
= GET_MODE (operands
[0]);
8975 val
= arc_process_double_reg_moves (operands
);
8980 for (i
= 0; i
< 2; i
++)
8982 if (MEM_P (operands
[i
]) && auto_inc_p (XEXP (operands
[i
], 0)))
8984 rtx addr
= XEXP (operands
[i
], 0);
8988 gcc_assert (!reg_overlap_mentioned_p (operands
[0], addr
));
8989 switch (GET_CODE (addr
))
8991 case PRE_DEC
: o
= GEN_INT (-8); goto pre_modify
;
8992 case PRE_INC
: o
= GEN_INT (8); goto pre_modify
;
8993 case PRE_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
8997 case POST_DEC
: o
= GEN_INT (-8); goto post_modify
;
8998 case POST_INC
: o
= GEN_INT (8); goto post_modify
;
8999 case POST_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
9008 xop
[0+i
] = adjust_automodify_address_nv
9009 (operands
[i
], SImode
,
9010 gen_rtx_fmt_ee (code
, Pmode
, r
,
9011 gen_rtx_PLUS (Pmode
, r
, o
)),
9013 xop
[2+i
] = adjust_automodify_address_nv
9014 (operands
[i
], SImode
, plus_constant (Pmode
, r
, 4), 4);
9018 xop
[0+i
] = operand_subword (operands
[i
], 0, 0, mode
);
9019 xop
[2+i
] = operand_subword (operands
[i
], 1, 0, mode
);
9022 if (reg_overlap_mentioned_p (xop
[0], xop
[3]))
9025 gcc_assert (!reg_overlap_mentioned_p (xop
[2], xop
[1]));
9027 operands
[2+swap
] = xop
[0];
9028 operands
[3+swap
] = xop
[1];
9029 operands
[4-swap
] = xop
[2];
9030 operands
[5-swap
] = xop
[3];
9033 emit_insn (gen_rtx_SET (VOIDmode
, operands
[2], operands
[3]));
9034 emit_insn (gen_rtx_SET (VOIDmode
, operands
[4], operands
[5]));
9041 /* Select between the instruction output templates s_tmpl (for short INSNs)
9042 and l_tmpl (for long INSNs). */
9045 arc_short_long (rtx_insn
*insn
, const char *s_tmpl
, const char *l_tmpl
)
9047 int is_short
= arc_verify_short (insn
, cfun
->machine
->unalign
, -1);
9049 extract_constrain_insn_cached (insn
);
9050 return is_short
? s_tmpl
: l_tmpl
;
9053 /* Searches X for any reference to REGNO, returning the rtx of the
9054 reference found if any. Otherwise, returns NULL_RTX. */
9057 arc_regno_use_in (unsigned int regno
, rtx x
)
9063 if (REG_P (x
) && refers_to_regno_p (regno
, regno
+1, x
, (rtx
*) 0))
9066 fmt
= GET_RTX_FORMAT (GET_CODE (x
));
9067 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
9071 if ((tem
= regno_use_in (regno
, XEXP (x
, i
))))
9074 else if (fmt
[i
] == 'E')
9075 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
9076 if ((tem
= regno_use_in (regno
, XVECEXP (x
, i
, j
))))
9083 /* Return the integer value of the "type" attribute for INSN, or -1 if
9084 INSN can't have attributes. */
9087 arc_attr_type (rtx_insn
*insn
)
9089 if (NONJUMP_INSN_P (insn
)
9090 ? (GET_CODE (PATTERN (insn
)) == USE
9091 || GET_CODE (PATTERN (insn
)) == CLOBBER
)
9093 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
9094 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
9097 return get_attr_type (insn
);
9100 /* Return true if insn sets the condition codes. */
9103 arc_sets_cc_p (rtx_insn
*insn
)
9105 if (NONJUMP_INSN_P (insn
))
9106 if (rtx_sequence
*seq
= dyn_cast
<rtx_sequence
*> (PATTERN (insn
)))
9107 insn
= seq
->insn (seq
->len () - 1);
9108 return arc_attr_type (insn
) == TYPE_COMPARE
;
9111 /* Return true if INSN is an instruction with a delay slot we may want
9115 arc_need_delay (rtx_insn
*insn
)
9119 if (!flag_delayed_branch
)
9121 /* The return at the end of a function needs a delay slot. */
9122 if (NONJUMP_INSN_P (insn
) && GET_CODE (PATTERN (insn
)) == USE
9123 && (!(next
= next_active_insn (insn
))
9124 || ((!NONJUMP_INSN_P (next
) || GET_CODE (PATTERN (next
)) != SEQUENCE
)
9125 && arc_attr_type (next
) == TYPE_RETURN
))
9126 && (!TARGET_PAD_RETURN
9127 || (prev_active_insn (insn
)
9128 && prev_active_insn (prev_active_insn (insn
))
9129 && prev_active_insn (prev_active_insn (prev_active_insn (insn
))))))
9131 if (NONJUMP_INSN_P (insn
)
9132 ? (GET_CODE (PATTERN (insn
)) == USE
9133 || GET_CODE (PATTERN (insn
)) == CLOBBER
9134 || GET_CODE (PATTERN (insn
)) == SEQUENCE
)
9136 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
9137 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
9140 return num_delay_slots (insn
) != 0;
9143 /* Return true if the scheduling pass(es) has/have already run,
9144 i.e. where possible, we should try to mitigate high latencies
9145 by different instruction selection. */
9148 arc_scheduling_not_expected (void)
9150 return cfun
->machine
->arc_reorg_started
;
9153 /* Oddly enough, sometimes we get a zero overhead loop that branch
9154 shortening doesn't think is a loop - observed with compile/pr24883.c
9155 -O3 -fomit-frame-pointer -funroll-loops. Make sure to include the
9156 alignment visible for branch shortening (we actually align the loop
9157 insn before it, but that is equivalent since the loop insn is 4 byte
9161 arc_label_align (rtx label
)
9163 int loop_align
= LOOP_ALIGN (LABEL
);
9165 if (loop_align
> align_labels_log
)
9167 rtx_insn
*prev
= prev_nonnote_insn (label
);
9169 if (prev
&& NONJUMP_INSN_P (prev
)
9170 && GET_CODE (PATTERN (prev
)) == PARALLEL
9171 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
)
9174 /* Code has a minimum p2 alignment of 1, which we must restore after an
9176 if (align_labels_log
< 1)
9178 rtx_insn
*next
= next_nonnote_nondebug_insn (label
);
9179 if (INSN_P (next
) && recog_memoized (next
) >= 0)
9182 return align_labels_log
;
9185 /* Return true if LABEL is in executable code. */
9188 arc_text_label (rtx_insn
*label
)
9192 /* ??? We use deleted labels like they were still there, see
9193 gcc.c-torture/compile/20000326-2.c . */
9194 gcc_assert (GET_CODE (label
) == CODE_LABEL
9195 || (GET_CODE (label
) == NOTE
9196 && NOTE_KIND (label
) == NOTE_INSN_DELETED_LABEL
));
9197 next
= next_nonnote_insn (label
);
9199 return (!JUMP_TABLE_DATA_P (next
)
9200 || GET_CODE (PATTERN (next
)) != ADDR_VEC
);
9201 else if (!PREV_INSN (label
))
9202 /* ??? sometimes text labels get inserted very late, see
9203 gcc.dg/torture/stackalign/comp-goto-1.c */
9208 /* Return the size of the pretend args for DECL. */
9211 arc_decl_pretend_args (tree decl
)
9213 /* struct function is in DECL_STRUCT_FUNCTION (decl), but no
9214 pretend_args there... See PR38391. */
9215 gcc_assert (decl
== current_function_decl
);
9216 return crtl
->args
.pretend_args_size
;
9219 /* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
9220 when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
9221 -D_PROFILE_USE; delay branch scheduling then follows a crossing jump
9222 to redirect two breqs. */
9225 arc_can_follow_jump (const rtx_insn
*follower
, const rtx_insn
*followee
)
9227 /* ??? get_attr_type is declared to take an rtx. */
9228 union { const rtx_insn
*c
; rtx_insn
*r
; } u
;
9231 if (CROSSING_JUMP_P (followee
))
9232 switch (get_attr_type (u
.r
))
9235 case TYPE_BRCC_NO_DELAY_SLOT
:
9243 /* Implement EPILOGUE__USES.
9244 Return true if REGNO should be added to the deemed uses of the epilogue.
9246 We use the return address
9247 arc_return_address_regs[arc_compute_function_type (cfun)] .
9248 But also, we have to make sure all the register restore instructions
9249 are known to be live in interrupt functions. */
9252 arc_epilogue_uses (int regno
)
9254 if (reload_completed
)
9256 if (ARC_INTERRUPT_P (cfun
->machine
->fn_type
))
9258 if (!fixed_regs
[regno
])
9260 return regno
== arc_return_address_regs
[cfun
->machine
->fn_type
];
9263 return regno
== RETURN_ADDR_REGNUM
;
9266 return regno
== arc_return_address_regs
[arc_compute_function_type (cfun
)];
9269 #ifndef TARGET_NO_LRA
9270 #define TARGET_NO_LRA !TARGET_LRA
9276 return !TARGET_NO_LRA
;
9279 /* ??? Should we define TARGET_REGISTER_PRIORITY? We might perfer to use
9280 Rcq registers, because some insn are shorter with them. OTOH we already
9281 have separate alternatives for this purpose, and other insns don't
9282 mind, so maybe we should rather prefer the other registers?
9283 We need more data, and we can only get that if we allow people to
9286 arc_register_priority (int r
)
9288 switch (arc_lra_priority_tag
)
9290 case ARC_LRA_PRIORITY_NONE
:
9292 case ARC_LRA_PRIORITY_NONCOMPACT
:
9293 return ((((r
& 7) ^ 4) - 4) & 15) != r
;
9294 case ARC_LRA_PRIORITY_COMPACT
:
9295 return ((((r
& 7) ^ 4) - 4) & 15) == r
;
9302 arc_spill_class (reg_class_t
/* orig_class */, machine_mode
)
9304 return GENERAL_REGS
;
9308 arc_legitimize_reload_address (rtx
*p
, machine_mode mode
, int opnum
,
9312 enum reload_type type
= (enum reload_type
) itype
;
9314 if (GET_CODE (x
) == PLUS
9315 && CONST_INT_P (XEXP (x
, 1))
9316 && (RTX_OK_FOR_BASE_P (XEXP (x
, 0), true)
9317 || (REG_P (XEXP (x
, 0))
9318 && reg_equiv_constant (REGNO (XEXP (x
, 0))))))
9320 int scale
= GET_MODE_SIZE (mode
);
9322 rtx index_rtx
= XEXP (x
, 1);
9323 HOST_WIDE_INT offset
= INTVAL (index_rtx
), offset_base
;
9328 if ((scale
-1) & offset
)
9331 offset_base
= (offset
+ (256 << shift
)) & (-512 << shift
);
9332 /* Sometimes the normal form does not suit DImode. We
9333 could avoid that by using smaller ranges, but that
9334 would give less optimized code when SImode is
9336 if (GET_MODE_SIZE (mode
) + offset
- offset_base
<= (256 << shift
))
9341 regno
= REGNO (reg
);
9342 sum2
= sum
= plus_constant (Pmode
, reg
, offset_base
);
9344 if (reg_equiv_constant (regno
))
9346 sum2
= plus_constant (Pmode
, reg_equiv_constant (regno
),
9348 if (GET_CODE (sum2
) == PLUS
)
9349 sum2
= gen_rtx_CONST (Pmode
, sum2
);
9351 *p
= gen_rtx_PLUS (Pmode
, sum
, GEN_INT (offset
- offset_base
));
9352 push_reload (sum2
, NULL_RTX
, &XEXP (*p
, 0), NULL
,
9353 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
,
9358 /* We must re-recognize what we created before. */
9359 else if (GET_CODE (x
) == PLUS
9360 && GET_CODE (XEXP (x
, 0)) == PLUS
9361 && CONST_INT_P (XEXP (XEXP (x
, 0), 1))
9362 && REG_P (XEXP (XEXP (x
, 0), 0))
9363 && CONST_INT_P (XEXP (x
, 1)))
9365 /* Because this address is so complex, we know it must have
9366 been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,
9367 it is already unshared, and needs no further unsharing. */
9368 push_reload (XEXP (x
, 0), NULL_RTX
, &XEXP (x
, 0), NULL
,
9369 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
, type
);
9375 /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P. */
9378 arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size
,
9380 enum by_pieces_operation op
,
9383 /* Let the movmem expander handle small block moves. */
9384 if (op
== MOVE_BY_PIECES
)
9387 return default_use_by_pieces_infrastructure_p (size
, align
, op
, speed_p
);
9390 struct gcc_target targetm
= TARGET_INITIALIZER
;