1 /* Subroutines used for code generation on the Synopsys DesignWare ARC cpu.
2 Copyright (C) 1994-2015 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"
41 #include "stringpool.h"
46 #include "diagnostic.h"
47 #include "fold-const.h"
49 #include "stor-layout.h"
52 #include "insn-attr.h"
56 #include "langhooks.h"
57 #include "tm-constrs.h"
58 #include "reload.h" /* For operands_match_p */
60 #include "tree-pass.h"
66 /* Which cpu we're compiling for (ARC600, ARC601, ARC700). */
67 static const char *arc_cpu_string
= "";
69 /* ??? Loads can handle any constant, stores can only handle small ones. */
70 /* OTOH, LIMMs cost extra, so their usefulness is limited. */
71 #define RTX_OK_FOR_OFFSET_P(MODE, X) \
72 (GET_CODE (X) == CONST_INT \
73 && SMALL_INT_RANGE (INTVAL (X), (GET_MODE_SIZE (MODE) - 1) & -4, \
74 (INTVAL (X) & (GET_MODE_SIZE (MODE) - 1) & 3 \
76 : -(-GET_MODE_SIZE (MODE) | -4) >> 1)))
78 #define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X, INDEX, STRICT) \
79 (GET_CODE (X) == PLUS \
80 && RTX_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
81 && ((INDEX && RTX_OK_FOR_INDEX_P (XEXP (X, 1), (STRICT)) \
82 && GET_MODE_SIZE ((MODE)) <= 4) \
83 || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
85 #define LEGITIMATE_SCALED_ADDRESS_P(MODE, X, STRICT) \
86 (GET_CODE (X) == PLUS \
87 && GET_CODE (XEXP (X, 0)) == MULT \
88 && RTX_OK_FOR_INDEX_P (XEXP (XEXP (X, 0), 0), (STRICT)) \
89 && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
90 && ((GET_MODE_SIZE (MODE) == 2 && INTVAL (XEXP (XEXP (X, 0), 1)) == 2) \
91 || (GET_MODE_SIZE (MODE) == 4 && INTVAL (XEXP (XEXP (X, 0), 1)) == 4)) \
92 && (RTX_OK_FOR_BASE_P (XEXP (X, 1), (STRICT)) \
93 || (flag_pic ? CONST_INT_P (XEXP (X, 1)) : CONSTANT_P (XEXP (X, 1)))))
95 #define LEGITIMATE_SMALL_DATA_ADDRESS_P(X) \
96 (GET_CODE (X) == PLUS \
97 && (REG_P (XEXP ((X), 0)) && REGNO (XEXP ((X), 0)) == SDATA_BASE_REGNUM) \
98 && ((GET_CODE (XEXP((X),1)) == SYMBOL_REF \
99 && SYMBOL_REF_SMALL_P (XEXP ((X), 1))) \
100 || (GET_CODE (XEXP ((X), 1)) == CONST \
101 && GET_CODE (XEXP (XEXP ((X), 1), 0)) == PLUS \
102 && GET_CODE (XEXP (XEXP (XEXP ((X), 1), 0), 0)) == SYMBOL_REF \
103 && SYMBOL_REF_SMALL_P (XEXP (XEXP (XEXP ((X), 1), 0), 0)) \
104 && GET_CODE (XEXP(XEXP (XEXP ((X), 1), 0), 1)) == CONST_INT)))
106 /* Array of valid operand punctuation characters. */
107 char arc_punct_chars
[256];
109 /* State used by arc_ccfsm_advance to implement conditional execution. */
110 struct GTY (()) arc_ccfsm
115 rtx_insn
*target_insn
;
119 #define arc_ccfsm_current cfun->machine->ccfsm_current
121 #define ARC_CCFSM_BRANCH_DELETED_P(STATE) \
122 ((STATE)->state == 1 || (STATE)->state == 2)
124 /* Indicate we're conditionalizing insns now. */
125 #define ARC_CCFSM_RECORD_BRANCH_DELETED(STATE) \
126 ((STATE)->state += 2)
128 #define ARC_CCFSM_COND_EXEC_P(STATE) \
129 ((STATE)->state == 3 || (STATE)->state == 4 || (STATE)->state == 5 \
130 || current_insn_predicate)
132 /* Check if INSN has a 16 bit opcode considering struct arc_ccfsm *STATE. */
133 #define CCFSM_ISCOMPACT(INSN,STATE) \
134 (ARC_CCFSM_COND_EXEC_P (STATE) \
135 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
136 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
137 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
139 /* Likewise, but also consider that INSN might be in a delay slot of JUMP. */
140 #define CCFSM_DBR_ISCOMPACT(INSN,JUMP,STATE) \
141 ((ARC_CCFSM_COND_EXEC_P (STATE) \
143 && INSN_ANNULLED_BRANCH_P (JUMP) \
144 && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (INSN)))) \
145 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
146 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
147 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
149 /* The maximum number of insns skipped which will be conditionalised if
151 /* When optimizing for speed:
152 Let p be the probability that the potentially skipped insns need to
153 be executed, pn the cost of a correctly predicted non-taken branch,
154 mt the cost of a mis/non-predicted taken branch,
155 mn mispredicted non-taken, pt correctly predicted taken ;
156 costs expressed in numbers of instructions like the ones considered
158 Unfortunately we don't have a measure of predictability - this
159 is linked to probability only in that in the no-eviction-scenario
160 there is a lower bound 1 - 2 * min (p, 1-p), and a somewhat larger
161 value that can be assumed *if* the distribution is perfectly random.
162 A predictability of 1 is perfectly plausible not matter what p is,
163 because the decision could be dependent on an invocation parameter
165 For large p, we want MAX_INSNS_SKIPPED == pn/(1-p) + mt - pn
166 For small p, we want MAX_INSNS_SKIPPED == pt
168 When optimizing for size:
169 We want to skip insn unless we could use 16 opcodes for the
170 non-conditionalized insn to balance the branch length or more.
171 Performance can be tie-breaker. */
172 /* If the potentially-skipped insns are likely to be executed, we'll
173 generally save one non-taken branch
175 this to be no less than the 1/p */
176 #define MAX_INSNS_SKIPPED 3
178 /* The values of unspec's first field. */
188 ARC_BUILTIN_NORM
= 3,
189 ARC_BUILTIN_NORMW
= 4,
190 ARC_BUILTIN_SWAP
= 5,
192 ARC_BUILTIN_DIVAW
= 7,
194 ARC_BUILTIN_MUL64
= 9,
195 ARC_BUILTIN_MULU64
= 10,
196 ARC_BUILTIN_RTIE
= 11,
197 ARC_BUILTIN_SYNC
= 12,
198 ARC_BUILTIN_CORE_READ
= 13,
199 ARC_BUILTIN_CORE_WRITE
= 14,
200 ARC_BUILTIN_FLAG
= 15,
203 ARC_BUILTIN_SLEEP
= 18,
204 ARC_BUILTIN_SWI
= 19,
205 ARC_BUILTIN_TRAP_S
= 20,
206 ARC_BUILTIN_UNIMP_S
= 21,
207 ARC_BUILTIN_ALIGNED
= 22,
209 /* Sentinel to mark start of simd builtins. */
210 ARC_SIMD_BUILTIN_BEGIN
= 1000,
212 ARC_SIMD_BUILTIN_VADDAW
= 1001,
213 ARC_SIMD_BUILTIN_VADDW
= 1002,
214 ARC_SIMD_BUILTIN_VAVB
= 1003,
215 ARC_SIMD_BUILTIN_VAVRB
= 1004,
216 ARC_SIMD_BUILTIN_VDIFAW
= 1005,
217 ARC_SIMD_BUILTIN_VDIFW
= 1006,
218 ARC_SIMD_BUILTIN_VMAXAW
= 1007,
219 ARC_SIMD_BUILTIN_VMAXW
= 1008,
220 ARC_SIMD_BUILTIN_VMINAW
= 1009,
221 ARC_SIMD_BUILTIN_VMINW
= 1010,
222 ARC_SIMD_BUILTIN_VMULAW
= 1011,
223 ARC_SIMD_BUILTIN_VMULFAW
= 1012,
224 ARC_SIMD_BUILTIN_VMULFW
= 1013,
225 ARC_SIMD_BUILTIN_VMULW
= 1014,
226 ARC_SIMD_BUILTIN_VSUBAW
= 1015,
227 ARC_SIMD_BUILTIN_VSUBW
= 1016,
228 ARC_SIMD_BUILTIN_VSUMMW
= 1017,
229 ARC_SIMD_BUILTIN_VAND
= 1018,
230 ARC_SIMD_BUILTIN_VANDAW
= 1019,
231 ARC_SIMD_BUILTIN_VBIC
= 1020,
232 ARC_SIMD_BUILTIN_VBICAW
= 1021,
233 ARC_SIMD_BUILTIN_VOR
= 1022,
234 ARC_SIMD_BUILTIN_VXOR
= 1023,
235 ARC_SIMD_BUILTIN_VXORAW
= 1024,
236 ARC_SIMD_BUILTIN_VEQW
= 1025,
237 ARC_SIMD_BUILTIN_VLEW
= 1026,
238 ARC_SIMD_BUILTIN_VLTW
= 1027,
239 ARC_SIMD_BUILTIN_VNEW
= 1028,
240 ARC_SIMD_BUILTIN_VMR1AW
= 1029,
241 ARC_SIMD_BUILTIN_VMR1W
= 1030,
242 ARC_SIMD_BUILTIN_VMR2AW
= 1031,
243 ARC_SIMD_BUILTIN_VMR2W
= 1032,
244 ARC_SIMD_BUILTIN_VMR3AW
= 1033,
245 ARC_SIMD_BUILTIN_VMR3W
= 1034,
246 ARC_SIMD_BUILTIN_VMR4AW
= 1035,
247 ARC_SIMD_BUILTIN_VMR4W
= 1036,
248 ARC_SIMD_BUILTIN_VMR5AW
= 1037,
249 ARC_SIMD_BUILTIN_VMR5W
= 1038,
250 ARC_SIMD_BUILTIN_VMR6AW
= 1039,
251 ARC_SIMD_BUILTIN_VMR6W
= 1040,
252 ARC_SIMD_BUILTIN_VMR7AW
= 1041,
253 ARC_SIMD_BUILTIN_VMR7W
= 1042,
254 ARC_SIMD_BUILTIN_VMRB
= 1043,
255 ARC_SIMD_BUILTIN_VH264F
= 1044,
256 ARC_SIMD_BUILTIN_VH264FT
= 1045,
257 ARC_SIMD_BUILTIN_VH264FW
= 1046,
258 ARC_SIMD_BUILTIN_VVC1F
= 1047,
259 ARC_SIMD_BUILTIN_VVC1FT
= 1048,
261 /* Va, Vb, rlimm instructions. */
262 ARC_SIMD_BUILTIN_VBADDW
= 1050,
263 ARC_SIMD_BUILTIN_VBMAXW
= 1051,
264 ARC_SIMD_BUILTIN_VBMINW
= 1052,
265 ARC_SIMD_BUILTIN_VBMULAW
= 1053,
266 ARC_SIMD_BUILTIN_VBMULFW
= 1054,
267 ARC_SIMD_BUILTIN_VBMULW
= 1055,
268 ARC_SIMD_BUILTIN_VBRSUBW
= 1056,
269 ARC_SIMD_BUILTIN_VBSUBW
= 1057,
271 /* Va, Vb, Ic instructions. */
272 ARC_SIMD_BUILTIN_VASRW
= 1060,
273 ARC_SIMD_BUILTIN_VSR8
= 1061,
274 ARC_SIMD_BUILTIN_VSR8AW
= 1062,
276 /* Va, Vb, u6 instructions. */
277 ARC_SIMD_BUILTIN_VASRRWi
= 1065,
278 ARC_SIMD_BUILTIN_VASRSRWi
= 1066,
279 ARC_SIMD_BUILTIN_VASRWi
= 1067,
280 ARC_SIMD_BUILTIN_VASRPWBi
= 1068,
281 ARC_SIMD_BUILTIN_VASRRPWBi
= 1069,
282 ARC_SIMD_BUILTIN_VSR8AWi
= 1070,
283 ARC_SIMD_BUILTIN_VSR8i
= 1071,
285 /* Va, Vb, u8 (simm) instructions. */
286 ARC_SIMD_BUILTIN_VMVAW
= 1075,
287 ARC_SIMD_BUILTIN_VMVW
= 1076,
288 ARC_SIMD_BUILTIN_VMVZW
= 1077,
289 ARC_SIMD_BUILTIN_VD6TAPF
= 1078,
291 /* Va, rlimm, u8 (simm) instructions. */
292 ARC_SIMD_BUILTIN_VMOVAW
= 1080,
293 ARC_SIMD_BUILTIN_VMOVW
= 1081,
294 ARC_SIMD_BUILTIN_VMOVZW
= 1082,
296 /* Va, Vb instructions. */
297 ARC_SIMD_BUILTIN_VABSAW
= 1085,
298 ARC_SIMD_BUILTIN_VABSW
= 1086,
299 ARC_SIMD_BUILTIN_VADDSUW
= 1087,
300 ARC_SIMD_BUILTIN_VSIGNW
= 1088,
301 ARC_SIMD_BUILTIN_VEXCH1
= 1089,
302 ARC_SIMD_BUILTIN_VEXCH2
= 1090,
303 ARC_SIMD_BUILTIN_VEXCH4
= 1091,
304 ARC_SIMD_BUILTIN_VUPBAW
= 1092,
305 ARC_SIMD_BUILTIN_VUPBW
= 1093,
306 ARC_SIMD_BUILTIN_VUPSBAW
= 1094,
307 ARC_SIMD_BUILTIN_VUPSBW
= 1095,
309 ARC_SIMD_BUILTIN_VDIRUN
= 1100,
310 ARC_SIMD_BUILTIN_VDORUN
= 1101,
311 ARC_SIMD_BUILTIN_VDIWR
= 1102,
312 ARC_SIMD_BUILTIN_VDOWR
= 1103,
314 ARC_SIMD_BUILTIN_VREC
= 1105,
315 ARC_SIMD_BUILTIN_VRUN
= 1106,
316 ARC_SIMD_BUILTIN_VRECRUN
= 1107,
317 ARC_SIMD_BUILTIN_VENDREC
= 1108,
319 ARC_SIMD_BUILTIN_VLD32WH
= 1110,
320 ARC_SIMD_BUILTIN_VLD32WL
= 1111,
321 ARC_SIMD_BUILTIN_VLD64
= 1112,
322 ARC_SIMD_BUILTIN_VLD32
= 1113,
323 ARC_SIMD_BUILTIN_VLD64W
= 1114,
324 ARC_SIMD_BUILTIN_VLD128
= 1115,
325 ARC_SIMD_BUILTIN_VST128
= 1116,
326 ARC_SIMD_BUILTIN_VST64
= 1117,
328 ARC_SIMD_BUILTIN_VST16_N
= 1120,
329 ARC_SIMD_BUILTIN_VST32_N
= 1121,
331 ARC_SIMD_BUILTIN_VINTI
= 1201,
336 /* A nop is needed between a 4 byte insn that sets the condition codes and
337 a branch that uses them (the same isn't true for an 8 byte insn that sets
338 the condition codes). Set by arc_ccfsm_advance. Used by
339 arc_print_operand. */
341 static int get_arc_condition_code (rtx
);
343 static tree
arc_handle_interrupt_attribute (tree
*, tree
, tree
, int, bool *);
345 /* Initialized arc_attribute_table to NULL since arc doesnot have any
346 machine specific supported attributes. */
347 const struct attribute_spec arc_attribute_table
[] =
349 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
350 affects_type_identity } */
351 { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute
, true },
352 /* Function calls made to this symbol must be done indirectly, because
353 it may lie outside of the 21/25 bit addressing range of a normal function
355 { "long_call", 0, 0, false, true, true, NULL
, false },
356 /* Whereas these functions are always known to reside within the 25 bit
357 addressing range of unconditionalized bl. */
358 { "medium_call", 0, 0, false, true, true, NULL
, false },
359 /* And these functions are always known to reside within the 21 bit
360 addressing range of blcc. */
361 { "short_call", 0, 0, false, true, true, NULL
, false },
362 { NULL
, 0, 0, false, false, false, NULL
, false }
364 static int arc_comp_type_attributes (const_tree
, const_tree
);
365 static void arc_file_start (void);
366 static void arc_internal_label (FILE *, const char *, unsigned long);
367 static void arc_output_mi_thunk (FILE *, tree
, HOST_WIDE_INT
, HOST_WIDE_INT
,
369 static int arc_address_cost (rtx
, machine_mode
, addr_space_t
, bool);
370 static void arc_encode_section_info (tree decl
, rtx rtl
, int first
);
372 static void arc_init_builtins (void);
373 static rtx
arc_expand_builtin (tree
, rtx
, rtx
, machine_mode
, int);
375 static int branch_dest (rtx
);
377 static void arc_output_pic_addr_const (FILE *, rtx
, int);
378 void emit_pic_move (rtx
*, machine_mode
);
379 bool arc_legitimate_pic_operand_p (rtx
);
380 static bool arc_function_ok_for_sibcall (tree
, tree
);
381 static rtx
arc_function_value (const_tree
, const_tree
, bool);
382 const char * output_shift (rtx
*);
383 static void arc_reorg (void);
384 static bool arc_in_small_data_p (const_tree
);
386 static void arc_init_reg_tables (void);
387 static bool arc_return_in_memory (const_tree
, const_tree
);
388 static void arc_init_simd_builtins (void);
389 static bool arc_vector_mode_supported_p (machine_mode
);
391 static bool arc_can_use_doloop_p (const widest_int
&, const widest_int
&,
393 static const char *arc_invalid_within_doloop (const rtx_insn
*);
395 static void output_short_suffix (FILE *file
);
397 static bool arc_frame_pointer_required (void);
399 static bool arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT
,
401 enum by_pieces_operation op
,
404 /* Implements target hook vector_mode_supported_p. */
407 arc_vector_mode_supported_p (machine_mode mode
)
409 if (!TARGET_SIMD_SET
)
412 if ((mode
== V4SImode
)
413 || (mode
== V8HImode
))
420 /* TARGET_PRESERVE_RELOAD_P is still awaiting patch re-evaluation / review. */
421 static bool arc_preserve_reload_p (rtx in
) ATTRIBUTE_UNUSED
;
422 static rtx
arc_delegitimize_address (rtx
);
423 static bool arc_can_follow_jump (const rtx_insn
*follower
,
424 const rtx_insn
*followee
);
426 static rtx
frame_insn (rtx
);
427 static void arc_function_arg_advance (cumulative_args_t
, machine_mode
,
429 static rtx
arc_legitimize_address_0 (rtx
, rtx
, machine_mode mode
);
431 static void arc_finalize_pic (void);
433 /* initialize the GCC target structure. */
434 #undef TARGET_COMP_TYPE_ATTRIBUTES
435 #define TARGET_COMP_TYPE_ATTRIBUTES arc_comp_type_attributes
436 #undef TARGET_ASM_FILE_START
437 #define TARGET_ASM_FILE_START arc_file_start
438 #undef TARGET_ATTRIBUTE_TABLE
439 #define TARGET_ATTRIBUTE_TABLE arc_attribute_table
440 #undef TARGET_ASM_INTERNAL_LABEL
441 #define TARGET_ASM_INTERNAL_LABEL arc_internal_label
442 #undef TARGET_RTX_COSTS
443 #define TARGET_RTX_COSTS arc_rtx_costs
444 #undef TARGET_ADDRESS_COST
445 #define TARGET_ADDRESS_COST arc_address_cost
447 #undef TARGET_ENCODE_SECTION_INFO
448 #define TARGET_ENCODE_SECTION_INFO arc_encode_section_info
450 #undef TARGET_CANNOT_FORCE_CONST_MEM
451 #define TARGET_CANNOT_FORCE_CONST_MEM arc_cannot_force_const_mem
453 #undef TARGET_INIT_BUILTINS
454 #define TARGET_INIT_BUILTINS arc_init_builtins
456 #undef TARGET_EXPAND_BUILTIN
457 #define TARGET_EXPAND_BUILTIN arc_expand_builtin
459 #undef TARGET_ASM_OUTPUT_MI_THUNK
460 #define TARGET_ASM_OUTPUT_MI_THUNK arc_output_mi_thunk
462 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
463 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
465 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
466 #define TARGET_FUNCTION_OK_FOR_SIBCALL arc_function_ok_for_sibcall
468 #undef TARGET_MACHINE_DEPENDENT_REORG
469 #define TARGET_MACHINE_DEPENDENT_REORG arc_reorg
471 #undef TARGET_IN_SMALL_DATA_P
472 #define TARGET_IN_SMALL_DATA_P arc_in_small_data_p
474 #undef TARGET_PROMOTE_FUNCTION_MODE
475 #define TARGET_PROMOTE_FUNCTION_MODE \
476 default_promote_function_mode_always_promote
478 #undef TARGET_PROMOTE_PROTOTYPES
479 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
481 #undef TARGET_RETURN_IN_MEMORY
482 #define TARGET_RETURN_IN_MEMORY arc_return_in_memory
483 #undef TARGET_PASS_BY_REFERENCE
484 #define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
486 #undef TARGET_SETUP_INCOMING_VARARGS
487 #define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
489 #undef TARGET_ARG_PARTIAL_BYTES
490 #define TARGET_ARG_PARTIAL_BYTES arc_arg_partial_bytes
492 #undef TARGET_MUST_PASS_IN_STACK
493 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
495 #undef TARGET_FUNCTION_VALUE
496 #define TARGET_FUNCTION_VALUE arc_function_value
498 #undef TARGET_SCHED_ADJUST_PRIORITY
499 #define TARGET_SCHED_ADJUST_PRIORITY arc_sched_adjust_priority
501 #undef TARGET_VECTOR_MODE_SUPPORTED_P
502 #define TARGET_VECTOR_MODE_SUPPORTED_P arc_vector_mode_supported_p
504 #undef TARGET_CAN_USE_DOLOOP_P
505 #define TARGET_CAN_USE_DOLOOP_P arc_can_use_doloop_p
507 #undef TARGET_INVALID_WITHIN_DOLOOP
508 #define TARGET_INVALID_WITHIN_DOLOOP arc_invalid_within_doloop
510 #undef TARGET_PRESERVE_RELOAD_P
511 #define TARGET_PRESERVE_RELOAD_P arc_preserve_reload_p
513 #undef TARGET_CAN_FOLLOW_JUMP
514 #define TARGET_CAN_FOLLOW_JUMP arc_can_follow_jump
516 #undef TARGET_DELEGITIMIZE_ADDRESS
517 #define TARGET_DELEGITIMIZE_ADDRESS arc_delegitimize_address
519 #undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
520 #define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
521 arc_use_by_pieces_infrastructure_p
523 /* Usually, we will be able to scale anchor offsets.
524 When this fails, we want LEGITIMIZE_ADDRESS to kick in. */
525 #undef TARGET_MIN_ANCHOR_OFFSET
526 #define TARGET_MIN_ANCHOR_OFFSET (-1024)
527 #undef TARGET_MAX_ANCHOR_OFFSET
528 #define TARGET_MAX_ANCHOR_OFFSET (1020)
530 #undef TARGET_SECONDARY_RELOAD
531 #define TARGET_SECONDARY_RELOAD arc_secondary_reload
533 #define TARGET_OPTION_OVERRIDE arc_override_options
535 #define TARGET_CONDITIONAL_REGISTER_USAGE arc_conditional_register_usage
537 #define TARGET_TRAMPOLINE_INIT arc_initialize_trampoline
539 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS arc_trampoline_adjust_address
541 #define TARGET_CAN_ELIMINATE arc_can_eliminate
543 #define TARGET_FRAME_POINTER_REQUIRED arc_frame_pointer_required
545 #define TARGET_FUNCTION_ARG arc_function_arg
547 #define TARGET_FUNCTION_ARG_ADVANCE arc_function_arg_advance
549 #define TARGET_LEGITIMATE_CONSTANT_P arc_legitimate_constant_p
551 #define TARGET_LEGITIMATE_ADDRESS_P arc_legitimate_address_p
553 #define TARGET_MODE_DEPENDENT_ADDRESS_P arc_mode_dependent_address_p
555 #define TARGET_LEGITIMIZE_ADDRESS arc_legitimize_address
557 #define TARGET_ADJUST_INSN_LENGTH arc_adjust_insn_length
559 #define TARGET_INSN_LENGTH_PARAMETERS arc_insn_length_parameters
561 #undef TARGET_NO_SPECULATION_IN_DELAY_SLOTS_P
562 #define TARGET_NO_SPECULATION_IN_DELAY_SLOTS_P \
563 arc_no_speculation_in_delay_slots_p
566 #define TARGET_LRA_P arc_lra_p
567 #define TARGET_REGISTER_PRIORITY arc_register_priority
568 /* Stores with scaled offsets have different displacement ranges. */
569 #define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
570 #define TARGET_SPILL_CLASS arc_spill_class
572 #include "target-def.h"
574 #undef TARGET_ASM_ALIGNED_HI_OP
575 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
576 #undef TARGET_ASM_ALIGNED_SI_OP
577 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
579 /* Try to keep the (mov:DF _, reg) as early as possible so
580 that the d<add/sub/mul>h-lr insns appear together and can
581 use the peephole2 pattern. */
584 arc_sched_adjust_priority (rtx_insn
*insn
, int priority
)
586 rtx set
= single_set (insn
);
588 && GET_MODE (SET_SRC(set
)) == DFmode
589 && GET_CODE (SET_SRC(set
)) == REG
)
591 /* Incrementing priority by 20 (empirically derived). */
592 return priority
+ 20;
598 /* For ARC base register + offset addressing, the validity of the
599 address is mode-dependent for most of the offset range, as the
600 offset can be scaled by the access size.
601 We don't expose these as mode-dependent addresses in the
602 mode_dependent_address_p target hook, because that would disable
603 lots of optimizations, and most uses of these addresses are for 32
604 or 64 bit accesses anyways, which are fine.
605 However, that leaves some addresses for 8 / 16 bit values not
606 properly reloaded by the generic code, which is why we have to
607 schedule secondary reloads for these. */
610 arc_secondary_reload (bool in_p
,
614 secondary_reload_info
*sri
)
616 enum rtx_code code
= GET_CODE (x
);
618 if (cl
== DOUBLE_REGS
)
621 /* The loop counter register can be stored, but not loaded directly. */
622 if ((cl
== LPCOUNT_REG
|| cl
== WRITABLE_CORE_REGS
)
623 && in_p
&& MEM_P (x
))
626 /* If we have a subreg (reg), where reg is a pseudo (that will end in
627 a memory location), then we may need a scratch register to handle
628 the fp/sp+largeoffset address. */
636 int regno
= REGNO (x
);
637 if (regno
>= FIRST_PSEUDO_REGISTER
)
638 regno
= reg_renumber
[regno
];
643 /* It is a pseudo that ends in a stack location. */
644 if (reg_equiv_mem (REGNO (x
)))
646 /* Get the equivalent address and check the range of the
648 rtx mem
= reg_equiv_mem (REGNO (x
));
649 addr
= find_replacement (&XEXP (mem
, 0));
654 gcc_assert (MEM_P (x
));
656 addr
= simplify_rtx (addr
);
658 if (addr
&& GET_CODE (addr
) == PLUS
659 && CONST_INT_P (XEXP (addr
, 1))
660 && (!RTX_OK_FOR_OFFSET_P (mode
, XEXP (addr
, 1))))
666 in_p
? CODE_FOR_reload_qi_load
: CODE_FOR_reload_qi_store
;
670 in_p
? CODE_FOR_reload_hi_load
: CODE_FOR_reload_hi_store
;
680 /* Convert reloads using offsets that are too large to use indirect
684 arc_secondary_reload_conv (rtx reg
, rtx mem
, rtx scratch
, bool store_p
)
688 gcc_assert (GET_CODE (mem
) == MEM
);
689 addr
= XEXP (mem
, 0);
691 /* Large offset: use a move. FIXME: ld ops accepts limms as
692 offsets. Hence, the following move insn is not required. */
693 emit_move_insn (scratch
, addr
);
694 mem
= replace_equiv_address_nv (mem
, scratch
);
696 /* Now create the move. */
698 emit_insn (gen_rtx_SET (mem
, reg
));
700 emit_insn (gen_rtx_SET (reg
, mem
));
705 static unsigned arc_ifcvt (void);
709 const pass_data pass_data_arc_ifcvt
=
712 "arc_ifcvt", /* name */
713 OPTGROUP_NONE
, /* optinfo_flags */
714 TV_IFCVT2
, /* tv_id */
715 0, /* properties_required */
716 0, /* properties_provided */
717 0, /* properties_destroyed */
718 0, /* todo_flags_start */
719 TODO_df_finish
/* todo_flags_finish */
722 class pass_arc_ifcvt
: public rtl_opt_pass
725 pass_arc_ifcvt(gcc::context
*ctxt
)
726 : rtl_opt_pass(pass_data_arc_ifcvt
, ctxt
)
729 /* opt_pass methods: */
730 opt_pass
* clone () { return new pass_arc_ifcvt (m_ctxt
); }
731 virtual unsigned int execute (function
*) { return arc_ifcvt (); }
737 make_pass_arc_ifcvt (gcc::context
*ctxt
)
739 return new pass_arc_ifcvt (ctxt
);
742 static unsigned arc_predicate_delay_insns (void);
746 const pass_data pass_data_arc_predicate_delay_insns
=
749 "arc_predicate_delay_insns", /* name */
750 OPTGROUP_NONE
, /* optinfo_flags */
751 TV_IFCVT2
, /* tv_id */
752 0, /* properties_required */
753 0, /* properties_provided */
754 0, /* properties_destroyed */
755 0, /* todo_flags_start */
756 TODO_df_finish
/* todo_flags_finish */
759 class pass_arc_predicate_delay_insns
: public rtl_opt_pass
762 pass_arc_predicate_delay_insns(gcc::context
*ctxt
)
763 : rtl_opt_pass(pass_data_arc_predicate_delay_insns
, ctxt
)
766 /* opt_pass methods: */
767 virtual unsigned int execute (function
*)
769 return arc_predicate_delay_insns ();
776 make_pass_arc_predicate_delay_insns (gcc::context
*ctxt
)
778 return new pass_arc_predicate_delay_insns (ctxt
);
781 /* Called by OVERRIDE_OPTIONS to initialize various things. */
786 enum attr_tune tune_dflt
= TUNE_NONE
;
790 case PROCESSOR_ARC600
:
791 arc_cpu_string
= "ARC600";
792 tune_dflt
= TUNE_ARC600
;
795 case PROCESSOR_ARC601
:
796 arc_cpu_string
= "ARC601";
797 tune_dflt
= TUNE_ARC600
;
800 case PROCESSOR_ARC700
:
801 arc_cpu_string
= "ARC700";
802 tune_dflt
= TUNE_ARC700_4_2_STD
;
805 case PROCESSOR_ARCEM
:
806 arc_cpu_string
= "EM";
809 case PROCESSOR_ARCHS
:
810 arc_cpu_string
= "HS";
817 if (arc_tune
== TUNE_NONE
)
818 arc_tune
= tune_dflt
;
819 /* Note: arc_multcost is only used in rtx_cost if speed is true. */
820 if (arc_multcost
< 0)
823 case TUNE_ARC700_4_2_STD
:
825 max throughput (1 multiply + 4 other insns) / 5 cycles. */
826 arc_multcost
= COSTS_N_INSNS (4);
827 if (TARGET_NOMPY_SET
)
828 arc_multcost
= COSTS_N_INSNS (30);
830 case TUNE_ARC700_4_2_XMAC
:
832 max throughput (1 multiply + 2 other insns) / 3 cycles. */
833 arc_multcost
= COSTS_N_INSNS (3);
834 if (TARGET_NOMPY_SET
)
835 arc_multcost
= COSTS_N_INSNS (30);
838 if (TARGET_MUL64_SET
)
840 arc_multcost
= COSTS_N_INSNS (4);
845 arc_multcost
= COSTS_N_INSNS (30);
849 /* Support mul64 generation only for ARC600. */
850 if (TARGET_MUL64_SET
&& (!TARGET_ARC600_FAMILY
))
851 error ("-mmul64 not supported for ARC700 or ARCv2");
853 /* MPY instructions valid only for ARC700 or ARCv2. */
854 if (TARGET_NOMPY_SET
&& TARGET_ARC600_FAMILY
)
855 error ("-mno-mpy supported only for ARC700 or ARCv2");
857 /* mul/mac instructions only for ARC600. */
858 if (TARGET_MULMAC_32BY16_SET
&& (!TARGET_ARC600_FAMILY
))
859 error ("-mmul32x16 supported only for ARC600 or ARC601");
861 if (!TARGET_DPFP
&& TARGET_DPFP_DISABLE_LRSR
)
862 error ("-mno-dpfp-lrsr supported only with -mdpfp");
864 /* FPX-1. No fast and compact together. */
865 if ((TARGET_DPFP_FAST_SET
&& TARGET_DPFP_COMPACT_SET
)
866 || (TARGET_SPFP_FAST_SET
&& TARGET_SPFP_COMPACT_SET
))
867 error ("FPX fast and compact options cannot be specified together");
869 /* FPX-2. No fast-spfp for arc600 or arc601. */
870 if (TARGET_SPFP_FAST_SET
&& TARGET_ARC600_FAMILY
)
871 error ("-mspfp_fast not available on ARC600 or ARC601");
873 /* FPX-3. No FPX extensions on pre-ARC600 cores. */
874 if ((TARGET_DPFP
|| TARGET_SPFP
)
875 && !TARGET_ARCOMPACT_FAMILY
)
876 error ("FPX extensions not available on pre-ARC600 cores");
878 /* Only selected multiplier configurations are available for HS. */
879 if (TARGET_HS
&& ((arc_mpy_option
> 2 && arc_mpy_option
< 7)
880 || (arc_mpy_option
== 1)))
881 error ("This multiplier configuration is not available for HS cores");
883 /* Warn for unimplemented PIC in pre-ARC700 cores, and disable flag_pic. */
884 if (flag_pic
&& TARGET_ARC600_FAMILY
)
887 "PIC is not supported for %s. Generating non-PIC code only..",
892 if (TARGET_ATOMIC
&& !(TARGET_ARC700
|| TARGET_HS
))
893 error ("-matomic is only supported for ARC700 or ARC HS cores");
895 arc_init_reg_tables ();
897 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
898 memset (arc_punct_chars
, 0, sizeof (arc_punct_chars
));
899 arc_punct_chars
['#'] = 1;
900 arc_punct_chars
['*'] = 1;
901 arc_punct_chars
['?'] = 1;
902 arc_punct_chars
['!'] = 1;
903 arc_punct_chars
['^'] = 1;
904 arc_punct_chars
['&'] = 1;
905 arc_punct_chars
['+'] = 1;
906 arc_punct_chars
['_'] = 1;
908 if (optimize
> 1 && !TARGET_NO_COND_EXEC
)
910 /* There are two target-independent ifcvt passes, and arc_reorg may do
911 one or more arc_ifcvt calls. */
912 opt_pass
*pass_arc_ifcvt_4
= make_pass_arc_ifcvt (g
);
913 struct register_pass_info arc_ifcvt4_info
914 = { pass_arc_ifcvt_4
, "dbr", 1, PASS_POS_INSERT_AFTER
};
915 struct register_pass_info arc_ifcvt5_info
916 = { pass_arc_ifcvt_4
->clone (), "shorten", 1, PASS_POS_INSERT_BEFORE
};
918 register_pass (&arc_ifcvt4_info
);
919 register_pass (&arc_ifcvt5_info
);
922 if (flag_delayed_branch
)
924 opt_pass
*pass_arc_predicate_delay_insns
925 = make_pass_arc_predicate_delay_insns (g
);
926 struct register_pass_info arc_predicate_delay_info
927 = { pass_arc_predicate_delay_insns
, "dbr", 1, PASS_POS_INSERT_AFTER
};
929 register_pass (&arc_predicate_delay_info
);
933 /* Check ARC options, generate derived target attributes. */
936 arc_override_options (void)
938 if (arc_cpu
== PROCESSOR_NONE
)
939 arc_cpu
= PROCESSOR_ARC700
;
941 if (arc_size_opt_level
== 3)
945 target_flags
|= MASK_NO_SDATA_SET
;
947 if (flag_no_common
== 255)
948 flag_no_common
= !TARGET_NO_SDATA_SET
;
950 /* TARGET_COMPACT_CASESI needs the "q" register class. */
951 if (TARGET_MIXED_CODE
)
954 TARGET_COMPACT_CASESI
= 0;
955 if (TARGET_COMPACT_CASESI
)
956 TARGET_CASE_VECTOR_PC_RELATIVE
= 1;
958 /* These need to be done at start up. It's convenient to do them here. */
962 /* The condition codes of the ARC, and the inverse function. */
963 /* For short branches, the "c" / "nc" names are not defined in the ARC
964 Programmers manual, so we have to use "lo" / "hs"" instead. */
965 static const char *arc_condition_codes
[] =
967 "al", 0, "eq", "ne", "p", "n", "lo", "hs", "v", "nv",
968 "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
971 enum arc_cc_code_index
973 ARC_CC_AL
, ARC_CC_EQ
= ARC_CC_AL
+2, ARC_CC_NE
, ARC_CC_P
, ARC_CC_N
,
974 ARC_CC_C
, ARC_CC_NC
, ARC_CC_V
, ARC_CC_NV
,
975 ARC_CC_GT
, ARC_CC_LE
, ARC_CC_GE
, ARC_CC_LT
, ARC_CC_HI
, ARC_CC_LS
, ARC_CC_PNZ
,
976 ARC_CC_LO
= ARC_CC_C
, ARC_CC_HS
= ARC_CC_NC
979 #define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
981 /* Returns the index of the ARC condition code string in
982 `arc_condition_codes'. COMPARISON should be an rtx like
983 `(eq (...) (...))'. */
986 get_arc_condition_code (rtx comparison
)
988 switch (GET_MODE (XEXP (comparison
, 0)))
991 case SImode
: /* For BRcc. */
992 switch (GET_CODE (comparison
))
994 case EQ
: return ARC_CC_EQ
;
995 case NE
: return ARC_CC_NE
;
996 case GT
: return ARC_CC_GT
;
997 case LE
: return ARC_CC_LE
;
998 case GE
: return ARC_CC_GE
;
999 case LT
: return ARC_CC_LT
;
1000 case GTU
: return ARC_CC_HI
;
1001 case LEU
: return ARC_CC_LS
;
1002 case LTU
: return ARC_CC_LO
;
1003 case GEU
: return ARC_CC_HS
;
1004 default : gcc_unreachable ();
1007 switch (GET_CODE (comparison
))
1009 case EQ
: return ARC_CC_EQ
;
1010 case NE
: return ARC_CC_NE
;
1011 case GE
: return ARC_CC_P
;
1012 case LT
: return ARC_CC_N
;
1013 case GT
: return ARC_CC_PNZ
;
1014 default : gcc_unreachable ();
1017 switch (GET_CODE (comparison
))
1019 case EQ
: return ARC_CC_EQ
;
1020 case NE
: return ARC_CC_NE
;
1021 default : gcc_unreachable ();
1024 switch (GET_CODE (comparison
))
1026 case LTU
: return ARC_CC_C
;
1027 case GEU
: return ARC_CC_NC
;
1028 default : gcc_unreachable ();
1031 if (TARGET_ARGONAUT_SET
&& TARGET_SPFP
)
1032 switch (GET_CODE (comparison
))
1034 case GT
: return ARC_CC_N
;
1035 case UNLE
: return ARC_CC_P
;
1036 default : gcc_unreachable ();
1039 switch (GET_CODE (comparison
))
1041 case GT
: return ARC_CC_HI
;
1042 case UNLE
: return ARC_CC_LS
;
1043 default : gcc_unreachable ();
1046 /* Same for FPX and non-FPX. */
1047 switch (GET_CODE (comparison
))
1049 case GE
: return ARC_CC_HS
;
1050 case UNLT
: return ARC_CC_LO
;
1051 default : gcc_unreachable ();
1053 case CC_FP_UNEQmode
:
1054 switch (GET_CODE (comparison
))
1056 case UNEQ
: return ARC_CC_EQ
;
1057 case LTGT
: return ARC_CC_NE
;
1058 default : gcc_unreachable ();
1061 switch (GET_CODE (comparison
))
1063 case UNORDERED
: return ARC_CC_C
;
1064 case ORDERED
: return ARC_CC_NC
;
1065 default : gcc_unreachable ();
1068 switch (GET_CODE (comparison
))
1070 case EQ
: return ARC_CC_EQ
;
1071 case NE
: return ARC_CC_NE
;
1072 case UNORDERED
: return ARC_CC_C
;
1073 case ORDERED
: return ARC_CC_NC
;
1074 case LTGT
: return ARC_CC_HI
;
1075 case UNEQ
: return ARC_CC_LS
;
1076 default : gcc_unreachable ();
1078 default : gcc_unreachable ();
1084 /* Return true if COMPARISON has a short form that can accomodate OFFSET. */
1087 arc_short_comparison_p (rtx comparison
, int offset
)
1089 gcc_assert (ARC_CC_NC
== ARC_CC_HS
);
1090 gcc_assert (ARC_CC_C
== ARC_CC_LO
);
1091 switch (get_arc_condition_code (comparison
))
1093 case ARC_CC_EQ
: case ARC_CC_NE
:
1094 return offset
>= -512 && offset
<= 506;
1095 case ARC_CC_GT
: case ARC_CC_LE
: case ARC_CC_GE
: case ARC_CC_LT
:
1096 case ARC_CC_HI
: case ARC_CC_LS
: case ARC_CC_LO
: case ARC_CC_HS
:
1097 return offset
>= -64 && offset
<= 58;
1103 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
1104 return the mode to be used for the comparison. */
1107 arc_select_cc_mode (enum rtx_code op
, rtx x
, rtx y
)
1109 machine_mode mode
= GET_MODE (x
);
1112 /* For an operation that sets the condition codes as a side-effect, the
1113 C and V flags is not set as for cmp, so we can only use comparisons where
1114 this doesn't matter. (For LT and GE we can use "mi" and "pl"
1116 /* ??? We could use "pnz" for greater than zero, however, we could then
1117 get into trouble because the comparison could not be reversed. */
1118 if (GET_MODE_CLASS (mode
) == MODE_INT
1120 && (op
== EQ
|| op
== NE
1121 || ((op
== LT
|| op
== GE
) && GET_MODE_SIZE (GET_MODE (x
)) <= 4)))
1124 /* add.f for if (a+b) */
1126 && GET_CODE (y
) == NEG
1127 && (op
== EQ
|| op
== NE
))
1130 /* Check if this is a test suitable for bxor.f . */
1131 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1132 && ((INTVAL (y
) - 1) & INTVAL (y
)) == 0
1136 /* Check if this is a test suitable for add / bmsk.f . */
1137 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1138 && GET_CODE (x
) == AND
&& CONST_INT_P ((x1
= XEXP (x
, 1)))
1139 && ((INTVAL (x1
) + 1) & INTVAL (x1
)) == 0
1140 && (~INTVAL (x1
) | INTVAL (y
)) < 0
1141 && (~INTVAL (x1
) | INTVAL (y
)) > -0x800)
1144 if (GET_MODE (x
) == SImode
&& (op
== LTU
|| op
== GEU
)
1145 && GET_CODE (x
) == PLUS
1146 && (rtx_equal_p (XEXP (x
, 0), y
) || rtx_equal_p (XEXP (x
, 1), y
)))
1149 if (TARGET_ARGONAUT_SET
1150 && ((mode
== SFmode
&& TARGET_SPFP
) || (mode
== DFmode
&& TARGET_DPFP
)))
1153 case EQ
: case NE
: case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1155 case LT
: case UNGE
: case GT
: case UNLE
:
1156 return CC_FP_GTmode
;
1157 case LE
: case UNGT
: case GE
: case UNLT
:
1158 return CC_FP_GEmode
;
1159 default: gcc_unreachable ();
1161 else if (GET_MODE_CLASS (mode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1164 case EQ
: case NE
: return CC_Zmode
;
1166 case GT
: case UNLE
: return CC_FP_GTmode
;
1168 case GE
: case UNLT
: return CC_FP_GEmode
;
1169 case UNEQ
: case LTGT
: return CC_FP_UNEQmode
;
1170 case ORDERED
: case UNORDERED
: return CC_FP_ORDmode
;
1171 default: gcc_unreachable ();
1177 /* Vectors to keep interesting information about registers where it can easily
1178 be got. We use to use the actual mode value as the bit number, but there
1179 is (or may be) more than 32 modes now. Instead we use two tables: one
1180 indexed by hard register number, and one indexed by mode. */
1182 /* The purpose of arc_mode_class is to shrink the range of modes so that
1183 they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
1184 mapped into one arc_mode_class mode. */
1186 enum arc_mode_class
{
1188 S_MODE
, D_MODE
, T_MODE
, O_MODE
,
1189 SF_MODE
, DF_MODE
, TF_MODE
, OF_MODE
,
1193 /* Modes for condition codes. */
1194 #define C_MODES (1 << (int) C_MODE)
1196 /* Modes for single-word and smaller quantities. */
1197 #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
1199 /* Modes for double-word and smaller quantities. */
1200 #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
1202 /* Mode for 8-byte DF values only. */
1203 #define DF_MODES (1 << DF_MODE)
1205 /* Modes for quad-word and smaller quantities. */
1206 #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
1208 /* Modes for 128-bit vectors. */
1209 #define V_MODES (1 << (int) V_MODE)
1211 /* Value is 1 if register/mode pair is acceptable on arc. */
1213 unsigned int arc_hard_regno_mode_ok
[] = {
1214 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1215 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1216 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, D_MODES
,
1217 D_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1219 /* ??? Leave these as S_MODES for now. */
1220 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1221 DF_MODES
, 0, DF_MODES
, 0, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1222 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1223 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, C_MODES
, S_MODES
,
1225 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1226 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1227 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1228 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1230 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1231 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1232 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1233 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1235 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1236 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
1239 unsigned int arc_mode_class
[NUM_MACHINE_MODES
];
1241 enum reg_class arc_regno_reg_class
[FIRST_PSEUDO_REGISTER
];
1244 arc_preferred_reload_class (rtx
, enum reg_class cl
)
1246 if ((cl
) == CHEAP_CORE_REGS
|| (cl
) == WRITABLE_CORE_REGS
)
1247 return GENERAL_REGS
;
1251 /* Initialize the arc_mode_class array. */
1254 arc_init_reg_tables (void)
1258 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
1260 machine_mode m
= (machine_mode
) i
;
1262 switch (GET_MODE_CLASS (m
))
1265 case MODE_PARTIAL_INT
:
1266 case MODE_COMPLEX_INT
:
1267 if (GET_MODE_SIZE (m
) <= 4)
1268 arc_mode_class
[i
] = 1 << (int) S_MODE
;
1269 else if (GET_MODE_SIZE (m
) == 8)
1270 arc_mode_class
[i
] = 1 << (int) D_MODE
;
1271 else if (GET_MODE_SIZE (m
) == 16)
1272 arc_mode_class
[i
] = 1 << (int) T_MODE
;
1273 else if (GET_MODE_SIZE (m
) == 32)
1274 arc_mode_class
[i
] = 1 << (int) O_MODE
;
1276 arc_mode_class
[i
] = 0;
1279 case MODE_COMPLEX_FLOAT
:
1280 if (GET_MODE_SIZE (m
) <= 4)
1281 arc_mode_class
[i
] = 1 << (int) SF_MODE
;
1282 else if (GET_MODE_SIZE (m
) == 8)
1283 arc_mode_class
[i
] = 1 << (int) DF_MODE
;
1284 else if (GET_MODE_SIZE (m
) == 16)
1285 arc_mode_class
[i
] = 1 << (int) TF_MODE
;
1286 else if (GET_MODE_SIZE (m
) == 32)
1287 arc_mode_class
[i
] = 1 << (int) OF_MODE
;
1289 arc_mode_class
[i
] = 0;
1291 case MODE_VECTOR_INT
:
1292 arc_mode_class
[i
] = (1<< (int) V_MODE
);
1296 /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
1297 we must explicitly check for them here. */
1298 if (i
== (int) CCmode
|| i
== (int) CC_ZNmode
|| i
== (int) CC_Zmode
1299 || i
== (int) CC_Cmode
1300 || i
== CC_FP_GTmode
|| i
== CC_FP_GEmode
|| i
== CC_FP_ORDmode
)
1301 arc_mode_class
[i
] = 1 << (int) C_MODE
;
1303 arc_mode_class
[i
] = 0;
1309 /* Core registers 56..59 are used for multiply extension options.
1310 The dsp option uses r56 and r57, these are then named acc1 and acc2.
1311 acc1 is the highpart, and acc2 the lowpart, so which register gets which
1312 number depends on endianness.
1313 The mul64 multiplier options use r57 for mlo, r58 for mmid and r59 for mhi.
1314 Because mlo / mhi form a 64 bit value, we use different gcc internal
1315 register numbers to make them form a register pair as the gcc internals
1316 know it. mmid gets number 57, if still available, and mlo / mhi get
1317 number 58 and 59, depending on endianness. We use DBX_REGISTER_NUMBER
1318 to map this back. */
1319 char rname56
[5] = "r56";
1320 char rname57
[5] = "r57";
1321 char rname58
[5] = "r58";
1322 char rname59
[5] = "r59";
1323 char rname29
[7] = "ilink1";
1324 char rname30
[7] = "ilink2";
1327 arc_conditional_register_usage (void)
1331 int fix_start
= 60, fix_end
= 55;
1335 /* For ARCv2 the core register set is changed. */
1336 strcpy (rname29
, "ilink");
1337 strcpy (rname30
, "r30");
1338 fixed_regs
[30] = call_used_regs
[30] = 1;
1341 if (TARGET_MUL64_SET
)
1346 /* We don't provide a name for mmed. In rtl / assembly resource lists,
1347 you are supposed to refer to it as mlo & mhi, e.g
1348 (zero_extract:SI (reg:DI 58) (const_int 32) (16)) .
1349 In an actual asm instruction, you are of course use mmed.
1350 The point of avoiding having a separate register for mmed is that
1351 this way, we don't have to carry clobbers of that reg around in every
1352 isntruction that modifies mlo and/or mhi. */
1353 strcpy (rname57
, "");
1354 strcpy (rname58
, TARGET_BIG_ENDIAN
? "mhi" : "mlo");
1355 strcpy (rname59
, TARGET_BIG_ENDIAN
? "mlo" : "mhi");
1357 if (TARGET_MULMAC_32BY16_SET
)
1360 fix_end
= fix_end
> 57 ? fix_end
: 57;
1361 strcpy (rname56
, TARGET_BIG_ENDIAN
? "acc1" : "acc2");
1362 strcpy (rname57
, TARGET_BIG_ENDIAN
? "acc2" : "acc1");
1364 for (regno
= fix_start
; regno
<= fix_end
; regno
++)
1366 if (!fixed_regs
[regno
])
1367 warning (0, "multiply option implies r%d is fixed", regno
);
1368 fixed_regs
[regno
] = call_used_regs
[regno
] = 1;
1372 reg_alloc_order
[2] = 12;
1373 reg_alloc_order
[3] = 13;
1374 reg_alloc_order
[4] = 14;
1375 reg_alloc_order
[5] = 15;
1376 reg_alloc_order
[6] = 1;
1377 reg_alloc_order
[7] = 0;
1378 reg_alloc_order
[8] = 4;
1379 reg_alloc_order
[9] = 5;
1380 reg_alloc_order
[10] = 6;
1381 reg_alloc_order
[11] = 7;
1382 reg_alloc_order
[12] = 8;
1383 reg_alloc_order
[13] = 9;
1384 reg_alloc_order
[14] = 10;
1385 reg_alloc_order
[15] = 11;
1387 if (TARGET_SIMD_SET
)
1390 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1391 reg_alloc_order
[i
] = i
;
1392 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1393 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1394 reg_alloc_order
[i
] = i
;
1396 /* For ARC600, lp_count may not be read in an instruction
1397 following immediately after another one setting it to a new value.
1398 There was some discussion on how to enforce scheduling constraints for
1399 processors with missing interlocks on the gcc mailing list:
1400 http://gcc.gnu.org/ml/gcc/2008-05/msg00021.html .
1401 However, we can't actually use this approach, because for ARC the
1402 delay slot scheduling pass is active, which runs after
1403 machine_dependent_reorg. */
1405 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1406 else if (!TARGET_LP_WR_INTERLOCK
)
1407 fixed_regs
[LP_COUNT
] = 1;
1408 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
1409 if (!call_used_regs
[regno
])
1410 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], regno
);
1411 for (regno
= 32; regno
< 60; regno
++)
1412 if (!fixed_regs
[regno
])
1413 SET_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], regno
);
1414 if (!TARGET_ARC600_FAMILY
)
1416 for (regno
= 32; regno
<= 60; regno
++)
1417 CLEAR_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], regno
);
1419 /* If they have used -ffixed-lp_count, make sure it takes
1421 if (fixed_regs
[LP_COUNT
])
1423 CLEAR_HARD_REG_BIT (reg_class_contents
[LPCOUNT_REG
], LP_COUNT
);
1424 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1425 CLEAR_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], LP_COUNT
);
1427 /* Instead of taking out SF_MODE like below, forbid it outright. */
1428 arc_hard_regno_mode_ok
[60] = 0;
1431 arc_hard_regno_mode_ok
[60] = 1 << (int) S_MODE
;
1434 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1438 if (TARGET_Q_CLASS
&& ((i
<= 3) || ((i
>= 12) && (i
<= 15))))
1439 arc_regno_reg_class
[i
] = ARCOMPACT16_REGS
;
1441 arc_regno_reg_class
[i
] = GENERAL_REGS
;
1444 arc_regno_reg_class
[i
]
1446 ? (TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
)
1447 ? CHEAP_CORE_REGS
: ALL_CORE_REGS
)
1448 : (((!TARGET_ARC600_FAMILY
)
1449 && TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
))
1450 ? CHEAP_CORE_REGS
: WRITABLE_CORE_REGS
));
1452 arc_regno_reg_class
[i
] = NO_REGS
;
1455 /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS has not been activated. */
1456 if (!TARGET_Q_CLASS
)
1458 CLEAR_HARD_REG_SET(reg_class_contents
[ARCOMPACT16_REGS
]);
1459 CLEAR_HARD_REG_SET(reg_class_contents
[AC16_BASE_REGS
]);
1462 gcc_assert (FIRST_PSEUDO_REGISTER
>= 144);
1464 /* Handle Special Registers. */
1465 arc_regno_reg_class
[29] = LINK_REGS
; /* ilink1 register. */
1467 arc_regno_reg_class
[30] = LINK_REGS
; /* ilink2 register. */
1468 arc_regno_reg_class
[31] = LINK_REGS
; /* blink register. */
1469 arc_regno_reg_class
[60] = LPCOUNT_REG
;
1470 arc_regno_reg_class
[61] = NO_REGS
; /* CC_REG: must be NO_REGS. */
1471 arc_regno_reg_class
[62] = GENERAL_REGS
;
1475 for (i
= 40; i
< 44; ++i
)
1477 arc_regno_reg_class
[i
] = DOUBLE_REGS
;
1479 /* Unless they want us to do 'mov d1, 0x00000000' make sure
1480 no attempt is made to use such a register as a destination
1481 operand in *movdf_insn. */
1482 if (!TARGET_ARGONAUT_SET
)
1484 /* Make sure no 'c', 'w', 'W', or 'Rac' constraint is
1485 interpreted to mean they can use D1 or D2 in their insn. */
1486 CLEAR_HARD_REG_BIT(reg_class_contents
[CHEAP_CORE_REGS
], i
);
1487 CLEAR_HARD_REG_BIT(reg_class_contents
[ALL_CORE_REGS
], i
);
1488 CLEAR_HARD_REG_BIT(reg_class_contents
[WRITABLE_CORE_REGS
], i
);
1489 CLEAR_HARD_REG_BIT(reg_class_contents
[MPY_WRITABLE_CORE_REGS
], i
);
1495 /* Disable all DOUBLE_REGISTER settings,
1496 if not generating DPFP code. */
1497 arc_regno_reg_class
[40] = ALL_REGS
;
1498 arc_regno_reg_class
[41] = ALL_REGS
;
1499 arc_regno_reg_class
[42] = ALL_REGS
;
1500 arc_regno_reg_class
[43] = ALL_REGS
;
1502 arc_hard_regno_mode_ok
[40] = 0;
1503 arc_hard_regno_mode_ok
[42] = 0;
1505 CLEAR_HARD_REG_SET(reg_class_contents
[DOUBLE_REGS
]);
1508 if (TARGET_SIMD_SET
)
1510 gcc_assert (ARC_FIRST_SIMD_VR_REG
== 64);
1511 gcc_assert (ARC_LAST_SIMD_VR_REG
== 127);
1513 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1514 arc_regno_reg_class
[i
] = SIMD_VR_REGS
;
1516 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_REG
== 128);
1517 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
== 128);
1518 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
== 136);
1519 gcc_assert (ARC_LAST_SIMD_DMA_CONFIG_REG
== 143);
1521 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1522 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1523 arc_regno_reg_class
[i
] = SIMD_DMA_CONFIG_REGS
;
1527 arc_regno_reg_class
[PROGRAM_COUNTER_REGNO
] = GENERAL_REGS
;
1530 /* Handle an "interrupt" attribute; arguments as in
1531 struct attribute_spec.handler. */
1534 arc_handle_interrupt_attribute (tree
*, tree name
, tree args
, int,
1539 tree value
= TREE_VALUE (args
);
1541 if (TREE_CODE (value
) != STRING_CST
)
1543 warning (OPT_Wattributes
,
1544 "argument of %qE attribute is not a string constant",
1546 *no_add_attrs
= true;
1548 else if (strcmp (TREE_STRING_POINTER (value
), "ilink1")
1549 && strcmp (TREE_STRING_POINTER (value
), "ilink2")
1552 warning (OPT_Wattributes
,
1553 "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
1555 *no_add_attrs
= true;
1558 && strcmp (TREE_STRING_POINTER (value
), "ilink"))
1560 warning (OPT_Wattributes
,
1561 "argument of %qE attribute is not \"ilink\"",
1563 *no_add_attrs
= true;
1569 /* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
1570 and two if they are nearly compatible (which causes a warning to be
1574 arc_comp_type_attributes (const_tree type1
,
1577 int l1
, l2
, m1
, m2
, s1
, s2
;
1579 /* Check for mismatch of non-default calling convention. */
1580 if (TREE_CODE (type1
) != FUNCTION_TYPE
)
1583 /* Check for mismatched call attributes. */
1584 l1
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1585 l2
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1586 m1
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1587 m2
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1588 s1
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1589 s2
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1591 /* Only bother to check if an attribute is defined. */
1592 if (l1
| l2
| m1
| m2
| s1
| s2
)
1594 /* If one type has an attribute, the other must have the same attribute. */
1595 if ((l1
!= l2
) || (m1
!= m2
) || (s1
!= s2
))
1598 /* Disallow mixed attributes. */
1599 if (l1
+ m1
+ s1
> 1)
1607 /* Set the default attributes for TYPE. */
1610 arc_set_default_type_attributes (tree type ATTRIBUTE_UNUSED
)
1615 /* Misc. utilities. */
1617 /* X and Y are two things to compare using CODE. Emit the compare insn and
1618 return the rtx for the cc reg in the proper mode. */
1621 gen_compare_reg (rtx comparison
, machine_mode omode
)
1623 enum rtx_code code
= GET_CODE (comparison
);
1624 rtx x
= XEXP (comparison
, 0);
1625 rtx y
= XEXP (comparison
, 1);
1627 machine_mode mode
, cmode
;
1630 cmode
= GET_MODE (x
);
1631 if (cmode
== VOIDmode
)
1632 cmode
= GET_MODE (y
);
1633 gcc_assert (cmode
== SImode
|| cmode
== SFmode
|| cmode
== DFmode
);
1634 if (cmode
== SImode
)
1636 if (!register_operand (x
, SImode
))
1638 if (register_operand (y
, SImode
))
1643 code
= swap_condition (code
);
1646 x
= copy_to_mode_reg (SImode
, x
);
1648 if (GET_CODE (y
) == SYMBOL_REF
&& flag_pic
)
1649 y
= copy_to_mode_reg (SImode
, y
);
1653 x
= force_reg (cmode
, x
);
1654 y
= force_reg (cmode
, y
);
1656 mode
= SELECT_CC_MODE (code
, x
, y
);
1658 cc_reg
= gen_rtx_REG (mode
, CC_REG
);
1660 /* ??? FIXME (x-y)==0, as done by both cmpsfpx_raw and
1661 cmpdfpx_raw, is not a correct comparison for floats:
1662 http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
1664 if (TARGET_ARGONAUT_SET
1665 && ((cmode
== SFmode
&& TARGET_SPFP
) || (cmode
== DFmode
&& TARGET_DPFP
)))
1669 case NE
: case EQ
: case LT
: case UNGE
: case LE
: case UNGT
:
1670 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1672 case GT
: case UNLE
: case GE
: case UNLT
:
1673 code
= swap_condition (code
);
1681 if (cmode
== SFmode
)
1683 emit_insn (gen_cmpsfpx_raw (x
, y
));
1687 /* Accepts Dx regs directly by insns. */
1688 emit_insn (gen_cmpdfpx_raw (x
, y
));
1691 if (mode
!= CC_FPXmode
)
1692 emit_insn (gen_rtx_SET (cc_reg
,
1693 gen_rtx_COMPARE (mode
,
1694 gen_rtx_REG (CC_FPXmode
, 61),
1697 else if (GET_MODE_CLASS (cmode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1699 rtx op0
= gen_rtx_REG (cmode
, 0);
1700 rtx op1
= gen_rtx_REG (cmode
, GET_MODE_SIZE (cmode
) / UNITS_PER_WORD
);
1705 case NE
: case EQ
: case GT
: case UNLE
: case GE
: case UNLT
:
1706 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1708 case LT
: case UNGE
: case LE
: case UNGT
:
1709 code
= swap_condition (code
);
1715 if (currently_expanding_to_rtl
)
1723 emit_move_insn (op0
, x
);
1724 emit_move_insn (op1
, y
);
1728 gcc_assert (rtx_equal_p (op0
, x
));
1729 gcc_assert (rtx_equal_p (op1
, y
));
1736 emit_insn (gen_cmp_float (cc_reg
, gen_rtx_COMPARE (mode
, op0
, op1
)));
1739 emit_insn (gen_rtx_SET (cc_reg
, gen_rtx_COMPARE (mode
, x
, y
)));
1740 return gen_rtx_fmt_ee (code
, omode
, cc_reg
, const0_rtx
);
1743 /* Return true if VALUE, a const_double, will fit in a limm (4 byte number).
1744 We assume the value can be either signed or unsigned. */
1747 arc_double_limm_p (rtx value
)
1749 HOST_WIDE_INT low
, high
;
1751 gcc_assert (GET_CODE (value
) == CONST_DOUBLE
);
1756 low
= CONST_DOUBLE_LOW (value
);
1757 high
= CONST_DOUBLE_HIGH (value
);
1759 if (low
& 0x80000000)
1761 return (((unsigned HOST_WIDE_INT
) low
<= 0xffffffff && high
== 0)
1762 || (((low
& - (unsigned HOST_WIDE_INT
) 0x80000000)
1763 == - (unsigned HOST_WIDE_INT
) 0x80000000)
1768 return (unsigned HOST_WIDE_INT
) low
<= 0x7fffffff && high
== 0;
1772 /* Do any needed setup for a variadic function. For the ARC, we must
1773 create a register parameter block, and then copy any anonymous arguments
1774 in registers to memory.
1776 CUM has not been updated for the last named argument which has type TYPE
1777 and mode MODE, and we rely on this fact. */
1780 arc_setup_incoming_varargs (cumulative_args_t args_so_far
,
1781 machine_mode mode
, tree type
,
1782 int *pretend_size
, int no_rtl
)
1785 CUMULATIVE_ARGS next_cum
;
1787 /* We must treat `__builtin_va_alist' as an anonymous arg. */
1789 next_cum
= *get_cumulative_args (args_so_far
);
1790 arc_function_arg_advance (pack_cumulative_args (&next_cum
), mode
, type
, 1);
1791 first_anon_arg
= next_cum
;
1793 if (first_anon_arg
< MAX_ARC_PARM_REGS
)
1795 /* First anonymous (unnamed) argument is in a reg. */
1797 /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
1798 int first_reg_offset
= first_anon_arg
;
1803 = gen_rtx_MEM (BLKmode
, plus_constant (Pmode
, arg_pointer_rtx
,
1804 FIRST_PARM_OFFSET (0)));
1805 move_block_from_reg (first_reg_offset
, regblock
,
1806 MAX_ARC_PARM_REGS
- first_reg_offset
);
1810 = ((MAX_ARC_PARM_REGS
- first_reg_offset
) * UNITS_PER_WORD
);
1814 /* Cost functions. */
1816 /* Provide the costs of an addressing mode that contains ADDR.
1817 If ADDR is not a valid address, its cost is irrelevant. */
1820 arc_address_cost (rtx addr
, machine_mode
, addr_space_t
, bool speed
)
1822 switch (GET_CODE (addr
))
1825 return speed
|| satisfies_constraint_Rcq (addr
) ? 0 : 1;
1826 case PRE_INC
: case PRE_DEC
: case POST_INC
: case POST_DEC
:
1827 case PRE_MODIFY
: case POST_MODIFY
:
1833 /* Most likely needs a LIMM. */
1834 return COSTS_N_INSNS (1);
1838 register rtx plus0
= XEXP (addr
, 0);
1839 register rtx plus1
= XEXP (addr
, 1);
1841 if (GET_CODE (plus0
) != REG
1842 && (GET_CODE (plus0
) != MULT
1843 || !CONST_INT_P (XEXP (plus0
, 1))
1844 || (INTVAL (XEXP (plus0
, 1)) != 2
1845 && INTVAL (XEXP (plus0
, 1)) != 4)))
1848 switch (GET_CODE (plus1
))
1851 return (!RTX_OK_FOR_OFFSET_P (SImode
, plus1
)
1855 : (satisfies_constraint_Rcq (plus0
)
1856 && satisfies_constraint_O (plus1
))
1860 return (speed
< 1 ? 0
1861 : (satisfies_constraint_Rcq (plus0
)
1862 && satisfies_constraint_Rcq (plus1
))
1867 return COSTS_N_INSNS (1);
1880 /* Emit instruction X with the frame related bit set. */
1886 RTX_FRAME_RELATED_P (x
) = 1;
1890 /* Emit a frame insn to move SRC to DST. */
1893 frame_move (rtx dst
, rtx src
)
1895 rtx tmp
= gen_rtx_SET (dst
, src
);
1896 RTX_FRAME_RELATED_P (tmp
) = 1;
1897 return frame_insn (tmp
);
1900 /* Like frame_move, but add a REG_INC note for REG if ADDR contains an
1901 auto increment address, or is zero. */
1904 frame_move_inc (rtx dst
, rtx src
, rtx reg
, rtx addr
)
1906 rtx insn
= frame_move (dst
, src
);
1909 || GET_CODE (addr
) == PRE_DEC
|| GET_CODE (addr
) == POST_INC
1910 || GET_CODE (addr
) == PRE_MODIFY
|| GET_CODE (addr
) == POST_MODIFY
)
1911 add_reg_note (insn
, REG_INC
, reg
);
1915 /* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
1918 frame_add (rtx reg
, HOST_WIDE_INT offset
)
1920 gcc_assert ((offset
& 0x3) == 0);
1923 return frame_move (reg
, plus_constant (Pmode
, reg
, offset
));
1926 /* Emit a frame insn which adjusts stack pointer by OFFSET. */
1929 frame_stack_add (HOST_WIDE_INT offset
)
1931 return frame_add (stack_pointer_rtx
, offset
);
1934 /* Traditionally, we push saved registers first in the prologue,
1935 then we allocate the rest of the frame - and reverse in the epilogue.
1936 This has still its merits for ease of debugging, or saving code size
1937 or even execution time if the stack frame is so large that some accesses
1938 can't be encoded anymore with offsets in the instruction code when using
1940 Also, it would be a good starting point if we got instructions to help
1941 with register save/restore.
1943 However, often stack frames are small, and the pushing / popping has
1945 - the stack modification prevents a lot of scheduling.
1946 - frame allocation / deallocation needs extra instructions.
1947 - unless we know that we compile ARC700 user code, we need to put
1948 a memory barrier after frame allocation / before deallocation to
1949 prevent interrupts clobbering our data in the frame.
1950 In particular, we don't have any such guarantees for library functions,
1951 which tend to, on the other hand, to have small frames.
1953 Thus, for small frames, we'd like to use a different scheme:
1954 - The frame is allocated in full with the first prologue instruction,
1955 and deallocated in full with the last epilogue instruction.
1956 Thus, the instructions in-betwen can be freely scheduled.
1957 - If the function has no outgoing arguments on the stack, we can allocate
1958 one register save slot at the top of the stack. This register can then
1959 be saved simultanously with frame allocation, and restored with
1961 This register can be picked depending on scheduling considerations,
1962 although same though should go into having some set of registers
1963 to be potentially lingering after a call, and others to be available
1964 immediately - i.e. in the absence of interprocedual optimization, we
1965 can use an ABI-like convention for register allocation to reduce
1966 stalls after function return. */
1967 /* Function prologue/epilogue handlers. */
1969 /* ARCompact stack frames look like:
1971 Before call After call
1972 high +-----------------------+ +-----------------------+
1973 mem | reg parm save area | | reg parm save area |
1974 | only created for | | only created for |
1975 | variable arg fns | | variable arg fns |
1976 AP +-----------------------+ +-----------------------+
1977 | return addr register | | return addr register |
1978 | (if required) | | (if required) |
1979 +-----------------------+ +-----------------------+
1981 | reg save area | | reg save area |
1983 +-----------------------+ +-----------------------+
1984 | frame pointer | | frame pointer |
1985 | (if required) | | (if required) |
1986 FP +-----------------------+ +-----------------------+
1988 | local/temp variables | | local/temp variables |
1990 +-----------------------+ +-----------------------+
1992 | arguments on stack | | arguments on stack |
1994 SP +-----------------------+ +-----------------------+
1995 | reg parm save area |
1996 | only created for |
1997 | variable arg fns |
1998 AP +-----------------------+
1999 | return addr register |
2001 +-----------------------+
2005 +-----------------------+
2008 FP +-----------------------+
2010 | local/temp variables |
2012 +-----------------------+
2014 | arguments on stack |
2016 mem SP +-----------------------+
2019 1) The "reg parm save area" does not exist for non variable argument fns.
2020 The "reg parm save area" can be eliminated completely if we created our
2021 own va-arc.h, but that has tradeoffs as well (so it's not done). */
2023 /* Structure to be filled in by arc_compute_frame_size with register
2024 save masks, and offsets for the current function. */
2025 struct GTY (()) arc_frame_info
2027 unsigned int total_size
; /* # bytes that the entire frame takes up. */
2028 unsigned int extra_size
; /* # bytes of extra stuff. */
2029 unsigned int pretend_size
; /* # bytes we push and pretend caller did. */
2030 unsigned int args_size
; /* # bytes that outgoing arguments take up. */
2031 unsigned int reg_size
; /* # bytes needed to store regs. */
2032 unsigned int var_size
; /* # bytes that variables take up. */
2033 unsigned int reg_offset
; /* Offset from new sp to store regs. */
2034 unsigned int gmask
; /* Mask of saved gp registers. */
2035 int initialized
; /* Nonzero if frame size already calculated. */
2036 short millicode_start_reg
;
2037 short millicode_end_reg
;
2038 bool save_return_addr
;
2041 /* Defining data structures for per-function information. */
2043 typedef struct GTY (()) machine_function
2045 enum arc_function_type fn_type
;
2046 struct arc_frame_info frame_info
;
2047 /* To keep track of unalignment caused by short insns. */
2049 int force_short_suffix
; /* Used when disgorging return delay slot insns. */
2050 const char *size_reason
;
2051 struct arc_ccfsm ccfsm_current
;
2052 /* Map from uid to ccfsm state during branch shortening. */
2053 rtx ccfsm_current_insn
;
2054 char arc_reorg_started
;
2055 char prescan_initialized
;
2058 /* Type of function DECL.
2060 The result is cached. To reset the cache at the end of a function,
2061 call with DECL = NULL_TREE. */
2063 enum arc_function_type
2064 arc_compute_function_type (struct function
*fun
)
2066 tree decl
= fun
->decl
;
2068 enum arc_function_type fn_type
= fun
->machine
->fn_type
;
2070 if (fn_type
!= ARC_FUNCTION_UNKNOWN
)
2073 /* Assume we have a normal function (not an interrupt handler). */
2074 fn_type
= ARC_FUNCTION_NORMAL
;
2076 /* Now see if this is an interrupt handler. */
2077 for (a
= DECL_ATTRIBUTES (decl
);
2081 tree name
= TREE_PURPOSE (a
), args
= TREE_VALUE (a
);
2083 if (name
== get_identifier ("interrupt")
2084 && list_length (args
) == 1
2085 && TREE_CODE (TREE_VALUE (args
)) == STRING_CST
)
2087 tree value
= TREE_VALUE (args
);
2089 if (!strcmp (TREE_STRING_POINTER (value
), "ilink1")
2090 || !strcmp (TREE_STRING_POINTER (value
), "ilink"))
2091 fn_type
= ARC_FUNCTION_ILINK1
;
2092 else if (!strcmp (TREE_STRING_POINTER (value
), "ilink2"))
2093 fn_type
= ARC_FUNCTION_ILINK2
;
2100 return fun
->machine
->fn_type
= fn_type
;
2103 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
2104 #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
2106 /* Tell prologue and epilogue if register REGNO should be saved / restored.
2107 The return address and frame pointer are treated separately.
2108 Don't consider them here.
2109 Addition for pic: The gp register needs to be saved if the current
2110 function changes it to access gotoff variables.
2111 FIXME: This will not be needed if we used some arbitrary register
2114 #define MUST_SAVE_REGISTER(regno, interrupt_p) \
2115 (((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
2116 && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p))) \
2117 || (flag_pic && crtl->uses_pic_offset_table \
2118 && regno == PIC_OFFSET_TABLE_REGNUM) )
2120 #define MUST_SAVE_RETURN_ADDR \
2121 (cfun->machine->frame_info.save_return_addr)
2123 /* Return non-zero if there are registers to be saved or loaded using
2124 millicode thunks. We can only use consecutive sequences starting
2125 with r13, and not going beyond r25.
2126 GMASK is a bitmask of registers to save. This function sets
2127 FRAME->millicod_start_reg .. FRAME->millicode_end_reg to the range
2128 of registers to be saved / restored with a millicode call. */
2131 arc_compute_millicode_save_restore_regs (unsigned int gmask
,
2132 struct arc_frame_info
*frame
)
2136 int start_reg
= 13, end_reg
= 25;
2138 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1L << regno
));)
2140 end_reg
= regno
- 1;
2141 /* There is no point in using millicode thunks if we don't save/restore
2142 at least three registers. For non-leaf functions we also have the
2144 if (regno
- start_reg
>= 3 - (crtl
->is_leaf
== 0))
2146 frame
->millicode_start_reg
= 13;
2147 frame
->millicode_end_reg
= regno
- 1;
2153 /* Return the bytes needed to compute the frame pointer from the current
2156 SIZE is the size needed for local variables. */
2159 arc_compute_frame_size (int size
) /* size = # of var. bytes allocated. */
2162 unsigned int total_size
, var_size
, args_size
, pretend_size
, extra_size
;
2163 unsigned int reg_size
, reg_offset
;
2165 enum arc_function_type fn_type
;
2167 struct arc_frame_info
*frame_info
= &cfun
->machine
->frame_info
;
2169 size
= ARC_STACK_ALIGN (size
);
2171 /* 1) Size of locals and temporaries */
2174 /* 2) Size of outgoing arguments */
2175 args_size
= crtl
->outgoing_args_size
;
2177 /* 3) Calculate space needed for saved registers.
2178 ??? We ignore the extension registers for now. */
2180 /* See if this is an interrupt handler. Call used registers must be saved
2185 fn_type
= arc_compute_function_type (cfun
);
2186 interrupt_p
= ARC_INTERRUPT_P (fn_type
);
2188 for (regno
= 0; regno
<= 31; regno
++)
2190 if (MUST_SAVE_REGISTER (regno
, interrupt_p
))
2192 reg_size
+= UNITS_PER_WORD
;
2193 gmask
|= 1 << regno
;
2197 /* 4) Space for back trace data structure.
2198 <return addr reg size> (if required) + <fp size> (if required). */
2199 frame_info
->save_return_addr
2200 = (!crtl
->is_leaf
|| df_regs_ever_live_p (RETURN_ADDR_REGNUM
));
2201 /* Saving blink reg in case of leaf function for millicode thunk calls. */
2202 if (optimize_size
&& !TARGET_NO_MILLICODE_THUNK_SET
)
2204 if (arc_compute_millicode_save_restore_regs (gmask
, frame_info
))
2205 frame_info
->save_return_addr
= true;
2209 if (MUST_SAVE_RETURN_ADDR
)
2211 if (frame_pointer_needed
)
2214 /* 5) Space for variable arguments passed in registers */
2215 pretend_size
= crtl
->args
.pretend_args_size
;
2217 /* Ensure everything before the locals is aligned appropriately. */
2219 unsigned int extra_plus_reg_size
;
2220 unsigned int extra_plus_reg_size_aligned
;
2222 extra_plus_reg_size
= extra_size
+ reg_size
;
2223 extra_plus_reg_size_aligned
= ARC_STACK_ALIGN(extra_plus_reg_size
);
2224 reg_size
= extra_plus_reg_size_aligned
- extra_size
;
2227 /* Compute total frame size. */
2228 total_size
= var_size
+ args_size
+ extra_size
+ pretend_size
+ reg_size
;
2230 total_size
= ARC_STACK_ALIGN (total_size
);
2232 /* Compute offset of register save area from stack pointer:
2233 Frame: pretend_size <blink> reg_size <fp> var_size args_size <--sp
2235 reg_offset
= (total_size
- (pretend_size
+ reg_size
+ extra_size
)
2236 + (frame_pointer_needed
? 4 : 0));
2238 /* Save computed information. */
2239 frame_info
->total_size
= total_size
;
2240 frame_info
->extra_size
= extra_size
;
2241 frame_info
->pretend_size
= pretend_size
;
2242 frame_info
->var_size
= var_size
;
2243 frame_info
->args_size
= args_size
;
2244 frame_info
->reg_size
= reg_size
;
2245 frame_info
->reg_offset
= reg_offset
;
2246 frame_info
->gmask
= gmask
;
2247 frame_info
->initialized
= reload_completed
;
2249 /* Ok, we're done. */
2253 /* Common code to save/restore registers. */
2254 /* BASE_REG is the base register to use for addressing and to adjust.
2255 GMASK is a bitmask of general purpose registers to save/restore.
2256 epilogue_p 0: prologue 1:epilogue 2:epilogue, sibling thunk
2257 If *FIRST_OFFSET is non-zero, add it first to BASE_REG - preferably
2258 using a pre-modify for the first memory access. *FIRST_OFFSET is then
2262 arc_save_restore (rtx base_reg
,
2263 unsigned int gmask
, int epilogue_p
, int *first_offset
)
2265 unsigned int offset
= 0;
2267 struct arc_frame_info
*frame
= &cfun
->machine
->frame_info
;
2268 rtx sibthunk_insn
= NULL_RTX
;
2272 /* Millicode thunks implementation:
2273 Generates calls to millicodes for registers starting from r13 to r25
2274 Present Limitations:
2275 - Only one range supported. The remaining regs will have the ordinary
2276 st and ld instructions for store and loads. Hence a gmask asking
2277 to store r13-14, r16-r25 will only generate calls to store and
2278 load r13 to r14 while store and load insns will be generated for
2279 r16 to r25 in the prologue and epilogue respectively.
2281 - Presently library only supports register ranges starting from r13.
2283 if (epilogue_p
== 2 || frame
->millicode_end_reg
> 14)
2285 int start_call
= frame
->millicode_start_reg
;
2286 int end_call
= frame
->millicode_end_reg
;
2287 int n_regs
= end_call
- start_call
+ 1;
2288 int i
= 0, r
, off
= 0;
2290 rtx ret_addr
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2294 /* "reg_size" won't be more than 127 . */
2295 gcc_assert (epilogue_p
|| abs (*first_offset
) <= 127);
2296 frame_add (base_reg
, *first_offset
);
2299 insn
= gen_rtx_PARALLEL
2300 (VOIDmode
, rtvec_alloc ((epilogue_p
== 2) + n_regs
+ 1));
2301 if (epilogue_p
== 2)
2304 XVECEXP (insn
, 0, n_regs
) = gen_rtx_CLOBBER (VOIDmode
, ret_addr
);
2305 for (r
= start_call
; r
<= end_call
; r
++, off
+= UNITS_PER_WORD
, i
++)
2307 rtx reg
= gen_rtx_REG (SImode
, r
);
2309 = gen_frame_mem (SImode
, plus_constant (Pmode
, base_reg
, off
));
2312 XVECEXP (insn
, 0, i
) = gen_rtx_SET (reg
, mem
);
2314 XVECEXP (insn
, 0, i
) = gen_rtx_SET (mem
, reg
);
2315 gmask
= gmask
& ~(1L << r
);
2317 if (epilogue_p
== 2)
2318 sibthunk_insn
= insn
;
2321 insn
= frame_insn (insn
);
2323 for (r
= start_call
; r
<= end_call
; r
++)
2325 rtx reg
= gen_rtx_REG (SImode
, r
);
2326 add_reg_note (insn
, REG_CFA_RESTORE
, reg
);
2332 for (regno
= 0; regno
<= 31; regno
++)
2334 if ((gmask
& (1L << regno
)) != 0)
2336 rtx reg
= gen_rtx_REG (SImode
, regno
);
2338 int cfa_adjust
= *first_offset
;
2342 gcc_assert (!offset
);
2343 addr
= plus_constant (Pmode
, base_reg
, *first_offset
);
2344 addr
= gen_rtx_PRE_MODIFY (Pmode
, base_reg
, addr
);
2349 gcc_assert (SMALL_INT (offset
));
2350 addr
= plus_constant (Pmode
, base_reg
, offset
);
2352 mem
= gen_frame_mem (SImode
, addr
);
2356 frame_move_inc (reg
, mem
, base_reg
, addr
);
2357 add_reg_note (insn
, REG_CFA_RESTORE
, reg
);
2360 enum reg_note note
= REG_CFA_ADJUST_CFA
;
2361 add_reg_note (insn
, note
,
2362 gen_rtx_SET (stack_pointer_rtx
,
2363 plus_constant (Pmode
,
2369 frame_move_inc (mem
, reg
, base_reg
, addr
);
2370 offset
+= UNITS_PER_WORD
;
2376 int start_call
= frame
->millicode_start_reg
;
2377 int end_call
= frame
->millicode_end_reg
;
2380 rtx r12
= gen_rtx_REG (Pmode
, 12);
2382 frame_insn (gen_rtx_SET (r12
, GEN_INT (offset
)));
2383 XVECEXP (sibthunk_insn
, 0, 0) = ret_rtx
;
2384 XVECEXP (sibthunk_insn
, 0, 1)
2385 = gen_rtx_SET (stack_pointer_rtx
,
2386 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, r12
));
2387 sibthunk_insn
= emit_jump_insn (sibthunk_insn
);
2388 RTX_FRAME_RELATED_P (sibthunk_insn
) = 1;
2390 /* Would be nice if we could do this earlier, when the PARALLEL
2391 is populated, but these need to be attached after the
2393 for (r
= start_call
; r
<= end_call
; r
++)
2395 rtx reg
= gen_rtx_REG (SImode
, r
);
2396 add_reg_note (sibthunk_insn
, REG_CFA_RESTORE
, reg
);
2399 } /* arc_save_restore */
2402 int arc_return_address_regs
[4]
2403 = {0, RETURN_ADDR_REGNUM
, ILINK1_REGNUM
, ILINK2_REGNUM
};
2405 /* Set up the stack and frame pointer (if desired) for the function. */
2408 arc_expand_prologue (void)
2410 int size
= get_frame_size ();
2411 unsigned int gmask
= cfun
->machine
->frame_info
.gmask
;
2412 /* unsigned int frame_pointer_offset;*/
2413 unsigned int frame_size_to_allocate
;
2414 /* (FIXME: The first store will use a PRE_MODIFY; this will usually be r13.
2415 Change the stack layout so that we rather store a high register with the
2416 PRE_MODIFY, thus enabling more short insn generation.) */
2417 int first_offset
= 0;
2419 size
= ARC_STACK_ALIGN (size
);
2421 /* Compute/get total frame size. */
2422 size
= (!cfun
->machine
->frame_info
.initialized
2423 ? arc_compute_frame_size (size
)
2424 : cfun
->machine
->frame_info
.total_size
);
2426 if (flag_stack_usage_info
)
2427 current_function_static_stack_size
= size
;
2429 /* Keep track of frame size to be allocated. */
2430 frame_size_to_allocate
= size
;
2432 /* These cases shouldn't happen. Catch them now. */
2433 gcc_assert (!(size
== 0 && gmask
));
2435 /* Allocate space for register arguments if this is a variadic function. */
2436 if (cfun
->machine
->frame_info
.pretend_size
!= 0)
2438 /* Ensure pretend_size is maximum of 8 * word_size. */
2439 gcc_assert (cfun
->machine
->frame_info
.pretend_size
<= 32);
2441 frame_stack_add (-(HOST_WIDE_INT
)cfun
->machine
->frame_info
.pretend_size
);
2442 frame_size_to_allocate
-= cfun
->machine
->frame_info
.pretend_size
;
2445 /* The home-grown ABI says link register is saved first. */
2446 if (MUST_SAVE_RETURN_ADDR
)
2448 rtx ra
= gen_rtx_REG (SImode
, RETURN_ADDR_REGNUM
);
2449 rtx mem
= gen_frame_mem (Pmode
, gen_rtx_PRE_DEC (Pmode
, stack_pointer_rtx
));
2451 frame_move_inc (mem
, ra
, stack_pointer_rtx
, 0);
2452 frame_size_to_allocate
-= UNITS_PER_WORD
;
2454 } /* MUST_SAVE_RETURN_ADDR */
2456 /* Save any needed call-saved regs (and call-used if this is an
2457 interrupt handler) for ARCompact ISA. */
2458 if (cfun
->machine
->frame_info
.reg_size
)
2460 first_offset
= -cfun
->machine
->frame_info
.reg_size
;
2461 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
2462 arc_save_restore (stack_pointer_rtx
, gmask
, 0, &first_offset
);
2463 frame_size_to_allocate
-= cfun
->machine
->frame_info
.reg_size
;
2467 /* Save frame pointer if needed. */
2468 if (frame_pointer_needed
)
2470 rtx addr
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
2471 GEN_INT (-UNITS_PER_WORD
+ first_offset
));
2472 rtx mem
= gen_frame_mem (Pmode
, gen_rtx_PRE_MODIFY (Pmode
,
2475 frame_move_inc (mem
, frame_pointer_rtx
, stack_pointer_rtx
, 0);
2476 frame_size_to_allocate
-= UNITS_PER_WORD
;
2478 frame_move (frame_pointer_rtx
, stack_pointer_rtx
);
2481 /* ??? We don't handle the case where the saved regs are more than 252
2482 bytes away from sp. This can be handled by decrementing sp once, saving
2483 the regs, and then decrementing it again. The epilogue doesn't have this
2484 problem as the `ld' insn takes reg+limm values (though it would be more
2485 efficient to avoid reg+limm). */
2487 frame_size_to_allocate
-= first_offset
;
2488 /* Allocate the stack frame. */
2489 if (frame_size_to_allocate
> 0)
2490 frame_stack_add ((HOST_WIDE_INT
) 0 - frame_size_to_allocate
);
2492 /* Setup the gp register, if needed. */
2493 if (crtl
->uses_pic_offset_table
)
2494 arc_finalize_pic ();
2497 /* Do any necessary cleanup after a function to restore stack, frame,
2501 arc_expand_epilogue (int sibcall_p
)
2503 int size
= get_frame_size ();
2504 enum arc_function_type fn_type
= arc_compute_function_type (cfun
);
2506 size
= ARC_STACK_ALIGN (size
);
2507 size
= (!cfun
->machine
->frame_info
.initialized
2508 ? arc_compute_frame_size (size
)
2509 : cfun
->machine
->frame_info
.total_size
);
2511 unsigned int pretend_size
= cfun
->machine
->frame_info
.pretend_size
;
2512 unsigned int frame_size
;
2513 unsigned int size_to_deallocate
;
2515 int can_trust_sp_p
= !cfun
->calls_alloca
;
2516 int first_offset
= 0;
2517 int millicode_p
= cfun
->machine
->frame_info
.millicode_end_reg
> 0;
2520 size_to_deallocate
= size
;
2522 frame_size
= size
- (pretend_size
+
2523 cfun
->machine
->frame_info
.reg_size
+
2524 cfun
->machine
->frame_info
.extra_size
);
2526 /* ??? There are lots of optimizations that can be done here.
2527 EG: Use fp to restore regs if it's closer.
2528 Maybe in time we'll do them all. For now, always restore regs from
2529 sp, but don't restore sp if we don't have to. */
2531 if (!can_trust_sp_p
)
2532 gcc_assert (frame_pointer_needed
);
2534 /* Restore stack pointer to the beginning of saved register area for
2538 if (frame_pointer_needed
)
2539 frame_move (stack_pointer_rtx
, frame_pointer_rtx
);
2541 first_offset
= frame_size
;
2542 size_to_deallocate
-= frame_size
;
2544 else if (!can_trust_sp_p
)
2545 frame_stack_add (-frame_size
);
2548 /* Restore any saved registers. */
2549 if (frame_pointer_needed
)
2551 rtx addr
= gen_rtx_POST_INC (Pmode
, stack_pointer_rtx
);
2553 insn
= frame_move_inc (frame_pointer_rtx
, gen_frame_mem (Pmode
, addr
),
2554 stack_pointer_rtx
, 0);
2555 add_reg_note (insn
, REG_CFA_RESTORE
, frame_pointer_rtx
);
2556 add_reg_note (insn
, REG_CFA_DEF_CFA
,
2557 plus_constant (SImode
, stack_pointer_rtx
,
2559 size_to_deallocate
-= UNITS_PER_WORD
;
2562 /* Load blink after the calls to thunk calls in case of optimize size. */
2565 int sibthunk_p
= (!sibcall_p
2566 && fn_type
== ARC_FUNCTION_NORMAL
2567 && !cfun
->machine
->frame_info
.pretend_size
);
2569 gcc_assert (!(cfun
->machine
->frame_info
.gmask
2570 & (FRAME_POINTER_MASK
| RETURN_ADDR_MASK
)));
2571 arc_save_restore (stack_pointer_rtx
,
2572 cfun
->machine
->frame_info
.gmask
,
2573 1 + sibthunk_p
, &first_offset
);
2577 /* If we are to restore registers, and first_offset would require
2578 a limm to be encoded in a PRE_MODIFY, yet we can add it with a
2579 fast add to the stack pointer, do this now. */
2580 if ((!SMALL_INT (first_offset
)
2581 && cfun
->machine
->frame_info
.gmask
2582 && ((TARGET_ARC700
&& !optimize_size
)
2583 ? first_offset
<= 0x800
2584 : satisfies_constraint_C2a (GEN_INT (first_offset
))))
2585 /* Also do this if we have both gprs and return
2586 address to restore, and they both would need a LIMM. */
2587 || (MUST_SAVE_RETURN_ADDR
2588 && !SMALL_INT ((cfun
->machine
->frame_info
.reg_size
+ first_offset
) >> 2)
2589 && cfun
->machine
->frame_info
.gmask
))
2591 frame_stack_add (first_offset
);
2594 if (MUST_SAVE_RETURN_ADDR
)
2596 rtx ra
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2597 int ra_offs
= cfun
->machine
->frame_info
.reg_size
+ first_offset
;
2598 rtx addr
= plus_constant (Pmode
, stack_pointer_rtx
, ra_offs
);
2599 HOST_WIDE_INT cfa_adjust
= 0;
2601 /* If the load of blink would need a LIMM, but we can add
2602 the offset quickly to sp, do the latter. */
2603 if (!SMALL_INT (ra_offs
>> 2)
2604 && !cfun
->machine
->frame_info
.gmask
2605 && ((TARGET_ARC700
&& !optimize_size
)
2607 : satisfies_constraint_C2a (GEN_INT (ra_offs
))))
2609 size_to_deallocate
-= ra_offs
- first_offset
;
2611 frame_stack_add (ra_offs
);
2613 addr
= stack_pointer_rtx
;
2615 /* See if we can combine the load of the return address with the
2616 final stack adjustment.
2617 We need a separate load if there are still registers to
2618 restore. We also want a separate load if the combined insn
2619 would need a limm, but a separate load doesn't. */
2621 && !cfun
->machine
->frame_info
.gmask
2622 && (SMALL_INT (ra_offs
) || !SMALL_INT (ra_offs
>> 2)))
2624 addr
= gen_rtx_PRE_MODIFY (Pmode
, stack_pointer_rtx
, addr
);
2625 cfa_adjust
= ra_offs
;
2627 size_to_deallocate
-= cfun
->machine
->frame_info
.reg_size
;
2629 else if (!ra_offs
&& size_to_deallocate
== UNITS_PER_WORD
)
2631 addr
= gen_rtx_POST_INC (Pmode
, addr
);
2632 cfa_adjust
= GET_MODE_SIZE (Pmode
);
2633 size_to_deallocate
= 0;
2636 insn
= frame_move_inc (ra
, gen_frame_mem (Pmode
, addr
),
2637 stack_pointer_rtx
, addr
);
2640 enum reg_note note
= REG_CFA_ADJUST_CFA
;
2642 add_reg_note (insn
, note
,
2643 gen_rtx_SET (stack_pointer_rtx
,
2644 plus_constant (SImode
, stack_pointer_rtx
,
2647 add_reg_note (insn
, REG_CFA_RESTORE
, ra
);
2652 if (cfun
->machine
->frame_info
.reg_size
)
2653 arc_save_restore (stack_pointer_rtx
,
2654 /* The zeroing of these two bits is unnecessary, but leave this in for clarity. */
2655 cfun
->machine
->frame_info
.gmask
2656 & ~(FRAME_POINTER_MASK
| RETURN_ADDR_MASK
), 1, &first_offset
);
2660 /* The rest of this function does the following:
2661 ARCompact : handle epilogue_delay, restore sp (phase-2), return
2664 /* Keep track of how much of the stack pointer we've restored.
2665 It makes the following a lot more readable. */
2666 size_to_deallocate
+= first_offset
;
2667 restored
= size
- size_to_deallocate
;
2669 if (size
> restored
)
2670 frame_stack_add (size
- restored
);
2672 /* Emit the return instruction. */
2673 if (sibcall_p
== FALSE
)
2674 emit_jump_insn (gen_simple_return ());
2677 /* Return the offset relative to the stack pointer where the return address
2678 is stored, or -1 if it is not stored. */
2681 arc_return_slot_offset ()
2683 struct arc_frame_info
*afi
= &cfun
->machine
->frame_info
;
2685 return (afi
->save_return_addr
2686 ? afi
->total_size
- afi
->pretend_size
- afi
->extra_size
: -1);
2691 /* Emit special PIC prologues and epilogues. */
2692 /* If the function has any GOTOFF relocations, then the GOTBASE
2693 register has to be setup in the prologue
2694 The instruction needed at the function start for setting up the
2697 ----------------------------------------------------------
2698 The rtl to be emitted for this should be:
2701 (const (unspec (symref _DYNAMIC) 3)))
2702 ---------------------------------------------------------- */
2705 arc_finalize_pic (void)
2708 rtx baseptr_rtx
= gen_rtx_REG (Pmode
, PIC_OFFSET_TABLE_REGNUM
);
2710 if (crtl
->uses_pic_offset_table
== 0)
2713 gcc_assert (flag_pic
!= 0);
2715 pat
= gen_rtx_SYMBOL_REF (Pmode
, "_DYNAMIC");
2716 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, pat
), ARC_UNSPEC_GOT
);
2717 pat
= gen_rtx_CONST (Pmode
, pat
);
2719 pat
= gen_rtx_SET (baseptr_rtx
, pat
);
2724 /* !TARGET_BARREL_SHIFTER support. */
2725 /* Emit a shift insn to set OP0 to OP1 shifted by OP2; CODE specifies what
2729 emit_shift (enum rtx_code code
, rtx op0
, rtx op1
, rtx op2
)
2731 rtx shift
= gen_rtx_fmt_ee (code
, SImode
, op1
, op2
);
2733 = ((shift4_operator (shift
, SImode
) ? gen_shift_si3
: gen_shift_si3_loop
)
2734 (op0
, op1
, op2
, shift
));
2738 /* Output the assembler code for doing a shift.
2739 We go to a bit of trouble to generate efficient code as the ARC601 only has
2740 single bit shifts. This is taken from the h8300 port. We only have one
2741 mode of shifting and can't access individual bytes like the h8300 can, so
2742 this is greatly simplified (at the expense of not generating hyper-
2745 This function is not used if the variable shift insns are present. */
2747 /* FIXME: This probably can be done using a define_split in arc.md.
2748 Alternately, generate rtx rather than output instructions. */
2751 output_shift (rtx
*operands
)
2753 /* static int loopend_lab;*/
2754 rtx shift
= operands
[3];
2755 machine_mode mode
= GET_MODE (shift
);
2756 enum rtx_code code
= GET_CODE (shift
);
2757 const char *shift_one
;
2759 gcc_assert (mode
== SImode
);
2763 case ASHIFT
: shift_one
= "add %0,%1,%1"; break;
2764 case ASHIFTRT
: shift_one
= "asr %0,%1"; break;
2765 case LSHIFTRT
: shift_one
= "lsr %0,%1"; break;
2766 default: gcc_unreachable ();
2769 if (GET_CODE (operands
[2]) != CONST_INT
)
2771 output_asm_insn ("and.f lp_count,%2, 0x1f", operands
);
2778 n
= INTVAL (operands
[2]);
2780 /* Only consider the lower 5 bits of the shift count. */
2783 /* First see if we can do them inline. */
2784 /* ??? We could get better scheduling & shorter code (using short insns)
2785 by using splitters. Alas, that'd be even more verbose. */
2786 if (code
== ASHIFT
&& n
<= 9 && n
> 2
2787 && dest_reg_operand (operands
[4], SImode
))
2789 output_asm_insn ("mov %4,0\n\tadd3 %0,%4,%1", operands
);
2790 for (n
-=3 ; n
>= 3; n
-= 3)
2791 output_asm_insn ("add3 %0,%4,%0", operands
);
2793 output_asm_insn ("add2 %0,%4,%0", operands
);
2795 output_asm_insn ("add %0,%0,%0", operands
);
2801 output_asm_insn (shift_one
, operands
);
2802 operands
[1] = operands
[0];
2805 /* See if we can use a rotate/and. */
2806 else if (n
== BITS_PER_WORD
- 1)
2811 output_asm_insn ("and %0,%1,1\n\tror %0,%0", operands
);
2814 /* The ARC doesn't have a rol insn. Use something else. */
2815 output_asm_insn ("add.f 0,%1,%1\n\tsbc %0,%0,%0", operands
);
2818 /* The ARC doesn't have a rol insn. Use something else. */
2819 output_asm_insn ("add.f 0,%1,%1\n\trlc %0,0", operands
);
2825 else if (n
== BITS_PER_WORD
- 2 && dest_reg_operand (operands
[4], SImode
))
2830 output_asm_insn ("and %0,%1,3\n\tror %0,%0\n\tror %0,%0", operands
);
2833 #if 1 /* Need some scheduling comparisons. */
2834 output_asm_insn ("add.f %4,%1,%1\n\tsbc %0,%0,%0\n\t"
2835 "add.f 0,%4,%4\n\trlc %0,%0", operands
);
2837 output_asm_insn ("add.f %4,%1,%1\n\tbxor %0,%4,31\n\t"
2838 "sbc.f %0,%0,%4\n\trlc %0,%0", operands
);
2843 output_asm_insn ("add.f %4,%1,%1\n\trlc %0,0\n\t"
2844 "add.f 0,%4,%4\n\trlc %0,%0", operands
);
2846 output_asm_insn ("add.f %0,%1,%1\n\trlc.f %0,0\n\t"
2847 "and %0,%0,1\n\trlc %0,%0", operands
);
2854 else if (n
== BITS_PER_WORD
- 3 && code
== ASHIFT
)
2855 output_asm_insn ("and %0,%1,7\n\tror %0,%0\n\tror %0,%0\n\tror %0,%0",
2860 operands
[2] = GEN_INT (n
);
2861 output_asm_insn ("mov.f lp_count, %2", operands
);
2865 output_asm_insn ("lpnz\t2f", operands
);
2866 output_asm_insn (shift_one
, operands
);
2867 output_asm_insn ("nop", operands
);
2868 fprintf (asm_out_file
, "2:\t%s end single insn loop\n",
2877 /* Nested function support. */
2879 /* Directly store VALUE into memory object BLOCK at OFFSET. */
2882 emit_store_direct (rtx block
, int offset
, int value
)
2884 emit_insn (gen_store_direct (adjust_address (block
, SImode
, offset
),
2886 gen_int_mode (value
, SImode
))));
2889 /* Emit RTL insns to initialize the variable parts of a trampoline.
2890 FNADDR is an RTX for the address of the function's pure code.
2891 CXT is an RTX for the static chain value for the function. */
2892 /* With potentially multiple shared objects loaded, and multiple stacks
2893 present for multiple thereds where trampolines might reside, a simple
2894 range check will likely not suffice for the profiler to tell if a callee
2895 is a trampoline. We a speedier check by making the trampoline start at
2896 an address that is not 4-byte aligned.
2897 A trampoline looks like this:
2901 ld_s r12,[pcl,12] 0xd403
2902 ld r11,[pcl,12] 0x170c 700b
2906 The fastest trampoline to execute for trampolines within +-8KB of CTX
2909 j [limm] 0x20200f80 limm
2910 and that would also be faster to write to the stack by computing the offset
2911 from CTX to TRAMP at compile time. However, it would really be better to
2912 get rid of the high cost of cache invalidation when generating trampolines,
2913 which requires that the code part of trampolines stays constant, and
2915 - making sure that no executable code but trampolines is on the stack,
2916 no icache entries linger for the area of the stack from when before the
2917 stack was allocated, and allocating trampolines in trampoline-only
2920 - allocate trampolines fram a special pool of pre-allocated trampolines. */
2923 arc_initialize_trampoline (rtx tramp
, tree fndecl
, rtx cxt
)
2925 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2927 emit_store_direct (tramp
, 0, TARGET_BIG_ENDIAN
? 0x78e0d403 : 0xd40378e0);
2928 emit_store_direct (tramp
, 4, TARGET_BIG_ENDIAN
? 0x170c700b : 0x700b170c);
2929 emit_store_direct (tramp
, 8, TARGET_BIG_ENDIAN
? 0x7c0078e0 : 0x78e07c00);
2930 emit_move_insn (adjust_address (tramp
, SImode
, 12), fnaddr
);
2931 emit_move_insn (adjust_address (tramp
, SImode
, 16), cxt
);
2932 emit_insn (gen_flush_icache (adjust_address (tramp
, SImode
, 0)));
2935 /* Allow the profiler to easily distinguish trampolines from normal
2939 arc_trampoline_adjust_address (rtx addr
)
2941 return plus_constant (Pmode
, addr
, 2);
2944 /* This is set briefly to 1 when we output a ".as" address modifer, and then
2945 reset when we output the scaled address. */
2946 static int output_scaled
= 0;
2948 /* Print operand X (an rtx) in assembler syntax to file FILE.
2949 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2950 For `%' followed by punctuation, CODE is the punctuation and X is null. */
2951 /* In final.c:output_asm_insn:
2954 'c' : constant address if CONSTANT_ADDRESS_P
2960 '#': condbranch delay slot suffix
2961 '*': jump delay slot suffix
2962 '?' : nonjump-insn suffix for conditional execution or short instruction
2963 '!' : jump / call suffix for conditional execution or short instruction
2964 '`': fold constant inside unary o-perator, re-recognize, and emit.
2969 'B': Branch comparison operand - suppress sda reference
2970 'H': Most significant word
2971 'L': Least significant word
2972 'A': ASCII decimal representation of floating point value
2973 'U': Load/store update or scaling indicator
2974 'V': cache bypass indicator for volatile
2979 'o': original symbol - no @ prepending. */
2982 arc_print_operand (FILE *file
, rtx x
, int code
)
2987 if (GET_CODE (x
) == CONST_INT
)
2988 fprintf (file
, "%d",exact_log2(INTVAL (x
) + 1) - 1 );
2990 output_operand_lossage ("invalid operand to %%Z code");
2995 if (GET_CODE (x
) == CONST_INT
)
2996 fprintf (file
, "%d",exact_log2(INTVAL (x
)) );
2998 output_operand_lossage ("invalid operand to %%z code");
3003 if (GET_CODE (x
) == CONST_INT
)
3004 fprintf (file
, "%d",exact_log2(~INTVAL (x
)) );
3006 output_operand_lossage ("invalid operand to %%M code");
3011 /* Conditional branches depending on condition codes.
3012 Note that this is only for branches that were known to depend on
3013 condition codes before delay slot scheduling;
3014 out-of-range brcc / bbit expansions should use '*'.
3015 This distinction is important because of the different
3016 allowable delay slot insns and the output of the delay suffix
3017 for TARGET_AT_DBR_COND_EXEC. */
3019 /* Unconditional branches / branches not depending on condition codes.
3020 This could also be a CALL_INSN.
3021 Output the appropriate delay slot suffix. */
3022 if (final_sequence
&& final_sequence
->len () != 1)
3024 rtx_insn
*jump
= final_sequence
->insn (0);
3025 rtx_insn
*delay
= final_sequence
->insn (1);
3027 /* For TARGET_PAD_RETURN we might have grabbed the delay insn. */
3028 if (delay
->deleted ())
3030 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
3031 fputs (INSN_FROM_TARGET_P (delay
) ? ".d"
3032 : TARGET_AT_DBR_CONDEXEC
&& code
== '#' ? ".d"
3033 : get_attr_type (jump
) == TYPE_RETURN
&& code
== '#' ? ""
3040 case '?' : /* with leading "." */
3041 case '!' : /* without leading "." */
3042 /* This insn can be conditionally executed. See if the ccfsm machinery
3043 says it should be conditionalized.
3044 If it shouldn't, we'll check the compact attribute if this insn
3045 has a short variant, which may be used depending on code size and
3046 alignment considerations. */
3047 if (current_insn_predicate
)
3048 arc_ccfsm_current
.cc
3049 = get_arc_condition_code (current_insn_predicate
);
3050 if (ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
))
3052 /* Is this insn in a delay slot sequence? */
3053 if (!final_sequence
|| XVECLEN (final_sequence
, 0) < 2
3054 || current_insn_predicate
3055 || CALL_P (final_sequence
->insn (0))
3056 || simplejump_p (final_sequence
->insn (0)))
3058 /* This insn isn't in a delay slot sequence, or conditionalized
3059 independently of its position in a delay slot. */
3060 fprintf (file
, "%s%s",
3061 code
== '?' ? "." : "",
3062 arc_condition_codes
[arc_ccfsm_current
.cc
]);
3063 /* If this is a jump, there are still short variants. However,
3064 only beq_s / bne_s have the same offset range as b_s,
3065 and the only short conditional returns are jeq_s and jne_s. */
3067 && (arc_ccfsm_current
.cc
== ARC_CC_EQ
3068 || arc_ccfsm_current
.cc
== ARC_CC_NE
3069 || 0 /* FIXME: check if branch in 7 bit range. */))
3070 output_short_suffix (file
);
3072 else if (code
== '!') /* Jump with delay slot. */
3073 fputs (arc_condition_codes
[arc_ccfsm_current
.cc
], file
);
3074 else /* An Instruction in a delay slot of a jump or call. */
3076 rtx jump
= XVECEXP (final_sequence
, 0, 0);
3077 rtx insn
= XVECEXP (final_sequence
, 0, 1);
3079 /* If the insn is annulled and is from the target path, we need
3080 to inverse the condition test. */
3081 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
3083 if (INSN_FROM_TARGET_P (insn
))
3084 fprintf (file
, "%s%s",
3085 code
== '?' ? "." : "",
3086 arc_condition_codes
[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current
.cc
)]);
3088 fprintf (file
, "%s%s",
3089 code
== '?' ? "." : "",
3090 arc_condition_codes
[arc_ccfsm_current
.cc
]);
3091 if (arc_ccfsm_current
.state
== 5)
3092 arc_ccfsm_current
.state
= 0;
3095 /* This insn is executed for either path, so don't
3096 conditionalize it at all. */
3097 output_short_suffix (file
);
3102 output_short_suffix (file
);
3105 /* FIXME: fold constant inside unary operator, re-recognize, and emit. */
3108 fputs (arc_condition_codes
[get_arc_condition_code (x
)], file
);
3111 fputs (arc_condition_codes
[ARC_INVERSE_CONDITION_CODE
3112 (get_arc_condition_code (x
))],
3116 /* Write second word of DImode or DFmode reference,
3117 register or memory. */
3118 if (GET_CODE (x
) == REG
)
3119 fputs (reg_names
[REGNO (x
)+1], file
);
3120 else if (GET_CODE (x
) == MEM
)
3124 /* Handle possible auto-increment. For PRE_INC / PRE_DEC /
3125 PRE_MODIFY, we will have handled the first word already;
3126 For POST_INC / POST_DEC / POST_MODIFY, the access to the
3127 first word will be done later. In either case, the access
3128 to the first word will do the modify, and we only have
3129 to add an offset of four here. */
3130 if (GET_CODE (XEXP (x
, 0)) == PRE_INC
3131 || GET_CODE (XEXP (x
, 0)) == PRE_DEC
3132 || GET_CODE (XEXP (x
, 0)) == PRE_MODIFY
3133 || GET_CODE (XEXP (x
, 0)) == POST_INC
3134 || GET_CODE (XEXP (x
, 0)) == POST_DEC
3135 || GET_CODE (XEXP (x
, 0)) == POST_MODIFY
)
3136 output_address (VOIDmode
,
3137 plus_constant (Pmode
, XEXP (XEXP (x
, 0), 0), 4));
3138 else if (output_scaled
)
3140 rtx addr
= XEXP (x
, 0);
3141 int size
= GET_MODE_SIZE (GET_MODE (x
));
3143 output_address (VOIDmode
,
3144 plus_constant (Pmode
, XEXP (addr
, 0),
3145 ((INTVAL (XEXP (addr
, 1)) + 4)
3146 >> (size
== 2 ? 1 : 2))));
3150 output_address (VOIDmode
,
3151 plus_constant (Pmode
, XEXP (x
, 0), 4));
3155 output_operand_lossage ("invalid operand to %%R code");
3158 /* FIXME: remove %S option. */
3160 case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
3163 output_addr_const (file
, x
);
3169 if (GET_CODE (x
) == REG
)
3171 /* L = least significant word, H = most significant word. */
3172 if ((WORDS_BIG_ENDIAN
!= 0) ^ (code
== 'L'))
3173 fputs (reg_names
[REGNO (x
)], file
);
3175 fputs (reg_names
[REGNO (x
)+1], file
);
3177 else if (GET_CODE (x
) == CONST_INT
3178 || GET_CODE (x
) == CONST_DOUBLE
)
3182 split_double (x
, &first
, &second
);
3184 if((WORDS_BIG_ENDIAN
) == 0)
3185 fprintf (file
, "0x%08" PRIx64
,
3186 code
== 'L' ? INTVAL (first
) : INTVAL (second
));
3188 fprintf (file
, "0x%08" PRIx64
,
3189 code
== 'L' ? INTVAL (second
) : INTVAL (first
));
3194 output_operand_lossage ("invalid operand to %%H/%%L code");
3200 gcc_assert (GET_CODE (x
) == CONST_DOUBLE
3201 && GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
);
3203 real_to_decimal (str
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (str
), 0, 1);
3204 fprintf (file
, "%s", str
);
3208 /* Output a load/store with update indicator if appropriate. */
3209 if (GET_CODE (x
) == MEM
)
3211 rtx addr
= XEXP (x
, 0);
3212 switch (GET_CODE (addr
))
3214 case PRE_INC
: case PRE_DEC
: case PRE_MODIFY
:
3215 fputs (".a", file
); break;
3216 case POST_INC
: case POST_DEC
: case POST_MODIFY
:
3217 fputs (".ab", file
); break;
3219 /* Are we using a scaled index? */
3220 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3221 fputs (".as", file
);
3222 /* Can we use a scaled offset? */
3223 else if (CONST_INT_P (XEXP (addr
, 1))
3224 && GET_MODE_SIZE (GET_MODE (x
)) > 1
3225 && (!(INTVAL (XEXP (addr
, 1))
3226 & (GET_MODE_SIZE (GET_MODE (x
)) - 1) & 3))
3227 /* Does it make a difference? */
3228 && !SMALL_INT_RANGE(INTVAL (XEXP (addr
, 1)),
3229 GET_MODE_SIZE (GET_MODE (x
)) - 2, 0))
3231 fputs (".as", file
);
3238 gcc_assert (CONSTANT_P (addr
)); break;
3242 output_operand_lossage ("invalid operand to %%U code");
3245 /* Output cache bypass indicator for a load/store insn. Volatile memory
3246 refs are defined to use the cache bypass mechanism. */
3247 if (GET_CODE (x
) == MEM
)
3249 if (MEM_VOLATILE_P (x
) && !TARGET_VOLATILE_CACHE_SET
)
3250 fputs (".di", file
);
3253 output_operand_lossage ("invalid operand to %%V code");
3258 /* Do nothing special. */
3261 fputs (reg_names
[REGNO (x
)]+1, file
);
3264 /* This punctuation character is needed because label references are
3265 printed in the output template using %l. This is a front end
3266 character, and when we want to emit a '@' before it, we have to use
3272 /* Output an operator. */
3273 switch (GET_CODE (x
))
3275 case PLUS
: fputs ("add", file
); return;
3276 case SS_PLUS
: fputs ("adds", file
); return;
3277 case AND
: fputs ("and", file
); return;
3278 case IOR
: fputs ("or", file
); return;
3279 case XOR
: fputs ("xor", file
); return;
3280 case MINUS
: fputs ("sub", file
); return;
3281 case SS_MINUS
: fputs ("subs", file
); return;
3282 case ASHIFT
: fputs ("asl", file
); return;
3283 case ASHIFTRT
: fputs ("asr", file
); return;
3284 case LSHIFTRT
: fputs ("lsr", file
); return;
3285 case ROTATERT
: fputs ("ror", file
); return;
3286 case MULT
: fputs ("mpy", file
); return;
3287 case ABS
: fputs ("abs", file
); return; /* Unconditional. */
3288 case NEG
: fputs ("neg", file
); return;
3289 case SS_NEG
: fputs ("negs", file
); return;
3290 case NOT
: fputs ("not", file
); return; /* Unconditional. */
3292 fputs ("ext", file
); /* bmsk allows predication. */
3294 case SIGN_EXTEND
: /* Unconditional. */
3295 fputs ("sex", file
);
3297 switch (GET_MODE (XEXP (x
, 0)))
3299 case QImode
: fputs ("b", file
); return;
3300 case HImode
: fputs ("w", file
); return;
3305 if (GET_MODE (x
) != HImode
)
3307 fputs ("sat16", file
);
3310 output_operand_lossage ("invalid operand to %%O code"); return;
3312 if (GET_CODE (x
) == SYMBOL_REF
)
3314 assemble_name (file
, XSTR (x
, 0));
3319 if (TARGET_ANNOTATE_ALIGN
&& cfun
->machine
->size_reason
)
3320 fprintf (file
, "; unalign: %d", cfun
->machine
->unalign
);
3336 output_operand_lossage ("invalid operand output code");
3339 switch (GET_CODE (x
))
3342 fputs (reg_names
[REGNO (x
)], file
);
3346 rtx addr
= XEXP (x
, 0);
3347 int size
= GET_MODE_SIZE (GET_MODE (x
));
3351 switch (GET_CODE (addr
))
3353 case PRE_INC
: case POST_INC
:
3354 output_address (VOIDmode
,
3355 plus_constant (Pmode
, XEXP (addr
, 0), size
)); break;
3356 case PRE_DEC
: case POST_DEC
:
3357 output_address (VOIDmode
,
3358 plus_constant (Pmode
, XEXP (addr
, 0), -size
));
3360 case PRE_MODIFY
: case POST_MODIFY
:
3361 output_address (VOIDmode
, XEXP (addr
, 1)); break;
3365 output_address (VOIDmode
,
3366 plus_constant (Pmode
, XEXP (addr
, 0),
3367 (INTVAL (XEXP (addr
, 1))
3368 >> (size
== 2 ? 1 : 2))));
3372 output_address (VOIDmode
, addr
);
3375 if (flag_pic
&& CONSTANT_ADDRESS_P (addr
))
3376 arc_output_pic_addr_const (file
, addr
, code
);
3378 output_address (VOIDmode
, addr
);
3385 /* We handle SFmode constants here as output_addr_const doesn't. */
3386 if (GET_MODE (x
) == SFmode
)
3390 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x
), l
);
3391 fprintf (file
, "0x%08lx", l
);
3394 /* Fall through. Let output_addr_const deal with it. */
3397 arc_output_pic_addr_const (file
, x
, code
);
3400 /* FIXME: Dirty way to handle @var@sda+const. Shd be handled
3401 with asm_output_symbol_ref */
3402 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == PLUS
)
3405 output_addr_const (file
, XEXP (x
, 0));
3406 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (XEXP (x
, 0)))
3407 fprintf (file
, "@sda");
3409 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
3410 || INTVAL (XEXP (x
, 1)) >= 0)
3411 fprintf (file
, "+");
3412 output_addr_const (file
, XEXP (x
, 1));
3415 output_addr_const (file
, x
);
3417 if (GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (x
))
3418 fprintf (file
, "@sda");
3423 /* Print a memory address as an operand to reference that memory location. */
3426 arc_print_operand_address (FILE *file
, rtx addr
)
3428 register rtx base
, index
= 0;
3430 switch (GET_CODE (addr
))
3433 fputs (reg_names
[REGNO (addr
)], file
);
3436 output_addr_const (file
, addr
);
3437 if (SYMBOL_REF_SMALL_P (addr
))
3438 fprintf (file
, "@sda");
3441 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3442 index
= XEXP (XEXP (addr
, 0), 0), base
= XEXP (addr
, 1);
3443 else if (CONST_INT_P (XEXP (addr
, 0)))
3444 index
= XEXP (addr
, 0), base
= XEXP (addr
, 1);
3446 base
= XEXP (addr
, 0), index
= XEXP (addr
, 1);
3448 gcc_assert (OBJECT_P (base
));
3449 arc_print_operand_address (file
, base
);
3450 if (CONSTANT_P (base
) && CONST_INT_P (index
))
3454 gcc_assert (OBJECT_P (index
));
3455 arc_print_operand_address (file
, index
);
3459 rtx c
= XEXP (addr
, 0);
3461 gcc_assert (GET_CODE (XEXP (c
, 0)) == SYMBOL_REF
);
3462 gcc_assert (GET_CODE (XEXP (c
, 1)) == CONST_INT
);
3464 output_address (VOIDmode
, XEXP (addr
, 0));
3470 /* We shouldn't get here as we've lost the mode of the memory object
3471 (which says how much to inc/dec by. */
3476 arc_output_pic_addr_const (file
, addr
, 0);
3478 output_addr_const (file
, addr
);
3483 /* Called via walk_stores. DATA points to a hash table we can use to
3484 establish a unique SYMBOL_REF for each counter, which corresponds to
3485 a caller-callee pair.
3486 X is a store which we want to examine for an UNSPEC_PROF, which
3487 would be an address loaded into a register, or directly used in a MEM.
3488 If we found an UNSPEC_PROF, if we encounter a new counter the first time,
3489 write out a description and a data allocation for a 32 bit counter.
3490 Also, fill in the appropriate symbol_ref into each UNSPEC_PROF instance. */
3493 write_profile_sections (rtx dest ATTRIBUTE_UNUSED
, rtx x
, void *data
)
3496 htab_t htab
= (htab_t
) data
;
3499 if (GET_CODE (x
) != SET
)
3501 srcp
= &SET_SRC (x
);
3503 srcp
= &XEXP (*srcp
, 0);
3504 else if (MEM_P (SET_DEST (x
)))
3505 srcp
= &XEXP (SET_DEST (x
), 0);
3507 if (GET_CODE (src
) != CONST
)
3509 src
= XEXP (src
, 0);
3510 if (GET_CODE (src
) != UNSPEC
|| XINT (src
, 1) != UNSPEC_PROF
)
3513 gcc_assert (XVECLEN (src
, 0) == 3);
3514 if (!htab_elements (htab
))
3516 output_asm_insn (".section .__arc_profile_desc, \"a\"\n"
3518 &XVECEXP (src
, 0, 0));
3520 slot
= (rtx
*) htab_find_slot (htab
, src
, INSERT
);
3521 if (*slot
== HTAB_EMPTY_ENTRY
)
3523 static int count_nr
;
3528 sprintf (buf
, "__prof_count%d", count_nr
++);
3529 count
= gen_rtx_SYMBOL_REF (Pmode
, xstrdup (buf
));
3530 XVECEXP (src
, 0, 2) = count
;
3531 output_asm_insn (".section\t.__arc_profile_desc, \"a\"\n"
3533 "\t.section\t.__arc_profile_counters, \"aw\"\n"
3534 "\t.type\t%o2, @object\n"
3537 &XVECEXP (src
, 0, 0));
3541 *srcp
= XVECEXP (*slot
, 0, 2);
3544 /* Hash function for UNSPEC_PROF htab. Use both the caller's name and
3545 the callee's name (if known). */
3548 unspec_prof_hash (const void *x
)
3550 const_rtx u
= (const_rtx
) x
;
3551 const_rtx s1
= XVECEXP (u
, 0, 1);
3553 return (htab_hash_string (XSTR (XVECEXP (u
, 0, 0), 0))
3554 ^ (s1
->code
== SYMBOL_REF
? htab_hash_string (XSTR (s1
, 0)) : 0));
3557 /* Equality function for UNSPEC_PROF htab. Two pieces of UNSPEC_PROF rtl
3558 shall refer to the same counter if both caller name and callee rtl
3562 unspec_prof_htab_eq (const void *x
, const void *y
)
3564 const_rtx u0
= (const_rtx
) x
;
3565 const_rtx u1
= (const_rtx
) y
;
3566 const_rtx s01
= XVECEXP (u0
, 0, 1);
3567 const_rtx s11
= XVECEXP (u1
, 0, 1);
3569 return (!strcmp (XSTR (XVECEXP (u0
, 0, 0), 0),
3570 XSTR (XVECEXP (u1
, 0, 0), 0))
3571 && rtx_equal_p (s01
, s11
));
3574 /* Conditional execution support.
3576 This is based on the ARM port but for now is much simpler.
3578 A finite state machine takes care of noticing whether or not instructions
3579 can be conditionally executed, and thus decrease execution time and code
3580 size by deleting branch instructions. The fsm is controlled by
3581 arc_ccfsm_advance (called by arc_final_prescan_insn), and controls the
3582 actions of PRINT_OPERAND. The patterns in the .md file for the branch
3583 insns also have a hand in this. */
3584 /* The way we leave dealing with non-anulled or annull-false delay slot
3585 insns to the consumer is awkward. */
3587 /* The state of the fsm controlling condition codes are:
3588 0: normal, do nothing special
3589 1: don't output this insn
3590 2: don't output this insn
3591 3: make insns conditional
3592 4: make insns conditional
3593 5: make insn conditional (only for outputting anulled delay slot insns)
3595 special value for cfun->machine->uid_ccfsm_state:
3596 6: return with but one insn before it since function start / call
3598 State transitions (state->state by whom, under what condition):
3599 0 -> 1 arc_ccfsm_advance, if insn is a conditional branch skipping over
3601 0 -> 2 arc_ccfsm_advance, if insn is a conditional branch followed
3602 by zero or more non-jump insns and an unconditional branch with
3603 the same target label as the condbranch.
3604 1 -> 3 branch patterns, after having not output the conditional branch
3605 2 -> 4 branch patterns, after having not output the conditional branch
3606 0 -> 5 branch patterns, for anulled delay slot insn.
3607 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL, if the `target' label is reached
3608 (the target label has CODE_LABEL_NUMBER equal to
3609 arc_ccfsm_target_label).
3610 4 -> 0 arc_ccfsm_advance, if `target' unconditional branch is reached
3611 3 -> 1 arc_ccfsm_advance, finding an 'else' jump skipping over some insns.
3612 5 -> 0 when outputting the delay slot insn
3614 If the jump clobbers the conditions then we use states 2 and 4.
3616 A similar thing can be done with conditional return insns.
3618 We also handle separating branches from sets of the condition code.
3619 This is done here because knowledge of the ccfsm state is required,
3620 we may not be outputting the branch. */
3622 /* arc_final_prescan_insn calls arc_ccfsm_advance to adjust arc_ccfsm_current,
3623 before letting final output INSN. */
3626 arc_ccfsm_advance (rtx_insn
*insn
, struct arc_ccfsm
*state
)
3628 /* BODY will hold the body of INSN. */
3631 /* This will be 1 if trying to repeat the trick (ie: do the `else' part of
3632 an if/then/else), and things need to be reversed. */
3635 /* If we start with a return insn, we only succeed if we find another one. */
3636 int seeking_return
= 0;
3638 /* START_INSN will hold the insn from where we start looking. This is the
3639 first insn after the following code_label if REVERSE is true. */
3640 rtx_insn
*start_insn
= insn
;
3642 /* Type of the jump_insn. Brcc insns don't affect ccfsm changes,
3643 since they don't rely on a cmp preceding the. */
3644 enum attr_type jump_insn_type
;
3646 /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
3647 We can't do this in macro FINAL_PRESCAN_INSN because its called from
3648 final_scan_insn which has `optimize' as a local. */
3649 if (optimize
< 2 || TARGET_NO_COND_EXEC
)
3652 /* Ignore notes and labels. */
3655 body
= PATTERN (insn
);
3656 /* If in state 4, check if the target branch is reached, in order to
3657 change back to state 0. */
3658 if (state
->state
== 4)
3660 if (insn
== state
->target_insn
)
3662 state
->target_insn
= NULL
;
3668 /* If in state 3, it is possible to repeat the trick, if this insn is an
3669 unconditional branch to a label, and immediately following this branch
3670 is the previous target label which is only used once, and the label this
3671 branch jumps to is not too far off. Or in other words "we've done the
3672 `then' part, see if we can do the `else' part." */
3673 if (state
->state
== 3)
3675 if (simplejump_p (insn
))
3677 start_insn
= next_nonnote_insn (start_insn
);
3678 if (GET_CODE (start_insn
) == BARRIER
)
3680 /* ??? Isn't this always a barrier? */
3681 start_insn
= next_nonnote_insn (start_insn
);
3683 if (GET_CODE (start_insn
) == CODE_LABEL
3684 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3685 && LABEL_NUSES (start_insn
) == 1)
3690 else if (GET_CODE (body
) == SIMPLE_RETURN
)
3692 start_insn
= next_nonnote_insn (start_insn
);
3693 if (GET_CODE (start_insn
) == BARRIER
)
3694 start_insn
= next_nonnote_insn (start_insn
);
3695 if (GET_CODE (start_insn
) == CODE_LABEL
3696 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3697 && LABEL_NUSES (start_insn
) == 1)
3709 if (GET_CODE (insn
) != JUMP_INSN
3710 || GET_CODE (PATTERN (insn
)) == ADDR_VEC
3711 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
3714 /* We can't predicate BRCC or loop ends.
3715 Also, when generating PIC code, and considering a medium range call,
3716 we can't predicate the call. */
3717 jump_insn_type
= get_attr_type (insn
);
3718 if (jump_insn_type
== TYPE_BRCC
3719 || jump_insn_type
== TYPE_BRCC_NO_DELAY_SLOT
3720 || jump_insn_type
== TYPE_LOOP_END
3721 || (jump_insn_type
== TYPE_CALL
&& !get_attr_predicable (insn
)))
3724 /* This jump might be paralleled with a clobber of the condition codes,
3725 the jump should always come first. */
3726 if (GET_CODE (body
) == PARALLEL
&& XVECLEN (body
, 0) > 0)
3727 body
= XVECEXP (body
, 0, 0);
3730 || (GET_CODE (body
) == SET
&& GET_CODE (SET_DEST (body
)) == PC
3731 && GET_CODE (SET_SRC (body
)) == IF_THEN_ELSE
))
3733 int insns_skipped
= 0, fail
= FALSE
, succeed
= FALSE
;
3734 /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
3735 int then_not_else
= TRUE
;
3736 /* Nonzero if next insn must be the target label. */
3737 int next_must_be_target_label_p
;
3738 rtx_insn
*this_insn
= start_insn
;
3741 /* Register the insn jumped to. */
3744 if (!seeking_return
)
3745 label
= XEXP (SET_SRC (body
), 0);
3747 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == LABEL_REF
)
3748 label
= XEXP (XEXP (SET_SRC (body
), 1), 0);
3749 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == LABEL_REF
)
3751 label
= XEXP (XEXP (SET_SRC (body
), 2), 0);
3752 then_not_else
= FALSE
;
3754 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == SIMPLE_RETURN
)
3756 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == SIMPLE_RETURN
)
3759 then_not_else
= FALSE
;
3764 /* If this is a non-annulled branch with a delay slot, there is
3765 no need to conditionalize the delay slot. */
3766 if (NEXT_INSN (PREV_INSN (insn
)) != insn
3767 && state
->state
== 0 && !INSN_ANNULLED_BRANCH_P (insn
))
3769 this_insn
= NEXT_INSN (this_insn
);
3770 gcc_assert (NEXT_INSN (NEXT_INSN (PREV_INSN (start_insn
)))
3771 == NEXT_INSN (this_insn
));
3773 /* See how many insns this branch skips, and what kind of insns. If all
3774 insns are okay, and the label or unconditional branch to the same
3775 label is not too far away, succeed. */
3776 for (insns_skipped
= 0, next_must_be_target_label_p
= FALSE
;
3777 !fail
&& !succeed
&& insns_skipped
< MAX_INSNS_SKIPPED
;
3782 this_insn
= next_nonnote_insn (this_insn
);
3786 if (next_must_be_target_label_p
)
3788 if (GET_CODE (this_insn
) == BARRIER
)
3790 if (GET_CODE (this_insn
) == CODE_LABEL
3791 && this_insn
== label
)
3801 scanbody
= PATTERN (this_insn
);
3803 switch (GET_CODE (this_insn
))
3806 /* Succeed if it is the target label, otherwise fail since
3807 control falls in from somewhere else. */
3808 if (this_insn
== label
)
3818 /* Succeed if the following insn is the target label.
3820 If return insns are used then the last insn in a function
3821 will be a barrier. */
3822 next_must_be_target_label_p
= TRUE
;
3826 /* Can handle a call insn if there are no insns after it.
3827 IE: The next "insn" is the target label. We don't have to
3828 worry about delay slots as such insns are SEQUENCE's inside
3829 INSN's. ??? It is possible to handle such insns though. */
3830 if (get_attr_cond (this_insn
) == COND_CANUSE
)
3831 next_must_be_target_label_p
= TRUE
;
3837 /* If this is an unconditional branch to the same label, succeed.
3838 If it is to another label, do nothing. If it is conditional,
3840 /* ??? Probably, the test for the SET and the PC are
3843 if (GET_CODE (scanbody
) == SET
3844 && GET_CODE (SET_DEST (scanbody
)) == PC
)
3846 if (GET_CODE (SET_SRC (scanbody
)) == LABEL_REF
3847 && XEXP (SET_SRC (scanbody
), 0) == label
&& !reverse
)
3852 else if (GET_CODE (SET_SRC (scanbody
)) == IF_THEN_ELSE
)
3854 else if (get_attr_cond (this_insn
) != COND_CANUSE
)
3857 else if (GET_CODE (scanbody
) == SIMPLE_RETURN
3863 else if (GET_CODE (scanbody
) == PARALLEL
)
3865 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3871 /* We can only do this with insns that can use the condition
3872 codes (and don't set them). */
3873 if (GET_CODE (scanbody
) == SET
3874 || GET_CODE (scanbody
) == PARALLEL
)
3876 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3879 /* We can't handle other insns like sequences. */
3891 if ((!seeking_return
) && (state
->state
== 1 || reverse
))
3892 state
->target_label
= CODE_LABEL_NUMBER (label
);
3893 else if (seeking_return
|| state
->state
== 2)
3895 while (this_insn
&& GET_CODE (PATTERN (this_insn
)) == USE
)
3897 this_insn
= next_nonnote_insn (this_insn
);
3899 gcc_assert (!this_insn
||
3900 (GET_CODE (this_insn
) != BARRIER
3901 && GET_CODE (this_insn
) != CODE_LABEL
));
3905 /* Oh dear! we ran off the end, give up. */
3906 extract_insn_cached (insn
);
3908 state
->target_insn
= NULL
;
3911 state
->target_insn
= this_insn
;
3916 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
3920 state
->cond
= XEXP (SET_SRC (body
), 0);
3921 state
->cc
= get_arc_condition_code (XEXP (SET_SRC (body
), 0));
3924 if (reverse
|| then_not_else
)
3925 state
->cc
= ARC_INVERSE_CONDITION_CODE (state
->cc
);
3928 /* Restore recog_operand. Getting the attributes of other insns can
3929 destroy this array, but final.c assumes that it remains intact
3930 across this call; since the insn has been recognized already we
3931 call insn_extract direct. */
3932 extract_insn_cached (insn
);
3936 /* Record that we are currently outputting label NUM with prefix PREFIX.
3937 It it's the label we're looking for, reset the ccfsm machinery.
3939 Called from ASM_OUTPUT_INTERNAL_LABEL. */
3942 arc_ccfsm_at_label (const char *prefix
, int num
, struct arc_ccfsm
*state
)
3944 if (state
->state
== 3 && state
->target_label
== num
3945 && !strcmp (prefix
, "L"))
3948 state
->target_insn
= NULL
;
3952 /* We are considering a conditional branch with the condition COND.
3953 Check if we want to conditionalize a delay slot insn, and if so modify
3954 the ccfsm state accordingly.
3955 REVERSE says branch will branch when the condition is false. */
3957 arc_ccfsm_record_condition (rtx cond
, bool reverse
, rtx_insn
*jump
,
3958 struct arc_ccfsm
*state
)
3960 rtx_insn
*seq_insn
= NEXT_INSN (PREV_INSN (jump
));
3962 state
= &arc_ccfsm_current
;
3964 gcc_assert (state
->state
== 0);
3965 if (seq_insn
!= jump
)
3967 rtx insn
= XVECEXP (PATTERN (seq_insn
), 0, 1);
3969 if (!as_a
<rtx_insn
*> (insn
)->deleted ()
3970 && INSN_ANNULLED_BRANCH_P (jump
)
3971 && (TARGET_AT_DBR_CONDEXEC
|| INSN_FROM_TARGET_P (insn
)))
3974 state
->cc
= get_arc_condition_code (cond
);
3976 arc_ccfsm_current
.cc
3977 = ARC_INVERSE_CONDITION_CODE (state
->cc
);
3978 rtx pat
= PATTERN (insn
);
3979 if (GET_CODE (pat
) == COND_EXEC
)
3980 gcc_assert ((INSN_FROM_TARGET_P (insn
)
3981 ? ARC_INVERSE_CONDITION_CODE (state
->cc
) : state
->cc
)
3982 == get_arc_condition_code (XEXP (pat
, 0)));
3989 /* Update *STATE as we would when we emit INSN. */
3992 arc_ccfsm_post_advance (rtx_insn
*insn
, struct arc_ccfsm
*state
)
3994 enum attr_type type
;
3997 arc_ccfsm_at_label ("L", CODE_LABEL_NUMBER (insn
), state
);
3998 else if (JUMP_P (insn
)
3999 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
4000 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
4001 && ((type
= get_attr_type (insn
)) == TYPE_BRANCH
4002 || (type
== TYPE_UNCOND_BRANCH
4003 /* ??? Maybe should also handle TYPE_RETURN here,
4004 but we don't have a testcase for that. */
4005 && ARC_CCFSM_BRANCH_DELETED_P (state
))))
4007 if (ARC_CCFSM_BRANCH_DELETED_P (state
))
4008 ARC_CCFSM_RECORD_BRANCH_DELETED (state
);
4011 rtx src
= SET_SRC (PATTERN (insn
));
4012 arc_ccfsm_record_condition (XEXP (src
, 0), XEXP (src
, 1) == pc_rtx
,
4016 else if (arc_ccfsm_current
.state
== 5)
4017 arc_ccfsm_current
.state
= 0;
4020 /* Return true if the current insn, which is a conditional branch, is to be
4024 arc_ccfsm_branch_deleted_p (void)
4026 return ARC_CCFSM_BRANCH_DELETED_P (&arc_ccfsm_current
);
4029 /* Record a branch isn't output because subsequent insns can be
4033 arc_ccfsm_record_branch_deleted (void)
4035 ARC_CCFSM_RECORD_BRANCH_DELETED (&arc_ccfsm_current
);
4038 /* During insn output, indicate if the current insn is predicated. */
4041 arc_ccfsm_cond_exec_p (void)
4043 return (cfun
->machine
->prescan_initialized
4044 && ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
));
4047 /* Like next_active_insn, but return NULL if we find an ADDR_(DIFF_)VEC,
4048 and look inside SEQUENCEs. */
4051 arc_next_active_insn (rtx_insn
*insn
, struct arc_ccfsm
*statep
)
4058 arc_ccfsm_post_advance (insn
, statep
);
4059 insn
= NEXT_INSN (insn
);
4060 if (!insn
|| BARRIER_P (insn
))
4063 arc_ccfsm_advance (insn
, statep
);
4065 while (NOTE_P (insn
)
4066 || (cfun
->machine
->arc_reorg_started
4067 && LABEL_P (insn
) && !label_to_alignment (insn
))
4068 || (NONJUMP_INSN_P (insn
)
4069 && (GET_CODE (PATTERN (insn
)) == USE
4070 || GET_CODE (PATTERN (insn
)) == CLOBBER
)));
4071 if (!LABEL_P (insn
))
4073 gcc_assert (INSN_P (insn
));
4074 pat
= PATTERN (insn
);
4075 if (GET_CODE (pat
) == ADDR_VEC
|| GET_CODE (pat
) == ADDR_DIFF_VEC
)
4077 if (GET_CODE (pat
) == SEQUENCE
)
4078 return as_a
<rtx_insn
*> (XVECEXP (pat
, 0, 0));
4083 /* When deciding if an insn should be output short, we want to know something
4084 about the following insns:
4085 - if another insn follows which we know we can output as a short insn
4086 before an alignment-sensitive point, we can output this insn short:
4087 the decision about the eventual alignment can be postponed.
4088 - if a to-be-aligned label comes next, we should output this insn such
4089 as to get / preserve 4-byte alignment.
4090 - if a likely branch without delay slot insn, or a call with an immediately
4091 following short insn comes next, we should out output this insn such as to
4092 get / preserve 2 mod 4 unalignment.
4093 - do the same for a not completely unlikely branch with a short insn
4094 following before any other branch / label.
4095 - in order to decide if we are actually looking at a branch, we need to
4096 call arc_ccfsm_advance.
4097 - in order to decide if we are looking at a short insn, we should know
4098 if it is conditionalized. To a first order of approximation this is
4099 the case if the state from arc_ccfsm_advance from before this insn
4100 indicates the insn is conditionalized. However, a further refinement
4101 could be to not conditionalize an insn if the destination register(s)
4102 is/are dead in the non-executed case. */
4103 /* Return non-zero if INSN should be output as a short insn. UNALIGN is
4104 zero if the current insn is aligned to a 4-byte-boundary, two otherwise.
4105 If CHECK_ATTR is greater than 0, check the iscompact attribute first. */
4108 arc_verify_short (rtx_insn
*insn
, int, int check_attr
)
4110 enum attr_iscompact iscompact
;
4111 struct machine_function
*machine
;
4115 iscompact
= get_attr_iscompact (insn
);
4116 if (iscompact
== ISCOMPACT_FALSE
)
4119 machine
= cfun
->machine
;
4121 if (machine
->force_short_suffix
>= 0)
4122 return machine
->force_short_suffix
;
4124 return (get_attr_length (insn
) & 2) != 0;
4127 /* When outputting an instruction (alternative) that can potentially be short,
4128 output the short suffix if the insn is in fact short, and update
4129 cfun->machine->unalign accordingly. */
4132 output_short_suffix (FILE *file
)
4134 rtx_insn
*insn
= current_output_insn
;
4136 if (arc_verify_short (insn
, cfun
->machine
->unalign
, 1))
4138 fprintf (file
, "_s");
4139 cfun
->machine
->unalign
^= 2;
4141 /* Restore recog_operand. */
4142 extract_insn_cached (insn
);
4145 /* Implement FINAL_PRESCAN_INSN. */
4148 arc_final_prescan_insn (rtx_insn
*insn
, rtx
*opvec ATTRIBUTE_UNUSED
,
4149 int noperands ATTRIBUTE_UNUSED
)
4151 if (TARGET_DUMPISIZE
)
4152 fprintf (asm_out_file
, "\n; at %04x\n", INSN_ADDRESSES (INSN_UID (insn
)));
4154 /* Output a nop if necessary to prevent a hazard.
4155 Don't do this for delay slots: inserting a nop would
4156 alter semantics, and the only time we would find a hazard is for a
4157 call function result - and in that case, the hazard is spurious to
4159 if (PREV_INSN (insn
)
4160 && PREV_INSN (NEXT_INSN (insn
)) == insn
4161 && arc_hazard (prev_real_insn (insn
), insn
))
4163 current_output_insn
=
4164 emit_insn_before (gen_nop (), NEXT_INSN (PREV_INSN (insn
)));
4165 final_scan_insn (current_output_insn
, asm_out_file
, optimize
, 1, NULL
);
4166 current_output_insn
= insn
;
4168 /* Restore extraction data which might have been clobbered by arc_hazard. */
4169 extract_constrain_insn_cached (insn
);
4171 if (!cfun
->machine
->prescan_initialized
)
4173 /* Clear lingering state from branch shortening. */
4174 memset (&arc_ccfsm_current
, 0, sizeof arc_ccfsm_current
);
4175 cfun
->machine
->prescan_initialized
= 1;
4177 arc_ccfsm_advance (insn
, &arc_ccfsm_current
);
4179 cfun
->machine
->size_reason
= 0;
4182 /* Given FROM and TO register numbers, say whether this elimination is allowed.
4183 Frame pointer elimination is automatically handled.
4185 All eliminations are permissible. If we need a frame
4186 pointer, we must eliminate ARG_POINTER_REGNUM into
4187 FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */
4190 arc_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
4192 return to
== FRAME_POINTER_REGNUM
|| !arc_frame_pointer_required ();
4195 /* Define the offset between two registers, one to be eliminated, and
4196 the other its replacement, at the start of a routine. */
4199 arc_initial_elimination_offset (int from
, int to
)
4201 if (! cfun
->machine
->frame_info
.initialized
)
4202 arc_compute_frame_size (get_frame_size ());
4204 if (from
== ARG_POINTER_REGNUM
&& to
== FRAME_POINTER_REGNUM
)
4206 return (cfun
->machine
->frame_info
.extra_size
4207 + cfun
->machine
->frame_info
.reg_size
);
4210 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
4212 return (cfun
->machine
->frame_info
.total_size
4213 - cfun
->machine
->frame_info
.pretend_size
);
4216 if ((from
== FRAME_POINTER_REGNUM
) && (to
== STACK_POINTER_REGNUM
))
4218 return (cfun
->machine
->frame_info
.total_size
4219 - (cfun
->machine
->frame_info
.pretend_size
4220 + cfun
->machine
->frame_info
.extra_size
4221 + cfun
->machine
->frame_info
.reg_size
));
4228 arc_frame_pointer_required (void)
4230 return cfun
->calls_alloca
;
4234 /* Return the destination address of a branch. */
4237 branch_dest (rtx branch
)
4239 rtx pat
= PATTERN (branch
);
4240 rtx dest
= (GET_CODE (pat
) == PARALLEL
4241 ? SET_SRC (XVECEXP (pat
, 0, 0)) : SET_SRC (pat
));
4244 if (GET_CODE (dest
) == IF_THEN_ELSE
)
4245 dest
= XEXP (dest
, XEXP (dest
, 1) == pc_rtx
? 2 : 1);
4247 dest
= XEXP (dest
, 0);
4248 dest_uid
= INSN_UID (dest
);
4250 return INSN_ADDRESSES (dest_uid
);
4254 /* Implement TARGET_ENCODE_SECTION_INFO hook. */
4257 arc_encode_section_info (tree decl
, rtx rtl
, int first
)
4259 /* For sdata, SYMBOL_FLAG_LOCAL and SYMBOL_FLAG_FUNCTION.
4260 This clears machine specific flags, so has to come first. */
4261 default_encode_section_info (decl
, rtl
, first
);
4263 /* Check if it is a function, and whether it has the
4264 [long/medium/short]_call attribute specified. */
4265 if (TREE_CODE (decl
) == FUNCTION_DECL
)
4267 rtx symbol
= XEXP (rtl
, 0);
4268 int flags
= SYMBOL_REF_FLAGS (symbol
);
4270 tree attr
= (TREE_TYPE (decl
) != error_mark_node
4271 ? TYPE_ATTRIBUTES (TREE_TYPE (decl
)) : NULL_TREE
);
4272 tree long_call_attr
= lookup_attribute ("long_call", attr
);
4273 tree medium_call_attr
= lookup_attribute ("medium_call", attr
);
4274 tree short_call_attr
= lookup_attribute ("short_call", attr
);
4276 if (long_call_attr
!= NULL_TREE
)
4277 flags
|= SYMBOL_FLAG_LONG_CALL
;
4278 else if (medium_call_attr
!= NULL_TREE
)
4279 flags
|= SYMBOL_FLAG_MEDIUM_CALL
;
4280 else if (short_call_attr
!= NULL_TREE
)
4281 flags
|= SYMBOL_FLAG_SHORT_CALL
;
4283 SYMBOL_REF_FLAGS (symbol
) = flags
;
4287 /* This is how to output a definition of an internal numbered label where
4288 PREFIX is the class of label and NUM is the number within the class. */
4290 static void arc_internal_label (FILE *stream
, const char *prefix
, unsigned long labelno
)
4293 arc_ccfsm_at_label (prefix
, labelno
, &arc_ccfsm_current
);
4294 default_internal_label (stream
, prefix
, labelno
);
4297 /* Set the cpu type and print out other fancy things,
4298 at the top of the file. */
4300 static void arc_file_start (void)
4302 default_file_start ();
4303 fprintf (asm_out_file
, "\t.cpu %s\n", arc_cpu_string
);
4306 /* Cost functions. */
4308 /* Compute a (partial) cost for rtx X. Return true if the complete
4309 cost has been computed, and false if subexpressions should be
4310 scanned. In either case, *TOTAL contains the cost result. */
4313 arc_rtx_costs (rtx x
, machine_mode mode
, int outer_code
,
4314 int opno ATTRIBUTE_UNUSED
, int *total
, bool speed
)
4316 int code
= GET_CODE (x
);
4320 /* Small integers are as cheap as registers. */
4323 bool nolimm
= false; /* Can we do without long immediate? */
4324 bool fast
= false; /* Is the result available immediately? */
4325 bool condexec
= false; /* Does this allow conditiobnal execution? */
4326 bool compact
= false; /* Is a 16 bit opcode available? */
4327 /* CONDEXEC also implies that we can have an unconditional
4328 3-address operation. */
4330 nolimm
= compact
= condexec
= false;
4331 if (UNSIGNED_INT6 (INTVAL (x
)))
4332 nolimm
= condexec
= compact
= true;
4335 if (SMALL_INT (INTVAL (x
)))
4336 nolimm
= fast
= true;
4339 case AND
: /* bclr, bmsk, ext[bw] */
4340 if (satisfies_constraint_Ccp (x
) /* bclr */
4341 || satisfies_constraint_C1p (x
) /* bmsk */)
4342 nolimm
= fast
= condexec
= compact
= true;
4344 case IOR
: /* bset */
4345 if (satisfies_constraint_C0p (x
)) /* bset */
4346 nolimm
= fast
= condexec
= compact
= true;
4349 if (satisfies_constraint_C0p (x
)) /* bxor */
4350 nolimm
= fast
= condexec
= true;
4353 if (satisfies_constraint_Crr (x
)) /* ror b,u6 */
4359 /* FIXME: Add target options to attach a small cost if
4360 condexec / compact is not true. */
4369 /* 4 byte values can be fetched as immediate constants -
4370 let's give that the cost of an extra insn. */
4374 *total
= COSTS_N_INSNS (1);
4383 *total
= COSTS_N_INSNS (1);
4386 /* FIXME: correct the order of high,low */
4387 split_double (x
, &high
, &low
);
4388 *total
= COSTS_N_INSNS (!SMALL_INT (INTVAL (high
))
4389 + !SMALL_INT (INTVAL (low
)));
4393 /* Encourage synth_mult to find a synthetic multiply when reasonable.
4394 If we need more than 12 insns to do a multiply, then go out-of-line,
4395 since the call overhead will be < 10% of the cost of the multiply. */
4399 if (TARGET_BARREL_SHIFTER
)
4401 /* If we want to shift a constant, we need a LIMM. */
4402 /* ??? when the optimizers want to know if a constant should be
4403 hoisted, they ask for the cost of the constant. OUTER_CODE is
4404 insufficient context for shifts since we don't know which operand
4405 we are looking at. */
4406 if (CONSTANT_P (XEXP (x
, 0)))
4408 *total
+= (COSTS_N_INSNS (2)
4409 + rtx_cost (XEXP (x
, 1), mode
, (enum rtx_code
) code
,
4413 *total
= COSTS_N_INSNS (1);
4415 else if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4416 *total
= COSTS_N_INSNS (16);
4419 *total
= COSTS_N_INSNS (INTVAL (XEXP ((x
), 1)));
4420 /* ??? want_to_gcse_p can throw negative shift counts at us,
4421 and then panics when it gets a negative cost as result.
4422 Seen for gcc.c-torture/compile/20020710-1.c -Os . */
4431 *total
= COSTS_N_INSNS(30);
4433 *total
= COSTS_N_INSNS(1);
4437 if ((TARGET_DPFP
&& GET_MODE (x
) == DFmode
))
4438 *total
= COSTS_N_INSNS (1);
4440 *total
= arc_multcost
;
4441 /* We do not want synth_mult sequences when optimizing
4443 else if (TARGET_MUL64_SET
|| TARGET_ARC700_MPY
)
4444 *total
= COSTS_N_INSNS (1);
4446 *total
= COSTS_N_INSNS (2);
4449 if (GET_CODE (XEXP (x
, 0)) == MULT
4450 && _2_4_8_operand (XEXP (XEXP (x
, 0), 1), VOIDmode
))
4452 *total
+= (rtx_cost (XEXP (x
, 1), mode
, PLUS
, 0, speed
)
4453 + rtx_cost (XEXP (XEXP (x
, 0), 0), mode
, PLUS
, 1, speed
));
4458 if (GET_CODE (XEXP (x
, 1)) == MULT
4459 && _2_4_8_operand (XEXP (XEXP (x
, 1), 1), VOIDmode
))
4461 *total
+= (rtx_cost (XEXP (x
, 0), mode
, PLUS
, 0, speed
)
4462 + rtx_cost (XEXP (XEXP (x
, 1), 0), mode
, PLUS
, 1, speed
));
4468 rtx op0
= XEXP (x
, 0);
4469 rtx op1
= XEXP (x
, 1);
4471 if (GET_CODE (op0
) == ZERO_EXTRACT
&& op1
== const0_rtx
4472 && XEXP (op0
, 1) == const1_rtx
)
4474 /* btst / bbit0 / bbit1:
4475 Small integers and registers are free; everything else can
4476 be put in a register. */
4477 mode
= GET_MODE (XEXP (op0
, 0));
4478 *total
= (rtx_cost (XEXP (op0
, 0), mode
, SET
, 1, speed
)
4479 + rtx_cost (XEXP (op0
, 2), mode
, SET
, 1, speed
));
4482 if (GET_CODE (op0
) == AND
&& op1
== const0_rtx
4483 && satisfies_constraint_C1p (XEXP (op0
, 1)))
4486 *total
= rtx_cost (XEXP (op0
, 0), VOIDmode
, SET
, 1, speed
);
4490 if (GET_CODE (op1
) == NEG
)
4492 /* op0 might be constant, the inside of op1 is rather
4493 unlikely to be so. So swapping the operands might lower
4495 mode
= GET_MODE (op0
);
4496 *total
= (rtx_cost (op0
, mode
, PLUS
, 1, speed
)
4497 + rtx_cost (XEXP (op1
, 0), mode
, PLUS
, 0, speed
));
4502 if (outer_code
== IF_THEN_ELSE
4503 && GET_CODE (XEXP (x
, 0)) == ZERO_EXTRACT
4504 && XEXP (x
, 1) == const0_rtx
4505 && XEXP (XEXP (x
, 0), 1) == const1_rtx
)
4507 /* btst / bbit0 / bbit1:
4508 Small integers and registers are free; everything else can
4509 be put in a register. */
4510 rtx op0
= XEXP (x
, 0);
4512 mode
= GET_MODE (XEXP (op0
, 0));
4513 *total
= (rtx_cost (XEXP (op0
, 0), mode
, SET
, 1, speed
)
4514 + rtx_cost (XEXP (op0
, 2), mode
, SET
, 1, speed
));
4518 /* scc_insn expands into two insns. */
4519 case GTU
: case GEU
: case LEU
:
4521 *total
+= COSTS_N_INSNS (1);
4523 case LTU
: /* might use adc. */
4525 *total
+= COSTS_N_INSNS (1) - 1;
4532 /* Return true if ADDR is an address that needs to be expressed as an
4533 explicit sum of pcl + offset. */
4536 arc_legitimate_pc_offset_p (rtx addr
)
4538 if (GET_CODE (addr
) != CONST
)
4540 addr
= XEXP (addr
, 0);
4541 if (GET_CODE (addr
) == PLUS
)
4543 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4545 addr
= XEXP (addr
, 0);
4547 return (GET_CODE (addr
) == UNSPEC
4548 && XVECLEN (addr
, 0) == 1
4549 && XINT (addr
, 1) == ARC_UNSPEC_GOT
4550 && GET_CODE (XVECEXP (addr
, 0, 0)) == SYMBOL_REF
);
4553 /* Return true if ADDR is a valid pic address.
4554 A valid pic address on arc should look like
4555 const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT)) */
4558 arc_legitimate_pic_addr_p (rtx addr
)
4560 if (GET_CODE (addr
) == LABEL_REF
)
4562 if (GET_CODE (addr
) != CONST
)
4565 addr
= XEXP (addr
, 0);
4568 if (GET_CODE (addr
) == PLUS
)
4570 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4572 addr
= XEXP (addr
, 0);
4575 if (GET_CODE (addr
) != UNSPEC
4576 || XVECLEN (addr
, 0) != 1)
4579 /* Must be @GOT or @GOTOFF. */
4580 if (XINT (addr
, 1) != ARC_UNSPEC_GOT
4581 && XINT (addr
, 1) != ARC_UNSPEC_GOTOFF
)
4584 if (GET_CODE (XVECEXP (addr
, 0, 0)) != SYMBOL_REF
4585 && GET_CODE (XVECEXP (addr
, 0, 0)) != LABEL_REF
)
4593 /* Return true if OP contains a symbol reference. */
4596 symbolic_reference_mentioned_p (rtx op
)
4598 register const char *fmt
;
4601 if (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == LABEL_REF
)
4604 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4605 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4611 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4612 if (symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
)))
4616 else if (fmt
[i
] == 'e' && symbolic_reference_mentioned_p (XEXP (op
, i
)))
4623 /* Return true if OP contains a SYMBOL_REF that is not wrapped in an unspec.
4624 If SKIP_LOCAL is true, skip symbols that bind locally.
4625 This is used further down in this file, and, without SKIP_LOCAL,
4626 in the addsi3 / subsi3 expanders when generating PIC code. */
4629 arc_raw_symbolic_reference_mentioned_p (rtx op
, bool skip_local
)
4631 register const char *fmt
;
4634 if (GET_CODE(op
) == UNSPEC
)
4637 if (GET_CODE (op
) == SYMBOL_REF
)
4639 tree decl
= SYMBOL_REF_DECL (op
);
4640 return !skip_local
|| !decl
|| !default_binds_local_p (decl
);
4643 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4644 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4650 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4651 if (arc_raw_symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
),
4656 else if (fmt
[i
] == 'e'
4657 && arc_raw_symbolic_reference_mentioned_p (XEXP (op
, i
),
4665 /* Legitimize a pic address reference in ORIG.
4666 The return value is the legitimated address.
4667 If OLDX is non-zero, it is the target to assign the address to first. */
4670 arc_legitimize_pic_address (rtx orig
, rtx oldx
)
4679 if (GET_CODE (addr
) == LABEL_REF
)
4681 else if (GET_CODE (addr
) == SYMBOL_REF
4682 && (CONSTANT_POOL_ADDRESS_P (addr
)
4683 || SYMBOL_REF_LOCAL_P (addr
)))
4685 /* This symbol may be referenced via a displacement from the PIC
4686 base address (@GOTOFF). */
4688 /* FIXME: if we had a way to emit pc-relative adds that don't
4689 create a GOT entry, we could do without the use of the gp register. */
4690 crtl
->uses_pic_offset_table
= 1;
4691 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOTOFF
);
4692 pat
= gen_rtx_CONST (Pmode
, pat
);
4693 pat
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, pat
);
4696 oldx
= gen_reg_rtx (Pmode
);
4700 emit_move_insn (oldx
, pat
);
4705 else if (GET_CODE (addr
) == SYMBOL_REF
)
4707 /* This symbol must be referenced via a load from the
4708 Global Offset Table (@GOTPC). */
4710 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOT
);
4711 pat
= gen_rtx_CONST (Pmode
, pat
);
4712 pat
= gen_const_mem (Pmode
, pat
);
4715 oldx
= gen_reg_rtx (Pmode
);
4717 emit_move_insn (oldx
, pat
);
4722 if (GET_CODE (addr
) == CONST
)
4724 addr
= XEXP (addr
, 0);
4725 if (GET_CODE (addr
) == UNSPEC
)
4727 /* Check that the unspec is one of the ones we generate? */
4730 gcc_assert (GET_CODE (addr
) == PLUS
);
4733 if (GET_CODE (addr
) == PLUS
)
4735 rtx op0
= XEXP (addr
, 0), op1
= XEXP (addr
, 1);
4737 /* Check first to see if this is a constant offset from a @GOTOFF
4738 symbol reference. */
4739 if ((GET_CODE (op0
) == LABEL_REF
4740 || (GET_CODE (op0
) == SYMBOL_REF
4741 && (CONSTANT_POOL_ADDRESS_P (op0
)
4742 || SYMBOL_REF_LOCAL_P (op0
))))
4743 && GET_CODE (op1
) == CONST_INT
)
4745 /* FIXME: like above, could do without gp reference. */
4746 crtl
->uses_pic_offset_table
= 1;
4748 = gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, op0
), ARC_UNSPEC_GOTOFF
);
4749 pat
= gen_rtx_PLUS (Pmode
, pat
, op1
);
4750 pat
= gen_rtx_CONST (Pmode
, pat
);
4751 pat
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, pat
);
4755 emit_move_insn (oldx
, pat
);
4761 base
= arc_legitimize_pic_address (XEXP (addr
, 0), oldx
);
4762 pat
= arc_legitimize_pic_address (XEXP (addr
, 1),
4763 base
== oldx
? NULL_RTX
: oldx
);
4765 if (GET_CODE (pat
) == CONST_INT
)
4766 pat
= plus_constant (Pmode
, base
, INTVAL (pat
));
4769 if (GET_CODE (pat
) == PLUS
&& CONSTANT_P (XEXP (pat
, 1)))
4771 base
= gen_rtx_PLUS (Pmode
, base
, XEXP (pat
, 0));
4772 pat
= XEXP (pat
, 1);
4774 pat
= gen_rtx_PLUS (Pmode
, base
, pat
);
4783 /* Output address constant X to FILE, taking PIC into account. */
4786 arc_output_pic_addr_const (FILE * file
, rtx x
, int code
)
4791 switch (GET_CODE (x
))
4801 output_addr_const (file
, x
);
4803 /* Local functions do not get references through the PLT. */
4804 if (code
== 'P' && ! SYMBOL_REF_LOCAL_P (x
))
4805 fputs ("@plt", file
);
4809 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (XEXP (x
, 0)));
4810 assemble_name (file
, buf
);
4814 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (x
));
4815 assemble_name (file
, buf
);
4819 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
));
4823 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4827 if (GET_MODE (x
) == VOIDmode
)
4829 /* We can use %d if the number is one word and positive. */
4830 if (CONST_DOUBLE_HIGH (x
))
4831 fprintf (file
, HOST_WIDE_INT_PRINT_DOUBLE_HEX
,
4832 CONST_DOUBLE_HIGH (x
), CONST_DOUBLE_LOW (x
));
4833 else if (CONST_DOUBLE_LOW (x
) < 0)
4834 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, CONST_DOUBLE_LOW (x
));
4836 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, CONST_DOUBLE_LOW (x
));
4839 /* We can't handle floating point constants;
4840 PRINT_OPERAND must handle them. */
4841 output_operand_lossage ("floating constant misused");
4845 /* FIXME: Not needed here. */
4846 /* Some assemblers need integer constants to appear last (eg masm). */
4847 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
4849 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4850 fprintf (file
, "+");
4851 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4853 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
4855 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4856 if (INTVAL (XEXP (x
, 1)) >= 0)
4857 fprintf (file
, "+");
4858 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4865 /* Avoid outputting things like x-x or x+5-x,
4866 since some assemblers can't handle that. */
4867 x
= simplify_subtraction (x
);
4868 if (GET_CODE (x
) != MINUS
)
4871 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4872 fprintf (file
, "-");
4873 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
4874 && INTVAL (XEXP (x
, 1)) < 0)
4876 fprintf (file
, "(");
4877 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4878 fprintf (file
, ")");
4881 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4886 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4891 gcc_assert (XVECLEN (x
, 0) == 1);
4892 if (XINT (x
, 1) == ARC_UNSPEC_GOT
)
4893 fputs ("pcl,", file
);
4894 arc_output_pic_addr_const (file
, XVECEXP (x
, 0, 0), code
);
4895 switch (XINT (x
, 1))
4897 case ARC_UNSPEC_GOT
:
4898 fputs ("@gotpc", file
);
4900 case ARC_UNSPEC_GOTOFF
:
4901 fputs ("@gotoff", file
);
4903 case ARC_UNSPEC_PLT
:
4904 fputs ("@plt", file
);
4907 output_operand_lossage ("invalid UNSPEC as operand: %d", XINT (x
,1));
4913 output_operand_lossage ("invalid expression as operand");
4917 #define SYMBOLIC_CONST(X) \
4918 (GET_CODE (X) == SYMBOL_REF \
4919 || GET_CODE (X) == LABEL_REF \
4920 || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
4922 /* Emit insns to move operands[1] into operands[0]. */
4925 emit_pic_move (rtx
*operands
, machine_mode
)
4927 rtx temp
= reload_in_progress
? operands
[0] : gen_reg_rtx (Pmode
);
4929 if (GET_CODE (operands
[0]) == MEM
&& SYMBOLIC_CONST (operands
[1]))
4930 operands
[1] = force_reg (Pmode
, operands
[1]);
4932 operands
[1] = arc_legitimize_pic_address (operands
[1], temp
);
4936 /* The function returning the number of words, at the beginning of an
4937 argument, must be put in registers. The returned value must be
4938 zero for arguments that are passed entirely in registers or that
4939 are entirely pushed on the stack.
4941 On some machines, certain arguments must be passed partially in
4942 registers and partially in memory. On these machines, typically
4943 the first N words of arguments are passed in registers, and the
4944 rest on the stack. If a multi-word argument (a `double' or a
4945 structure) crosses that boundary, its first few words must be
4946 passed in registers and the rest must be pushed. This function
4947 tells the compiler when this occurs, and how many of the words
4948 should go in registers.
4950 `FUNCTION_ARG' for these arguments should return the first register
4951 to be used by the caller for this argument; likewise
4952 `FUNCTION_INCOMING_ARG', for the called function.
4954 The function is used to implement macro FUNCTION_ARG_PARTIAL_NREGS. */
4956 /* If REGNO is the least arg reg available then what is the total number of arg
4958 #define GPR_REST_ARG_REGS(REGNO) \
4959 ((REGNO) <= MAX_ARC_PARM_REGS ? MAX_ARC_PARM_REGS - (REGNO) : 0 )
4961 /* Since arc parm regs are contiguous. */
4962 #define ARC_NEXT_ARG_REG(REGNO) ( (REGNO) + 1 )
4964 /* Implement TARGET_ARG_PARTIAL_BYTES. */
4967 arc_arg_partial_bytes (cumulative_args_t cum_v
, machine_mode mode
,
4968 tree type
, bool named ATTRIBUTE_UNUSED
)
4970 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4971 int bytes
= (mode
== BLKmode
4972 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
4973 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
4977 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
4978 ret
= GPR_REST_ARG_REGS (arg_num
);
4980 /* ICEd at function.c:2361, and ret is copied to data->partial */
4981 ret
= (ret
>= words
? 0 : ret
* UNITS_PER_WORD
);
4988 /* This function is used to control a function argument is passed in a
4989 register, and which register.
4991 The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes
4992 (in a way defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE)
4993 all of the previous arguments so far passed in registers; MODE, the
4994 machine mode of the argument; TYPE, the data type of the argument
4995 as a tree node or 0 if that is not known (which happens for C
4996 support library functions); and NAMED, which is 1 for an ordinary
4997 argument and 0 for nameless arguments that correspond to `...' in
4998 the called function's prototype.
5000 The returned value should either be a `reg' RTX for the hard
5001 register in which to pass the argument, or zero to pass the
5002 argument on the stack.
5004 For machines like the Vax and 68000, where normally all arguments
5005 are pushed, zero suffices as a definition.
5007 The usual way to make the ANSI library `stdarg.h' work on a machine
5008 where some arguments are usually passed in registers, is to cause
5009 nameless arguments to be passed on the stack instead. This is done
5010 by making the function return 0 whenever NAMED is 0.
5012 You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the
5013 definition of this function to determine if this argument is of a
5014 type that must be passed in the stack. If `REG_PARM_STACK_SPACE'
5015 is not defined and the function returns non-zero for such an
5016 argument, the compiler will abort. If `REG_PARM_STACK_SPACE' is
5017 defined, the argument will be computed in the stack and then loaded
5020 The function is used to implement macro FUNCTION_ARG. */
5021 /* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers
5022 and the rest are pushed. */
5025 arc_function_arg (cumulative_args_t cum_v
, machine_mode mode
,
5026 const_tree type ATTRIBUTE_UNUSED
, bool named ATTRIBUTE_UNUSED
)
5028 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
5031 const char *debstr ATTRIBUTE_UNUSED
;
5033 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
5034 /* Return a marker for use in the call instruction. */
5035 if (mode
== VOIDmode
)
5040 else if (GPR_REST_ARG_REGS (arg_num
) > 0)
5042 ret
= gen_rtx_REG (mode
, arg_num
);
5043 debstr
= reg_names
[arg_num
];
5053 /* The function to update the summarizer variable *CUM to advance past
5054 an argument in the argument list. The values MODE, TYPE and NAMED
5055 describe that argument. Once this is done, the variable *CUM is
5056 suitable for analyzing the *following* argument with
5057 `FUNCTION_ARG', etc.
5059 This function need not do anything if the argument in question was
5060 passed on the stack. The compiler knows how to track the amount of
5061 stack space used for arguments without any special help.
5063 The function is used to implement macro FUNCTION_ARG_ADVANCE. */
5064 /* For the ARC: the cum set here is passed on to function_arg where we
5065 look at its value and say which reg to use. Strategy: advance the
5066 regnumber here till we run out of arg regs, then set *cum to last
5067 reg. In function_arg, since *cum > last arg reg we would return 0
5068 and thus the arg will end up on the stack. For straddling args of
5069 course function_arg_partial_nregs will come into play. */
5072 arc_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
,
5073 const_tree type
, bool named ATTRIBUTE_UNUSED
)
5075 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
5076 int bytes
= (mode
== BLKmode
5077 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
5078 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
5082 *cum
= ROUND_ADVANCE_CUM (*cum
, mode
, type
);
5083 for (i
= 0; i
< words
; i
++)
5084 *cum
= ARC_NEXT_ARG_REG (*cum
);
5088 /* Define how to find the value returned by a function.
5089 VALTYPE is the data type of the value (as a tree).
5090 If the precise function being called is known, FN_DECL_OR_TYPE is its
5091 FUNCTION_DECL; otherwise, FN_DECL_OR_TYPE is its type. */
5094 arc_function_value (const_tree valtype
,
5095 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
5096 bool outgoing ATTRIBUTE_UNUSED
)
5098 machine_mode mode
= TYPE_MODE (valtype
);
5099 int unsignedp ATTRIBUTE_UNUSED
;
5101 unsignedp
= TYPE_UNSIGNED (valtype
);
5102 if (INTEGRAL_TYPE_P (valtype
) || TREE_CODE (valtype
) == OFFSET_TYPE
)
5103 PROMOTE_MODE (mode
, unsignedp
, valtype
);
5104 return gen_rtx_REG (mode
, 0);
5107 /* Returns the return address that is used by builtin_return_address. */
5110 arc_return_addr_rtx (int count
, ATTRIBUTE_UNUSED rtx frame
)
5115 return get_hard_reg_initial_val (Pmode
, RETURN_ADDR_REGNUM
);
5118 /* Nonzero if the constant value X is a legitimate general operand
5119 when generating PIC code. It is given that flag_pic is on and
5120 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
5123 arc_legitimate_pic_operand_p (rtx x
)
5125 return !arc_raw_symbolic_reference_mentioned_p (x
, true);
5128 /* Determine if a given RTX is a valid constant. We already know this
5129 satisfies CONSTANT_P. */
5132 arc_legitimate_constant_p (machine_mode
, rtx x
)
5137 switch (GET_CODE (x
))
5142 if (GET_CODE (x
) == PLUS
)
5144 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5149 /* Only some unspecs are valid as "constants". */
5150 if (GET_CODE (x
) == UNSPEC
)
5151 switch (XINT (x
, 1))
5153 case ARC_UNSPEC_PLT
:
5154 case ARC_UNSPEC_GOTOFF
:
5155 case ARC_UNSPEC_GOT
:
5163 /* We must have drilled down to a symbol. */
5164 if (arc_raw_symbolic_reference_mentioned_p (x
, false))
5178 /* Otherwise we handle everything else in the move patterns. */
5183 arc_legitimate_address_p (machine_mode mode
, rtx x
, bool strict
)
5185 if (RTX_OK_FOR_BASE_P (x
, strict
))
5187 if (LEGITIMATE_OFFSET_ADDRESS_P (mode
, x
, TARGET_INDEXED_LOADS
, strict
))
5189 if (LEGITIMATE_SCALED_ADDRESS_P (mode
, x
, strict
))
5191 if (LEGITIMATE_SMALL_DATA_ADDRESS_P (x
))
5193 if (GET_CODE (x
) == CONST_INT
&& LARGE_INT (INTVAL (x
)))
5195 if ((GET_MODE_SIZE (mode
) != 16)
5196 && (GET_CODE (x
) == SYMBOL_REF
5197 || GET_CODE (x
) == LABEL_REF
5198 || GET_CODE (x
) == CONST
))
5200 if (!flag_pic
|| arc_legitimate_pic_addr_p (x
))
5203 if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == PRE_INC
5204 || GET_CODE (x
) == POST_DEC
|| GET_CODE (x
) == POST_INC
)
5205 && RTX_OK_FOR_BASE_P (XEXP (x
, 0), strict
))
5207 /* We're restricted here by the `st' insn. */
5208 if ((GET_CODE (x
) == PRE_MODIFY
|| GET_CODE (x
) == POST_MODIFY
)
5209 && GET_CODE (XEXP ((x
), 1)) == PLUS
5210 && rtx_equal_p (XEXP ((x
), 0), XEXP (XEXP (x
, 1), 0))
5211 && LEGITIMATE_OFFSET_ADDRESS_P (QImode
, XEXP (x
, 1),
5212 TARGET_AUTO_MODIFY_REG
, strict
))
5217 /* Return true iff ADDR (a legitimate address expression)
5218 has an effect that depends on the machine mode it is used for. */
5221 arc_mode_dependent_address_p (const_rtx addr
, addr_space_t
)
5223 /* SYMBOL_REF is not mode dependent: it is either a small data reference,
5224 which is valid for loads and stores, or a limm offset, which is valid for
5226 /* Scaled indices are scaled by the access mode; likewise for scaled
5227 offsets, which are needed for maximum offset stores. */
5228 if (GET_CODE (addr
) == PLUS
5229 && (GET_CODE (XEXP ((addr
), 0)) == MULT
5230 || (CONST_INT_P (XEXP ((addr
), 1))
5231 && !SMALL_INT (INTVAL (XEXP ((addr
), 1))))))
5236 /* Determine if it's legal to put X into the constant pool. */
5239 arc_cannot_force_const_mem (machine_mode mode
, rtx x
)
5241 return !arc_legitimate_constant_p (mode
, x
);
5245 /* Generic function to define a builtin. */
5246 #define def_mbuiltin(MASK, NAME, TYPE, CODE) \
5250 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE); \
5256 arc_init_builtins (void)
5258 tree endlink
= void_list_node
;
5260 tree void_ftype_void
5261 = build_function_type (void_type_node
,
5265 = build_function_type (integer_type_node
,
5266 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
5268 tree pcvoid_type_node
5269 = build_pointer_type (build_qualified_type (void_type_node
, TYPE_QUAL_CONST
));
5270 tree int_ftype_pcvoid_int
5271 = build_function_type (integer_type_node
,
5272 tree_cons (NULL_TREE
, pcvoid_type_node
,
5273 tree_cons (NULL_TREE
, integer_type_node
,
5276 tree int_ftype_short_int
5277 = build_function_type (integer_type_node
,
5278 tree_cons (NULL_TREE
, short_integer_type_node
, endlink
));
5280 tree void_ftype_int_int
5281 = build_function_type (void_type_node
,
5282 tree_cons (NULL_TREE
, integer_type_node
,
5283 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5284 tree void_ftype_usint_usint
5285 = build_function_type (void_type_node
,
5286 tree_cons (NULL_TREE
, long_unsigned_type_node
,
5287 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
)));
5289 tree int_ftype_int_int
5290 = build_function_type (integer_type_node
,
5291 tree_cons (NULL_TREE
, integer_type_node
,
5292 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5294 tree usint_ftype_usint
5295 = build_function_type (long_unsigned_type_node
,
5296 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5298 tree void_ftype_usint
5299 = build_function_type (void_type_node
,
5300 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5302 /* Add the builtins. */
5303 def_mbuiltin (1,"__builtin_arc_nop", void_ftype_void
, ARC_BUILTIN_NOP
);
5304 def_mbuiltin (TARGET_NORM
, "__builtin_arc_norm", int_ftype_int
, ARC_BUILTIN_NORM
);
5305 def_mbuiltin (TARGET_NORM
, "__builtin_arc_normw", int_ftype_short_int
, ARC_BUILTIN_NORMW
);
5306 def_mbuiltin (TARGET_SWAP
, "__builtin_arc_swap", int_ftype_int
, ARC_BUILTIN_SWAP
);
5307 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mul64", void_ftype_int_int
, ARC_BUILTIN_MUL64
);
5308 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mulu64", void_ftype_usint_usint
, ARC_BUILTIN_MULU64
);
5309 def_mbuiltin (1,"__builtin_arc_rtie", void_ftype_void
, ARC_BUILTIN_RTIE
);
5310 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_sync", void_ftype_void
, ARC_BUILTIN_SYNC
);
5311 def_mbuiltin ((TARGET_EA_SET
),"__builtin_arc_divaw", int_ftype_int_int
, ARC_BUILTIN_DIVAW
);
5312 def_mbuiltin (1,"__builtin_arc_brk", void_ftype_void
, ARC_BUILTIN_BRK
);
5313 def_mbuiltin (1,"__builtin_arc_flag", void_ftype_usint
, ARC_BUILTIN_FLAG
);
5314 def_mbuiltin (1,"__builtin_arc_sleep", void_ftype_usint
, ARC_BUILTIN_SLEEP
);
5315 def_mbuiltin (1,"__builtin_arc_swi", void_ftype_void
, ARC_BUILTIN_SWI
);
5316 def_mbuiltin (1,"__builtin_arc_core_read", usint_ftype_usint
, ARC_BUILTIN_CORE_READ
);
5317 def_mbuiltin (1,"__builtin_arc_core_write", void_ftype_usint_usint
, ARC_BUILTIN_CORE_WRITE
);
5318 def_mbuiltin (1,"__builtin_arc_lr", usint_ftype_usint
, ARC_BUILTIN_LR
);
5319 def_mbuiltin (1,"__builtin_arc_sr", void_ftype_usint_usint
, ARC_BUILTIN_SR
);
5320 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_trap_s", void_ftype_usint
, ARC_BUILTIN_TRAP_S
);
5321 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_unimp_s", void_ftype_void
, ARC_BUILTIN_UNIMP_S
);
5322 def_mbuiltin (1,"__builtin_arc_aligned", int_ftype_pcvoid_int
, ARC_BUILTIN_ALIGNED
);
5324 if (TARGET_SIMD_SET
)
5325 arc_init_simd_builtins ();
5328 static rtx
arc_expand_simd_builtin (tree
, rtx
, rtx
, machine_mode
, int);
5330 /* Expand an expression EXP that calls a built-in function,
5331 with result going to TARGET if that's convenient
5332 (and in mode MODE if that's convenient).
5333 SUBTARGET may be used as the target for computing one of EXP's operands.
5334 IGNORE is nonzero if the value is to be ignored. */
5337 arc_expand_builtin (tree exp
,
5343 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
5348 int fcode
= DECL_FUNCTION_CODE (fndecl
);
5353 if (fcode
> ARC_SIMD_BUILTIN_BEGIN
&& fcode
< ARC_SIMD_BUILTIN_END
)
5354 return arc_expand_simd_builtin (exp
, target
, subtarget
, mode
, ignore
);
5358 case ARC_BUILTIN_NOP
:
5359 emit_insn (gen_nop ());
5362 case ARC_BUILTIN_NORM
:
5363 icode
= CODE_FOR_clrsbsi2
;
5364 arg0
= CALL_EXPR_ARG (exp
, 0);
5365 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5366 mode0
= insn_data
[icode
].operand
[1].mode
;
5367 target
= gen_reg_rtx (SImode
);
5369 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5370 op0
= copy_to_mode_reg (mode0
, op0
);
5372 emit_insn (gen_clrsbsi2 (target
, op0
));
5375 case ARC_BUILTIN_NORMW
:
5377 /* FIXME : This should all be HImode, not SImode. */
5378 icode
= CODE_FOR_normw
;
5379 arg0
= CALL_EXPR_ARG (exp
, 0);
5380 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5381 mode0
= insn_data
[icode
].operand
[1].mode
;
5382 target
= gen_reg_rtx (SImode
);
5384 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5385 op0
= copy_to_mode_reg (mode0
, convert_to_mode (mode0
, op0
,0));
5387 emit_insn (gen_normw (target
, op0
));
5390 case ARC_BUILTIN_MUL64
:
5391 icode
= CODE_FOR_mul64
;
5392 arg0
= CALL_EXPR_ARG (exp
, 0);
5393 arg1
= CALL_EXPR_ARG (exp
, 1);
5394 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5395 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5397 mode0
= insn_data
[icode
].operand
[0].mode
;
5398 mode1
= insn_data
[icode
].operand
[1].mode
;
5400 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5401 op0
= copy_to_mode_reg (mode0
, op0
);
5403 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5404 op1
= copy_to_mode_reg (mode1
, op1
);
5406 emit_insn (gen_mul64 (op0
,op1
));
5409 case ARC_BUILTIN_MULU64
:
5410 icode
= CODE_FOR_mulu64
;
5411 arg0
= CALL_EXPR_ARG (exp
, 0);
5412 arg1
= CALL_EXPR_ARG (exp
, 1);
5413 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5414 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5416 mode0
= insn_data
[icode
].operand
[0].mode
;
5417 mode1
= insn_data
[icode
].operand
[1].mode
;
5419 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5420 op0
= copy_to_mode_reg (mode0
, op0
);
5422 if (! (*insn_data
[icode
].operand
[0].predicate
) (op1
, mode1
))
5423 op1
= copy_to_mode_reg (mode1
, op1
);
5425 emit_insn (gen_mulu64 (op0
,op1
));
5428 case ARC_BUILTIN_RTIE
:
5429 icode
= CODE_FOR_rtie
;
5430 emit_insn (gen_rtie (const1_rtx
));
5433 case ARC_BUILTIN_SYNC
:
5434 icode
= CODE_FOR_sync
;
5435 emit_insn (gen_sync (const1_rtx
));
5438 case ARC_BUILTIN_SWAP
:
5439 icode
= CODE_FOR_swap
;
5440 arg0
= CALL_EXPR_ARG (exp
, 0);
5441 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5442 mode0
= insn_data
[icode
].operand
[1].mode
;
5443 target
= gen_reg_rtx (SImode
);
5445 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5446 op0
= copy_to_mode_reg (mode0
, op0
);
5448 emit_insn (gen_swap (target
, op0
));
5451 case ARC_BUILTIN_DIVAW
:
5452 icode
= CODE_FOR_divaw
;
5453 arg0
= CALL_EXPR_ARG (exp
, 0);
5454 arg1
= CALL_EXPR_ARG (exp
, 1);
5456 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5457 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5458 target
= gen_reg_rtx (SImode
);
5460 mode0
= insn_data
[icode
].operand
[0].mode
;
5461 mode1
= insn_data
[icode
].operand
[1].mode
;
5463 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5464 op0
= copy_to_mode_reg (mode0
, op0
);
5466 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5467 op1
= copy_to_mode_reg (mode1
, op1
);
5469 emit_insn (gen_divaw (target
, op0
, op1
));
5472 case ARC_BUILTIN_BRK
:
5473 icode
= CODE_FOR_brk
;
5474 emit_insn (gen_brk (const1_rtx
));
5477 case ARC_BUILTIN_SLEEP
:
5478 icode
= CODE_FOR_sleep
;
5479 arg0
= CALL_EXPR_ARG (exp
, 0);
5483 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5484 mode0
= insn_data
[icode
].operand
[1].mode
;
5486 emit_insn (gen_sleep (op0
));
5489 case ARC_BUILTIN_SWI
:
5490 icode
= CODE_FOR_swi
;
5491 emit_insn (gen_swi (const1_rtx
));
5494 case ARC_BUILTIN_FLAG
:
5495 icode
= CODE_FOR_flag
;
5496 arg0
= CALL_EXPR_ARG (exp
, 0);
5497 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5498 mode0
= insn_data
[icode
].operand
[0].mode
;
5500 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5501 op0
= copy_to_mode_reg (mode0
, op0
);
5503 emit_insn (gen_flag (op0
));
5506 case ARC_BUILTIN_CORE_READ
:
5507 icode
= CODE_FOR_core_read
;
5508 arg0
= CALL_EXPR_ARG (exp
, 0);
5509 target
= gen_reg_rtx (SImode
);
5513 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5514 mode0
= insn_data
[icode
].operand
[1].mode
;
5516 emit_insn (gen_core_read (target
, op0
));
5519 case ARC_BUILTIN_CORE_WRITE
:
5520 icode
= CODE_FOR_core_write
;
5521 arg0
= CALL_EXPR_ARG (exp
, 0);
5522 arg1
= CALL_EXPR_ARG (exp
, 1);
5526 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5527 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5529 mode0
= insn_data
[icode
].operand
[0].mode
;
5530 mode1
= insn_data
[icode
].operand
[1].mode
;
5532 emit_insn (gen_core_write (op0
, op1
));
5535 case ARC_BUILTIN_LR
:
5536 icode
= CODE_FOR_lr
;
5537 arg0
= CALL_EXPR_ARG (exp
, 0);
5538 target
= gen_reg_rtx (SImode
);
5542 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5543 mode0
= insn_data
[icode
].operand
[1].mode
;
5545 emit_insn (gen_lr (target
, op0
));
5548 case ARC_BUILTIN_SR
:
5549 icode
= CODE_FOR_sr
;
5550 arg0
= CALL_EXPR_ARG (exp
, 0);
5551 arg1
= CALL_EXPR_ARG (exp
, 1);
5555 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5556 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5558 mode0
= insn_data
[icode
].operand
[0].mode
;
5559 mode1
= insn_data
[icode
].operand
[1].mode
;
5561 emit_insn (gen_sr (op0
, op1
));
5564 case ARC_BUILTIN_TRAP_S
:
5565 icode
= CODE_FOR_trap_s
;
5566 arg0
= CALL_EXPR_ARG (exp
, 0);
5570 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5571 mode0
= insn_data
[icode
].operand
[1].mode
;
5573 /* We don't give an error for non-cost values here because
5574 we still want to allow things to be fixed up by later inlining /
5575 constant folding / dead code elimination. */
5576 if (CONST_INT_P (op0
) && !satisfies_constraint_L (op0
))
5578 /* Keep this message in sync with the one in arc.md:trap_s,
5579 because *.md files don't get scanned by exgettext. */
5580 error ("operand to trap_s should be an unsigned 6-bit value");
5582 emit_insn (gen_trap_s (op0
));
5585 case ARC_BUILTIN_UNIMP_S
:
5586 icode
= CODE_FOR_unimp_s
;
5587 emit_insn (gen_unimp_s (const1_rtx
));
5590 case ARC_BUILTIN_ALIGNED
:
5591 /* __builtin_arc_aligned (void* val, int alignval) */
5592 arg0
= CALL_EXPR_ARG (exp
, 0);
5593 arg1
= CALL_EXPR_ARG (exp
, 1);
5595 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5596 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5597 target
= gen_reg_rtx (SImode
);
5599 if (!CONST_INT_P (op1
))
5601 /* If we can't fold the alignment to a constant integer
5602 whilst optimizing, this is probably a user error. */
5604 warning (0, "__builtin_arc_aligned with non-constant alignment");
5608 HOST_WIDE_INT alignTest
= INTVAL (op1
);
5609 /* Check alignTest is positive, and a power of two. */
5610 if (alignTest
<= 0 || alignTest
!= (alignTest
& -alignTest
))
5612 error ("invalid alignment value for __builtin_arc_aligned");
5616 if (CONST_INT_P (op0
))
5618 HOST_WIDE_INT pnt
= INTVAL (op0
);
5620 if ((pnt
& (alignTest
- 1)) == 0)
5625 unsigned align
= get_pointer_alignment (arg0
);
5626 unsigned numBits
= alignTest
* BITS_PER_UNIT
;
5628 if (align
&& align
>= numBits
)
5630 /* Another attempt to ascertain alignment. Check the type
5631 we are pointing to. */
5632 if (POINTER_TYPE_P (TREE_TYPE (arg0
))
5633 && TYPE_ALIGN (TREE_TYPE (TREE_TYPE (arg0
))) >= numBits
)
5638 /* Default to false. */
5645 /* @@@ Should really do something sensible here. */
5649 /* Returns true if the operands[opno] is a valid compile-time constant to be
5650 used as register number in the code for builtins. Else it flags an error
5651 and returns false. */
5654 check_if_valid_regno_const (rtx
*operands
, int opno
)
5657 switch (GET_CODE (operands
[opno
]))
5664 error ("register number must be a compile-time constant. Try giving higher optimization levels");
5670 /* Check that after all the constant folding, whether the operand to
5671 __builtin_arc_sleep is an unsigned int of 6 bits. If not, flag an error. */
5674 check_if_valid_sleep_operand (rtx
*operands
, int opno
)
5676 switch (GET_CODE (operands
[opno
]))
5680 if( UNSIGNED_INT6 (INTVAL (operands
[opno
])))
5683 fatal_error (input_location
,
5684 "operand for sleep instruction must be an unsigned 6 bit compile-time constant");
5690 /* Return true if it is ok to make a tail-call to DECL. */
5693 arc_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED
,
5694 tree exp ATTRIBUTE_UNUSED
)
5696 /* Never tailcall from an ISR routine - it needs a special exit sequence. */
5697 if (ARC_INTERRUPT_P (arc_compute_function_type (cfun
)))
5700 /* Everything else is ok. */
5704 /* Output code to add DELTA to the first argument, and then jump
5705 to FUNCTION. Used for C++ multiple inheritance. */
5708 arc_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
5709 HOST_WIDE_INT delta
,
5710 HOST_WIDE_INT vcall_offset
,
5713 int mi_delta
= delta
;
5714 const char *const mi_op
= mi_delta
< 0 ? "sub" : "add";
5717 = aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
) ? 1 : 0;
5721 mi_delta
= - mi_delta
;
5723 /* Add DELTA. When possible use a plain add, otherwise load it into
5724 a register first. */
5726 while (mi_delta
!= 0)
5728 if ((mi_delta
& (3 << shift
)) == 0)
5732 asm_fprintf (file
, "\t%s\t%s, %s, %d\n",
5733 mi_op
, reg_names
[this_regno
], reg_names
[this_regno
],
5734 mi_delta
& (0xff << shift
));
5735 mi_delta
&= ~(0xff << shift
);
5740 /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
5741 if (vcall_offset
!= 0)
5743 /* ld r12,[this] --> temp = *this
5744 add r12,r12,vcall_offset --> temp = *(*this + vcall_offset)
5746 add this,this,r12 --> this+ = *(*this + vcall_offset) */
5747 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5748 ARC_TEMP_SCRATCH_REG
, reg_names
[this_regno
]);
5749 asm_fprintf (file
, "\tadd\t%s, %s, " HOST_WIDE_INT_PRINT_DEC
"\n",
5750 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
, vcall_offset
);
5751 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5752 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
);
5753 asm_fprintf (file
, "\tadd\t%s, %s, %s\n", reg_names
[this_regno
],
5754 reg_names
[this_regno
], ARC_TEMP_SCRATCH_REG
);
5757 fnaddr
= XEXP (DECL_RTL (function
), 0);
5759 if (arc_is_longcall_p (fnaddr
))
5760 fputs ("\tj\t", file
);
5762 fputs ("\tb\t", file
);
5763 assemble_name (file
, XSTR (fnaddr
, 0));
5767 /* Return true if a 32 bit "long_call" should be generated for
5768 this calling SYM_REF. We generate a long_call if the function:
5770 a. has an __attribute__((long call))
5771 or b. the -mlong-calls command line switch has been specified
5773 However we do not generate a long call if the function has an
5774 __attribute__ ((short_call)) or __attribute__ ((medium_call))
5776 This function will be called by C fragments contained in the machine
5777 description file. */
5780 arc_is_longcall_p (rtx sym_ref
)
5782 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5785 return (SYMBOL_REF_LONG_CALL_P (sym_ref
)
5786 || (TARGET_LONG_CALLS_SET
5787 && !SYMBOL_REF_SHORT_CALL_P (sym_ref
)
5788 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
5792 /* Likewise for short calls. */
5795 arc_is_shortcall_p (rtx sym_ref
)
5797 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5800 return (SYMBOL_REF_SHORT_CALL_P (sym_ref
)
5801 || (!TARGET_LONG_CALLS_SET
&& !TARGET_MEDIUM_CALLS
5802 && !SYMBOL_REF_LONG_CALL_P (sym_ref
)
5803 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
5807 /* Emit profiling code for calling CALLEE. Return true if a special
5808 call pattern needs to be generated. */
5811 arc_profile_call (rtx callee
)
5813 rtx from
= XEXP (DECL_RTL (current_function_decl
), 0);
5815 if (TARGET_UCB_MCOUNT
)
5816 /* Profiling is done by instrumenting the callee. */
5819 if (CONSTANT_P (callee
))
5822 = gen_rtx_CONST (Pmode
,
5823 gen_rtx_UNSPEC (Pmode
,
5824 gen_rtvec (3, from
, callee
,
5825 CONST0_RTX (Pmode
)),
5827 rtx counter
= gen_rtx_MEM (SImode
, count_ptr
);
5828 /* ??? The increment would better be done atomically, but as there is
5829 no proper hardware support, that would be too expensive. */
5830 emit_move_insn (counter
,
5831 force_reg (SImode
, plus_constant (SImode
, counter
, 1)));
5837 = gen_rtx_CONST (Pmode
,
5838 gen_rtx_UNSPEC (Pmode
,
5839 gen_rtvec (3, from
, CONST0_RTX (Pmode
),
5840 CONST0_RTX (Pmode
)),
5842 emit_move_insn (gen_rtx_REG (Pmode
, 8), count_list_ptr
);
5843 emit_move_insn (gen_rtx_REG (Pmode
, 9), callee
);
5848 /* Worker function for TARGET_RETURN_IN_MEMORY. */
5851 arc_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
5853 if (AGGREGATE_TYPE_P (type
) || TREE_ADDRESSABLE (type
))
5857 HOST_WIDE_INT size
= int_size_in_bytes (type
);
5858 return (size
== -1 || size
> (TARGET_V2
? 16 : 8));
5863 /* This was in rtlanal.c, and can go in there when we decide we want
5864 to submit the change for inclusion in the GCC tree. */
5865 /* Like note_stores, but allow the callback to have side effects on the rtl
5866 (like the note_stores of yore):
5867 Call FUN on each register or MEM that is stored into or clobbered by X.
5868 (X would be the pattern of an insn). DATA is an arbitrary pointer,
5869 ignored by note_stores, but passed to FUN.
5870 FUN may alter parts of the RTL.
5872 FUN receives three arguments:
5873 1. the REG, MEM, CC0 or PC being stored in or clobbered,
5874 2. the SET or CLOBBER rtx that does the store,
5875 3. the pointer DATA provided to note_stores.
5877 If the item being stored in or clobbered is a SUBREG of a hard register,
5878 the SUBREG will be passed. */
5880 /* For now. */ static
5882 walk_stores (rtx x
, void (*fun
) (rtx
, rtx
, void *), void *data
)
5886 if (GET_CODE (x
) == COND_EXEC
)
5887 x
= COND_EXEC_CODE (x
);
5889 if (GET_CODE (x
) == SET
|| GET_CODE (x
) == CLOBBER
)
5891 rtx dest
= SET_DEST (x
);
5893 while ((GET_CODE (dest
) == SUBREG
5894 && (!REG_P (SUBREG_REG (dest
))
5895 || REGNO (SUBREG_REG (dest
)) >= FIRST_PSEUDO_REGISTER
))
5896 || GET_CODE (dest
) == ZERO_EXTRACT
5897 || GET_CODE (dest
) == STRICT_LOW_PART
)
5898 dest
= XEXP (dest
, 0);
5900 /* If we have a PARALLEL, SET_DEST is a list of EXPR_LIST expressions,
5901 each of whose first operand is a register. */
5902 if (GET_CODE (dest
) == PARALLEL
)
5904 for (i
= XVECLEN (dest
, 0) - 1; i
>= 0; i
--)
5905 if (XEXP (XVECEXP (dest
, 0, i
), 0) != 0)
5906 (*fun
) (XEXP (XVECEXP (dest
, 0, i
), 0), x
, data
);
5909 (*fun
) (dest
, x
, data
);
5912 else if (GET_CODE (x
) == PARALLEL
)
5913 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
5914 walk_stores (XVECEXP (x
, 0, i
), fun
, data
);
5918 arc_pass_by_reference (cumulative_args_t ca_v ATTRIBUTE_UNUSED
,
5919 machine_mode mode ATTRIBUTE_UNUSED
,
5921 bool named ATTRIBUTE_UNUSED
)
5924 && (TREE_CODE (TYPE_SIZE (type
)) != INTEGER_CST
5925 || TREE_ADDRESSABLE (type
)));
5928 /* Implement TARGET_CAN_USE_DOLOOP_P. */
5931 arc_can_use_doloop_p (const widest_int
&iterations
, const widest_int
&,
5932 unsigned int loop_depth
, bool entered_at_top
)
5936 /* Setting up the loop with two sr instructions costs 6 cycles. */
5939 && wi::gtu_p (iterations
, 0)
5940 && wi::leu_p (iterations
, flag_pic
? 6 : 3))
5945 /* NULL if INSN insn is valid within a low-overhead loop.
5946 Otherwise return why doloop cannot be applied. */
5949 arc_invalid_within_doloop (const rtx_insn
*insn
)
5952 return "Function call in the loop.";
5956 /* The same functionality as arc_hazard. It is called in machine
5957 reorg before any other optimization. Hence, the NOP size is taken
5958 into account when doing branch shortening. */
5961 workaround_arc_anomaly (void)
5963 rtx_insn
*insn
, *succ0
;
5965 /* For any architecture: call arc_hazard here. */
5966 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5968 succ0
= next_real_insn (insn
);
5969 if (arc_hazard (insn
, succ0
))
5971 emit_insn_before (gen_nopv (), succ0
);
5976 static int arc_reorg_in_progress
= 0;
5978 /* ARC's machince specific reorg function. */
5989 workaround_arc_anomaly ();
5991 cfun
->machine
->arc_reorg_started
= 1;
5992 arc_reorg_in_progress
= 1;
5994 /* Emit special sections for profiling. */
5997 section
*save_text_section
;
5999 int size
= get_max_uid () >> 4;
6000 htab_t htab
= htab_create (size
, unspec_prof_hash
, unspec_prof_htab_eq
,
6003 save_text_section
= in_section
;
6004 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
6005 if (NONJUMP_INSN_P (insn
))
6006 walk_stores (PATTERN (insn
), write_profile_sections
, htab
);
6007 if (htab_elements (htab
))
6009 switch_to_section (save_text_section
);
6013 /* Link up loop ends with their loop start. */
6015 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
6016 if (GET_CODE (insn
) == JUMP_INSN
6017 && recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
6020 = as_a
<rtx_insn
*> (XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 1), 0));
6021 rtx num
= GEN_INT (CODE_LABEL_NUMBER (top_label
));
6022 rtx_insn
*lp
, *prev
= prev_nonnote_insn (top_label
);
6023 rtx_insn
*lp_simple
= NULL
;
6024 rtx_insn
*next
= NULL
;
6025 rtx op0
= XEXP (XVECEXP (PATTERN (insn
), 0, 1), 0);
6026 HOST_WIDE_INT loop_end_id
6027 = -INTVAL (XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0));
6031 (lp
&& NONJUMP_INSN_P (lp
)
6032 && recog_memoized (lp
) != CODE_FOR_doloop_begin_i
);
6033 lp
= prev_nonnote_insn (lp
))
6035 if (!lp
|| !NONJUMP_INSN_P (lp
)
6036 || dead_or_set_regno_p (lp
, LP_COUNT
))
6038 for (prev
= next
= insn
, lp
= NULL
; prev
|| next
;)
6042 if (NONJUMP_INSN_P (prev
)
6043 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
6044 && (INTVAL (XEXP (XVECEXP (PATTERN (prev
), 0, 5), 0))
6050 else if (LABEL_P (prev
))
6052 prev
= prev_nonnote_insn (prev
);
6056 if (NONJUMP_INSN_P (next
)
6057 && recog_memoized (next
) == CODE_FOR_doloop_begin_i
6058 && (INTVAL (XEXP (XVECEXP (PATTERN (next
), 0, 5), 0))
6064 next
= next_nonnote_insn (next
);
6071 if (lp
&& !dead_or_set_regno_p (lp
, LP_COUNT
))
6073 rtx begin_cnt
= XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0);
6074 if (INTVAL (XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0)))
6075 /* The loop end insn has been duplicated. That can happen
6076 when there is a conditional block at the very end of
6079 /* If Register allocation failed to allocate to the right
6080 register, There is no point into teaching reload to
6081 fix this up with reloads, as that would cost more
6082 than using an ordinary core register with the
6083 doloop_fallback pattern. */
6084 if ((true_regnum (op0
) != LP_COUNT
|| !REG_P (begin_cnt
))
6085 /* Likewise, if the loop setup is evidently inside the loop,
6087 || (!lp_simple
&& lp
!= next
&& !seen_label
))
6092 /* It is common that the optimizers copy the loop count from
6093 another register, and doloop_begin_i is stuck with the
6094 source of the move. Making doloop_begin_i only accept "l"
6095 is nonsentical, as this then makes reload evict the pseudo
6096 used for the loop end. The underlying cause is that the
6097 optimizers don't understand that the register allocation for
6098 doloop_begin_i should be treated as part of the loop.
6099 Try to work around this problem by verifying the previous
6101 if (true_regnum (begin_cnt
) != LP_COUNT
)
6106 for (mov
= prev_nonnote_insn (lp
); mov
;
6107 mov
= prev_nonnote_insn (mov
))
6109 if (!NONJUMP_INSN_P (mov
))
6111 else if ((set
= single_set (mov
))
6112 && rtx_equal_p (SET_SRC (set
), begin_cnt
)
6113 && rtx_equal_p (SET_DEST (set
), op0
))
6118 XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0) = op0
;
6119 note
= find_regno_note (lp
, REG_DEAD
, REGNO (begin_cnt
));
6121 remove_note (lp
, note
);
6129 XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0) = num
;
6130 XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0) = num
;
6132 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const2_rtx
;
6133 else if (!lp_simple
)
6134 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const1_rtx
;
6135 else if (prev
!= lp
)
6138 add_insn_after (lp
, prev
, NULL
);
6142 XEXP (XVECEXP (PATTERN (lp
), 0, 7), 0)
6143 = gen_rtx_LABEL_REF (Pmode
, top_label
);
6144 add_reg_note (lp
, REG_LABEL_OPERAND
, top_label
);
6145 LABEL_NUSES (top_label
)++;
6147 /* We can avoid tedious loop start / end setting for empty loops
6148 be merely setting the loop count to its final value. */
6149 if (next_active_insn (top_label
) == insn
)
6152 = gen_rtx_SET (XEXP (XVECEXP (PATTERN (lp
), 0, 3), 0),
6155 rtx_insn
*lc_set_insn
= emit_insn_before (lc_set
, insn
);
6160 /* If the loop is non-empty with zero length, we can't make it
6161 a zero-overhead loop. That can happen for empty asms. */
6166 for (scan
= top_label
;
6167 (scan
&& scan
!= insn
6168 && (!NONJUMP_INSN_P (scan
) || !get_attr_length (scan
)));
6169 scan
= NEXT_INSN (scan
));
6179 /* Sometimes the loop optimizer makes a complete hash of the
6180 loop. If it were only that the loop is not entered at the
6181 top, we could fix this up by setting LP_START with SR .
6182 However, if we can't find the loop begin were it should be,
6183 chances are that it does not even dominate the loop, but is
6184 inside the loop instead. Using SR there would kill
6186 We use the doloop_fallback pattern here, which executes
6187 in two cycles on the ARC700 when predicted correctly. */
6191 rtx op3
= XEXP (XVECEXP (PATTERN (insn
), 0, 5), 0);
6193 emit_insn_before (gen_move_insn (op3
, op0
), insn
);
6195 = gen_doloop_fallback_m (op3
, JUMP_LABEL (insn
), op0
);
6198 XVEC (PATTERN (insn
), 0)
6199 = gen_rtvec (2, XVECEXP (PATTERN (insn
), 0, 0),
6200 XVECEXP (PATTERN (insn
), 0, 1));
6201 INSN_CODE (insn
) = -1;
6206 /* FIXME: should anticipate ccfsm action, generate special patterns for
6207 to-be-deleted branches that have no delay slot and have at least the
6208 length of the size increase forced on other insns that are conditionalized.
6209 This can also have an insn_list inside that enumerates insns which are
6210 not actually conditionalized because the destinations are dead in the
6212 Could also tag branches that we want to be unaligned if they get no delay
6213 slot, or even ones that we don't want to do delay slot sheduling for
6214 because we can unalign them.
6216 However, there are cases when conditional execution is only possible after
6217 delay slot scheduling:
6219 - If a delay slot is filled with a nocond/set insn from above, the previous
6220 basic block can become elegible for conditional execution.
6221 - If a delay slot is filled with a nocond insn from the fall-through path,
6222 the branch with that delay slot can become eligble for conditional
6223 execution (however, with the same sort of data flow analysis that dbr
6224 does, we could have figured out before that we don't need to
6225 conditionalize this insn.)
6226 - If a delay slot insn is filled with an insn from the target, the
6227 target label gets its uses decremented (even deleted if falling to zero),
6228 thus possibly creating more condexec opportunities there.
6229 Therefore, we should still be prepared to apply condexec optimization on
6230 non-prepared branches if the size increase of conditionalized insns is no
6231 more than the size saved from eliminating the branch. An invocation option
6232 could also be used to reserve a bit of extra size for condbranches so that
6233 this'll work more often (could also test in arc_reorg if the block is
6234 'close enough' to be eligible for condexec to make this likely, and
6235 estimate required size increase). */
6236 /* Generate BRcc insns, by combining cmp and Bcc insns wherever possible. */
6237 if (TARGET_NO_BRCC_SET
)
6242 init_insn_lengths();
6245 if (optimize
> 1 && !TARGET_NO_COND_EXEC
)
6248 unsigned int flags
= pass_data_arc_ifcvt
.todo_flags_finish
;
6249 df_finish_pass ((flags
& TODO_df_verify
) != 0);
6252 /* Call shorten_branches to calculate the insn lengths. */
6253 shorten_branches (get_insns());
6254 cfun
->machine
->ccfsm_current_insn
= NULL_RTX
;
6256 if (!INSN_ADDRESSES_SET_P())
6257 fatal_error (input_location
, "Insn addresses not set after shorten_branches");
6259 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
6262 enum attr_type insn_type
;
6264 /* If a non-jump insn (or a casesi jump table), continue. */
6265 if (GET_CODE (insn
) != JUMP_INSN
||
6266 GET_CODE (PATTERN (insn
)) == ADDR_VEC
6267 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
6270 /* If we already have a brcc, note if it is suitable for brcc_s.
6271 Be a bit generous with the brcc_s range so that we can take
6272 advantage of any code shortening from delay slot scheduling. */
6273 if (recog_memoized (insn
) == CODE_FOR_cbranchsi4_scratch
)
6275 rtx pat
= PATTERN (insn
);
6276 rtx op
= XEXP (SET_SRC (XVECEXP (pat
, 0, 0)), 0);
6277 rtx
*ccp
= &XEXP (XVECEXP (pat
, 0, 1), 0);
6279 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6280 if ((offset
>= -140 && offset
< 140)
6281 && rtx_equal_p (XEXP (op
, 1), const0_rtx
)
6282 && compact_register_operand (XEXP (op
, 0), VOIDmode
)
6283 && equality_comparison_operator (op
, VOIDmode
))
6284 PUT_MODE (*ccp
, CC_Zmode
);
6285 else if (GET_MODE (*ccp
) == CC_Zmode
)
6286 PUT_MODE (*ccp
, CC_ZNmode
);
6289 if ((insn_type
= get_attr_type (insn
)) == TYPE_BRCC
6290 || insn_type
== TYPE_BRCC_NO_DELAY_SLOT
)
6293 /* OK. so we have a jump insn. */
6294 /* We need to check that it is a bcc. */
6295 /* Bcc => set (pc) (if_then_else ) */
6296 pattern
= PATTERN (insn
);
6297 if (GET_CODE (pattern
) != SET
6298 || GET_CODE (SET_SRC (pattern
)) != IF_THEN_ELSE
6299 || ANY_RETURN_P (XEXP (SET_SRC (pattern
), 1)))
6302 /* Now check if the jump is beyond the s9 range. */
6303 if (CROSSING_JUMP_P (insn
))
6305 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6307 if(offset
> 253 || offset
< -254)
6310 pc_target
= SET_SRC (pattern
);
6312 /* Now go back and search for the set cc insn. */
6314 label
= XEXP (pc_target
, 1);
6318 rtx_insn
*scan
, *link_insn
= NULL
;
6320 for (scan
= PREV_INSN (insn
);
6321 scan
&& GET_CODE (scan
) != CODE_LABEL
;
6322 scan
= PREV_INSN (scan
))
6324 if (! INSN_P (scan
))
6326 pat
= PATTERN (scan
);
6327 if (GET_CODE (pat
) == SET
6328 && cc_register (SET_DEST (pat
), VOIDmode
))
6337 /* Check if this is a data dependency. */
6339 rtx op
, cc_clob_rtx
, op0
, op1
, brcc_insn
, note
;
6342 /* Ok this is the set cc. copy args here. */
6343 op
= XEXP (pc_target
, 0);
6345 op0
= cmp0
= XEXP (SET_SRC (pat
), 0);
6346 op1
= cmp1
= XEXP (SET_SRC (pat
), 1);
6347 if (GET_CODE (op0
) == ZERO_EXTRACT
6348 && XEXP (op0
, 1) == const1_rtx
6349 && (GET_CODE (op
) == EQ
6350 || GET_CODE (op
) == NE
))
6352 /* btst / b{eq,ne} -> bbit{0,1} */
6353 op0
= XEXP (cmp0
, 0);
6354 op1
= XEXP (cmp0
, 2);
6356 else if (!register_operand (op0
, VOIDmode
)
6357 || !general_operand (op1
, VOIDmode
))
6359 /* Be careful not to break what cmpsfpx_raw is
6360 trying to create for checking equality of
6361 single-precision floats. */
6362 else if (TARGET_SPFP
6363 && GET_MODE (op0
) == SFmode
6364 && GET_MODE (op1
) == SFmode
)
6367 /* None of the two cmp operands should be set between the
6368 cmp and the branch. */
6369 if (reg_set_between_p (op0
, link_insn
, insn
))
6372 if (reg_set_between_p (op1
, link_insn
, insn
))
6375 /* Since the MODE check does not work, check that this is
6376 CC reg's last set location before insn, and also no
6377 instruction between the cmp and branch uses the
6379 if ((reg_set_between_p (SET_DEST (pat
), link_insn
, insn
))
6380 || (reg_used_between_p (SET_DEST (pat
), link_insn
, insn
)))
6383 /* CC reg should be dead after insn. */
6384 if (!find_regno_note (insn
, REG_DEAD
, CC_REG
))
6387 op
= gen_rtx_fmt_ee (GET_CODE (op
),
6388 GET_MODE (op
), cmp0
, cmp1
);
6389 /* If we create a LIMM where there was none before,
6390 we only benefit if we can avoid a scheduling bubble
6391 for the ARC600. Otherwise, we'd only forgo chances
6392 at short insn generation, and risk out-of-range
6394 if (!brcc_nolimm_operator (op
, VOIDmode
)
6395 && !long_immediate_operand (op1
, VOIDmode
)
6397 || next_active_insn (link_insn
) != insn
))
6400 /* Emit bbit / brcc (or brcc_s if possible).
6401 CC_Zmode indicates that brcc_s is possible. */
6404 cc_clob_rtx
= gen_rtx_REG (CC_ZNmode
, CC_REG
);
6405 else if ((offset
>= -140 && offset
< 140)
6406 && rtx_equal_p (op1
, const0_rtx
)
6407 && compact_register_operand (op0
, VOIDmode
)
6408 && (GET_CODE (op
) == EQ
6409 || GET_CODE (op
) == NE
))
6410 cc_clob_rtx
= gen_rtx_REG (CC_Zmode
, CC_REG
);
6412 cc_clob_rtx
= gen_rtx_REG (CCmode
, CC_REG
);
6415 = gen_rtx_IF_THEN_ELSE (VOIDmode
, op
, label
, pc_rtx
);
6416 brcc_insn
= gen_rtx_SET (pc_rtx
, brcc_insn
);
6417 cc_clob_rtx
= gen_rtx_CLOBBER (VOIDmode
, cc_clob_rtx
);
6420 (VOIDmode
, gen_rtvec (2, brcc_insn
, cc_clob_rtx
));
6421 brcc_insn
= emit_jump_insn_before (brcc_insn
, insn
);
6423 JUMP_LABEL (brcc_insn
) = JUMP_LABEL (insn
);
6424 note
= find_reg_note (insn
, REG_BR_PROB
, 0);
6427 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6428 REG_NOTES (brcc_insn
) = note
;
6430 note
= find_reg_note (link_insn
, REG_DEAD
, op0
);
6433 remove_note (link_insn
, note
);
6434 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6435 REG_NOTES (brcc_insn
) = note
;
6437 note
= find_reg_note (link_insn
, REG_DEAD
, op1
);
6440 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6441 REG_NOTES (brcc_insn
) = note
;
6446 /* Delete the bcc insn. */
6447 set_insn_deleted (insn
);
6449 /* Delete the cmp insn. */
6450 set_insn_deleted (link_insn
);
6455 /* Clear out insn_addresses. */
6456 INSN_ADDRESSES_FREE ();
6460 if (INSN_ADDRESSES_SET_P())
6461 fatal_error (input_location
, "insn addresses not freed");
6463 arc_reorg_in_progress
= 0;
6466 /* Check if the operands are valid for BRcc.d generation
6467 Valid Brcc.d patterns are
6471 For cc={GT, LE, GTU, LEU}, u6=63 can not be allowed,
6472 since they are encoded by the assembler as {GE, LT, HS, LS} 64, which
6473 does not have a delay slot
6475 Assumed precondition: Second operand is either a register or a u6 value. */
6478 valid_brcc_with_delay_p (rtx
*operands
)
6480 if (optimize_size
&& GET_MODE (operands
[4]) == CC_Zmode
)
6482 return brcc_nolimm_operator (operands
[0], VOIDmode
);
6485 /* ??? Hack. This should no really be here. See PR32143. */
6487 arc_decl_anon_ns_mem_p (const_tree decl
)
6491 if (decl
== NULL_TREE
|| decl
== error_mark_node
)
6493 if (TREE_CODE (decl
) == NAMESPACE_DECL
6494 && DECL_NAME (decl
) == NULL_TREE
)
6496 /* Classes and namespaces inside anonymous namespaces have
6497 TREE_PUBLIC == 0, so we can shortcut the search. */
6498 else if (TYPE_P (decl
))
6499 return (TREE_PUBLIC (TYPE_NAME (decl
)) == 0);
6500 else if (TREE_CODE (decl
) == NAMESPACE_DECL
)
6501 return (TREE_PUBLIC (decl
) == 0);
6503 decl
= DECL_CONTEXT (decl
);
6507 /* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
6508 access DECL using %gp_rel(...)($gp). */
6511 arc_in_small_data_p (const_tree decl
)
6515 if (TREE_CODE (decl
) == STRING_CST
|| TREE_CODE (decl
) == FUNCTION_DECL
)
6519 /* We don't yet generate small-data references for -mabicalls. See related
6520 -G handling in override_options. */
6521 if (TARGET_NO_SDATA_SET
)
6524 if (TREE_CODE (decl
) == VAR_DECL
&& DECL_SECTION_NAME (decl
) != 0)
6528 /* Reject anything that isn't in a known small-data section. */
6529 name
= DECL_SECTION_NAME (decl
);
6530 if (strcmp (name
, ".sdata") != 0 && strcmp (name
, ".sbss") != 0)
6533 /* If a symbol is defined externally, the assembler will use the
6534 usual -G rules when deciding how to implement macros. */
6535 if (!DECL_EXTERNAL (decl
))
6538 /* Only global variables go into sdata section for now. */
6541 /* Don't put constants into the small data section: we want them
6542 to be in ROM rather than RAM. */
6543 if (TREE_CODE (decl
) != VAR_DECL
)
6546 if (TREE_READONLY (decl
)
6547 && !TREE_SIDE_EFFECTS (decl
)
6548 && (!DECL_INITIAL (decl
) || TREE_CONSTANT (DECL_INITIAL (decl
))))
6551 /* TREE_PUBLIC might change after the first call, because of the patch
6553 if (default_binds_local_p_1 (decl
, 1)
6554 || arc_decl_anon_ns_mem_p (decl
))
6557 /* To ensure -mvolatile-cache works
6558 ld.di does not have a gp-relative variant. */
6559 if (TREE_THIS_VOLATILE (decl
))
6563 /* Disable sdata references to weak variables. */
6564 if (DECL_WEAK (decl
))
6567 size
= int_size_in_bytes (TREE_TYPE (decl
));
6569 /* if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) */
6572 /* Allow only <=4B long data types into sdata. */
6573 return (size
> 0 && size
<= 4);
6576 /* Return true if X is a small data address that can be rewritten
6580 arc_rewrite_small_data_p (const_rtx x
)
6582 if (GET_CODE (x
) == CONST
)
6585 if (GET_CODE (x
) == PLUS
)
6587 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
6591 return (GET_CODE (x
) == SYMBOL_REF
6592 && SYMBOL_REF_SMALL_P(x
));
6595 /* If possible, rewrite OP so that it refers to small data using
6596 explicit relocations. */
6599 arc_rewrite_small_data (rtx op
)
6601 op
= copy_insn (op
);
6602 subrtx_ptr_iterator::array_type array
;
6603 FOR_EACH_SUBRTX_PTR (iter
, array
, &op
, ALL
)
6606 if (arc_rewrite_small_data_p (*loc
))
6608 gcc_assert (SDATA_BASE_REGNUM
== PIC_OFFSET_TABLE_REGNUM
);
6609 *loc
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, *loc
);
6612 if (GET_CODE (op
) == MEM
&& &XEXP (op
, 0) == loc
)
6614 else if (GET_CODE (op
) == MEM
6615 && GET_CODE (XEXP (op
, 0)) == PLUS
6616 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == MULT
)
6617 *loc
= force_reg (Pmode
, *loc
);
6621 iter
.skip_subrtxes ();
6623 else if (GET_CODE (*loc
) == PLUS
6624 && rtx_equal_p (XEXP (*loc
, 0), pic_offset_table_rtx
))
6625 iter
.skip_subrtxes ();
6630 /* Return true if OP refers to small data symbols directly, not through
6634 small_data_pattern (rtx op
, machine_mode
)
6636 if (GET_CODE (op
) == SEQUENCE
)
6638 subrtx_iterator::array_type array
;
6639 FOR_EACH_SUBRTX (iter
, array
, op
, ALL
)
6641 const_rtx x
= *iter
;
6642 if (GET_CODE (x
) == PLUS
6643 && rtx_equal_p (XEXP (x
, 0), pic_offset_table_rtx
))
6644 iter
.skip_subrtxes ();
6645 else if (arc_rewrite_small_data_p (x
))
6651 /* Return true if OP is an acceptable memory operand for ARCompact
6652 16-bit gp-relative load instructions.
6653 op shd look like : [r26, symref@sda]
6654 i.e. (mem (plus (reg 26) (symref with smalldata flag set))
6656 /* volatile cache option still to be handled. */
6659 compact_sda_memory_operand (rtx op
, machine_mode mode
)
6664 /* Eliminate non-memory operations. */
6665 if (GET_CODE (op
) != MEM
)
6668 if (mode
== VOIDmode
)
6669 mode
= GET_MODE (op
);
6671 size
= GET_MODE_SIZE (mode
);
6673 /* dword operations really put out 2 instructions, so eliminate them. */
6674 if (size
> UNITS_PER_WORD
)
6677 /* Decode the address now. */
6678 addr
= XEXP (op
, 0);
6680 return LEGITIMATE_SMALL_DATA_ADDRESS_P (addr
);
6683 /* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */
6686 arc_asm_output_aligned_decl_local (FILE * stream
, tree decl
, const char * name
,
6687 unsigned HOST_WIDE_INT size
,
6688 unsigned HOST_WIDE_INT align
,
6689 unsigned HOST_WIDE_INT globalize_p
)
6691 int in_small_data
= arc_in_small_data_p (decl
);
6694 switch_to_section (get_named_section (NULL
, ".sbss", 0));
6695 /* named_section (0,".sbss",0); */
6697 switch_to_section (bss_section
);
6700 (*targetm
.asm_out
.globalize_label
) (stream
, name
);
6702 ASM_OUTPUT_ALIGN (stream
, floor_log2 ((align
) / BITS_PER_UNIT
));
6703 ASM_OUTPUT_TYPE_DIRECTIVE (stream
, name
, "object");
6704 ASM_OUTPUT_SIZE_DIRECTIVE (stream
, name
, size
);
6705 ASM_OUTPUT_LABEL (stream
, name
);
6708 ASM_OUTPUT_SKIP (stream
, size
);
6744 /* SIMD builtins support. */
6745 enum simd_insn_args_type
{
6768 struct builtin_description
6770 enum simd_insn_args_type args_type
;
6771 const enum insn_code icode
;
6772 const char * const name
;
6773 const enum arc_builtins code
;
6776 static const struct builtin_description arc_simd_builtin_desc_list
[] =
6778 /* VVV builtins go first. */
6779 #define SIMD_BUILTIN(type, code, string, builtin) \
6780 { type,CODE_FOR_##code, "__builtin_arc_" string, \
6781 ARC_SIMD_BUILTIN_##builtin },
6783 SIMD_BUILTIN (Va_Vb_Vc
, vaddaw_insn
, "vaddaw", VADDAW
)
6784 SIMD_BUILTIN (Va_Vb_Vc
, vaddw_insn
, "vaddw", VADDW
)
6785 SIMD_BUILTIN (Va_Vb_Vc
, vavb_insn
, "vavb", VAVB
)
6786 SIMD_BUILTIN (Va_Vb_Vc
, vavrb_insn
, "vavrb", VAVRB
)
6787 SIMD_BUILTIN (Va_Vb_Vc
, vdifaw_insn
, "vdifaw", VDIFAW
)
6788 SIMD_BUILTIN (Va_Vb_Vc
, vdifw_insn
, "vdifw", VDIFW
)
6789 SIMD_BUILTIN (Va_Vb_Vc
, vmaxaw_insn
, "vmaxaw", VMAXAW
)
6790 SIMD_BUILTIN (Va_Vb_Vc
, vmaxw_insn
, "vmaxw", VMAXW
)
6791 SIMD_BUILTIN (Va_Vb_Vc
, vminaw_insn
, "vminaw", VMINAW
)
6792 SIMD_BUILTIN (Va_Vb_Vc
, vminw_insn
, "vminw", VMINW
)
6793 SIMD_BUILTIN (Va_Vb_Vc
, vmulaw_insn
, "vmulaw", VMULAW
)
6794 SIMD_BUILTIN (Va_Vb_Vc
, vmulfaw_insn
, "vmulfaw", VMULFAW
)
6795 SIMD_BUILTIN (Va_Vb_Vc
, vmulfw_insn
, "vmulfw", VMULFW
)
6796 SIMD_BUILTIN (Va_Vb_Vc
, vmulw_insn
, "vmulw", VMULW
)
6797 SIMD_BUILTIN (Va_Vb_Vc
, vsubaw_insn
, "vsubaw", VSUBAW
)
6798 SIMD_BUILTIN (Va_Vb_Vc
, vsubw_insn
, "vsubw", VSUBW
)
6799 SIMD_BUILTIN (Va_Vb_Vc
, vsummw_insn
, "vsummw", VSUMMW
)
6800 SIMD_BUILTIN (Va_Vb_Vc
, vand_insn
, "vand", VAND
)
6801 SIMD_BUILTIN (Va_Vb_Vc
, vandaw_insn
, "vandaw", VANDAW
)
6802 SIMD_BUILTIN (Va_Vb_Vc
, vbic_insn
, "vbic", VBIC
)
6803 SIMD_BUILTIN (Va_Vb_Vc
, vbicaw_insn
, "vbicaw", VBICAW
)
6804 SIMD_BUILTIN (Va_Vb_Vc
, vor_insn
, "vor", VOR
)
6805 SIMD_BUILTIN (Va_Vb_Vc
, vxor_insn
, "vxor", VXOR
)
6806 SIMD_BUILTIN (Va_Vb_Vc
, vxoraw_insn
, "vxoraw", VXORAW
)
6807 SIMD_BUILTIN (Va_Vb_Vc
, veqw_insn
, "veqw", VEQW
)
6808 SIMD_BUILTIN (Va_Vb_Vc
, vlew_insn
, "vlew", VLEW
)
6809 SIMD_BUILTIN (Va_Vb_Vc
, vltw_insn
, "vltw", VLTW
)
6810 SIMD_BUILTIN (Va_Vb_Vc
, vnew_insn
, "vnew", VNEW
)
6811 SIMD_BUILTIN (Va_Vb_Vc
, vmr1aw_insn
, "vmr1aw", VMR1AW
)
6812 SIMD_BUILTIN (Va_Vb_Vc
, vmr1w_insn
, "vmr1w", VMR1W
)
6813 SIMD_BUILTIN (Va_Vb_Vc
, vmr2aw_insn
, "vmr2aw", VMR2AW
)
6814 SIMD_BUILTIN (Va_Vb_Vc
, vmr2w_insn
, "vmr2w", VMR2W
)
6815 SIMD_BUILTIN (Va_Vb_Vc
, vmr3aw_insn
, "vmr3aw", VMR3AW
)
6816 SIMD_BUILTIN (Va_Vb_Vc
, vmr3w_insn
, "vmr3w", VMR3W
)
6817 SIMD_BUILTIN (Va_Vb_Vc
, vmr4aw_insn
, "vmr4aw", VMR4AW
)
6818 SIMD_BUILTIN (Va_Vb_Vc
, vmr4w_insn
, "vmr4w", VMR4W
)
6819 SIMD_BUILTIN (Va_Vb_Vc
, vmr5aw_insn
, "vmr5aw", VMR5AW
)
6820 SIMD_BUILTIN (Va_Vb_Vc
, vmr5w_insn
, "vmr5w", VMR5W
)
6821 SIMD_BUILTIN (Va_Vb_Vc
, vmr6aw_insn
, "vmr6aw", VMR6AW
)
6822 SIMD_BUILTIN (Va_Vb_Vc
, vmr6w_insn
, "vmr6w", VMR6W
)
6823 SIMD_BUILTIN (Va_Vb_Vc
, vmr7aw_insn
, "vmr7aw", VMR7AW
)
6824 SIMD_BUILTIN (Va_Vb_Vc
, vmr7w_insn
, "vmr7w", VMR7W
)
6825 SIMD_BUILTIN (Va_Vb_Vc
, vmrb_insn
, "vmrb", VMRB
)
6826 SIMD_BUILTIN (Va_Vb_Vc
, vh264f_insn
, "vh264f", VH264F
)
6827 SIMD_BUILTIN (Va_Vb_Vc
, vh264ft_insn
, "vh264ft", VH264FT
)
6828 SIMD_BUILTIN (Va_Vb_Vc
, vh264fw_insn
, "vh264fw", VH264FW
)
6829 SIMD_BUILTIN (Va_Vb_Vc
, vvc1f_insn
, "vvc1f", VVC1F
)
6830 SIMD_BUILTIN (Va_Vb_Vc
, vvc1ft_insn
, "vvc1ft", VVC1FT
)
6832 SIMD_BUILTIN (Va_Vb_rlimm
, vbaddw_insn
, "vbaddw", VBADDW
)
6833 SIMD_BUILTIN (Va_Vb_rlimm
, vbmaxw_insn
, "vbmaxw", VBMAXW
)
6834 SIMD_BUILTIN (Va_Vb_rlimm
, vbminw_insn
, "vbminw", VBMINW
)
6835 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulaw_insn
, "vbmulaw", VBMULAW
)
6836 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulfw_insn
, "vbmulfw", VBMULFW
)
6837 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulw_insn
, "vbmulw", VBMULW
)
6838 SIMD_BUILTIN (Va_Vb_rlimm
, vbrsubw_insn
, "vbrsubw", VBRSUBW
)
6839 SIMD_BUILTIN (Va_Vb_rlimm
, vbsubw_insn
, "vbsubw", VBSUBW
)
6841 /* Va, Vb, Ic instructions. */
6842 SIMD_BUILTIN (Va_Vb_Ic
, vasrw_insn
, "vasrw", VASRW
)
6843 SIMD_BUILTIN (Va_Vb_Ic
, vsr8_insn
, "vsr8", VSR8
)
6844 SIMD_BUILTIN (Va_Vb_Ic
, vsr8aw_insn
, "vsr8aw", VSR8AW
)
6846 /* Va, Vb, u6 instructions. */
6847 SIMD_BUILTIN (Va_Vb_u6
, vasrrwi_insn
, "vasrrwi", VASRRWi
)
6848 SIMD_BUILTIN (Va_Vb_u6
, vasrsrwi_insn
, "vasrsrwi", VASRSRWi
)
6849 SIMD_BUILTIN (Va_Vb_u6
, vasrwi_insn
, "vasrwi", VASRWi
)
6850 SIMD_BUILTIN (Va_Vb_u6
, vasrpwbi_insn
, "vasrpwbi", VASRPWBi
)
6851 SIMD_BUILTIN (Va_Vb_u6
, vasrrpwbi_insn
,"vasrrpwbi", VASRRPWBi
)
6852 SIMD_BUILTIN (Va_Vb_u6
, vsr8awi_insn
, "vsr8awi", VSR8AWi
)
6853 SIMD_BUILTIN (Va_Vb_u6
, vsr8i_insn
, "vsr8i", VSR8i
)
6855 /* Va, Vb, u8 (simm) instructions. */
6856 SIMD_BUILTIN (Va_Vb_u8
, vmvaw_insn
, "vmvaw", VMVAW
)
6857 SIMD_BUILTIN (Va_Vb_u8
, vmvw_insn
, "vmvw", VMVW
)
6858 SIMD_BUILTIN (Va_Vb_u8
, vmvzw_insn
, "vmvzw", VMVZW
)
6859 SIMD_BUILTIN (Va_Vb_u8
, vd6tapf_insn
, "vd6tapf", VD6TAPF
)
6861 /* Va, rlimm, u8 (simm) instructions. */
6862 SIMD_BUILTIN (Va_rlimm_u8
, vmovaw_insn
, "vmovaw", VMOVAW
)
6863 SIMD_BUILTIN (Va_rlimm_u8
, vmovw_insn
, "vmovw", VMOVW
)
6864 SIMD_BUILTIN (Va_rlimm_u8
, vmovzw_insn
, "vmovzw", VMOVZW
)
6866 /* Va, Vb instructions. */
6867 SIMD_BUILTIN (Va_Vb
, vabsaw_insn
, "vabsaw", VABSAW
)
6868 SIMD_BUILTIN (Va_Vb
, vabsw_insn
, "vabsw", VABSW
)
6869 SIMD_BUILTIN (Va_Vb
, vaddsuw_insn
, "vaddsuw", VADDSUW
)
6870 SIMD_BUILTIN (Va_Vb
, vsignw_insn
, "vsignw", VSIGNW
)
6871 SIMD_BUILTIN (Va_Vb
, vexch1_insn
, "vexch1", VEXCH1
)
6872 SIMD_BUILTIN (Va_Vb
, vexch2_insn
, "vexch2", VEXCH2
)
6873 SIMD_BUILTIN (Va_Vb
, vexch4_insn
, "vexch4", VEXCH4
)
6874 SIMD_BUILTIN (Va_Vb
, vupbaw_insn
, "vupbaw", VUPBAW
)
6875 SIMD_BUILTIN (Va_Vb
, vupbw_insn
, "vupbw", VUPBW
)
6876 SIMD_BUILTIN (Va_Vb
, vupsbaw_insn
, "vupsbaw", VUPSBAW
)
6877 SIMD_BUILTIN (Va_Vb
, vupsbw_insn
, "vupsbw", VUPSBW
)
6879 /* DIb, rlimm, rlimm instructions. */
6880 SIMD_BUILTIN (Da_rlimm_rlimm
, vdirun_insn
, "vdirun", VDIRUN
)
6881 SIMD_BUILTIN (Da_rlimm_rlimm
, vdorun_insn
, "vdorun", VDORUN
)
6883 /* DIb, limm, rlimm instructions. */
6884 SIMD_BUILTIN (Da_u3_rlimm
, vdiwr_insn
, "vdiwr", VDIWR
)
6885 SIMD_BUILTIN (Da_u3_rlimm
, vdowr_insn
, "vdowr", VDOWR
)
6887 /* rlimm instructions. */
6888 SIMD_BUILTIN (void_rlimm
, vrec_insn
, "vrec", VREC
)
6889 SIMD_BUILTIN (void_rlimm
, vrun_insn
, "vrun", VRUN
)
6890 SIMD_BUILTIN (void_rlimm
, vrecrun_insn
, "vrecrun", VRECRUN
)
6891 SIMD_BUILTIN (void_rlimm
, vendrec_insn
, "vendrec", VENDREC
)
6893 /* Va, [Ib,u8] instructions. */
6894 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wh_insn
, "vld32wh", VLD32WH
)
6895 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wl_insn
, "vld32wl", VLD32WL
)
6896 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld64_insn
, "vld64", VLD64
)
6897 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32_insn
, "vld32", VLD32
)
6899 SIMD_BUILTIN (Va_Ib_u8
, vld64w_insn
, "vld64w", VLD64W
)
6900 SIMD_BUILTIN (Va_Ib_u8
, vld128_insn
, "vld128", VLD128
)
6901 SIMD_BUILTIN (void_Va_Ib_u8
, vst128_insn
, "vst128", VST128
)
6902 SIMD_BUILTIN (void_Va_Ib_u8
, vst64_insn
, "vst64", VST64
)
6904 /* Va, [Ib, u8] instructions. */
6905 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst16_n_insn
, "vst16_n", VST16_N
)
6906 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst32_n_insn
, "vst32_n", VST32_N
)
6908 SIMD_BUILTIN (void_u6
, vinti_insn
, "vinti", VINTI
)
6912 arc_init_simd_builtins (void)
6915 tree endlink
= void_list_node
;
6916 tree V8HI_type_node
= build_vector_type_for_mode (intHI_type_node
, V8HImode
);
6918 tree v8hi_ftype_v8hi_v8hi
6919 = build_function_type (V8HI_type_node
,
6920 tree_cons (NULL_TREE
, V8HI_type_node
,
6921 tree_cons (NULL_TREE
, V8HI_type_node
,
6923 tree v8hi_ftype_v8hi_int
6924 = build_function_type (V8HI_type_node
,
6925 tree_cons (NULL_TREE
, V8HI_type_node
,
6926 tree_cons (NULL_TREE
, integer_type_node
,
6929 tree v8hi_ftype_v8hi_int_int
6930 = build_function_type (V8HI_type_node
,
6931 tree_cons (NULL_TREE
, V8HI_type_node
,
6932 tree_cons (NULL_TREE
, integer_type_node
,
6933 tree_cons (NULL_TREE
,
6937 tree void_ftype_v8hi_int_int
6938 = build_function_type (void_type_node
,
6939 tree_cons (NULL_TREE
, V8HI_type_node
,
6940 tree_cons (NULL_TREE
, integer_type_node
,
6941 tree_cons (NULL_TREE
,
6945 tree void_ftype_v8hi_int_int_int
6946 = (build_function_type
6948 tree_cons (NULL_TREE
, V8HI_type_node
,
6949 tree_cons (NULL_TREE
, integer_type_node
,
6950 tree_cons (NULL_TREE
, integer_type_node
,
6951 tree_cons (NULL_TREE
,
6955 tree v8hi_ftype_int_int
6956 = build_function_type (V8HI_type_node
,
6957 tree_cons (NULL_TREE
, integer_type_node
,
6958 tree_cons (NULL_TREE
, integer_type_node
,
6961 tree void_ftype_int_int
6962 = build_function_type (void_type_node
,
6963 tree_cons (NULL_TREE
, integer_type_node
,
6964 tree_cons (NULL_TREE
, integer_type_node
,
6968 = build_function_type (void_type_node
,
6969 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
6971 tree v8hi_ftype_v8hi
6972 = build_function_type (V8HI_type_node
, tree_cons (NULL_TREE
, V8HI_type_node
,
6975 /* These asserts have been introduced to ensure that the order of builtins
6976 does not get messed up, else the initialization goes wrong. */
6977 gcc_assert (arc_simd_builtin_desc_list
[0].args_type
== Va_Vb_Vc
);
6978 for (i
=0; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Vc
; i
++)
6979 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6980 v8hi_ftype_v8hi_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
6982 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
);
6983 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
; i
++)
6984 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6985 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6987 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
);
6988 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
; i
++)
6989 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6990 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6992 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
);
6993 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
; i
++)
6994 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6995 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6997 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
);
6998 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
; i
++)
6999 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
7000 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
7002 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
);
7003 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
; i
++)
7004 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
7005 v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
7007 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
);
7008 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
; i
++)
7009 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
7010 v8hi_ftype_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
7012 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
);
7013 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
; i
++)
7014 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
7015 void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
7017 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
);
7018 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
; i
++)
7019 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
7020 void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
7022 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
);
7023 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
; i
++)
7024 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
7025 void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
7027 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
);
7028 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
; i
++)
7029 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
7030 v8hi_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
7032 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
);
7033 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
; i
++)
7034 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
7035 v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
7037 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
);
7038 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
; i
++)
7039 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
7040 void_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
7042 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
);
7043 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
; i
++)
7044 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
7045 void_ftype_v8hi_int_int_int
,
7046 arc_simd_builtin_desc_list
[i
].code
);
7048 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_u6
);
7049 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_u6
; i
++)
7050 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
7051 void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
7053 gcc_assert(i
== ARRAY_SIZE (arc_simd_builtin_desc_list
));
7056 /* Helper function of arc_expand_builtin; has the same parameters,
7057 except that EXP is now known to be a call to a simd builtin. */
7060 arc_expand_simd_builtin (tree exp
,
7062 rtx subtarget ATTRIBUTE_UNUSED
,
7063 machine_mode mode ATTRIBUTE_UNUSED
,
7064 int ignore ATTRIBUTE_UNUSED
)
7066 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
7078 int fcode
= DECL_FUNCTION_CODE (fndecl
);
7085 const struct builtin_description
* d
;
7087 for (i
= 0, d
= arc_simd_builtin_desc_list
;
7088 i
< ARRAY_SIZE (arc_simd_builtin_desc_list
); i
++, d
++)
7089 if (d
->code
== (const enum arc_builtins
) fcode
)
7092 /* We must get an entry here. */
7093 gcc_assert (i
< ARRAY_SIZE (arc_simd_builtin_desc_list
));
7095 switch (d
->args_type
)
7099 arg0
= CALL_EXPR_ARG (exp
, 0);
7100 arg1
= CALL_EXPR_ARG (exp
, 1);
7101 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7102 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7104 target
= gen_reg_rtx (V8HImode
);
7105 mode0
= insn_data
[icode
].operand
[1].mode
;
7106 mode1
= insn_data
[icode
].operand
[2].mode
;
7108 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7109 op0
= copy_to_mode_reg (mode0
, op0
);
7111 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7112 op1
= copy_to_mode_reg (mode1
, op1
);
7114 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7124 arg0
= CALL_EXPR_ARG (exp
, 0);
7125 arg1
= CALL_EXPR_ARG (exp
, 1);
7126 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7127 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7129 target
= gen_reg_rtx (V8HImode
);
7130 mode0
= insn_data
[icode
].operand
[1].mode
;
7131 mode1
= insn_data
[icode
].operand
[2].mode
;
7133 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7134 op0
= copy_to_mode_reg (mode0
, op0
);
7136 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
)
7137 || (d
->args_type
== Va_Vb_u6
&& !UNSIGNED_INT6 (INTVAL (op1
)))
7138 || (d
->args_type
== Va_Vb_u8
&& !UNSIGNED_INT8 (INTVAL (op1
))))
7139 error ("operand 2 of %s instruction should be an unsigned %d-bit value",
7141 (d
->args_type
== Va_Vb_u6
)? 6: 8);
7143 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7152 arg0
= CALL_EXPR_ARG (exp
, 0);
7153 arg1
= CALL_EXPR_ARG (exp
, 1);
7154 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7155 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7157 target
= gen_reg_rtx (V8HImode
);
7158 mode0
= insn_data
[icode
].operand
[1].mode
;
7159 mode1
= insn_data
[icode
].operand
[2].mode
;
7161 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7162 op0
= copy_to_mode_reg (mode0
, op0
);
7164 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7165 || !(UNSIGNED_INT8 (INTVAL (op1
))))
7166 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7169 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7178 arg0
= CALL_EXPR_ARG (exp
, 0);
7179 arg1
= CALL_EXPR_ARG (exp
, 1);
7180 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7181 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7182 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
7184 target
= gen_reg_rtx (V8HImode
);
7185 mode0
= insn_data
[icode
].operand
[1].mode
;
7186 mode1
= insn_data
[icode
].operand
[2].mode
;
7188 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7189 op0
= copy_to_mode_reg (mode0
, op0
);
7191 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7192 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7193 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7196 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
7205 arg0
= CALL_EXPR_ARG (exp
, 0);
7206 arg1
= CALL_EXPR_ARG (exp
, 1);
7207 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7208 op1
= expand_expr (arg1
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7210 target
= gen_reg_rtx (V8HImode
);
7211 mode0
= insn_data
[icode
].operand
[1].mode
;
7212 mode1
= insn_data
[icode
].operand
[2].mode
;
7214 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7215 op0
= copy_to_mode_reg (mode0
, op0
);
7217 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7218 op1
= copy_to_mode_reg (mode1
, op1
);
7220 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7229 arg0
= CALL_EXPR_ARG (exp
, 0);
7230 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7232 target
= gen_reg_rtx (V8HImode
);
7233 mode0
= insn_data
[icode
].operand
[1].mode
;
7235 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7236 op0
= copy_to_mode_reg (mode0
, op0
);
7238 pat
= GEN_FCN (icode
) (target
, op0
);
7245 case Da_rlimm_rlimm
:
7247 arg0
= CALL_EXPR_ARG (exp
, 0);
7248 arg1
= CALL_EXPR_ARG (exp
, 1);
7249 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7250 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7253 if (icode
== CODE_FOR_vdirun_insn
)
7254 target
= gen_rtx_REG (SImode
, 131);
7255 else if (icode
== CODE_FOR_vdorun_insn
)
7256 target
= gen_rtx_REG (SImode
, 139);
7260 mode0
= insn_data
[icode
].operand
[1].mode
;
7261 mode1
= insn_data
[icode
].operand
[2].mode
;
7263 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7264 op0
= copy_to_mode_reg (mode0
, op0
);
7266 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7267 op1
= copy_to_mode_reg (mode1
, op1
);
7270 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7279 arg0
= CALL_EXPR_ARG (exp
, 0);
7280 arg1
= CALL_EXPR_ARG (exp
, 1);
7281 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7282 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7285 if (! (GET_CODE (op0
) == CONST_INT
)
7286 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7287 error ("operand 1 of %s instruction should be an unsigned 3-bit value (DR0-DR7)",
7290 mode1
= insn_data
[icode
].operand
[1].mode
;
7292 if (icode
== CODE_FOR_vdiwr_insn
)
7293 target
= gen_rtx_REG (SImode
,
7294 ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
+ INTVAL (op0
));
7295 else if (icode
== CODE_FOR_vdowr_insn
)
7296 target
= gen_rtx_REG (SImode
,
7297 ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
+ INTVAL (op0
));
7301 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7302 op1
= copy_to_mode_reg (mode1
, op1
);
7304 pat
= GEN_FCN (icode
) (target
, op1
);
7313 arg0
= CALL_EXPR_ARG (exp
, 0);
7317 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7318 mode0
= insn_data
[icode
].operand
[0].mode
;
7320 /* op0 should be u6. */
7321 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
)
7322 || !(UNSIGNED_INT6 (INTVAL (op0
))))
7323 error ("operand of %s instruction should be an unsigned 6-bit value",
7326 pat
= GEN_FCN (icode
) (op0
);
7335 arg0
= CALL_EXPR_ARG (exp
, 0);
7339 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7340 mode0
= insn_data
[icode
].operand
[0].mode
;
7342 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7343 op0
= copy_to_mode_reg (mode0
, op0
);
7345 pat
= GEN_FCN (icode
) (op0
);
7356 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7357 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7358 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7360 src_vreg
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7361 op0
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* [I]0-7 */
7362 op1
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7363 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7365 /* target <- src vreg */
7366 emit_insn (gen_move_insn (target
, src_vreg
));
7368 /* target <- vec_concat: target, mem(Ib, u8) */
7369 mode0
= insn_data
[icode
].operand
[3].mode
;
7370 mode1
= insn_data
[icode
].operand
[1].mode
;
7372 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op0
, mode0
))
7373 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7374 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7377 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7378 || !(UNSIGNED_INT8 (INTVAL (op1
))))
7379 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7382 pat
= GEN_FCN (icode
) (target
, op1
, op2
, op0
);
7392 arg0
= CALL_EXPR_ARG (exp
, 0); /* src vreg */
7393 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7394 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7396 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7397 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* I[0-7] */
7398 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7399 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
); /* Vdest */
7401 mode0
= insn_data
[icode
].operand
[0].mode
;
7402 mode1
= insn_data
[icode
].operand
[1].mode
;
7403 mode2
= insn_data
[icode
].operand
[2].mode
;
7404 mode3
= insn_data
[icode
].operand
[3].mode
;
7406 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7407 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7408 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7411 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7412 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7413 error ("operand 3 of %s instruction should be an unsigned 8-bit value",
7416 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7417 op3
= copy_to_mode_reg (mode3
, op3
);
7419 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
);
7428 arg0
= CALL_EXPR_ARG (exp
, 0); /* dest vreg */
7429 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7431 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7432 op1
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* I[0-7] */
7433 op2
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7435 /* target <- src vreg */
7436 target
= gen_reg_rtx (V8HImode
);
7438 /* target <- vec_concat: target, mem(Ib, u8) */
7439 mode0
= insn_data
[icode
].operand
[1].mode
;
7440 mode1
= insn_data
[icode
].operand
[2].mode
;
7441 mode2
= insn_data
[icode
].operand
[3].mode
;
7443 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7444 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7445 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7448 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op2
, mode2
))
7449 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7450 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7453 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
7460 case void_Va_u3_Ib_u8
:
7462 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7463 arg1
= CALL_EXPR_ARG (exp
, 1); /* u3 */
7464 arg2
= CALL_EXPR_ARG (exp
, 2); /* [I]0-7 */
7465 arg3
= CALL_EXPR_ARG (exp
, 3); /* u8 */
7467 op0
= expand_expr (arg3
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7468 op1
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR */
7469 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* [I]0-7 */
7470 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);/* vreg to be stored */
7471 op4
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* vreg 0-7 subreg no. */
7473 mode0
= insn_data
[icode
].operand
[0].mode
;
7474 mode2
= insn_data
[icode
].operand
[2].mode
;
7475 mode3
= insn_data
[icode
].operand
[3].mode
;
7476 mode4
= insn_data
[icode
].operand
[4].mode
;
7478 /* Do some correctness checks for the operands. */
7479 if ( (!(*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7480 || !(UNSIGNED_INT8 (INTVAL (op0
))))
7481 error ("operand 4 of %s instruction should be an unsigned 8-bit value (0-255)",
7484 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7485 || !(UNSIGNED_INT3 (INTVAL (op2
))))
7486 error ("operand 3 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7489 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7490 op3
= copy_to_mode_reg (mode3
, op3
);
7492 if ( (!(*insn_data
[icode
].operand
[4].predicate
) (op4
, mode4
))
7493 || !(UNSIGNED_INT3 (INTVAL (op4
))))
7494 error ("operand 2 of %s instruction should be an unsigned 3-bit value (subreg 0-7)",
7496 else if (icode
== CODE_FOR_vst32_n_insn
7497 && ((INTVAL(op4
) % 2 ) != 0))
7498 error ("operand 2 of %s instruction should be an even 3-bit value (subreg 0,2,4,6)",
7501 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
, op4
);
7515 arc_preserve_reload_p (rtx in
)
7517 return (GET_CODE (in
) == PLUS
7518 && RTX_OK_FOR_BASE_P (XEXP (in
, 0), true)
7519 && CONST_INT_P (XEXP (in
, 1))
7520 && !((INTVAL (XEXP (in
, 1)) & 511)));
7524 arc_register_move_cost (machine_mode
,
7525 enum reg_class from_class
, enum reg_class to_class
)
7527 /* The ARC600 has no bypass for extension registers, hence a nop might be
7528 needed to be inserted after a write so that reads are safe. */
7531 if (to_class
== MPY_WRITABLE_CORE_REGS
)
7533 /* Instructions modifying LP_COUNT need 4 additional cycles before
7534 the register will actually contain the value. */
7535 else if (to_class
== LPCOUNT_REG
)
7537 else if (to_class
== WRITABLE_CORE_REGS
)
7541 /* The ARC700 stalls for 3 cycles when *reading* from lp_count. */
7543 && (from_class
== LPCOUNT_REG
|| from_class
== ALL_CORE_REGS
7544 || from_class
== WRITABLE_CORE_REGS
))
7547 /* Force an attempt to 'mov Dy,Dx' to spill. */
7548 if (TARGET_ARC700
&& TARGET_DPFP
7549 && from_class
== DOUBLE_REGS
&& to_class
== DOUBLE_REGS
)
7555 /* Emit code for an addsi3 instruction with OPERANDS.
7556 COND_P indicates if this will use conditional execution.
7557 Return the length of the instruction.
7558 If OUTPUT_P is false, don't actually output the instruction, just return
7561 arc_output_addsi (rtx
*operands
, bool cond_p
, bool output_p
)
7565 int match
= operands_match_p (operands
[0], operands
[1]);
7566 int match2
= operands_match_p (operands
[0], operands
[2]);
7567 int intval
= (REG_P (operands
[2]) ? 1
7568 : CONST_INT_P (operands
[2]) ? INTVAL (operands
[2]) : 0xbadc057);
7569 int neg_intval
= -intval
;
7570 int short_0
= satisfies_constraint_Rcq (operands
[0]);
7571 int short_p
= (!cond_p
&& short_0
&& satisfies_constraint_Rcq (operands
[1]));
7574 #define ADDSI_OUTPUT1(FORMAT) do {\
7576 output_asm_insn (FORMAT, operands);\
7579 #define ADDSI_OUTPUT(LIST) do {\
7582 ADDSI_OUTPUT1 (format);\
7586 /* First try to emit a 16 bit insn. */
7589 /* If we are actually about to output this insn, don't try a 16 bit
7590 variant if we already decided that we don't want that
7591 (I.e. we upsized this insn to align some following insn.)
7592 E.g. add_s r0,sp,70 is 16 bit, but add r0,sp,70 requires a LIMM -
7593 but add1 r0,sp,35 doesn't. */
7594 && (!output_p
|| (get_attr_length (current_output_insn
) & 2)))
7597 && (REG_P (operands
[2])
7598 ? (match
|| satisfies_constraint_Rcq (operands
[2]))
7599 : (unsigned) intval
<= (match
? 127 : 7)))
7600 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7601 if (short_0
&& REG_P (operands
[1]) && match2
)
7602 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7603 if ((short_0
|| REGNO (operands
[0]) == STACK_POINTER_REGNUM
)
7604 && REGNO (operands
[1]) == STACK_POINTER_REGNUM
&& !(intval
& ~124))
7605 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7607 if ((short_p
&& (unsigned) neg_intval
<= (match
? 31 : 7))
7608 || (REGNO (operands
[0]) == STACK_POINTER_REGNUM
7609 && match
&& !(neg_intval
& ~124)))
7610 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7613 /* Now try to emit a 32 bit insn without long immediate. */
7615 if (!match
&& match2
&& REG_P (operands
[1]))
7616 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7617 if (match
|| !cond_p
)
7619 int limit
= (match
&& !cond_p
) ? 0x7ff : 0x3f;
7620 int range_factor
= neg_intval
& intval
;
7623 if (intval
== (HOST_WIDE_INT
) (HOST_WIDE_INT_M1U
<< 31))
7624 ADDSI_OUTPUT1 ("bxor%? %0,%1,31");
7626 /* If we can use a straight add / sub instead of a {add,sub}[123] of
7627 same size, do, so - the insn latency is lower. */
7628 /* -0x800 is a 12-bit constant for add /add3 / sub / sub3, but
7630 if ((intval
>= 0 && intval
<= limit
)
7631 || (intval
== -0x800 && limit
== 0x7ff))
7632 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7633 else if ((intval
< 0 && neg_intval
<= limit
)
7634 || (intval
== 0x800 && limit
== 0x7ff))
7635 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7636 shift
= range_factor
>= 8 ? 3 : (range_factor
>> 1);
7637 gcc_assert (shift
== 0 || shift
== 1 || shift
== 2 || shift
== 3);
7638 gcc_assert ((((1 << shift
) - 1) & intval
) == 0);
7639 if (((intval
< 0 && intval
!= -0x4000)
7640 /* sub[123] is slower than add_s / sub, only use it if it
7641 avoids a long immediate. */
7642 && neg_intval
<= limit
<< shift
)
7643 || (intval
== 0x4000 && limit
== 0x7ff))
7644 ADDSI_OUTPUT ((format
, "sub%d%%? %%0,%%1,%d",
7645 shift
, neg_intval
>> shift
));
7646 else if ((intval
>= 0 && intval
<= limit
<< shift
)
7647 || (intval
== -0x4000 && limit
== 0x7ff))
7648 ADDSI_OUTPUT ((format
, "add%d%%? %%0,%%1,%d", shift
, intval
>> shift
));
7650 /* Try to emit a 16 bit opcode with long immediate. */
7652 if (short_p
&& match
)
7653 ADDSI_OUTPUT1 ("add%? %0,%1,%S2");
7655 /* We have to use a 32 bit opcode, and with a long immediate. */
7657 ADDSI_OUTPUT1 (intval
< 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%S2");
7660 /* Emit code for an commutative_cond_exec instruction with OPERANDS.
7661 Return the length of the instruction.
7662 If OUTPUT_P is false, don't actually output the instruction, just return
7665 arc_output_commutative_cond_exec (rtx
*operands
, bool output_p
)
7667 enum rtx_code commutative_op
= GET_CODE (operands
[3]);
7668 const char *pat
= NULL
;
7670 /* Canonical rtl should not have a constant in the first operand position. */
7671 gcc_assert (!CONSTANT_P (operands
[1]));
7673 switch (commutative_op
)
7676 if (satisfies_constraint_C1p (operands
[2]))
7677 pat
= "bmsk%? %0,%1,%Z2";
7678 else if (satisfies_constraint_Ccp (operands
[2]))
7679 pat
= "bclr%? %0,%1,%M2";
7680 else if (satisfies_constraint_CnL (operands
[2]))
7681 pat
= "bic%? %0,%1,%n2-1";
7684 if (satisfies_constraint_C0p (operands
[2]))
7685 pat
= "bset%? %0,%1,%z2";
7688 if (satisfies_constraint_C0p (operands
[2]))
7689 pat
= "bxor%? %0,%1,%z2";
7692 return arc_output_addsi (operands
, true, output_p
);
7696 output_asm_insn (pat
? pat
: "%O3.%d5 %0,%1,%2", operands
);
7697 if (pat
|| REG_P (operands
[2]) || satisfies_constraint_L (operands
[2]))
7702 /* Helper function of arc_expand_movmem. ADDR points to a chunk of memory.
7703 Emit code and return an potentially modified address such that offsets
7704 up to SIZE are can be added to yield a legitimate address.
7705 if REUSE is set, ADDR is a register that may be modified. */
7708 force_offsettable (rtx addr
, HOST_WIDE_INT size
, bool reuse
)
7711 rtx offs
= const0_rtx
;
7713 if (GET_CODE (base
) == PLUS
)
7715 offs
= XEXP (base
, 1);
7716 base
= XEXP (base
, 0);
7719 || (REGNO (base
) != STACK_POINTER_REGNUM
7720 && REGNO_PTR_FRAME_P (REGNO (addr
)))
7721 || !CONST_INT_P (offs
) || !SMALL_INT (INTVAL (offs
))
7722 || !SMALL_INT (INTVAL (offs
) + size
))
7725 emit_insn (gen_add2_insn (addr
, offs
));
7727 addr
= copy_to_mode_reg (Pmode
, addr
);
7732 /* Like move_by_pieces, but take account of load latency,
7733 and actual offset ranges.
7734 Return true on success. */
7737 arc_expand_movmem (rtx
*operands
)
7739 rtx dst
= operands
[0];
7740 rtx src
= operands
[1];
7741 rtx dst_addr
, src_addr
;
7743 int align
= INTVAL (operands
[3]);
7750 if (!CONST_INT_P (operands
[2]))
7752 size
= INTVAL (operands
[2]);
7753 /* move_by_pieces_ninsns is static, so we can't use it. */
7755 n_pieces
= (size
+ 2) / 4U + (size
& 1);
7756 else if (align
== 2)
7757 n_pieces
= (size
+ 1) / 2U;
7760 if (n_pieces
>= (unsigned int) (optimize_size
? 3 : 15))
7764 dst_addr
= force_offsettable (XEXP (operands
[0], 0), size
, 0);
7765 src_addr
= force_offsettable (XEXP (operands
[1], 0), size
, 0);
7766 store
[0] = store
[1] = NULL_RTX
;
7767 tmpx
[0] = tmpx
[1] = NULL_RTX
;
7768 for (i
= 0; size
> 0; i
^= 1, size
-= piece
)
7774 piece
= size
& -size
;
7775 mode
= smallest_mode_for_size (piece
* BITS_PER_UNIT
, MODE_INT
);
7776 /* If we don't re-use temporaries, the scheduler gets carried away,
7777 and the register pressure gets unnecessarily high. */
7778 if (0 && tmpx
[i
] && GET_MODE (tmpx
[i
]) == mode
)
7781 tmpx
[i
] = tmp
= gen_reg_rtx (mode
);
7782 dst_addr
= force_offsettable (dst_addr
, piece
, 1);
7783 src_addr
= force_offsettable (src_addr
, piece
, 1);
7785 emit_insn (store
[i
]);
7786 emit_move_insn (tmp
, change_address (src
, mode
, src_addr
));
7787 store
[i
] = gen_move_insn (change_address (dst
, mode
, dst_addr
), tmp
);
7788 dst_addr
= plus_constant (Pmode
, dst_addr
, piece
);
7789 src_addr
= plus_constant (Pmode
, src_addr
, piece
);
7792 emit_insn (store
[i
]);
7794 emit_insn (store
[i
^1]);
7798 /* Prepare operands for move in MODE. Return true iff the move has
7802 prepare_move_operands (rtx
*operands
, machine_mode mode
)
7804 /* We used to do this only for MODE_INT Modes, but addresses to floating
7805 point variables may well be in the small data section. */
7808 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[0], Pmode
))
7809 operands
[0] = arc_rewrite_small_data (operands
[0]);
7810 else if (mode
== SImode
&& flag_pic
&& SYMBOLIC_CONST (operands
[1]))
7812 emit_pic_move (operands
, SImode
);
7814 /* Disable any REG_EQUALs associated with the symref
7815 otherwise the optimization pass undoes the work done
7816 here and references the variable directly. */
7818 else if (GET_CODE (operands
[0]) != MEM
7819 && !TARGET_NO_SDATA_SET
7820 && small_data_pattern (operands
[1], Pmode
))
7822 /* This is to take care of address calculations involving sdata
7824 operands
[1] = arc_rewrite_small_data (operands
[1]);
7826 emit_insn (gen_rtx_SET (operands
[0],operands
[1]));
7827 /* ??? This note is useless, since it only restates the set itself.
7828 We should rather use the original SYMBOL_REF. However, there is
7829 the problem that we are lying to the compiler about these
7830 SYMBOL_REFs to start with. symbol@sda should be encoded specially
7831 so that we can tell it apart from an actual symbol. */
7832 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7834 /* Take care of the REG_EQUAL note that will be attached to mark the
7835 output reg equal to the initial symbol_ref after this code is
7837 emit_move_insn (operands
[0], operands
[0]);
7842 if (MEM_P (operands
[0])
7843 && !(reload_in_progress
|| reload_completed
))
7845 operands
[1] = force_reg (mode
, operands
[1]);
7846 if (!move_dest_operand (operands
[0], mode
))
7848 rtx addr
= copy_to_mode_reg (Pmode
, XEXP (operands
[0], 0));
7849 /* This is like change_address_1 (operands[0], mode, 0, 1) ,
7850 except that we can't use that function because it is static. */
7851 rtx pat
= change_address (operands
[0], mode
, addr
);
7852 MEM_COPY_ATTRIBUTES (pat
, operands
[0]);
7855 if (!cse_not_expected
)
7857 rtx pat
= XEXP (operands
[0], 0);
7859 pat
= arc_legitimize_address_0 (pat
, pat
, mode
);
7862 pat
= change_address (operands
[0], mode
, pat
);
7863 MEM_COPY_ATTRIBUTES (pat
, operands
[0]);
7869 if (MEM_P (operands
[1]) && !cse_not_expected
)
7871 rtx pat
= XEXP (operands
[1], 0);
7873 pat
= arc_legitimize_address_0 (pat
, pat
, mode
);
7876 pat
= change_address (operands
[1], mode
, pat
);
7877 MEM_COPY_ATTRIBUTES (pat
, operands
[1]);
7885 /* Prepare OPERANDS for an extension using CODE to OMODE.
7886 Return true iff the move has been emitted. */
7889 prepare_extend_operands (rtx
*operands
, enum rtx_code code
,
7892 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[1], Pmode
))
7894 /* This is to take care of address calculations involving sdata
7897 = gen_rtx_fmt_e (code
, omode
, arc_rewrite_small_data (operands
[1]));
7898 emit_insn (gen_rtx_SET (operands
[0], operands
[1]));
7899 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7901 /* Take care of the REG_EQUAL note that will be attached to mark the
7902 output reg equal to the initial extension after this code is
7904 emit_move_insn (operands
[0], operands
[0]);
7910 /* Output a library call to a function called FNAME that has been arranged
7911 to be local to any dso. */
7914 arc_output_libcall (const char *fname
)
7916 unsigned len
= strlen (fname
);
7917 static char buf
[64];
7919 gcc_assert (len
< sizeof buf
- 35);
7920 if (TARGET_LONG_CALLS_SET
7921 || (TARGET_MEDIUM_CALLS
&& arc_ccfsm_cond_exec_p ()))
7924 sprintf (buf
, "add r12,pcl,@%s-(.&-4)\n\tjl%%!%%* [r12]", fname
);
7926 sprintf (buf
, "jl%%! @%s", fname
);
7929 sprintf (buf
, "bl%%!%%* @%s", fname
);
7933 /* Return the SImode highpart of the DImode value IN. */
7936 disi_highpart (rtx in
)
7938 return simplify_gen_subreg (SImode
, in
, DImode
, TARGET_BIG_ENDIAN
? 0 : 4);
7941 /* Return length adjustment for INSN.
7943 A write to a core reg greater or equal to 32 must not be immediately
7944 followed by a use. Anticipate the length requirement to insert a nop
7945 between PRED and SUCC to prevent a hazard. */
7948 arc600_corereg_hazard (rtx_insn
*pred
, rtx_insn
*succ
)
7952 /* If SUCC is a doloop_end_i with a preceding label, we must output a nop
7953 in front of SUCC anyway, so there will be separation between PRED and
7955 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
7956 && LABEL_P (prev_nonnote_insn (succ
)))
7958 if (recog_memoized (succ
) == CODE_FOR_doloop_begin_i
)
7960 if (GET_CODE (PATTERN (pred
)) == SEQUENCE
)
7961 pred
= as_a
<rtx_sequence
*> (PATTERN (pred
))->insn (1);
7962 if (GET_CODE (PATTERN (succ
)) == SEQUENCE
)
7963 succ
= as_a
<rtx_sequence
*> (PATTERN (succ
))->insn (0);
7964 if (recog_memoized (pred
) == CODE_FOR_mulsi_600
7965 || recog_memoized (pred
) == CODE_FOR_umul_600
7966 || recog_memoized (pred
) == CODE_FOR_mac_600
7967 || recog_memoized (pred
) == CODE_FOR_mul64_600
7968 || recog_memoized (pred
) == CODE_FOR_mac64_600
7969 || recog_memoized (pred
) == CODE_FOR_umul64_600
7970 || recog_memoized (pred
) == CODE_FOR_umac64_600
)
7972 subrtx_iterator::array_type array
;
7973 FOR_EACH_SUBRTX (iter
, array
, PATTERN (pred
), NONCONST
)
7975 const_rtx x
= *iter
;
7976 switch (GET_CODE (x
))
7978 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
7981 /* This is also fine for PRE/POST_MODIFY, because they
7985 rtx dest
= XEXP (x
, 0);
7986 /* Check if this sets a an extension register. N.B. we use 61 for the
7987 condition codes, which is definitely not an extension register. */
7988 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61
7989 /* Check if the same register is used by the PAT. */
7990 && (refers_to_regno_p
7992 REGNO (dest
) + (GET_MODE_SIZE (GET_MODE (dest
)) + 3) / 4U,
7993 PATTERN (succ
), 0)))
7999 /* Given a rtx, check if it is an assembly instruction or not. */
8002 arc_asm_insn_p (rtx x
)
8009 switch (GET_CODE (x
))
8016 return arc_asm_insn_p (SET_SRC (x
));
8020 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
8021 j
+= arc_asm_insn_p (XVECEXP (x
, 0, i
));
8033 /* We might have a CALL to a non-returning function before a loop end.
8034 ??? Although the manual says that's OK (the target is outside the
8035 loop, and the loop counter unused there), the assembler barfs on
8036 this for ARC600, so we must insert a nop before such a call too.
8037 For ARC700, and ARCv2 is not allowed to have the last ZOL
8038 instruction a jump to a location where lp_count is modified. */
8041 arc_loop_hazard (rtx_insn
*pred
, rtx_insn
*succ
)
8043 rtx_insn
*jump
= NULL
;
8044 rtx_insn
*label
= NULL
;
8045 basic_block succ_bb
;
8047 if (recog_memoized (succ
) != CODE_FOR_doloop_end_i
)
8050 /* Phase 1: ARC600 and ARCv2HS doesn't allow any control instruction
8051 (i.e., jump/call) as the last instruction of a ZOL. */
8052 if (TARGET_ARC600
|| TARGET_HS
)
8053 if (JUMP_P (pred
) || CALL_P (pred
)
8054 || arc_asm_insn_p (PATTERN (pred
))
8055 || GET_CODE (PATTERN (pred
)) == SEQUENCE
)
8058 /* Phase 2: Any architecture, it is not allowed to have the last ZOL
8059 instruction a jump to a location where lp_count is modified. */
8061 /* Phase 2a: Dig for the jump instruction. */
8064 else if (GET_CODE (PATTERN (pred
)) == SEQUENCE
8065 && JUMP_P (XVECEXP (PATTERN (pred
), 0, 0)))
8066 jump
= as_a
<rtx_insn
*> XVECEXP (PATTERN (pred
), 0, 0);
8070 label
= JUMP_LABEL_AS_INSN (jump
);
8074 /* Phase 2b: Make sure is not a millicode jump. */
8075 if ((GET_CODE (PATTERN (jump
)) == PARALLEL
)
8076 && (XVECEXP (PATTERN (jump
), 0, 0) == ret_rtx
))
8079 /* Phase 2c: Make sure is not a simple_return. */
8080 if ((GET_CODE (PATTERN (jump
)) == SIMPLE_RETURN
)
8081 || (GET_CODE (label
) == SIMPLE_RETURN
))
8084 /* Pahse 2d: Go to the target of the jump and check for aliveness of
8085 LP_COUNT register. */
8086 succ_bb
= BLOCK_FOR_INSN (label
);
8089 gcc_assert (NEXT_INSN (label
));
8090 if (NOTE_INSN_BASIC_BLOCK_P (NEXT_INSN (label
)))
8091 succ_bb
= NOTE_BASIC_BLOCK (NEXT_INSN (label
));
8093 succ_bb
= BLOCK_FOR_INSN (NEXT_INSN (label
));
8096 if (succ_bb
&& REGNO_REG_SET_P (df_get_live_out (succ_bb
), LP_COUNT
))
8103 A write to a core reg greater or equal to 32 must not be immediately
8104 followed by a use. Anticipate the length requirement to insert a nop
8105 between PRED and SUCC to prevent a hazard. */
8108 arc_hazard (rtx_insn
*pred
, rtx_insn
*succ
)
8110 if (!pred
|| !INSN_P (pred
) || !succ
|| !INSN_P (succ
))
8113 if (arc_loop_hazard (pred
, succ
))
8117 return arc600_corereg_hazard (pred
, succ
);
8122 /* Return length adjustment for INSN. */
8125 arc_adjust_insn_length (rtx_insn
*insn
, int len
, bool)
8129 /* We already handle sequences by ignoring the delay sequence flag. */
8130 if (GET_CODE (PATTERN (insn
)) == SEQUENCE
)
8133 /* It is impossible to jump to the very end of a Zero-Overhead Loop, as
8134 the ZOL mechanism only triggers when advancing to the end address,
8135 so if there's a label at the end of a ZOL, we need to insert a nop.
8136 The ARC600 ZOL also has extra restrictions on jumps at the end of a
8138 if (recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
8140 rtx_insn
*prev
= prev_nonnote_insn (insn
);
8142 return ((LABEL_P (prev
)
8145 || CALL_P (prev
) /* Could be a noreturn call. */
8146 || (NONJUMP_INSN_P (prev
)
8147 && GET_CODE (PATTERN (prev
)) == SEQUENCE
))))
8151 /* Check for return with but one preceding insn since function
8153 if (TARGET_PAD_RETURN
8155 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
8156 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
8157 && get_attr_type (insn
) == TYPE_RETURN
)
8159 rtx_insn
*prev
= prev_active_insn (insn
);
8161 if (!prev
|| !(prev
= prev_active_insn (prev
))
8162 || ((NONJUMP_INSN_P (prev
)
8163 && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8164 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
8166 : CALL_ATTR (prev
, NON_SIBCALL
)))
8171 rtx_insn
*succ
= next_real_insn (insn
);
8173 /* One the ARC600, a write to an extension register must be separated
8175 if (succ
&& INSN_P (succ
))
8176 len
+= arc600_corereg_hazard (insn
, succ
);
8179 /* Restore extracted operands - otherwise splitters like the addsi3_mixed one
8181 extract_constrain_insn_cached (insn
);
8186 /* Values for length_sensitive. */
8190 ARC_LS_25
, // 25 bit offset, B
8191 ARC_LS_21
, // 21 bit offset, Bcc
8192 ARC_LS_U13
,// 13 bit unsigned offset, LP
8193 ARC_LS_10
, // 10 bit offset, B_s, Beq_s, Bne_s
8194 ARC_LS_9
, // 9 bit offset, BRcc
8195 ARC_LS_8
, // 8 bit offset, BRcc_s
8196 ARC_LS_U7
, // 7 bit unsigned offset, LPcc
8197 ARC_LS_7
// 7 bit offset, Bcc_s
8200 /* While the infrastructure patch is waiting for review, duplicate the
8201 struct definitions, to allow this file to compile. */
8206 /* Cost as a branch / call target or call return address. */
8208 int fallthrough_cost
;
8211 /* 0 for not length sensitive, 1 for largest offset range,
8212 * 2 for next smaller etc. */
8213 unsigned length_sensitive
: 8;
8215 } insn_length_variant_t
;
8217 typedef struct insn_length_parameters_s
8222 int (*get_variants
) (rtx_insn
*, int, bool, bool, insn_length_variant_t
*);
8223 } insn_length_parameters_t
;
8226 arc_insn_length_parameters (insn_length_parameters_t
*ilp
) ATTRIBUTE_UNUSED
;
8230 arc_get_insn_variants (rtx_insn
*insn
, int len
, bool, bool target_p
,
8231 insn_length_variant_t
*ilv
)
8233 if (!NONDEBUG_INSN_P (insn
))
8235 enum attr_type type
;
8236 /* shorten_branches doesn't take optimize_size into account yet for the
8237 get_variants mechanism, so turn this off for now. */
8240 if (rtx_sequence
*pat
= dyn_cast
<rtx_sequence
*> (PATTERN (insn
)))
8242 /* The interaction of a short delay slot insn with a short branch is
8243 too weird for shorten_branches to piece together, so describe the
8246 if (TARGET_UPSIZE_DBR
8247 && get_attr_length (pat
->insn (1)) <= 2
8248 && (((type
= get_attr_type (inner
= pat
->insn (0)))
8249 == TYPE_UNCOND_BRANCH
)
8250 || type
== TYPE_BRANCH
)
8251 && get_attr_delay_slot_filled (inner
) == DELAY_SLOT_FILLED_YES
)
8254 = arc_get_insn_variants (inner
, get_attr_length (inner
), true,
8256 /* The short variant gets split into a higher-cost aligned
8257 and a lower cost unaligned variant. */
8258 gcc_assert (n_variants
);
8259 gcc_assert (ilv
[1].length_sensitive
== ARC_LS_7
8260 || ilv
[1].length_sensitive
== ARC_LS_10
);
8261 gcc_assert (ilv
[1].align_set
== 3);
8263 ilv
[0].align_set
= 1;
8264 ilv
[0].branch_cost
+= 1;
8265 ilv
[1].align_set
= 2;
8267 for (int i
= 0; i
< n_variants
; i
++)
8269 /* In case an instruction with aligned size is wanted, and
8270 the short variants are unavailable / too expensive, add
8271 versions of long branch + long delay slot. */
8272 for (int i
= 2, end
= n_variants
; i
< end
; i
++, n_variants
++)
8274 ilv
[n_variants
] = ilv
[i
];
8275 ilv
[n_variants
].length
+= 2;
8281 insn_length_variant_t
*first_ilv
= ilv
;
8282 type
= get_attr_type (insn
);
8284 = (get_attr_delay_slot_filled (insn
) == DELAY_SLOT_FILLED_YES
);
8285 int branch_align_cost
= delay_filled
? 0 : 1;
8286 int branch_unalign_cost
= delay_filled
? 0 : TARGET_UNALIGN_BRANCH
? 0 : 1;
8287 /* If the previous instruction is an sfunc call, this insn is always
8288 a target, even though the middle-end is unaware of this. */
8289 bool force_target
= false;
8290 rtx_insn
*prev
= prev_active_insn (insn
);
8291 if (prev
&& arc_next_active_insn (prev
, 0) == insn
8292 && ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8293 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
8295 : (CALL_ATTR (prev
, NON_SIBCALL
)
8296 && NEXT_INSN (PREV_INSN (prev
)) == prev
)))
8297 force_target
= true;
8302 /* Short BRCC only comes in no-delay-slot version, and without limm */
8307 ilv
->branch_cost
= 1;
8308 ilv
->enabled
= (len
== 2);
8309 ilv
->length_sensitive
= ARC_LS_8
;
8313 case TYPE_BRCC_NO_DELAY_SLOT
:
8314 /* doloop_fallback* patterns are TYPE_BRCC_NO_DELAY_SLOT for
8315 (delay slot) scheduling purposes, but they are longer. */
8316 if (GET_CODE (PATTERN (insn
)) == PARALLEL
8317 && GET_CODE (XVECEXP (PATTERN (insn
), 0, 1)) == SET
)
8319 /* Standard BRCC: 4 bytes, or 8 bytes with limm. */
8320 ilv
->length
= ((type
== TYPE_BRCC
) ? 4 : 8);
8322 ilv
->branch_cost
= branch_align_cost
;
8323 ilv
->enabled
= (len
<= ilv
->length
);
8324 ilv
->length_sensitive
= ARC_LS_9
;
8325 if ((target_p
|| force_target
)
8326 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8332 ilv
->target_cost
= 1;
8333 ilv
->branch_cost
= branch_unalign_cost
;
8338 op
= XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 0);
8341 if (GET_CODE (op0
) == ZERO_EXTRACT
8342 && satisfies_constraint_L (XEXP (op0
, 2)))
8343 op0
= XEXP (op0
, 0);
8344 if (satisfies_constraint_Rcq (op0
))
8346 ilv
->length
= ((type
== TYPE_BRCC
) ? 6 : 10);
8348 ilv
->branch_cost
= 1 + branch_align_cost
;
8349 ilv
->fallthrough_cost
= 1;
8350 ilv
->enabled
= true;
8351 ilv
->length_sensitive
= ARC_LS_21
;
8352 if (!delay_filled
&& TARGET_UNALIGN_BRANCH
)
8358 ilv
->branch_cost
= 1 + branch_unalign_cost
;
8362 ilv
->length
= ((type
== TYPE_BRCC
) ? 8 : 12);
8364 ilv
->branch_cost
= 1 + branch_align_cost
;
8365 ilv
->fallthrough_cost
= 1;
8366 ilv
->enabled
= true;
8367 ilv
->length_sensitive
= ARC_LS_21
;
8368 if ((target_p
|| force_target
)
8369 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8375 ilv
->target_cost
= 1;
8376 ilv
->branch_cost
= 1 + branch_unalign_cost
;
8384 case TYPE_CALL_NO_DELAY_SLOT
:
8389 ilv
->length_sensitive
8390 = GET_CODE (PATTERN (insn
)) == COND_EXEC
? ARC_LS_21
: ARC_LS_25
;
8393 ilv
->fallthrough_cost
= branch_align_cost
;
8394 ilv
->enabled
= true;
8395 if ((target_p
|| force_target
)
8396 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8402 ilv
->target_cost
= 1;
8403 ilv
->fallthrough_cost
= branch_unalign_cost
;
8407 case TYPE_UNCOND_BRANCH
:
8408 /* Strictly speaking, this should be ARC_LS_10 for equality comparisons,
8409 but that makes no difference at the moment. */
8410 ilv
->length_sensitive
= ARC_LS_7
;
8411 ilv
[1].length_sensitive
= ARC_LS_25
;
8414 ilv
->length_sensitive
= ARC_LS_10
;
8415 ilv
[1].length_sensitive
= ARC_LS_21
;
8419 ilv
->branch_cost
= branch_align_cost
;
8420 ilv
->enabled
= (len
== ilv
->length
);
8424 ilv
->branch_cost
= branch_align_cost
;
8425 ilv
->enabled
= true;
8426 if ((target_p
|| force_target
)
8427 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8433 ilv
->target_cost
= 1;
8434 ilv
->branch_cost
= branch_unalign_cost
;
8441 /* For every short insn, there is generally also a long insn.
8442 trap_s is an exception. */
8443 if ((len
& 2) == 0 || recog_memoized (insn
) == CODE_FOR_trap_s
)
8450 ilv
->length
= len
+ 2;
8452 if (target_p
|| force_target
)
8458 ilv
->target_cost
= 1;
8462 /* If the previous instruction is an sfunc call, this insn is always
8463 a target, even though the middle-end is unaware of this.
8464 Therefore, if we have a call predecessor, transfer the target cost
8465 to the fallthrough and branch costs. */
8468 for (insn_length_variant_t
*p
= first_ilv
; p
< ilv
; p
++)
8470 p
->fallthrough_cost
+= p
->target_cost
;
8471 p
->branch_cost
+= p
->target_cost
;
8476 return ilv
- first_ilv
;
8480 arc_insn_length_parameters (insn_length_parameters_t
*ilp
)
8482 ilp
->align_unit_log
= 1;
8483 ilp
->align_base_log
= 1;
8484 ilp
->max_variants
= 7;
8485 ilp
->get_variants
= arc_get_insn_variants
;
8488 /* Return a copy of COND from *STATEP, inverted if that is indicated by the
8489 CC field of *STATEP. */
8492 arc_get_ccfsm_cond (struct arc_ccfsm
*statep
, bool reverse
)
8494 rtx cond
= statep
->cond
;
8495 int raw_cc
= get_arc_condition_code (cond
);
8497 raw_cc
= ARC_INVERSE_CONDITION_CODE (raw_cc
);
8499 if (statep
->cc
== raw_cc
)
8500 return copy_rtx (cond
);
8502 gcc_assert (ARC_INVERSE_CONDITION_CODE (raw_cc
) == statep
->cc
);
8504 machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
8505 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
8506 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
8507 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
8509 return gen_rtx_fmt_ee (code
, GET_MODE (cond
),
8510 copy_rtx (XEXP (cond
, 0)), copy_rtx (XEXP (cond
, 1)));
8513 /* Return version of PAT conditionalized with COND, which is part of INSN.
8514 ANNULLED indicates if INSN is an annulled delay-slot insn.
8515 Register further changes if necessary. */
8517 conditionalize_nonjump (rtx pat
, rtx cond
, rtx insn
, bool annulled
)
8519 /* For commutative operators, we generally prefer to have
8520 the first source match the destination. */
8521 if (GET_CODE (pat
) == SET
)
8523 rtx src
= SET_SRC (pat
);
8525 if (COMMUTATIVE_P (src
))
8527 rtx src0
= XEXP (src
, 0);
8528 rtx src1
= XEXP (src
, 1);
8529 rtx dst
= SET_DEST (pat
);
8531 if (rtx_equal_p (src1
, dst
) && !rtx_equal_p (src0
, dst
)
8532 /* Leave add_n alone - the canonical form is to
8533 have the complex summand first. */
8535 pat
= gen_rtx_SET (dst
,
8536 gen_rtx_fmt_ee (GET_CODE (src
), GET_MODE (src
),
8541 /* dwarf2out.c:dwarf2out_frame_debug_expr doesn't know
8542 what to do with COND_EXEC. */
8543 if (RTX_FRAME_RELATED_P (insn
))
8545 /* If this is the delay slot insn of an anulled branch,
8546 dwarf2out.c:scan_trace understands the anulling semantics
8547 without the COND_EXEC. */
8548 gcc_assert (annulled
);
8549 rtx note
= alloc_reg_note (REG_FRAME_RELATED_EXPR
, pat
,
8551 validate_change (insn
, ®_NOTES (insn
), note
, 1);
8553 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
8557 /* Use the ccfsm machinery to do if conversion. */
8562 struct arc_ccfsm
*statep
= &cfun
->machine
->ccfsm_current
;
8563 basic_block merge_bb
= 0;
8565 memset (statep
, 0, sizeof *statep
);
8566 for (rtx_insn
*insn
= get_insns (); insn
; insn
= next_insn (insn
))
8568 arc_ccfsm_advance (insn
, statep
);
8570 switch (statep
->state
)
8578 /* Deleted branch. */
8579 gcc_assert (!merge_bb
);
8580 merge_bb
= BLOCK_FOR_INSN (insn
);
8582 = BLOCK_FOR_INSN (NEXT_INSN (NEXT_INSN (PREV_INSN (insn
))));
8583 arc_ccfsm_post_advance (insn
, statep
);
8584 gcc_assert (!IN_RANGE (statep
->state
, 1, 2));
8585 rtx_insn
*seq
= NEXT_INSN (PREV_INSN (insn
));
8588 rtx slot
= XVECEXP (PATTERN (seq
), 0, 1);
8589 rtx pat
= PATTERN (slot
);
8590 if (INSN_ANNULLED_BRANCH_P (insn
))
8593 = arc_get_ccfsm_cond (statep
, INSN_FROM_TARGET_P (slot
));
8594 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
8596 if (!validate_change (seq
, &PATTERN (seq
), pat
, 0))
8598 PUT_CODE (slot
, NOTE
);
8599 NOTE_KIND (slot
) = NOTE_INSN_DELETED
;
8600 if (merge_bb
&& succ_bb
)
8601 merge_blocks (merge_bb
, succ_bb
);
8603 else if (merge_bb
&& succ_bb
)
8605 set_insn_deleted (insn
);
8606 merge_blocks (merge_bb
, succ_bb
);
8610 PUT_CODE (insn
, NOTE
);
8611 NOTE_KIND (insn
) = NOTE_INSN_DELETED
;
8617 && statep
->target_label
== CODE_LABEL_NUMBER (insn
))
8619 arc_ccfsm_post_advance (insn
, statep
);
8620 basic_block succ_bb
= BLOCK_FOR_INSN (insn
);
8621 if (merge_bb
&& succ_bb
)
8622 merge_blocks (merge_bb
, succ_bb
);
8623 else if (--LABEL_NUSES (insn
) == 0)
8625 const char *name
= LABEL_NAME (insn
);
8626 PUT_CODE (insn
, NOTE
);
8627 NOTE_KIND (insn
) = NOTE_INSN_DELETED_LABEL
;
8628 NOTE_DELETED_LABEL_NAME (insn
) = name
;
8635 if (!NONDEBUG_INSN_P (insn
))
8638 /* Conditionalized insn. */
8640 rtx_insn
*prev
, *pprev
;
8641 rtx
*patp
, pat
, cond
;
8642 bool annulled
; annulled
= false;
8644 /* If this is a delay slot insn in a non-annulled branch,
8645 don't conditionalize it. N.B., this should be fine for
8646 conditional return too. However, don't do this for
8647 unconditional branches, as these would be encountered when
8648 processing an 'else' part. */
8649 prev
= PREV_INSN (insn
);
8650 pprev
= PREV_INSN (prev
);
8651 if (pprev
&& NEXT_INSN (NEXT_INSN (pprev
)) == NEXT_INSN (insn
)
8652 && JUMP_P (prev
) && get_attr_cond (prev
) == COND_USE
)
8654 if (!INSN_ANNULLED_BRANCH_P (prev
))
8659 patp
= &PATTERN (insn
);
8661 cond
= arc_get_ccfsm_cond (statep
, INSN_FROM_TARGET_P (insn
));
8662 if (NONJUMP_INSN_P (insn
) || CALL_P (insn
))
8664 /* ??? don't conditionalize if all side effects are dead
8665 in the not-execute case. */
8667 pat
= conditionalize_nonjump (pat
, cond
, insn
, annulled
);
8669 else if (simplejump_p (insn
))
8671 patp
= &SET_SRC (pat
);
8672 pat
= gen_rtx_IF_THEN_ELSE (VOIDmode
, cond
, *patp
, pc_rtx
);
8674 else if (JUMP_P (insn
) && ANY_RETURN_P (PATTERN (insn
)))
8676 pat
= gen_rtx_IF_THEN_ELSE (VOIDmode
, cond
, pat
, pc_rtx
);
8677 pat
= gen_rtx_SET (pc_rtx
, pat
);
8681 validate_change (insn
, patp
, pat
, 1);
8682 if (!apply_change_group ())
8686 rtx_insn
*next
= next_nonnote_insn (insn
);
8687 if (GET_CODE (next
) == BARRIER
)
8689 if (statep
->state
== 3)
8696 arc_ccfsm_post_advance (insn
, statep
);
8701 /* Find annulled delay insns and convert them to use the appropriate predicate.
8702 This allows branch shortening to size up these insns properly. */
8705 arc_predicate_delay_insns (void)
8707 for (rtx_insn
*insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
8709 rtx pat
, jump
, dlay
, src
, cond
, *patp
;
8712 if (!NONJUMP_INSN_P (insn
)
8713 || GET_CODE (pat
= PATTERN (insn
)) != SEQUENCE
)
8715 jump
= XVECEXP (pat
, 0, 0);
8716 dlay
= XVECEXP (pat
, 0, 1);
8717 if (!JUMP_P (jump
) || !INSN_ANNULLED_BRANCH_P (jump
))
8719 /* If the branch insn does the annulling, leave the delay insn alone. */
8720 if (!TARGET_AT_DBR_CONDEXEC
&& !INSN_FROM_TARGET_P (dlay
))
8722 /* ??? Could also leave DLAY un-conditionalized if its target is dead
8723 on the other path. */
8724 gcc_assert (GET_CODE (PATTERN (jump
)) == SET
);
8725 gcc_assert (SET_DEST (PATTERN (jump
)) == pc_rtx
);
8726 src
= SET_SRC (PATTERN (jump
));
8727 gcc_assert (GET_CODE (src
) == IF_THEN_ELSE
);
8728 cond
= XEXP (src
, 0);
8729 if (XEXP (src
, 2) == pc_rtx
)
8731 else if (XEXP (src
, 1) == pc_rtx
)
8735 if (reverse
!= !INSN_FROM_TARGET_P (dlay
))
8737 machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
8738 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
8739 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
8740 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
8742 cond
= gen_rtx_fmt_ee (code
, GET_MODE (cond
),
8743 copy_rtx (XEXP (cond
, 0)),
8744 copy_rtx (XEXP (cond
, 1)));
8747 cond
= copy_rtx (cond
);
8748 patp
= &PATTERN (dlay
);
8750 pat
= conditionalize_nonjump (pat
, cond
, dlay
, true);
8751 validate_change (dlay
, patp
, pat
, 1);
8752 if (!apply_change_group ())
8758 /* For ARC600: If a write to a core reg >=32 appears in a delay slot
8759 (other than of a forward brcc), it creates a hazard when there is a read
8760 of the same register at the branch target. We can't know what is at the
8761 branch target of calls, and for branches, we don't really know before the
8762 end of delay slot scheduling, either. Not only can individual instruction
8763 be hoisted out into a delay slot, a basic block can also be emptied this
8764 way, and branch and/or fall through targets be redirected. Hence we don't
8765 want such writes in a delay slot. */
8767 /* Return nonzreo iff INSN writes to an extension core register. */
8770 arc_write_ext_corereg (rtx insn
)
8772 subrtx_iterator::array_type array
;
8773 FOR_EACH_SUBRTX (iter
, array
, PATTERN (insn
), NONCONST
)
8775 const_rtx x
= *iter
;
8776 switch (GET_CODE (x
))
8778 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
8781 /* This is also fine for PRE/POST_MODIFY, because they
8785 const_rtx dest
= XEXP (x
, 0);
8786 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61)
8792 /* This is like the hook, but returns NULL when it can't / won't generate
8793 a legitimate address. */
8796 arc_legitimize_address_0 (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
8801 if (flag_pic
&& SYMBOLIC_CONST (x
))
8802 (x
) = arc_legitimize_pic_address (x
, 0);
8804 if (GET_CODE (addr
) == CONST
)
8805 addr
= XEXP (addr
, 0);
8806 if (GET_CODE (addr
) == PLUS
8807 && CONST_INT_P (XEXP (addr
, 1))
8808 && ((GET_CODE (XEXP (addr
, 0)) == SYMBOL_REF
8809 && !SYMBOL_REF_FUNCTION_P (XEXP (addr
, 0)))
8810 || (REG_P (XEXP (addr
, 0))
8811 && (INTVAL (XEXP (addr
, 1)) & 252))))
8813 HOST_WIDE_INT offs
, upper
;
8814 int size
= GET_MODE_SIZE (mode
);
8816 offs
= INTVAL (XEXP (addr
, 1));
8817 upper
= (offs
+ 256 * size
) & ~511 * size
;
8818 inner
= plus_constant (Pmode
, XEXP (addr
, 0), upper
);
8819 #if 0 /* ??? this produces worse code for EEMBC idctrn01 */
8820 if (GET_CODE (x
) == CONST
)
8821 inner
= gen_rtx_CONST (Pmode
, inner
);
8823 addr
= plus_constant (Pmode
, force_reg (Pmode
, inner
), offs
- upper
);
8826 else if (GET_CODE (addr
) == SYMBOL_REF
&& !SYMBOL_REF_FUNCTION_P (addr
))
8827 x
= force_reg (Pmode
, x
);
8828 if (memory_address_p ((machine_mode
) mode
, x
))
8834 arc_legitimize_address (rtx orig_x
, rtx oldx
, machine_mode mode
)
8836 rtx new_x
= arc_legitimize_address_0 (orig_x
, oldx
, mode
);
8844 arc_delegitimize_address_0 (rtx x
)
8848 if (GET_CODE (x
) == CONST
&& GET_CODE (u
= XEXP (x
, 0)) == UNSPEC
)
8850 if (XINT (u
, 1) == ARC_UNSPEC_GOT
)
8851 return XVECEXP (u
, 0, 0);
8853 else if (GET_CODE (x
) == PLUS
8854 && ((REG_P (gp
= XEXP (x
, 0))
8855 && REGNO (gp
) == PIC_OFFSET_TABLE_REGNUM
)
8856 || (GET_CODE (gp
) == CONST
8857 && GET_CODE (u
= XEXP (gp
, 0)) == UNSPEC
8858 && XINT (u
, 1) == ARC_UNSPEC_GOT
8859 && GET_CODE (XVECEXP (u
, 0, 0)) == SYMBOL_REF
8860 && !strcmp (XSTR (XVECEXP (u
, 0, 0), 0), "_DYNAMIC")))
8861 && GET_CODE (XEXP (x
, 1)) == CONST
8862 && GET_CODE (u
= XEXP (XEXP (x
, 1), 0)) == UNSPEC
8863 && XINT (u
, 1) == ARC_UNSPEC_GOTOFF
)
8864 return XVECEXP (u
, 0, 0);
8865 else if (GET_CODE (x
) == PLUS
&& GET_CODE (XEXP (x
, 0)) == PLUS
8866 && ((REG_P (gp
= XEXP (XEXP (x
, 0), 1))
8867 && REGNO (gp
) == PIC_OFFSET_TABLE_REGNUM
)
8868 || (GET_CODE (gp
) == CONST
8869 && GET_CODE (u
= XEXP (gp
, 0)) == UNSPEC
8870 && XINT (u
, 1) == ARC_UNSPEC_GOT
8871 && GET_CODE (XVECEXP (u
, 0, 0)) == SYMBOL_REF
8872 && !strcmp (XSTR (XVECEXP (u
, 0, 0), 0), "_DYNAMIC")))
8873 && GET_CODE (XEXP (x
, 1)) == CONST
8874 && GET_CODE (u
= XEXP (XEXP (x
, 1), 0)) == UNSPEC
8875 && XINT (u
, 1) == ARC_UNSPEC_GOTOFF
)
8876 return gen_rtx_PLUS (GET_MODE (x
), XEXP (XEXP (x
, 0), 0),
8878 else if (GET_CODE (x
) == PLUS
8879 && (u
= arc_delegitimize_address_0 (XEXP (x
, 1))))
8880 return gen_rtx_PLUS (GET_MODE (x
), XEXP (x
, 0), u
);
8885 arc_delegitimize_address (rtx x
)
8887 rtx orig_x
= x
= delegitimize_mem_from_attrs (x
);
8888 if (GET_CODE (x
) == MEM
)
8890 x
= arc_delegitimize_address_0 (x
);
8894 x
= replace_equiv_address_nv (orig_x
, x
);
8900 /* Return a REG rtx for acc1. N.B. the gcc-internal representation may
8901 differ from the hardware register number in order to allow the generic
8902 code to correctly split the concatenation of acc1 and acc2. */
8907 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 56: 57);
8910 /* Return a REG rtx for acc2. N.B. the gcc-internal representation may
8911 differ from the hardware register number in order to allow the generic
8912 code to correctly split the concatenation of acc1 and acc2. */
8917 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 57: 56);
8920 /* Return a REG rtx for mlo. N.B. the gcc-internal representation may
8921 differ from the hardware register number in order to allow the generic
8922 code to correctly split the concatenation of mhi and mlo. */
8927 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 59: 58);
8930 /* Return a REG rtx for mhi. N.B. the gcc-internal representation may
8931 differ from the hardware register number in order to allow the generic
8932 code to correctly split the concatenation of mhi and mlo. */
8937 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 58: 59);
8940 /* FIXME: a parameter should be added, and code added to final.c,
8941 to reproduce this functionality in shorten_branches. */
8943 /* Return nonzero iff BRANCH should be unaligned if possible by upsizing
8944 a previous instruction. */
8946 arc_unalign_branch_p (rtx branch
)
8950 if (!TARGET_UNALIGN_BRANCH
)
8952 /* Do not do this if we have a filled delay slot. */
8953 if (get_attr_delay_slot_filled (branch
) == DELAY_SLOT_FILLED_YES
8954 && !NEXT_INSN (branch
)->deleted ())
8956 note
= find_reg_note (branch
, REG_BR_PROB
, 0);
8958 || (arc_unalign_prob_threshold
&& !br_prob_note_reliable_p (note
))
8959 || INTVAL (XEXP (note
, 0)) < arc_unalign_prob_threshold
);
8963 /* When estimating sizes during arc_reorg, when optimizing for speed, there
8964 are three reasons why we need to consider branches to be length 6:
8965 - annull-false delay slot insns are implemented using conditional execution,
8966 thus preventing short insn formation where used.
8967 - for ARC600: annul-true delay slot insns are implemented where possible
8968 using conditional execution, preventing short insn formation where used.
8969 - for ARC700: likely or somewhat likely taken branches are made long and
8970 unaligned if possible to avoid branch penalty. */
8973 arc_branch_size_unknown_p (void)
8975 return !optimize_size
&& arc_reorg_in_progress
;
8978 /* We are about to output a return insn. Add padding if necessary to avoid
8979 a mispredict. A return could happen immediately after the function
8980 start, but after a call we know that there will be at least a blink
8984 arc_pad_return (void)
8986 rtx_insn
*insn
= current_output_insn
;
8987 rtx_insn
*prev
= prev_active_insn (insn
);
8992 fputs ("\tnop_s\n", asm_out_file
);
8993 cfun
->machine
->unalign
^= 2;
8996 /* If PREV is a sequence, we know it must be a branch / jump or a tailcall,
8997 because after a call, we'd have to restore blink first. */
8998 else if (GET_CODE (PATTERN (prev
)) == SEQUENCE
)
9002 want_long
= (get_attr_length (prev
) == 2);
9003 prev
= prev_active_insn (prev
);
9006 || ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
9007 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
9009 : CALL_ATTR (prev
, NON_SIBCALL
)))
9012 cfun
->machine
->size_reason
9013 = "call/return and return/return must be 6 bytes apart to avoid mispredict";
9014 else if (TARGET_UNALIGN_BRANCH
&& cfun
->machine
->unalign
)
9016 cfun
->machine
->size_reason
9017 = "Long unaligned jump avoids non-delay slot penalty";
9020 /* Disgorge delay insn, if there is any, and it may be moved. */
9022 /* ??? Annulled would be OK if we can and do conditionalize
9023 the delay slot insn accordingly. */
9024 && !INSN_ANNULLED_BRANCH_P (insn
)
9025 && (get_attr_cond (insn
) != COND_USE
9026 || !reg_set_p (gen_rtx_REG (CCmode
, CC_REG
),
9027 XVECEXP (final_sequence
, 0, 1))))
9029 prev
= as_a
<rtx_insn
*> (XVECEXP (final_sequence
, 0, 1));
9030 gcc_assert (!prev_real_insn (insn
)
9031 || !arc_hazard (prev_real_insn (insn
), prev
));
9032 cfun
->machine
->force_short_suffix
= !want_long
;
9033 rtx save_pred
= current_insn_predicate
;
9034 final_scan_insn (prev
, asm_out_file
, optimize
, 1, NULL
);
9035 cfun
->machine
->force_short_suffix
= -1;
9036 prev
->set_deleted ();
9037 current_output_insn
= insn
;
9038 current_insn_predicate
= save_pred
;
9041 fputs ("\tnop\n", asm_out_file
);
9044 fputs ("\tnop_s\n", asm_out_file
);
9045 cfun
->machine
->unalign
^= 2;
9051 /* The usual; we set up our machine_function data. */
9053 static struct machine_function
*
9054 arc_init_machine_status (void)
9056 struct machine_function
*machine
;
9057 machine
= ggc_cleared_alloc
<machine_function
> ();
9058 machine
->fn_type
= ARC_FUNCTION_UNKNOWN
;
9059 machine
->force_short_suffix
= -1;
9064 /* Implements INIT_EXPANDERS. We just set up to call the above
9068 arc_init_expanders (void)
9070 init_machine_status
= arc_init_machine_status
;
9073 /* Check if OP is a proper parallel of a millicode call pattern. OFFSET
9074 indicates a number of elements to ignore - that allows to have a
9075 sibcall pattern that starts with (return). LOAD_P is zero for store
9076 multiple (for prologues), and one for load multiples (for epilogues),
9077 and two for load multiples where no final clobber of blink is required.
9078 We also skip the first load / store element since this is supposed to
9079 be checked in the instruction pattern. */
9082 arc_check_millicode (rtx op
, int offset
, int load_p
)
9084 int len
= XVECLEN (op
, 0) - offset
;
9089 if (len
< 2 || len
> 13)
9095 rtx elt
= XVECEXP (op
, 0, --len
);
9097 if (GET_CODE (elt
) != CLOBBER
9098 || !REG_P (XEXP (elt
, 0))
9099 || REGNO (XEXP (elt
, 0)) != RETURN_ADDR_REGNUM
9100 || len
< 3 || len
> 13)
9103 for (i
= 1; i
< len
; i
++)
9105 rtx elt
= XVECEXP (op
, 0, i
+ offset
);
9108 if (GET_CODE (elt
) != SET
)
9110 mem
= XEXP (elt
, load_p
);
9111 reg
= XEXP (elt
, 1-load_p
);
9112 if (!REG_P (reg
) || REGNO (reg
) != 13U+i
|| !MEM_P (mem
))
9114 addr
= XEXP (mem
, 0);
9115 if (GET_CODE (addr
) != PLUS
9116 || !rtx_equal_p (stack_pointer_rtx
, XEXP (addr
, 0))
9117 || !CONST_INT_P (XEXP (addr
, 1)) || INTVAL (XEXP (addr
, 1)) != i
*4)
9123 /* Accessor functions for cfun->machine->unalign. */
9126 arc_get_unalign (void)
9128 return cfun
->machine
->unalign
;
9132 arc_clear_unalign (void)
9135 cfun
->machine
->unalign
= 0;
9139 arc_toggle_unalign (void)
9141 cfun
->machine
->unalign
^= 2;
9144 /* Operands 0..2 are the operands of a addsi which uses a 12 bit
9145 constant in operand 2, but which would require a LIMM because of
9147 operands 3 and 4 are new SET_SRCs for operands 0. */
9150 split_addsi (rtx
*operands
)
9152 int val
= INTVAL (operands
[2]);
9154 /* Try for two short insns first. Lengths being equal, we prefer
9155 expansions with shorter register lifetimes. */
9156 if (val
> 127 && val
<= 255
9157 && satisfies_constraint_Rcq (operands
[0]))
9159 operands
[3] = operands
[2];
9160 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
9164 operands
[3] = operands
[1];
9165 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[2]);
9169 /* Operands 0..2 are the operands of a subsi which uses a 12 bit
9170 constant in operand 1, but which would require a LIMM because of
9172 operands 3 and 4 are new SET_SRCs for operands 0. */
9175 split_subsi (rtx
*operands
)
9177 int val
= INTVAL (operands
[1]);
9179 /* Try for two short insns first. Lengths being equal, we prefer
9180 expansions with shorter register lifetimes. */
9181 if (satisfies_constraint_Rcq (operands
[0])
9182 && satisfies_constraint_Rcq (operands
[2]))
9184 if (val
>= -31 && val
<= 127)
9186 operands
[3] = gen_rtx_NEG (SImode
, operands
[2]);
9187 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
9190 else if (val
>= 0 && val
< 255)
9192 operands
[3] = operands
[1];
9193 operands
[4] = gen_rtx_MINUS (SImode
, operands
[0], operands
[2]);
9197 /* If the destination is not an ARCompact16 register, we might
9198 still have a chance to make a short insn if the source is;
9199 we need to start with a reg-reg move for this. */
9200 operands
[3] = operands
[2];
9201 operands
[4] = gen_rtx_MINUS (SImode
, operands
[1], operands
[0]);
9204 /* Handle DOUBLE_REGS uses.
9205 Operand 0: destination register
9206 Operand 1: source register */
9209 arc_process_double_reg_moves (rtx
*operands
)
9211 rtx dest
= operands
[0];
9212 rtx src
= operands
[1];
9215 enum usesDxState
{ none
, srcDx
, destDx
, maxDx
};
9216 enum usesDxState state
= none
;
9218 if (refers_to_regno_p (40, 44, src
, 0))
9220 if (refers_to_regno_p (40, 44, dest
, 0))
9222 /* Via arc_register_move_cost, we should never see D,D moves. */
9223 gcc_assert (state
== none
);
9234 /* Without the LR insn, we need to split this into a
9235 sequence of insns which will use the DEXCLx and DADDHxy
9236 insns to be able to read the Dx register in question. */
9237 if (TARGET_DPFP_DISABLE_LRSR
)
9239 /* gen *movdf_insn_nolrsr */
9240 rtx set
= gen_rtx_SET (dest
, src
);
9241 rtx use1
= gen_rtx_USE (VOIDmode
, const1_rtx
);
9242 emit_insn (gen_rtx_PARALLEL (VOIDmode
, gen_rtvec (2, set
, use1
)));
9246 /* When we have 'mov D, r' or 'mov D, D' then get the target
9247 register pair for use with LR insn. */
9248 rtx destHigh
= simplify_gen_subreg(SImode
, dest
, DFmode
, 4);
9249 rtx destLow
= simplify_gen_subreg(SImode
, dest
, DFmode
, 0);
9251 /* Produce the two LR insns to get the high and low parts. */
9252 emit_insn (gen_rtx_SET (destHigh
,
9253 gen_rtx_UNSPEC_VOLATILE (Pmode
, gen_rtvec (1, src
),
9255 emit_insn (gen_rtx_SET (destLow
,
9256 gen_rtx_UNSPEC_VOLATILE (Pmode
, gen_rtvec (1, src
),
9260 else if (state
== destDx
)
9262 /* When we have 'mov r, D' or 'mov D, D' and we have access to the
9263 LR insn get the target register pair. */
9264 rtx srcHigh
= simplify_gen_subreg(SImode
, src
, DFmode
, 4);
9265 rtx srcLow
= simplify_gen_subreg(SImode
, src
, DFmode
, 0);
9267 emit_insn (gen_rtx_UNSPEC_VOLATILE (Pmode
,
9268 gen_rtvec (3, dest
, srcHigh
, srcLow
),
9269 VUNSPEC_DEXCL_NORES
));
9280 /* operands 0..1 are the operands of a 64 bit move instruction.
9281 split it into two moves with operands 2/3 and 4/5. */
9284 arc_split_move (rtx
*operands
)
9286 machine_mode mode
= GET_MODE (operands
[0]);
9294 val
= arc_process_double_reg_moves (operands
);
9299 for (i
= 0; i
< 2; i
++)
9301 if (MEM_P (operands
[i
]) && auto_inc_p (XEXP (operands
[i
], 0)))
9303 rtx addr
= XEXP (operands
[i
], 0);
9307 gcc_assert (!reg_overlap_mentioned_p (operands
[0], addr
));
9308 switch (GET_CODE (addr
))
9310 case PRE_DEC
: o
= GEN_INT (-8); goto pre_modify
;
9311 case PRE_INC
: o
= GEN_INT (8); goto pre_modify
;
9312 case PRE_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
9316 case POST_DEC
: o
= GEN_INT (-8); goto post_modify
;
9317 case POST_INC
: o
= GEN_INT (8); goto post_modify
;
9318 case POST_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
9327 xop
[0+i
] = adjust_automodify_address_nv
9328 (operands
[i
], SImode
,
9329 gen_rtx_fmt_ee (code
, Pmode
, r
,
9330 gen_rtx_PLUS (Pmode
, r
, o
)),
9332 xop
[2+i
] = adjust_automodify_address_nv
9333 (operands
[i
], SImode
, plus_constant (Pmode
, r
, 4), 4);
9337 xop
[0+i
] = operand_subword (operands
[i
], 0, 0, mode
);
9338 xop
[2+i
] = operand_subword (operands
[i
], 1, 0, mode
);
9341 if (reg_overlap_mentioned_p (xop
[0], xop
[3]))
9344 gcc_assert (!reg_overlap_mentioned_p (xop
[2], xop
[1]));
9346 operands
[2+swap
] = xop
[0];
9347 operands
[3+swap
] = xop
[1];
9348 operands
[4-swap
] = xop
[2];
9349 operands
[5-swap
] = xop
[3];
9352 emit_insn (gen_rtx_SET (operands
[2], operands
[3]));
9353 emit_insn (gen_rtx_SET (operands
[4], operands
[5]));
9360 /* Select between the instruction output templates s_tmpl (for short INSNs)
9361 and l_tmpl (for long INSNs). */
9364 arc_short_long (rtx_insn
*insn
, const char *s_tmpl
, const char *l_tmpl
)
9366 int is_short
= arc_verify_short (insn
, cfun
->machine
->unalign
, -1);
9368 extract_constrain_insn_cached (insn
);
9369 return is_short
? s_tmpl
: l_tmpl
;
9372 /* Searches X for any reference to REGNO, returning the rtx of the
9373 reference found if any. Otherwise, returns NULL_RTX. */
9376 arc_regno_use_in (unsigned int regno
, rtx x
)
9382 if (REG_P (x
) && refers_to_regno_p (regno
, x
))
9385 fmt
= GET_RTX_FORMAT (GET_CODE (x
));
9386 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
9390 if ((tem
= regno_use_in (regno
, XEXP (x
, i
))))
9393 else if (fmt
[i
] == 'E')
9394 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
9395 if ((tem
= regno_use_in (regno
, XVECEXP (x
, i
, j
))))
9402 /* Return the integer value of the "type" attribute for INSN, or -1 if
9403 INSN can't have attributes. */
9406 arc_attr_type (rtx_insn
*insn
)
9408 if (NONJUMP_INSN_P (insn
)
9409 ? (GET_CODE (PATTERN (insn
)) == USE
9410 || GET_CODE (PATTERN (insn
)) == CLOBBER
)
9412 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
9413 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
9416 return get_attr_type (insn
);
9419 /* Return true if insn sets the condition codes. */
9422 arc_sets_cc_p (rtx_insn
*insn
)
9424 if (NONJUMP_INSN_P (insn
))
9425 if (rtx_sequence
*seq
= dyn_cast
<rtx_sequence
*> (PATTERN (insn
)))
9426 insn
= seq
->insn (seq
->len () - 1);
9427 return arc_attr_type (insn
) == TYPE_COMPARE
;
9430 /* Return true if INSN is an instruction with a delay slot we may want
9434 arc_need_delay (rtx_insn
*insn
)
9438 if (!flag_delayed_branch
)
9440 /* The return at the end of a function needs a delay slot. */
9441 if (NONJUMP_INSN_P (insn
) && GET_CODE (PATTERN (insn
)) == USE
9442 && (!(next
= next_active_insn (insn
))
9443 || ((!NONJUMP_INSN_P (next
) || GET_CODE (PATTERN (next
)) != SEQUENCE
)
9444 && arc_attr_type (next
) == TYPE_RETURN
))
9445 && (!TARGET_PAD_RETURN
9446 || (prev_active_insn (insn
)
9447 && prev_active_insn (prev_active_insn (insn
))
9448 && prev_active_insn (prev_active_insn (prev_active_insn (insn
))))))
9450 if (NONJUMP_INSN_P (insn
)
9451 ? (GET_CODE (PATTERN (insn
)) == USE
9452 || GET_CODE (PATTERN (insn
)) == CLOBBER
9453 || GET_CODE (PATTERN (insn
)) == SEQUENCE
)
9455 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
9456 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
9459 return num_delay_slots (insn
) != 0;
9462 /* Return true if the scheduling pass(es) has/have already run,
9463 i.e. where possible, we should try to mitigate high latencies
9464 by different instruction selection. */
9467 arc_scheduling_not_expected (void)
9469 return cfun
->machine
->arc_reorg_started
;
9472 /* Oddly enough, sometimes we get a zero overhead loop that branch
9473 shortening doesn't think is a loop - observed with compile/pr24883.c
9474 -O3 -fomit-frame-pointer -funroll-loops. Make sure to include the
9475 alignment visible for branch shortening (we actually align the loop
9476 insn before it, but that is equivalent since the loop insn is 4 byte
9480 arc_label_align (rtx label
)
9482 int loop_align
= LOOP_ALIGN (LABEL
);
9484 if (loop_align
> align_labels_log
)
9486 rtx_insn
*prev
= prev_nonnote_insn (label
);
9488 if (prev
&& NONJUMP_INSN_P (prev
)
9489 && GET_CODE (PATTERN (prev
)) == PARALLEL
9490 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
)
9493 /* Code has a minimum p2 alignment of 1, which we must restore after an
9495 if (align_labels_log
< 1)
9497 rtx_insn
*next
= next_nonnote_nondebug_insn (label
);
9498 if (INSN_P (next
) && recog_memoized (next
) >= 0)
9501 return align_labels_log
;
9504 /* Return true if LABEL is in executable code. */
9507 arc_text_label (rtx_insn
*label
)
9511 /* ??? We use deleted labels like they were still there, see
9512 gcc.c-torture/compile/20000326-2.c . */
9513 gcc_assert (GET_CODE (label
) == CODE_LABEL
9514 || (GET_CODE (label
) == NOTE
9515 && NOTE_KIND (label
) == NOTE_INSN_DELETED_LABEL
));
9516 next
= next_nonnote_insn (label
);
9518 return (!JUMP_TABLE_DATA_P (next
)
9519 || GET_CODE (PATTERN (next
)) != ADDR_VEC
);
9520 else if (!PREV_INSN (label
))
9521 /* ??? sometimes text labels get inserted very late, see
9522 gcc.dg/torture/stackalign/comp-goto-1.c */
9527 /* Return the size of the pretend args for DECL. */
9530 arc_decl_pretend_args (tree decl
)
9532 /* struct function is in DECL_STRUCT_FUNCTION (decl), but no
9533 pretend_args there... See PR38391. */
9534 gcc_assert (decl
== current_function_decl
);
9535 return crtl
->args
.pretend_args_size
;
9538 /* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
9539 when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
9540 -D_PROFILE_USE; delay branch scheduling then follows a crossing jump
9541 to redirect two breqs. */
9544 arc_can_follow_jump (const rtx_insn
*follower
, const rtx_insn
*followee
)
9546 /* ??? get_attr_type is declared to take an rtx. */
9547 union { const rtx_insn
*c
; rtx_insn
*r
; } u
;
9550 if (CROSSING_JUMP_P (followee
))
9551 switch (get_attr_type (u
.r
))
9554 case TYPE_BRCC_NO_DELAY_SLOT
:
9562 /* Implement EPILOGUE__USES.
9563 Return true if REGNO should be added to the deemed uses of the epilogue.
9565 We use the return address
9566 arc_return_address_regs[arc_compute_function_type (cfun)] .
9567 But also, we have to make sure all the register restore instructions
9568 are known to be live in interrupt functions. */
9571 arc_epilogue_uses (int regno
)
9573 if (reload_completed
)
9575 if (ARC_INTERRUPT_P (cfun
->machine
->fn_type
))
9577 if (!fixed_regs
[regno
])
9579 return regno
== arc_return_address_regs
[cfun
->machine
->fn_type
];
9582 return regno
== RETURN_ADDR_REGNUM
;
9585 return regno
== arc_return_address_regs
[arc_compute_function_type (cfun
)];
9588 #ifndef TARGET_NO_LRA
9589 #define TARGET_NO_LRA !TARGET_LRA
9595 return !TARGET_NO_LRA
;
9598 /* ??? Should we define TARGET_REGISTER_PRIORITY? We might perfer to use
9599 Rcq registers, because some insn are shorter with them. OTOH we already
9600 have separate alternatives for this purpose, and other insns don't
9601 mind, so maybe we should rather prefer the other registers?
9602 We need more data, and we can only get that if we allow people to
9605 arc_register_priority (int r
)
9607 switch (arc_lra_priority_tag
)
9609 case ARC_LRA_PRIORITY_NONE
:
9611 case ARC_LRA_PRIORITY_NONCOMPACT
:
9612 return ((((r
& 7) ^ 4) - 4) & 15) != r
;
9613 case ARC_LRA_PRIORITY_COMPACT
:
9614 return ((((r
& 7) ^ 4) - 4) & 15) == r
;
9621 arc_spill_class (reg_class_t
/* orig_class */, machine_mode
)
9623 return GENERAL_REGS
;
9627 arc_legitimize_reload_address (rtx
*p
, machine_mode mode
, int opnum
,
9631 enum reload_type type
= (enum reload_type
) itype
;
9633 if (GET_CODE (x
) == PLUS
9634 && CONST_INT_P (XEXP (x
, 1))
9635 && (RTX_OK_FOR_BASE_P (XEXP (x
, 0), true)
9636 || (REG_P (XEXP (x
, 0))
9637 && reg_equiv_constant (REGNO (XEXP (x
, 0))))))
9639 int scale
= GET_MODE_SIZE (mode
);
9641 rtx index_rtx
= XEXP (x
, 1);
9642 HOST_WIDE_INT offset
= INTVAL (index_rtx
), offset_base
;
9647 if ((scale
-1) & offset
)
9651 = ((offset
+ (256 << shift
))
9652 & ((HOST_WIDE_INT
)((unsigned HOST_WIDE_INT
) -512 << shift
)));
9653 /* Sometimes the normal form does not suit DImode. We
9654 could avoid that by using smaller ranges, but that
9655 would give less optimized code when SImode is
9657 if (GET_MODE_SIZE (mode
) + offset
- offset_base
<= (256 << shift
))
9662 regno
= REGNO (reg
);
9663 sum2
= sum
= plus_constant (Pmode
, reg
, offset_base
);
9665 if (reg_equiv_constant (regno
))
9667 sum2
= plus_constant (Pmode
, reg_equiv_constant (regno
),
9669 if (GET_CODE (sum2
) == PLUS
)
9670 sum2
= gen_rtx_CONST (Pmode
, sum2
);
9672 *p
= gen_rtx_PLUS (Pmode
, sum
, GEN_INT (offset
- offset_base
));
9673 push_reload (sum2
, NULL_RTX
, &XEXP (*p
, 0), NULL
,
9674 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
,
9679 /* We must re-recognize what we created before. */
9680 else if (GET_CODE (x
) == PLUS
9681 && GET_CODE (XEXP (x
, 0)) == PLUS
9682 && CONST_INT_P (XEXP (XEXP (x
, 0), 1))
9683 && REG_P (XEXP (XEXP (x
, 0), 0))
9684 && CONST_INT_P (XEXP (x
, 1)))
9686 /* Because this address is so complex, we know it must have
9687 been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,
9688 it is already unshared, and needs no further unsharing. */
9689 push_reload (XEXP (x
, 0), NULL_RTX
, &XEXP (x
, 0), NULL
,
9690 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
, type
);
9696 /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P. */
9699 arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size
,
9701 enum by_pieces_operation op
,
9704 /* Let the movmem expander handle small block moves. */
9705 if (op
== MOVE_BY_PIECES
)
9708 return default_use_by_pieces_infrastructure_p (size
, align
, op
, speed_p
);
9711 /* Emit a (pre) memory barrier around an atomic sequence according to
9715 arc_pre_atomic_barrier (enum memmodel model
)
9717 if (need_atomic_barrier_p (model
, true))
9718 emit_insn (gen_memory_barrier ());
9721 /* Emit a (post) memory barrier around an atomic sequence according to
9725 arc_post_atomic_barrier (enum memmodel model
)
9727 if (need_atomic_barrier_p (model
, false))
9728 emit_insn (gen_memory_barrier ());
9731 /* Expand a compare and swap pattern. */
9734 emit_unlikely_jump (rtx insn
)
9736 int very_unlikely
= REG_BR_PROB_BASE
/ 100 - 1;
9738 insn
= emit_jump_insn (insn
);
9739 add_int_reg_note (insn
, REG_BR_PROB
, very_unlikely
);
9742 /* Expand code to perform a 8 or 16-bit compare and swap by doing
9743 32-bit compare and swap on the word containing the byte or
9744 half-word. The difference between a weak and a strong CAS is that
9745 the weak version may simply fail. The strong version relies on two
9746 loops, one checks if the SCOND op is succsfully or not, the other
9747 checks if the 32 bit accessed location which contains the 8 or 16
9748 bit datum is not changed by other thread. The first loop is
9749 implemented by the atomic_compare_and_swapsi_1 pattern. The second
9750 loops is implemented by this routine. */
9753 arc_expand_compare_and_swap_qh (rtx bool_result
, rtx result
, rtx mem
,
9754 rtx oldval
, rtx newval
, rtx weak
,
9755 rtx mod_s
, rtx mod_f
)
9757 rtx addr1
= force_reg (Pmode
, XEXP (mem
, 0));
9758 rtx addr
= gen_reg_rtx (Pmode
);
9759 rtx off
= gen_reg_rtx (SImode
);
9760 rtx oldv
= gen_reg_rtx (SImode
);
9761 rtx newv
= gen_reg_rtx (SImode
);
9762 rtx oldvalue
= gen_reg_rtx (SImode
);
9763 rtx newvalue
= gen_reg_rtx (SImode
);
9764 rtx res
= gen_reg_rtx (SImode
);
9765 rtx resv
= gen_reg_rtx (SImode
);
9766 rtx memsi
, val
, mask
, end_label
, loop_label
, cc
, x
;
9768 bool is_weak
= (weak
!= const0_rtx
);
9770 /* Truncate the address. */
9771 emit_insn (gen_rtx_SET (addr
,
9772 gen_rtx_AND (Pmode
, addr1
, GEN_INT (-4))));
9774 /* Compute the datum offset. */
9775 emit_insn (gen_rtx_SET (off
,
9776 gen_rtx_AND (SImode
, addr1
, GEN_INT (3))));
9777 if (TARGET_BIG_ENDIAN
)
9778 emit_insn (gen_rtx_SET (off
,
9779 gen_rtx_MINUS (SImode
,
9780 (GET_MODE (mem
) == QImode
) ?
9781 GEN_INT (3) : GEN_INT (2), off
)));
9783 /* Normal read from truncated address. */
9784 memsi
= gen_rtx_MEM (SImode
, addr
);
9785 set_mem_alias_set (memsi
, ALIAS_SET_MEMORY_BARRIER
);
9786 MEM_VOLATILE_P (memsi
) = MEM_VOLATILE_P (mem
);
9788 val
= copy_to_reg (memsi
);
9790 /* Convert the offset in bits. */
9791 emit_insn (gen_rtx_SET (off
,
9792 gen_rtx_ASHIFT (SImode
, off
, GEN_INT (3))));
9794 /* Get the proper mask. */
9795 if (GET_MODE (mem
) == QImode
)
9796 mask
= force_reg (SImode
, GEN_INT (0xff));
9798 mask
= force_reg (SImode
, GEN_INT (0xffff));
9800 emit_insn (gen_rtx_SET (mask
,
9801 gen_rtx_ASHIFT (SImode
, mask
, off
)));
9803 /* Prepare the old and new values. */
9804 emit_insn (gen_rtx_SET (val
,
9805 gen_rtx_AND (SImode
, gen_rtx_NOT (SImode
, mask
),
9808 oldval
= gen_lowpart (SImode
, oldval
);
9809 emit_insn (gen_rtx_SET (oldv
,
9810 gen_rtx_ASHIFT (SImode
, oldval
, off
)));
9812 newval
= gen_lowpart_common (SImode
, newval
);
9813 emit_insn (gen_rtx_SET (newv
,
9814 gen_rtx_ASHIFT (SImode
, newval
, off
)));
9816 emit_insn (gen_rtx_SET (oldv
,
9817 gen_rtx_AND (SImode
, oldv
, mask
)));
9819 emit_insn (gen_rtx_SET (newv
,
9820 gen_rtx_AND (SImode
, newv
, mask
)));
9824 end_label
= gen_label_rtx ();
9825 loop_label
= gen_label_rtx ();
9826 emit_label (loop_label
);
9829 /* Make the old and new values. */
9830 emit_insn (gen_rtx_SET (oldvalue
,
9831 gen_rtx_IOR (SImode
, oldv
, val
)));
9833 emit_insn (gen_rtx_SET (newvalue
,
9834 gen_rtx_IOR (SImode
, newv
, val
)));
9836 /* Try an 32bit atomic compare and swap. It clobbers the CC
9838 emit_insn (gen_atomic_compare_and_swapsi_1 (res
, memsi
, oldvalue
, newvalue
,
9839 weak
, mod_s
, mod_f
));
9841 /* Regardless of the weakness of the operation, a proper boolean
9842 result needs to be provided. */
9843 x
= gen_rtx_REG (CC_Zmode
, CC_REG
);
9844 x
= gen_rtx_EQ (SImode
, x
, const0_rtx
);
9845 emit_insn (gen_rtx_SET (bool_result
, x
));
9849 /* Check the results: if the atomic op is successfully the goto
9851 x
= gen_rtx_REG (CC_Zmode
, CC_REG
);
9852 x
= gen_rtx_EQ (VOIDmode
, x
, const0_rtx
);
9853 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
9854 gen_rtx_LABEL_REF (Pmode
, end_label
), pc_rtx
);
9855 emit_jump_insn (gen_rtx_SET (pc_rtx
, x
));
9857 /* Wait for the right moment when the accessed 32-bit location
9859 emit_insn (gen_rtx_SET (resv
,
9860 gen_rtx_AND (SImode
, gen_rtx_NOT (SImode
, mask
),
9862 mode
= SELECT_CC_MODE (NE
, resv
, val
);
9863 cc
= gen_rtx_REG (mode
, CC_REG
);
9864 emit_insn (gen_rtx_SET (cc
, gen_rtx_COMPARE (mode
, resv
, val
)));
9866 /* Set the new value of the 32 bit location, proper masked. */
9867 emit_insn (gen_rtx_SET (val
, resv
));
9869 /* Try again if location is unstable. Fall through if only
9871 x
= gen_rtx_NE (VOIDmode
, cc
, const0_rtx
);
9872 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
9873 gen_rtx_LABEL_REF (Pmode
, loop_label
), pc_rtx
);
9874 emit_unlikely_jump (gen_rtx_SET (pc_rtx
, x
));
9876 emit_label (end_label
);
9879 /* End: proper return the result for the given mode. */
9880 emit_insn (gen_rtx_SET (res
,
9881 gen_rtx_AND (SImode
, res
, mask
)));
9883 emit_insn (gen_rtx_SET (res
,
9884 gen_rtx_LSHIFTRT (SImode
, res
, off
)));
9886 emit_move_insn (result
, gen_lowpart (GET_MODE (result
), res
));
9889 /* Helper function used by "atomic_compare_and_swap" expand
9893 arc_expand_compare_and_swap (rtx operands
[])
9895 rtx bval
, rval
, mem
, oldval
, newval
, is_weak
, mod_s
, mod_f
, x
;
9901 oldval
= operands
[3];
9902 newval
= operands
[4];
9903 is_weak
= operands
[5];
9904 mod_s
= operands
[6];
9905 mod_f
= operands
[7];
9906 mode
= GET_MODE (mem
);
9908 if (reg_overlap_mentioned_p (rval
, oldval
))
9909 oldval
= copy_to_reg (oldval
);
9913 emit_insn (gen_atomic_compare_and_swapsi_1 (rval
, mem
, oldval
, newval
,
9914 is_weak
, mod_s
, mod_f
));
9915 x
= gen_rtx_REG (CC_Zmode
, CC_REG
);
9916 x
= gen_rtx_EQ (SImode
, x
, const0_rtx
);
9917 emit_insn (gen_rtx_SET (bval
, x
));
9921 arc_expand_compare_and_swap_qh (bval
, rval
, mem
, oldval
, newval
,
9922 is_weak
, mod_s
, mod_f
);
9926 /* Helper function used by the "atomic_compare_and_swapsi_1"
9930 arc_split_compare_and_swap (rtx operands
[])
9932 rtx rval
, mem
, oldval
, newval
;
9934 enum memmodel mod_s
, mod_f
;
9936 rtx label1
, label2
, x
, cond
;
9940 oldval
= operands
[2];
9941 newval
= operands
[3];
9942 is_weak
= (operands
[4] != const0_rtx
);
9943 mod_s
= (enum memmodel
) INTVAL (operands
[5]);
9944 mod_f
= (enum memmodel
) INTVAL (operands
[6]);
9945 mode
= GET_MODE (mem
);
9947 /* ARC atomic ops work only with 32-bit aligned memories. */
9948 gcc_assert (mode
== SImode
);
9950 arc_pre_atomic_barrier (mod_s
);
9955 label1
= gen_label_rtx ();
9956 emit_label (label1
);
9958 label2
= gen_label_rtx ();
9960 /* Load exclusive. */
9961 emit_insn (gen_arc_load_exclusivesi (rval
, mem
));
9963 /* Check if it is oldval. */
9964 mode
= SELECT_CC_MODE (NE
, rval
, oldval
);
9965 cond
= gen_rtx_REG (mode
, CC_REG
);
9966 emit_insn (gen_rtx_SET (cond
, gen_rtx_COMPARE (mode
, rval
, oldval
)));
9968 x
= gen_rtx_NE (VOIDmode
, cond
, const0_rtx
);
9969 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
9970 gen_rtx_LABEL_REF (Pmode
, label2
), pc_rtx
);
9971 emit_unlikely_jump (gen_rtx_SET (pc_rtx
, x
));
9973 /* Exclusively store new item. Store clobbers CC reg. */
9974 emit_insn (gen_arc_store_exclusivesi (mem
, newval
));
9978 /* Check the result of the store. */
9979 cond
= gen_rtx_REG (CC_Zmode
, CC_REG
);
9980 x
= gen_rtx_NE (VOIDmode
, cond
, const0_rtx
);
9981 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
9982 gen_rtx_LABEL_REF (Pmode
, label1
), pc_rtx
);
9983 emit_unlikely_jump (gen_rtx_SET (pc_rtx
, x
));
9986 if (mod_f
!= MEMMODEL_RELAXED
)
9987 emit_label (label2
);
9989 arc_post_atomic_barrier (mod_s
);
9991 if (mod_f
== MEMMODEL_RELAXED
)
9992 emit_label (label2
);
9995 /* Expand an atomic fetch-and-operate pattern. CODE is the binary operation
9996 to perform. MEM is the memory on which to operate. VAL is the second
9997 operand of the binary operator. BEFORE and AFTER are optional locations to
9998 return the value of MEM either before of after the operation. MODEL_RTX
9999 is a CONST_INT containing the memory model to use. */
10002 arc_expand_atomic_op (enum rtx_code code
, rtx mem
, rtx val
,
10003 rtx orig_before
, rtx orig_after
, rtx model_rtx
)
10005 enum memmodel model
= (enum memmodel
) INTVAL (model_rtx
);
10006 machine_mode mode
= GET_MODE (mem
);
10007 rtx label
, x
, cond
;
10008 rtx before
= orig_before
, after
= orig_after
;
10010 /* ARC atomic ops work only with 32-bit aligned memories. */
10011 gcc_assert (mode
== SImode
);
10013 arc_pre_atomic_barrier (model
);
10015 label
= gen_label_rtx ();
10016 emit_label (label
);
10017 label
= gen_rtx_LABEL_REF (VOIDmode
, label
);
10019 if (before
== NULL_RTX
)
10020 before
= gen_reg_rtx (mode
);
10022 if (after
== NULL_RTX
)
10023 after
= gen_reg_rtx (mode
);
10025 /* Load exclusive. */
10026 emit_insn (gen_arc_load_exclusivesi (before
, mem
));
10031 x
= gen_rtx_AND (mode
, before
, val
);
10032 emit_insn (gen_rtx_SET (after
, x
));
10033 x
= gen_rtx_NOT (mode
, after
);
10034 emit_insn (gen_rtx_SET (after
, x
));
10038 if (CONST_INT_P (val
))
10040 val
= GEN_INT (-INTVAL (val
));
10046 x
= gen_rtx_fmt_ee (code
, mode
, before
, val
);
10047 emit_insn (gen_rtx_SET (after
, x
));
10051 /* Exclusively store new item. Store clobbers CC reg. */
10052 emit_insn (gen_arc_store_exclusivesi (mem
, after
));
10054 /* Check the result of the store. */
10055 cond
= gen_rtx_REG (CC_Zmode
, CC_REG
);
10056 x
= gen_rtx_NE (VOIDmode
, cond
, const0_rtx
);
10057 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
10059 emit_unlikely_jump (gen_rtx_SET (pc_rtx
, x
));
10061 arc_post_atomic_barrier (model
);
10064 /* Implement TARGET_NO_SPECULATION_IN_DELAY_SLOTS_P. */
10067 arc_no_speculation_in_delay_slots_p ()
10072 struct gcc_target targetm
= TARGET_INITIALIZER
;
10074 #include "gt-arc.h"