Rebase.
[official-gcc.git] / gcc / config / arc / arc.c
blob6a17966daa2dc02921540b0c2c145b2ee9f3eb13
1 /* Subroutines used for code generation on the Synopsys DesignWare ARC cpu.
2 Copyright (C) 1994-2014 Free Software Foundation, Inc.
4 Sources derived from work done by Sankhya Technologies (www.sankhya.com) on
5 behalf of Synopsys Inc.
7 Position Independent Code support added,Code cleaned up,
8 Comments and Support For ARC700 instructions added by
9 Saurabh Verma (saurabh.verma@codito.com)
10 Ramana Radhakrishnan(ramana.radhakrishnan@codito.com)
12 Fixing ABI inconsistencies, optimizations for ARC600 / ARC700 pipelines,
13 profiling support added by Joern Rennecke <joern.rennecke@embecosm.com>
15 This file is part of GCC.
17 GCC is free software; you can redistribute it and/or modify
18 it under the terms of the GNU General Public License as published by
19 the Free Software Foundation; either version 3, or (at your option)
20 any later version.
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/>. */
31 #include "config.h"
32 #include "system.h"
33 #include "coretypes.h"
34 #include "tm.h"
35 #include "tree.h"
36 #include "varasm.h"
37 #include "stor-layout.h"
38 #include "stringpool.h"
39 #include "calls.h"
40 #include "rtl.h"
41 #include "regs.h"
42 #include "hard-reg-set.h"
43 #include "real.h"
44 #include "insn-config.h"
45 #include "conditions.h"
46 #include "insn-flags.h"
47 #include "function.h"
48 #include "toplev.h"
49 #include "ggc.h"
50 #include "tm_p.h"
51 #include "target.h"
52 #include "output.h"
53 #include "insn-attr.h"
54 #include "flags.h"
55 #include "expr.h"
56 #include "recog.h"
57 #include "debug.h"
58 #include "diagnostic.h"
59 #include "insn-codes.h"
60 #include "langhooks.h"
61 #include "optabs.h"
62 #include "tm-constrs.h"
63 #include "reload.h" /* For operands_match_p */
64 #include "df.h"
65 #include "tree-pass.h"
66 #include "context.h"
67 #include "pass_manager.h"
68 #include "wide-int.h"
69 #include "builtins.h"
71 /* Which cpu we're compiling for (A5, ARC600, ARC601, ARC700). */
72 static const char *arc_cpu_string = "";
74 /* ??? Loads can handle any constant, stores can only handle small ones. */
75 /* OTOH, LIMMs cost extra, so their usefulness is limited. */
76 #define RTX_OK_FOR_OFFSET_P(MODE, X) \
77 (GET_CODE (X) == CONST_INT \
78 && SMALL_INT_RANGE (INTVAL (X), (GET_MODE_SIZE (MODE) - 1) & -4, \
79 (INTVAL (X) & (GET_MODE_SIZE (MODE) - 1) & 3 \
80 ? 0 \
81 : -(-GET_MODE_SIZE (MODE) | -4) >> 1)))
83 #define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X, INDEX, STRICT) \
84 (GET_CODE (X) == PLUS \
85 && RTX_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
86 && ((INDEX && RTX_OK_FOR_INDEX_P (XEXP (X, 1), (STRICT)) \
87 && GET_MODE_SIZE ((MODE)) <= 4) \
88 || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
90 #define LEGITIMATE_SCALED_ADDRESS_P(MODE, X, STRICT) \
91 (GET_CODE (X) == PLUS \
92 && GET_CODE (XEXP (X, 0)) == MULT \
93 && RTX_OK_FOR_INDEX_P (XEXP (XEXP (X, 0), 0), (STRICT)) \
94 && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
95 && ((GET_MODE_SIZE (MODE) == 2 && INTVAL (XEXP (XEXP (X, 0), 1)) == 2) \
96 || (GET_MODE_SIZE (MODE) == 4 && INTVAL (XEXP (XEXP (X, 0), 1)) == 4)) \
97 && (RTX_OK_FOR_BASE_P (XEXP (X, 1), (STRICT)) \
98 || (flag_pic ? CONST_INT_P (XEXP (X, 1)) : CONSTANT_P (XEXP (X, 1)))))
100 #define LEGITIMATE_SMALL_DATA_ADDRESS_P(X) \
101 (GET_CODE (X) == PLUS \
102 && (REG_P (XEXP ((X), 0)) && REGNO (XEXP ((X), 0)) == SDATA_BASE_REGNUM) \
103 && ((GET_CODE (XEXP((X),1)) == SYMBOL_REF \
104 && SYMBOL_REF_SMALL_P (XEXP ((X), 1))) \
105 || (GET_CODE (XEXP ((X), 1)) == CONST \
106 && GET_CODE (XEXP (XEXP ((X), 1), 0)) == PLUS \
107 && GET_CODE (XEXP (XEXP (XEXP ((X), 1), 0), 0)) == SYMBOL_REF \
108 && SYMBOL_REF_SMALL_P (XEXP (XEXP (XEXP ((X), 1), 0), 0)) \
109 && GET_CODE (XEXP(XEXP (XEXP ((X), 1), 0), 1)) == CONST_INT)))
111 /* Array of valid operand punctuation characters. */
112 char arc_punct_chars[256];
114 /* State used by arc_ccfsm_advance to implement conditional execution. */
115 struct GTY (()) arc_ccfsm
117 int state;
118 int cc;
119 rtx cond;
120 rtx target_insn;
121 int target_label;
124 #define arc_ccfsm_current cfun->machine->ccfsm_current
126 #define ARC_CCFSM_BRANCH_DELETED_P(STATE) \
127 ((STATE)->state == 1 || (STATE)->state == 2)
129 /* Indicate we're conditionalizing insns now. */
130 #define ARC_CCFSM_RECORD_BRANCH_DELETED(STATE) \
131 ((STATE)->state += 2)
133 #define ARC_CCFSM_COND_EXEC_P(STATE) \
134 ((STATE)->state == 3 || (STATE)->state == 4 || (STATE)->state == 5 \
135 || current_insn_predicate)
137 /* Check if INSN has a 16 bit opcode considering struct arc_ccfsm *STATE. */
138 #define CCFSM_ISCOMPACT(INSN,STATE) \
139 (ARC_CCFSM_COND_EXEC_P (STATE) \
140 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
141 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
142 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
144 /* Likewise, but also consider that INSN might be in a delay slot of JUMP. */
145 #define CCFSM_DBR_ISCOMPACT(INSN,JUMP,STATE) \
146 ((ARC_CCFSM_COND_EXEC_P (STATE) \
147 || (JUMP_P (JUMP) \
148 && INSN_ANNULLED_BRANCH_P (JUMP) \
149 && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (INSN)))) \
150 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
151 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
152 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
154 /* The maximum number of insns skipped which will be conditionalised if
155 possible. */
156 /* When optimizing for speed:
157 Let p be the probability that the potentially skipped insns need to
158 be executed, pn the cost of a correctly predicted non-taken branch,
159 mt the cost of a mis/non-predicted taken branch,
160 mn mispredicted non-taken, pt correctly predicted taken ;
161 costs expressed in numbers of instructions like the ones considered
162 skipping.
163 Unfortunately we don't have a measure of predictability - this
164 is linked to probability only in that in the no-eviction-scenario
165 there is a lower bound 1 - 2 * min (p, 1-p), and a somewhat larger
166 value that can be assumed *if* the distribution is perfectly random.
167 A predictability of 1 is perfectly plausible not matter what p is,
168 because the decision could be dependent on an invocation parameter
169 of the program.
170 For large p, we want MAX_INSNS_SKIPPED == pn/(1-p) + mt - pn
171 For small p, we want MAX_INSNS_SKIPPED == pt
173 When optimizing for size:
174 We want to skip insn unless we could use 16 opcodes for the
175 non-conditionalized insn to balance the branch length or more.
176 Performance can be tie-breaker. */
177 /* If the potentially-skipped insns are likely to be executed, we'll
178 generally save one non-taken branch
180 this to be no less than the 1/p */
181 #define MAX_INSNS_SKIPPED 3
183 /* The values of unspec's first field. */
184 enum {
185 ARC_UNSPEC_PLT = 3,
186 ARC_UNSPEC_GOT,
187 ARC_UNSPEC_GOTOFF
191 enum arc_builtins {
192 ARC_BUILTIN_NOP = 2,
193 ARC_BUILTIN_NORM = 3,
194 ARC_BUILTIN_NORMW = 4,
195 ARC_BUILTIN_SWAP = 5,
196 ARC_BUILTIN_BRK = 6,
197 ARC_BUILTIN_DIVAW = 7,
198 ARC_BUILTIN_EX = 8,
199 ARC_BUILTIN_MUL64 = 9,
200 ARC_BUILTIN_MULU64 = 10,
201 ARC_BUILTIN_RTIE = 11,
202 ARC_BUILTIN_SYNC = 12,
203 ARC_BUILTIN_CORE_READ = 13,
204 ARC_BUILTIN_CORE_WRITE = 14,
205 ARC_BUILTIN_FLAG = 15,
206 ARC_BUILTIN_LR = 16,
207 ARC_BUILTIN_SR = 17,
208 ARC_BUILTIN_SLEEP = 18,
209 ARC_BUILTIN_SWI = 19,
210 ARC_BUILTIN_TRAP_S = 20,
211 ARC_BUILTIN_UNIMP_S = 21,
212 ARC_BUILTIN_ALIGNED = 22,
214 /* Sentinel to mark start of simd builtins. */
215 ARC_SIMD_BUILTIN_BEGIN = 1000,
217 ARC_SIMD_BUILTIN_VADDAW = 1001,
218 ARC_SIMD_BUILTIN_VADDW = 1002,
219 ARC_SIMD_BUILTIN_VAVB = 1003,
220 ARC_SIMD_BUILTIN_VAVRB = 1004,
221 ARC_SIMD_BUILTIN_VDIFAW = 1005,
222 ARC_SIMD_BUILTIN_VDIFW = 1006,
223 ARC_SIMD_BUILTIN_VMAXAW = 1007,
224 ARC_SIMD_BUILTIN_VMAXW = 1008,
225 ARC_SIMD_BUILTIN_VMINAW = 1009,
226 ARC_SIMD_BUILTIN_VMINW = 1010,
227 ARC_SIMD_BUILTIN_VMULAW = 1011,
228 ARC_SIMD_BUILTIN_VMULFAW = 1012,
229 ARC_SIMD_BUILTIN_VMULFW = 1013,
230 ARC_SIMD_BUILTIN_VMULW = 1014,
231 ARC_SIMD_BUILTIN_VSUBAW = 1015,
232 ARC_SIMD_BUILTIN_VSUBW = 1016,
233 ARC_SIMD_BUILTIN_VSUMMW = 1017,
234 ARC_SIMD_BUILTIN_VAND = 1018,
235 ARC_SIMD_BUILTIN_VANDAW = 1019,
236 ARC_SIMD_BUILTIN_VBIC = 1020,
237 ARC_SIMD_BUILTIN_VBICAW = 1021,
238 ARC_SIMD_BUILTIN_VOR = 1022,
239 ARC_SIMD_BUILTIN_VXOR = 1023,
240 ARC_SIMD_BUILTIN_VXORAW = 1024,
241 ARC_SIMD_BUILTIN_VEQW = 1025,
242 ARC_SIMD_BUILTIN_VLEW = 1026,
243 ARC_SIMD_BUILTIN_VLTW = 1027,
244 ARC_SIMD_BUILTIN_VNEW = 1028,
245 ARC_SIMD_BUILTIN_VMR1AW = 1029,
246 ARC_SIMD_BUILTIN_VMR1W = 1030,
247 ARC_SIMD_BUILTIN_VMR2AW = 1031,
248 ARC_SIMD_BUILTIN_VMR2W = 1032,
249 ARC_SIMD_BUILTIN_VMR3AW = 1033,
250 ARC_SIMD_BUILTIN_VMR3W = 1034,
251 ARC_SIMD_BUILTIN_VMR4AW = 1035,
252 ARC_SIMD_BUILTIN_VMR4W = 1036,
253 ARC_SIMD_BUILTIN_VMR5AW = 1037,
254 ARC_SIMD_BUILTIN_VMR5W = 1038,
255 ARC_SIMD_BUILTIN_VMR6AW = 1039,
256 ARC_SIMD_BUILTIN_VMR6W = 1040,
257 ARC_SIMD_BUILTIN_VMR7AW = 1041,
258 ARC_SIMD_BUILTIN_VMR7W = 1042,
259 ARC_SIMD_BUILTIN_VMRB = 1043,
260 ARC_SIMD_BUILTIN_VH264F = 1044,
261 ARC_SIMD_BUILTIN_VH264FT = 1045,
262 ARC_SIMD_BUILTIN_VH264FW = 1046,
263 ARC_SIMD_BUILTIN_VVC1F = 1047,
264 ARC_SIMD_BUILTIN_VVC1FT = 1048,
266 /* Va, Vb, rlimm instructions. */
267 ARC_SIMD_BUILTIN_VBADDW = 1050,
268 ARC_SIMD_BUILTIN_VBMAXW = 1051,
269 ARC_SIMD_BUILTIN_VBMINW = 1052,
270 ARC_SIMD_BUILTIN_VBMULAW = 1053,
271 ARC_SIMD_BUILTIN_VBMULFW = 1054,
272 ARC_SIMD_BUILTIN_VBMULW = 1055,
273 ARC_SIMD_BUILTIN_VBRSUBW = 1056,
274 ARC_SIMD_BUILTIN_VBSUBW = 1057,
276 /* Va, Vb, Ic instructions. */
277 ARC_SIMD_BUILTIN_VASRW = 1060,
278 ARC_SIMD_BUILTIN_VSR8 = 1061,
279 ARC_SIMD_BUILTIN_VSR8AW = 1062,
281 /* Va, Vb, u6 instructions. */
282 ARC_SIMD_BUILTIN_VASRRWi = 1065,
283 ARC_SIMD_BUILTIN_VASRSRWi = 1066,
284 ARC_SIMD_BUILTIN_VASRWi = 1067,
285 ARC_SIMD_BUILTIN_VASRPWBi = 1068,
286 ARC_SIMD_BUILTIN_VASRRPWBi = 1069,
287 ARC_SIMD_BUILTIN_VSR8AWi = 1070,
288 ARC_SIMD_BUILTIN_VSR8i = 1071,
290 /* Va, Vb, u8 (simm) instructions. */
291 ARC_SIMD_BUILTIN_VMVAW = 1075,
292 ARC_SIMD_BUILTIN_VMVW = 1076,
293 ARC_SIMD_BUILTIN_VMVZW = 1077,
294 ARC_SIMD_BUILTIN_VD6TAPF = 1078,
296 /* Va, rlimm, u8 (simm) instructions. */
297 ARC_SIMD_BUILTIN_VMOVAW = 1080,
298 ARC_SIMD_BUILTIN_VMOVW = 1081,
299 ARC_SIMD_BUILTIN_VMOVZW = 1082,
301 /* Va, Vb instructions. */
302 ARC_SIMD_BUILTIN_VABSAW = 1085,
303 ARC_SIMD_BUILTIN_VABSW = 1086,
304 ARC_SIMD_BUILTIN_VADDSUW = 1087,
305 ARC_SIMD_BUILTIN_VSIGNW = 1088,
306 ARC_SIMD_BUILTIN_VEXCH1 = 1089,
307 ARC_SIMD_BUILTIN_VEXCH2 = 1090,
308 ARC_SIMD_BUILTIN_VEXCH4 = 1091,
309 ARC_SIMD_BUILTIN_VUPBAW = 1092,
310 ARC_SIMD_BUILTIN_VUPBW = 1093,
311 ARC_SIMD_BUILTIN_VUPSBAW = 1094,
312 ARC_SIMD_BUILTIN_VUPSBW = 1095,
314 ARC_SIMD_BUILTIN_VDIRUN = 1100,
315 ARC_SIMD_BUILTIN_VDORUN = 1101,
316 ARC_SIMD_BUILTIN_VDIWR = 1102,
317 ARC_SIMD_BUILTIN_VDOWR = 1103,
319 ARC_SIMD_BUILTIN_VREC = 1105,
320 ARC_SIMD_BUILTIN_VRUN = 1106,
321 ARC_SIMD_BUILTIN_VRECRUN = 1107,
322 ARC_SIMD_BUILTIN_VENDREC = 1108,
324 ARC_SIMD_BUILTIN_VLD32WH = 1110,
325 ARC_SIMD_BUILTIN_VLD32WL = 1111,
326 ARC_SIMD_BUILTIN_VLD64 = 1112,
327 ARC_SIMD_BUILTIN_VLD32 = 1113,
328 ARC_SIMD_BUILTIN_VLD64W = 1114,
329 ARC_SIMD_BUILTIN_VLD128 = 1115,
330 ARC_SIMD_BUILTIN_VST128 = 1116,
331 ARC_SIMD_BUILTIN_VST64 = 1117,
333 ARC_SIMD_BUILTIN_VST16_N = 1120,
334 ARC_SIMD_BUILTIN_VST32_N = 1121,
336 ARC_SIMD_BUILTIN_VINTI = 1201,
338 ARC_SIMD_BUILTIN_END
341 /* A nop is needed between a 4 byte insn that sets the condition codes and
342 a branch that uses them (the same isn't true for an 8 byte insn that sets
343 the condition codes). Set by arc_ccfsm_advance. Used by
344 arc_print_operand. */
346 static int get_arc_condition_code (rtx);
348 static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
350 /* Initialized arc_attribute_table to NULL since arc doesnot have any
351 machine specific supported attributes. */
352 const struct attribute_spec arc_attribute_table[] =
354 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
355 affects_type_identity } */
356 { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute, true },
357 /* Function calls made to this symbol must be done indirectly, because
358 it may lie outside of the 21/25 bit addressing range of a normal function
359 call. */
360 { "long_call", 0, 0, false, true, true, NULL, false },
361 /* Whereas these functions are always known to reside within the 25 bit
362 addressing range of unconditionalized bl. */
363 { "medium_call", 0, 0, false, true, true, NULL, false },
364 /* And these functions are always known to reside within the 21 bit
365 addressing range of blcc. */
366 { "short_call", 0, 0, false, true, true, NULL, false },
367 { NULL, 0, 0, false, false, false, NULL, false }
369 static int arc_comp_type_attributes (const_tree, const_tree);
370 static void arc_file_start (void);
371 static void arc_internal_label (FILE *, const char *, unsigned long);
372 static void arc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
373 tree);
374 static int arc_address_cost (rtx, enum machine_mode, addr_space_t, bool);
375 static void arc_encode_section_info (tree decl, rtx rtl, int first);
377 static void arc_init_builtins (void);
378 static rtx arc_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
380 static int branch_dest (rtx);
382 static void arc_output_pic_addr_const (FILE *, rtx, int);
383 void emit_pic_move (rtx *, enum machine_mode);
384 bool arc_legitimate_pic_operand_p (rtx);
385 static bool arc_function_ok_for_sibcall (tree, tree);
386 static rtx arc_function_value (const_tree, const_tree, bool);
387 const char * output_shift (rtx *);
388 static void arc_reorg (void);
389 static bool arc_in_small_data_p (const_tree);
391 static void arc_init_reg_tables (void);
392 static bool arc_return_in_memory (const_tree, const_tree);
393 static void arc_init_simd_builtins (void);
394 static bool arc_vector_mode_supported_p (enum machine_mode);
396 static bool arc_can_use_doloop_p (const widest_int &, const widest_int &,
397 unsigned int, bool);
398 static const char *arc_invalid_within_doloop (const_rtx);
400 static void output_short_suffix (FILE *file);
402 static bool arc_frame_pointer_required (void);
404 /* Implements target hook vector_mode_supported_p. */
406 static bool
407 arc_vector_mode_supported_p (enum machine_mode mode)
409 if (!TARGET_SIMD_SET)
410 return false;
412 if ((mode == V4SImode)
413 || (mode == V8HImode))
414 return true;
416 return false;
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 follower, const_rtx followee);
425 static rtx frame_insn (rtx);
426 static void arc_function_arg_advance (cumulative_args_t, enum machine_mode,
427 const_tree, bool);
428 static rtx arc_legitimize_address_0 (rtx, rtx, enum machine_mode mode);
430 static void arc_finalize_pic (void);
432 /* initialize the GCC target structure. */
433 #undef TARGET_COMP_TYPE_ATTRIBUTES
434 #define TARGET_COMP_TYPE_ATTRIBUTES arc_comp_type_attributes
435 #undef TARGET_ASM_FILE_START
436 #define TARGET_ASM_FILE_START arc_file_start
437 #undef TARGET_ATTRIBUTE_TABLE
438 #define TARGET_ATTRIBUTE_TABLE arc_attribute_table
439 #undef TARGET_ASM_INTERNAL_LABEL
440 #define TARGET_ASM_INTERNAL_LABEL arc_internal_label
441 #undef TARGET_RTX_COSTS
442 #define TARGET_RTX_COSTS arc_rtx_costs
443 #undef TARGET_ADDRESS_COST
444 #define TARGET_ADDRESS_COST arc_address_cost
446 #undef TARGET_ENCODE_SECTION_INFO
447 #define TARGET_ENCODE_SECTION_INFO arc_encode_section_info
449 #undef TARGET_CANNOT_FORCE_CONST_MEM
450 #define TARGET_CANNOT_FORCE_CONST_MEM arc_cannot_force_const_mem
452 #undef TARGET_INIT_BUILTINS
453 #define TARGET_INIT_BUILTINS arc_init_builtins
455 #undef TARGET_EXPAND_BUILTIN
456 #define TARGET_EXPAND_BUILTIN arc_expand_builtin
458 #undef TARGET_ASM_OUTPUT_MI_THUNK
459 #define TARGET_ASM_OUTPUT_MI_THUNK arc_output_mi_thunk
461 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
462 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
464 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
465 #define TARGET_FUNCTION_OK_FOR_SIBCALL arc_function_ok_for_sibcall
467 #undef TARGET_MACHINE_DEPENDENT_REORG
468 #define TARGET_MACHINE_DEPENDENT_REORG arc_reorg
470 #undef TARGET_IN_SMALL_DATA_P
471 #define TARGET_IN_SMALL_DATA_P arc_in_small_data_p
473 #undef TARGET_PROMOTE_FUNCTION_MODE
474 #define TARGET_PROMOTE_FUNCTION_MODE \
475 default_promote_function_mode_always_promote
477 #undef TARGET_PROMOTE_PROTOTYPES
478 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
480 #undef TARGET_RETURN_IN_MEMORY
481 #define TARGET_RETURN_IN_MEMORY arc_return_in_memory
482 #undef TARGET_PASS_BY_REFERENCE
483 #define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
485 #undef TARGET_SETUP_INCOMING_VARARGS
486 #define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
488 #undef TARGET_ARG_PARTIAL_BYTES
489 #define TARGET_ARG_PARTIAL_BYTES arc_arg_partial_bytes
491 #undef TARGET_MUST_PASS_IN_STACK
492 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
494 #undef TARGET_FUNCTION_VALUE
495 #define TARGET_FUNCTION_VALUE arc_function_value
497 #undef TARGET_SCHED_ADJUST_PRIORITY
498 #define TARGET_SCHED_ADJUST_PRIORITY arc_sched_adjust_priority
500 #undef TARGET_VECTOR_MODE_SUPPORTED_P
501 #define TARGET_VECTOR_MODE_SUPPORTED_P arc_vector_mode_supported_p
503 #undef TARGET_CAN_USE_DOLOOP_P
504 #define TARGET_CAN_USE_DOLOOP_P arc_can_use_doloop_p
506 #undef TARGET_INVALID_WITHIN_DOLOOP
507 #define TARGET_INVALID_WITHIN_DOLOOP arc_invalid_within_doloop
509 #undef TARGET_PRESERVE_RELOAD_P
510 #define TARGET_PRESERVE_RELOAD_P arc_preserve_reload_p
512 #undef TARGET_CAN_FOLLOW_JUMP
513 #define TARGET_CAN_FOLLOW_JUMP arc_can_follow_jump
515 #undef TARGET_DELEGITIMIZE_ADDRESS
516 #define TARGET_DELEGITIMIZE_ADDRESS arc_delegitimize_address
518 /* Usually, we will be able to scale anchor offsets.
519 When this fails, we want LEGITIMIZE_ADDRESS to kick in. */
520 #undef TARGET_MIN_ANCHOR_OFFSET
521 #define TARGET_MIN_ANCHOR_OFFSET (-1024)
522 #undef TARGET_MAX_ANCHOR_OFFSET
523 #define TARGET_MAX_ANCHOR_OFFSET (1020)
525 #undef TARGET_SECONDARY_RELOAD
526 #define TARGET_SECONDARY_RELOAD arc_secondary_reload
528 #define TARGET_OPTION_OVERRIDE arc_override_options
530 #define TARGET_CONDITIONAL_REGISTER_USAGE arc_conditional_register_usage
532 #define TARGET_TRAMPOLINE_INIT arc_initialize_trampoline
534 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS arc_trampoline_adjust_address
536 #define TARGET_CAN_ELIMINATE arc_can_eliminate
538 #define TARGET_FRAME_POINTER_REQUIRED arc_frame_pointer_required
540 #define TARGET_FUNCTION_ARG arc_function_arg
542 #define TARGET_FUNCTION_ARG_ADVANCE arc_function_arg_advance
544 #define TARGET_LEGITIMATE_CONSTANT_P arc_legitimate_constant_p
546 #define TARGET_LEGITIMATE_ADDRESS_P arc_legitimate_address_p
548 #define TARGET_MODE_DEPENDENT_ADDRESS_P arc_mode_dependent_address_p
550 #define TARGET_LEGITIMIZE_ADDRESS arc_legitimize_address
552 #define TARGET_ADJUST_INSN_LENGTH arc_adjust_insn_length
554 #define TARGET_INSN_LENGTH_PARAMETERS arc_insn_length_parameters
556 #undef TARGET_LRA_P
557 #define TARGET_LRA_P arc_lra_p
558 #define TARGET_REGISTER_PRIORITY arc_register_priority
559 /* Stores with scaled offsets have different displacement ranges. */
560 #define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
561 #define TARGET_SPILL_CLASS arc_spill_class
563 #include "target-def.h"
565 #undef TARGET_ASM_ALIGNED_HI_OP
566 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
567 #undef TARGET_ASM_ALIGNED_SI_OP
568 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
570 /* Try to keep the (mov:DF _, reg) as early as possible so
571 that the d<add/sub/mul>h-lr insns appear together and can
572 use the peephole2 pattern. */
574 static int
575 arc_sched_adjust_priority (rtx insn, int priority)
577 rtx set = single_set (insn);
578 if (set
579 && GET_MODE (SET_SRC(set)) == DFmode
580 && GET_CODE (SET_SRC(set)) == REG)
582 /* Incrementing priority by 20 (empirically derived). */
583 return priority + 20;
586 return priority;
589 static reg_class_t
590 arc_secondary_reload (bool in_p, rtx x, reg_class_t cl, enum machine_mode,
591 secondary_reload_info *)
593 if (cl == DOUBLE_REGS)
594 return GENERAL_REGS;
596 /* The loop counter register can be stored, but not loaded directly. */
597 if ((cl == LPCOUNT_REG || cl == WRITABLE_CORE_REGS)
598 && in_p && MEM_P (x))
599 return GENERAL_REGS;
600 return NO_REGS;
603 static unsigned arc_ifcvt (void);
605 namespace {
607 const pass_data pass_data_arc_ifcvt =
609 RTL_PASS,
610 "arc_ifcvt", /* name */
611 OPTGROUP_NONE, /* optinfo_flags */
612 TV_IFCVT2, /* tv_id */
613 0, /* properties_required */
614 0, /* properties_provided */
615 0, /* properties_destroyed */
616 0, /* todo_flags_start */
617 TODO_df_finish /* todo_flags_finish */
620 class pass_arc_ifcvt : public rtl_opt_pass
622 public:
623 pass_arc_ifcvt(gcc::context *ctxt)
624 : rtl_opt_pass(pass_data_arc_ifcvt, ctxt)
627 /* opt_pass methods: */
628 opt_pass * clone () { return new pass_arc_ifcvt (m_ctxt); }
629 virtual unsigned int execute (function *) { return arc_ifcvt (); }
632 } // anon namespace
634 rtl_opt_pass *
635 make_pass_arc_ifcvt (gcc::context *ctxt)
637 return new pass_arc_ifcvt (ctxt);
640 static unsigned arc_predicate_delay_insns (void);
642 namespace {
644 const pass_data pass_data_arc_predicate_delay_insns =
646 RTL_PASS,
647 "arc_predicate_delay_insns", /* name */
648 OPTGROUP_NONE, /* optinfo_flags */
649 TV_IFCVT2, /* tv_id */
650 0, /* properties_required */
651 0, /* properties_provided */
652 0, /* properties_destroyed */
653 0, /* todo_flags_start */
654 TODO_df_finish /* todo_flags_finish */
657 class pass_arc_predicate_delay_insns : public rtl_opt_pass
659 public:
660 pass_arc_predicate_delay_insns(gcc::context *ctxt)
661 : rtl_opt_pass(pass_data_arc_predicate_delay_insns, ctxt)
664 /* opt_pass methods: */
665 virtual unsigned int execute (function *)
667 return arc_predicate_delay_insns ();
671 } // anon namespace
673 rtl_opt_pass *
674 make_pass_arc_predicate_delay_insns (gcc::context *ctxt)
676 return new pass_arc_predicate_delay_insns (ctxt);
679 /* Called by OVERRIDE_OPTIONS to initialize various things. */
681 void
682 arc_init (void)
684 enum attr_tune tune_dflt = TUNE_NONE;
686 if (TARGET_A5)
688 arc_cpu_string = "A5";
690 else if (TARGET_ARC600)
692 arc_cpu_string = "ARC600";
693 tune_dflt = TUNE_ARC600;
695 else if (TARGET_ARC601)
697 arc_cpu_string = "ARC601";
698 tune_dflt = TUNE_ARC600;
700 else if (TARGET_ARC700)
702 arc_cpu_string = "ARC700";
703 tune_dflt = TUNE_ARC700_4_2_STD;
705 else
706 gcc_unreachable ();
707 if (arc_tune == TUNE_NONE)
708 arc_tune = tune_dflt;
709 /* Note: arc_multcost is only used in rtx_cost if speed is true. */
710 if (arc_multcost < 0)
711 switch (arc_tune)
713 case TUNE_ARC700_4_2_STD:
714 /* latency 7;
715 max throughput (1 multiply + 4 other insns) / 5 cycles. */
716 arc_multcost = COSTS_N_INSNS (4);
717 if (TARGET_NOMPY_SET)
718 arc_multcost = COSTS_N_INSNS (30);
719 break;
720 case TUNE_ARC700_4_2_XMAC:
721 /* latency 5;
722 max throughput (1 multiply + 2 other insns) / 3 cycles. */
723 arc_multcost = COSTS_N_INSNS (3);
724 if (TARGET_NOMPY_SET)
725 arc_multcost = COSTS_N_INSNS (30);
726 break;
727 case TUNE_ARC600:
728 if (TARGET_MUL64_SET)
730 arc_multcost = COSTS_N_INSNS (4);
731 break;
733 /* Fall through. */
734 default:
735 arc_multcost = COSTS_N_INSNS (30);
736 break;
739 /* Support mul64 generation only for A5 and ARC600. */
740 if (TARGET_MUL64_SET && TARGET_ARC700)
741 error ("-mmul64 not supported for ARC700");
743 /* MPY instructions valid only for ARC700. */
744 if (TARGET_NOMPY_SET && !TARGET_ARC700)
745 error ("-mno-mpy supported only for ARC700");
747 /* mul/mac instructions only for ARC600. */
748 if (TARGET_MULMAC_32BY16_SET && !(TARGET_ARC600 || TARGET_ARC601))
749 error ("-mmul32x16 supported only for ARC600 or ARC601");
751 if (!TARGET_DPFP && TARGET_DPFP_DISABLE_LRSR)
752 error ("-mno-dpfp-lrsr supported only with -mdpfp");
754 /* FPX-1. No fast and compact together. */
755 if ((TARGET_DPFP_FAST_SET && TARGET_DPFP_COMPACT_SET)
756 || (TARGET_SPFP_FAST_SET && TARGET_SPFP_COMPACT_SET))
757 error ("FPX fast and compact options cannot be specified together");
759 /* FPX-2. No fast-spfp for arc600 or arc601. */
760 if (TARGET_SPFP_FAST_SET && (TARGET_ARC600 || TARGET_ARC601))
761 error ("-mspfp_fast not available on ARC600 or ARC601");
763 /* FPX-3. No FPX extensions on pre-ARC600 cores. */
764 if ((TARGET_DPFP || TARGET_SPFP)
765 && !(TARGET_ARC600 || TARGET_ARC601 || TARGET_ARC700))
766 error ("FPX extensions not available on pre-ARC600 cores");
768 /* Warn for unimplemented PIC in pre-ARC700 cores, and disable flag_pic. */
769 if (flag_pic && !TARGET_ARC700)
771 warning (DK_WARNING, "PIC is not supported for %s. Generating non-PIC code only..", arc_cpu_string);
772 flag_pic = 0;
775 arc_init_reg_tables ();
777 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
778 memset (arc_punct_chars, 0, sizeof (arc_punct_chars));
779 arc_punct_chars['#'] = 1;
780 arc_punct_chars['*'] = 1;
781 arc_punct_chars['?'] = 1;
782 arc_punct_chars['!'] = 1;
783 arc_punct_chars['^'] = 1;
784 arc_punct_chars['&'] = 1;
786 if (optimize > 1 && !TARGET_NO_COND_EXEC)
788 /* There are two target-independent ifcvt passes, and arc_reorg may do
789 one or more arc_ifcvt calls. */
790 opt_pass *pass_arc_ifcvt_4 = make_pass_arc_ifcvt (g);
791 struct register_pass_info arc_ifcvt4_info
792 = { pass_arc_ifcvt_4, "dbr", 1, PASS_POS_INSERT_AFTER };
793 struct register_pass_info arc_ifcvt5_info
794 = { pass_arc_ifcvt_4->clone (), "shorten", 1, PASS_POS_INSERT_BEFORE };
796 register_pass (&arc_ifcvt4_info);
797 register_pass (&arc_ifcvt5_info);
800 if (flag_delayed_branch)
802 opt_pass *pass_arc_predicate_delay_insns
803 = make_pass_arc_predicate_delay_insns (g);
804 struct register_pass_info arc_predicate_delay_info
805 = { pass_arc_predicate_delay_insns, "dbr", 1, PASS_POS_INSERT_AFTER };
807 register_pass (&arc_predicate_delay_info);
811 /* Check ARC options, generate derived target attributes. */
813 static void
814 arc_override_options (void)
816 if (arc_cpu == PROCESSOR_NONE)
817 arc_cpu = PROCESSOR_ARC700;
819 if (arc_size_opt_level == 3)
820 optimize_size = 1;
822 if (flag_pic)
823 target_flags |= MASK_NO_SDATA_SET;
825 if (flag_no_common == 255)
826 flag_no_common = !TARGET_NO_SDATA_SET;
828 /* TARGET_COMPACT_CASESI needs the "q" register class. */ \
829 if (TARGET_MIXED_CODE)
830 TARGET_Q_CLASS = 1;
831 if (!TARGET_Q_CLASS)
832 TARGET_COMPACT_CASESI = 0;
833 if (TARGET_COMPACT_CASESI)
834 TARGET_CASE_VECTOR_PC_RELATIVE = 1;
836 /* These need to be done at start up. It's convenient to do them here. */
837 arc_init ();
840 /* The condition codes of the ARC, and the inverse function. */
841 /* For short branches, the "c" / "nc" names are not defined in the ARC
842 Programmers manual, so we have to use "lo" / "hs"" instead. */
843 static const char *arc_condition_codes[] =
845 "al", 0, "eq", "ne", "p", "n", "lo", "hs", "v", "nv",
846 "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
849 enum arc_cc_code_index
851 ARC_CC_AL, ARC_CC_EQ = ARC_CC_AL+2, ARC_CC_NE, ARC_CC_P, ARC_CC_N,
852 ARC_CC_C, ARC_CC_NC, ARC_CC_V, ARC_CC_NV,
853 ARC_CC_GT, ARC_CC_LE, ARC_CC_GE, ARC_CC_LT, ARC_CC_HI, ARC_CC_LS, ARC_CC_PNZ,
854 ARC_CC_LO = ARC_CC_C, ARC_CC_HS = ARC_CC_NC
857 #define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
859 /* Returns the index of the ARC condition code string in
860 `arc_condition_codes'. COMPARISON should be an rtx like
861 `(eq (...) (...))'. */
863 static int
864 get_arc_condition_code (rtx comparison)
866 switch (GET_MODE (XEXP (comparison, 0)))
868 case CCmode:
869 case SImode: /* For BRcc. */
870 switch (GET_CODE (comparison))
872 case EQ : return ARC_CC_EQ;
873 case NE : return ARC_CC_NE;
874 case GT : return ARC_CC_GT;
875 case LE : return ARC_CC_LE;
876 case GE : return ARC_CC_GE;
877 case LT : return ARC_CC_LT;
878 case GTU : return ARC_CC_HI;
879 case LEU : return ARC_CC_LS;
880 case LTU : return ARC_CC_LO;
881 case GEU : return ARC_CC_HS;
882 default : gcc_unreachable ();
884 case CC_ZNmode:
885 switch (GET_CODE (comparison))
887 case EQ : return ARC_CC_EQ;
888 case NE : return ARC_CC_NE;
889 case GE: return ARC_CC_P;
890 case LT: return ARC_CC_N;
891 case GT : return ARC_CC_PNZ;
892 default : gcc_unreachable ();
894 case CC_Zmode:
895 switch (GET_CODE (comparison))
897 case EQ : return ARC_CC_EQ;
898 case NE : return ARC_CC_NE;
899 default : gcc_unreachable ();
901 case CC_Cmode:
902 switch (GET_CODE (comparison))
904 case LTU : return ARC_CC_C;
905 case GEU : return ARC_CC_NC;
906 default : gcc_unreachable ();
908 case CC_FP_GTmode:
909 if (TARGET_ARGONAUT_SET && TARGET_SPFP)
910 switch (GET_CODE (comparison))
912 case GT : return ARC_CC_N;
913 case UNLE: return ARC_CC_P;
914 default : gcc_unreachable ();
916 else
917 switch (GET_CODE (comparison))
919 case GT : return ARC_CC_HI;
920 case UNLE : return ARC_CC_LS;
921 default : gcc_unreachable ();
923 case CC_FP_GEmode:
924 /* Same for FPX and non-FPX. */
925 switch (GET_CODE (comparison))
927 case GE : return ARC_CC_HS;
928 case UNLT : return ARC_CC_LO;
929 default : gcc_unreachable ();
931 case CC_FP_UNEQmode:
932 switch (GET_CODE (comparison))
934 case UNEQ : return ARC_CC_EQ;
935 case LTGT : return ARC_CC_NE;
936 default : gcc_unreachable ();
938 case CC_FP_ORDmode:
939 switch (GET_CODE (comparison))
941 case UNORDERED : return ARC_CC_C;
942 case ORDERED : return ARC_CC_NC;
943 default : gcc_unreachable ();
945 case CC_FPXmode:
946 switch (GET_CODE (comparison))
948 case EQ : return ARC_CC_EQ;
949 case NE : return ARC_CC_NE;
950 case UNORDERED : return ARC_CC_C;
951 case ORDERED : return ARC_CC_NC;
952 case LTGT : return ARC_CC_HI;
953 case UNEQ : return ARC_CC_LS;
954 default : gcc_unreachable ();
956 default : gcc_unreachable ();
958 /*NOTREACHED*/
959 return (42);
962 /* Return true if COMPARISON has a short form that can accomodate OFFSET. */
964 bool
965 arc_short_comparison_p (rtx comparison, int offset)
967 gcc_assert (ARC_CC_NC == ARC_CC_HS);
968 gcc_assert (ARC_CC_C == ARC_CC_LO);
969 switch (get_arc_condition_code (comparison))
971 case ARC_CC_EQ: case ARC_CC_NE:
972 return offset >= -512 && offset <= 506;
973 case ARC_CC_GT: case ARC_CC_LE: case ARC_CC_GE: case ARC_CC_LT:
974 case ARC_CC_HI: case ARC_CC_LS: case ARC_CC_LO: case ARC_CC_HS:
975 return offset >= -64 && offset <= 58;
976 default:
977 return false;
981 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
982 return the mode to be used for the comparison. */
984 enum machine_mode
985 arc_select_cc_mode (enum rtx_code op, rtx x, rtx y)
987 enum machine_mode mode = GET_MODE (x);
988 rtx x1;
990 /* For an operation that sets the condition codes as a side-effect, the
991 C and V flags is not set as for cmp, so we can only use comparisons where
992 this doesn't matter. (For LT and GE we can use "mi" and "pl"
993 instead.) */
994 /* ??? We could use "pnz" for greater than zero, however, we could then
995 get into trouble because the comparison could not be reversed. */
996 if (GET_MODE_CLASS (mode) == MODE_INT
997 && y == const0_rtx
998 && (op == EQ || op == NE
999 || ((op == LT || op == GE) && GET_MODE_SIZE (GET_MODE (x)) <= 4)))
1000 return CC_ZNmode;
1002 /* add.f for if (a+b) */
1003 if (mode == SImode
1004 && GET_CODE (y) == NEG
1005 && (op == EQ || op == NE))
1006 return CC_ZNmode;
1008 /* Check if this is a test suitable for bxor.f . */
1009 if (mode == SImode && (op == EQ || op == NE) && CONST_INT_P (y)
1010 && ((INTVAL (y) - 1) & INTVAL (y)) == 0
1011 && INTVAL (y))
1012 return CC_Zmode;
1014 /* Check if this is a test suitable for add / bmsk.f . */
1015 if (mode == SImode && (op == EQ || op == NE) && CONST_INT_P (y)
1016 && GET_CODE (x) == AND && CONST_INT_P ((x1 = XEXP (x, 1)))
1017 && ((INTVAL (x1) + 1) & INTVAL (x1)) == 0
1018 && (~INTVAL (x1) | INTVAL (y)) < 0
1019 && (~INTVAL (x1) | INTVAL (y)) > -0x800)
1020 return CC_Zmode;
1022 if (GET_MODE (x) == SImode && (op == LTU || op == GEU)
1023 && GET_CODE (x) == PLUS
1024 && (rtx_equal_p (XEXP (x, 0), y) || rtx_equal_p (XEXP (x, 1), y)))
1025 return CC_Cmode;
1027 if (TARGET_ARGONAUT_SET
1028 && ((mode == SFmode && TARGET_SPFP) || (mode == DFmode && TARGET_DPFP)))
1029 switch (op)
1031 case EQ: case NE: case UNEQ: case LTGT: case ORDERED: case UNORDERED:
1032 return CC_FPXmode;
1033 case LT: case UNGE: case GT: case UNLE:
1034 return CC_FP_GTmode;
1035 case LE: case UNGT: case GE: case UNLT:
1036 return CC_FP_GEmode;
1037 default: gcc_unreachable ();
1039 else if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_OPTFPE)
1040 switch (op)
1042 case EQ: case NE: return CC_Zmode;
1043 case LT: case UNGE:
1044 case GT: case UNLE: return CC_FP_GTmode;
1045 case LE: case UNGT:
1046 case GE: case UNLT: return CC_FP_GEmode;
1047 case UNEQ: case LTGT: return CC_FP_UNEQmode;
1048 case ORDERED: case UNORDERED: return CC_FP_ORDmode;
1049 default: gcc_unreachable ();
1052 return CCmode;
1055 /* Vectors to keep interesting information about registers where it can easily
1056 be got. We use to use the actual mode value as the bit number, but there
1057 is (or may be) more than 32 modes now. Instead we use two tables: one
1058 indexed by hard register number, and one indexed by mode. */
1060 /* The purpose of arc_mode_class is to shrink the range of modes so that
1061 they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
1062 mapped into one arc_mode_class mode. */
1064 enum arc_mode_class {
1065 C_MODE,
1066 S_MODE, D_MODE, T_MODE, O_MODE,
1067 SF_MODE, DF_MODE, TF_MODE, OF_MODE,
1068 V_MODE
1071 /* Modes for condition codes. */
1072 #define C_MODES (1 << (int) C_MODE)
1074 /* Modes for single-word and smaller quantities. */
1075 #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
1077 /* Modes for double-word and smaller quantities. */
1078 #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
1080 /* Mode for 8-byte DF values only. */
1081 #define DF_MODES (1 << DF_MODE)
1083 /* Modes for quad-word and smaller quantities. */
1084 #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
1086 /* Modes for 128-bit vectors. */
1087 #define V_MODES (1 << (int) V_MODE)
1089 /* Value is 1 if register/mode pair is acceptable on arc. */
1091 unsigned int arc_hard_regno_mode_ok[] = {
1092 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
1093 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
1094 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, D_MODES,
1095 D_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
1097 /* ??? Leave these as S_MODES for now. */
1098 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
1099 DF_MODES, 0, DF_MODES, 0, S_MODES, S_MODES, S_MODES, S_MODES,
1100 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
1101 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, C_MODES, S_MODES,
1103 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1104 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1105 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1106 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1108 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1109 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1110 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1111 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1113 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
1114 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES
1117 unsigned int arc_mode_class [NUM_MACHINE_MODES];
1119 enum reg_class arc_regno_reg_class[FIRST_PSEUDO_REGISTER];
1121 enum reg_class
1122 arc_preferred_reload_class (rtx, enum reg_class cl)
1124 if ((cl) == CHEAP_CORE_REGS || (cl) == WRITABLE_CORE_REGS)
1125 return GENERAL_REGS;
1126 return cl;
1129 /* Initialize the arc_mode_class array. */
1131 static void
1132 arc_init_reg_tables (void)
1134 int i;
1136 for (i = 0; i < NUM_MACHINE_MODES; i++)
1138 enum machine_mode m = (enum machine_mode) i;
1140 switch (GET_MODE_CLASS (m))
1142 case MODE_INT:
1143 case MODE_PARTIAL_INT:
1144 case MODE_COMPLEX_INT:
1145 if (GET_MODE_SIZE (m) <= 4)
1146 arc_mode_class[i] = 1 << (int) S_MODE;
1147 else if (GET_MODE_SIZE (m) == 8)
1148 arc_mode_class[i] = 1 << (int) D_MODE;
1149 else if (GET_MODE_SIZE (m) == 16)
1150 arc_mode_class[i] = 1 << (int) T_MODE;
1151 else if (GET_MODE_SIZE (m) == 32)
1152 arc_mode_class[i] = 1 << (int) O_MODE;
1153 else
1154 arc_mode_class[i] = 0;
1155 break;
1156 case MODE_FLOAT:
1157 case MODE_COMPLEX_FLOAT:
1158 if (GET_MODE_SIZE (m) <= 4)
1159 arc_mode_class[i] = 1 << (int) SF_MODE;
1160 else if (GET_MODE_SIZE (m) == 8)
1161 arc_mode_class[i] = 1 << (int) DF_MODE;
1162 else if (GET_MODE_SIZE (m) == 16)
1163 arc_mode_class[i] = 1 << (int) TF_MODE;
1164 else if (GET_MODE_SIZE (m) == 32)
1165 arc_mode_class[i] = 1 << (int) OF_MODE;
1166 else
1167 arc_mode_class[i] = 0;
1168 break;
1169 case MODE_VECTOR_INT:
1170 arc_mode_class [i] = (1<< (int) V_MODE);
1171 break;
1172 case MODE_CC:
1173 default:
1174 /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
1175 we must explicitly check for them here. */
1176 if (i == (int) CCmode || i == (int) CC_ZNmode || i == (int) CC_Zmode
1177 || i == (int) CC_Cmode
1178 || i == CC_FP_GTmode || i == CC_FP_GEmode || i == CC_FP_ORDmode)
1179 arc_mode_class[i] = 1 << (int) C_MODE;
1180 else
1181 arc_mode_class[i] = 0;
1182 break;
1187 /* Core registers 56..59 are used for multiply extension options.
1188 The dsp option uses r56 and r57, these are then named acc1 and acc2.
1189 acc1 is the highpart, and acc2 the lowpart, so which register gets which
1190 number depends on endianness.
1191 The mul64 multiplier options use r57 for mlo, r58 for mmid and r59 for mhi.
1192 Because mlo / mhi form a 64 bit value, we use different gcc internal
1193 register numbers to make them form a register pair as the gcc internals
1194 know it. mmid gets number 57, if still available, and mlo / mhi get
1195 number 58 and 59, depending on endianness. We use DBX_REGISTER_NUMBER
1196 to map this back. */
1197 char rname56[5] = "r56";
1198 char rname57[5] = "r57";
1199 char rname58[5] = "r58";
1200 char rname59[5] = "r59";
1202 static void
1203 arc_conditional_register_usage (void)
1205 int regno;
1206 int i;
1207 int fix_start = 60, fix_end = 55;
1209 if (TARGET_MUL64_SET)
1211 fix_start = 57;
1212 fix_end = 59;
1214 /* We don't provide a name for mmed. In rtl / assembly resource lists,
1215 you are supposed to refer to it as mlo & mhi, e.g
1216 (zero_extract:SI (reg:DI 58) (const_int 32) (16)) .
1217 In an actual asm instruction, you are of course use mmed.
1218 The point of avoiding having a separate register for mmed is that
1219 this way, we don't have to carry clobbers of that reg around in every
1220 isntruction that modifies mlo and/or mhi. */
1221 strcpy (rname57, "");
1222 strcpy (rname58, TARGET_BIG_ENDIAN ? "mhi" : "mlo");
1223 strcpy (rname59, TARGET_BIG_ENDIAN ? "mlo" : "mhi");
1225 if (TARGET_MULMAC_32BY16_SET)
1227 fix_start = 56;
1228 fix_end = fix_end > 57 ? fix_end : 57;
1229 strcpy (rname56, TARGET_BIG_ENDIAN ? "acc1" : "acc2");
1230 strcpy (rname57, TARGET_BIG_ENDIAN ? "acc2" : "acc1");
1232 for (regno = fix_start; regno <= fix_end; regno++)
1234 if (!fixed_regs[regno])
1235 warning (0, "multiply option implies r%d is fixed", regno);
1236 fixed_regs [regno] = call_used_regs[regno] = 1;
1238 if (TARGET_Q_CLASS)
1240 reg_alloc_order[2] = 12;
1241 reg_alloc_order[3] = 13;
1242 reg_alloc_order[4] = 14;
1243 reg_alloc_order[5] = 15;
1244 reg_alloc_order[6] = 1;
1245 reg_alloc_order[7] = 0;
1246 reg_alloc_order[8] = 4;
1247 reg_alloc_order[9] = 5;
1248 reg_alloc_order[10] = 6;
1249 reg_alloc_order[11] = 7;
1250 reg_alloc_order[12] = 8;
1251 reg_alloc_order[13] = 9;
1252 reg_alloc_order[14] = 10;
1253 reg_alloc_order[15] = 11;
1255 if (TARGET_SIMD_SET)
1257 int i;
1258 for (i = ARC_FIRST_SIMD_VR_REG; i <= ARC_LAST_SIMD_VR_REG; i++)
1259 reg_alloc_order [i] = i;
1260 for (i = ARC_FIRST_SIMD_DMA_CONFIG_REG;
1261 i <= ARC_LAST_SIMD_DMA_CONFIG_REG; i++)
1262 reg_alloc_order [i] = i;
1264 /* For Arctangent-A5 / ARC600, lp_count may not be read in an instruction
1265 following immediately after another one setting it to a new value.
1266 There was some discussion on how to enforce scheduling constraints for
1267 processors with missing interlocks on the gcc mailing list:
1268 http://gcc.gnu.org/ml/gcc/2008-05/msg00021.html .
1269 However, we can't actually use this approach, because for ARC the
1270 delay slot scheduling pass is active, which runs after
1271 machine_dependent_reorg. */
1272 if (TARGET_ARC600)
1273 CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], LP_COUNT);
1274 else if (!TARGET_ARC700)
1275 fixed_regs[LP_COUNT] = 1;
1276 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1277 if (!call_used_regs[regno])
1278 CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno);
1279 for (regno = 32; regno < 60; regno++)
1280 if (!fixed_regs[regno])
1281 SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], regno);
1282 if (TARGET_ARC700)
1284 for (regno = 32; regno <= 60; regno++)
1285 CLEAR_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], regno);
1287 /* If they have used -ffixed-lp_count, make sure it takes
1288 effect. */
1289 if (fixed_regs[LP_COUNT])
1291 CLEAR_HARD_REG_BIT (reg_class_contents[LPCOUNT_REG], LP_COUNT);
1292 CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], LP_COUNT);
1293 CLEAR_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], LP_COUNT);
1295 /* Instead of taking out SF_MODE like below, forbid it outright. */
1296 arc_hard_regno_mode_ok[60] = 0;
1298 else
1299 arc_hard_regno_mode_ok[60] = 1 << (int) S_MODE;
1302 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1304 if (i < 29)
1306 if (TARGET_Q_CLASS && ((i <= 3) || ((i >= 12) && (i <= 15))))
1307 arc_regno_reg_class[i] = ARCOMPACT16_REGS;
1308 else
1309 arc_regno_reg_class[i] = GENERAL_REGS;
1311 else if (i < 60)
1312 arc_regno_reg_class[i]
1313 = (fixed_regs[i]
1314 ? (TEST_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], i)
1315 ? CHEAP_CORE_REGS : ALL_CORE_REGS)
1316 : ((TARGET_ARC700
1317 && TEST_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], i))
1318 ? CHEAP_CORE_REGS : WRITABLE_CORE_REGS));
1319 else
1320 arc_regno_reg_class[i] = NO_REGS;
1323 /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS has not been activated. */
1324 if (!TARGET_Q_CLASS)
1326 CLEAR_HARD_REG_SET(reg_class_contents [ARCOMPACT16_REGS]);
1327 CLEAR_HARD_REG_SET(reg_class_contents [AC16_BASE_REGS]);
1330 gcc_assert (FIRST_PSEUDO_REGISTER >= 144);
1332 /* Handle Special Registers. */
1333 arc_regno_reg_class[29] = LINK_REGS; /* ilink1 register. */
1334 arc_regno_reg_class[30] = LINK_REGS; /* ilink2 register. */
1335 arc_regno_reg_class[31] = LINK_REGS; /* blink register. */
1336 arc_regno_reg_class[60] = LPCOUNT_REG;
1337 arc_regno_reg_class[61] = NO_REGS; /* CC_REG: must be NO_REGS. */
1338 arc_regno_reg_class[62] = GENERAL_REGS;
1340 if (TARGET_DPFP)
1342 for (i = 40; i < 44; ++i)
1344 arc_regno_reg_class[i] = DOUBLE_REGS;
1346 /* Unless they want us to do 'mov d1, 0x00000000' make sure
1347 no attempt is made to use such a register as a destination
1348 operand in *movdf_insn. */
1349 if (!TARGET_ARGONAUT_SET)
1351 /* Make sure no 'c', 'w', 'W', or 'Rac' constraint is
1352 interpreted to mean they can use D1 or D2 in their insn. */
1353 CLEAR_HARD_REG_BIT(reg_class_contents[CHEAP_CORE_REGS ], i);
1354 CLEAR_HARD_REG_BIT(reg_class_contents[ALL_CORE_REGS ], i);
1355 CLEAR_HARD_REG_BIT(reg_class_contents[WRITABLE_CORE_REGS ], i);
1356 CLEAR_HARD_REG_BIT(reg_class_contents[MPY_WRITABLE_CORE_REGS], i);
1360 else
1362 /* Disable all DOUBLE_REGISTER settings,
1363 if not generating DPFP code. */
1364 arc_regno_reg_class[40] = ALL_REGS;
1365 arc_regno_reg_class[41] = ALL_REGS;
1366 arc_regno_reg_class[42] = ALL_REGS;
1367 arc_regno_reg_class[43] = ALL_REGS;
1369 arc_hard_regno_mode_ok[40] = 0;
1370 arc_hard_regno_mode_ok[42] = 0;
1372 CLEAR_HARD_REG_SET(reg_class_contents [DOUBLE_REGS]);
1375 if (TARGET_SIMD_SET)
1377 gcc_assert (ARC_FIRST_SIMD_VR_REG == 64);
1378 gcc_assert (ARC_LAST_SIMD_VR_REG == 127);
1380 for (i = ARC_FIRST_SIMD_VR_REG; i <= ARC_LAST_SIMD_VR_REG; i++)
1381 arc_regno_reg_class [i] = SIMD_VR_REGS;
1383 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_REG == 128);
1384 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_IN_REG == 128);
1385 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG == 136);
1386 gcc_assert (ARC_LAST_SIMD_DMA_CONFIG_REG == 143);
1388 for (i = ARC_FIRST_SIMD_DMA_CONFIG_REG;
1389 i <= ARC_LAST_SIMD_DMA_CONFIG_REG; i++)
1390 arc_regno_reg_class [i] = SIMD_DMA_CONFIG_REGS;
1393 /* pc : r63 */
1394 arc_regno_reg_class[PROGRAM_COUNTER_REGNO] = GENERAL_REGS;
1397 /* Handle an "interrupt" attribute; arguments as in
1398 struct attribute_spec.handler. */
1400 static tree
1401 arc_handle_interrupt_attribute (tree *, tree name, tree args, int,
1402 bool *no_add_attrs)
1404 gcc_assert (args);
1406 tree value = TREE_VALUE (args);
1408 if (TREE_CODE (value) != STRING_CST)
1410 warning (OPT_Wattributes,
1411 "argument of %qE attribute is not a string constant",
1412 name);
1413 *no_add_attrs = true;
1415 else if (strcmp (TREE_STRING_POINTER (value), "ilink1")
1416 && strcmp (TREE_STRING_POINTER (value), "ilink2"))
1418 warning (OPT_Wattributes,
1419 "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
1420 name);
1421 *no_add_attrs = true;
1423 return NULL_TREE;
1426 /* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
1427 and two if they are nearly compatible (which causes a warning to be
1428 generated). */
1430 static int
1431 arc_comp_type_attributes (const_tree type1,
1432 const_tree type2)
1434 int l1, l2, m1, m2, s1, s2;
1436 /* Check for mismatch of non-default calling convention. */
1437 if (TREE_CODE (type1) != FUNCTION_TYPE)
1438 return 1;
1440 /* Check for mismatched call attributes. */
1441 l1 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1)) != NULL;
1442 l2 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2)) != NULL;
1443 m1 = lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type1)) != NULL;
1444 m2 = lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type2)) != NULL;
1445 s1 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1)) != NULL;
1446 s2 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2)) != NULL;
1448 /* Only bother to check if an attribute is defined. */
1449 if (l1 | l2 | m1 | m2 | s1 | s2)
1451 /* If one type has an attribute, the other must have the same attribute. */
1452 if ((l1 != l2) || (m1 != m2) || (s1 != s2))
1453 return 0;
1455 /* Disallow mixed attributes. */
1456 if (l1 + m1 + s1 > 1)
1457 return 0;
1461 return 1;
1464 /* Set the default attributes for TYPE. */
1466 void
1467 arc_set_default_type_attributes (tree type ATTRIBUTE_UNUSED)
1469 gcc_unreachable();
1472 /* Misc. utilities. */
1474 /* X and Y are two things to compare using CODE. Emit the compare insn and
1475 return the rtx for the cc reg in the proper mode. */
1478 gen_compare_reg (rtx comparison, enum machine_mode omode)
1480 enum rtx_code code = GET_CODE (comparison);
1481 rtx x = XEXP (comparison, 0);
1482 rtx y = XEXP (comparison, 1);
1483 rtx tmp, cc_reg;
1484 enum machine_mode mode, cmode;
1487 cmode = GET_MODE (x);
1488 if (cmode == VOIDmode)
1489 cmode = GET_MODE (y);
1490 gcc_assert (cmode == SImode || cmode == SFmode || cmode == DFmode);
1491 if (cmode == SImode)
1493 if (!register_operand (x, SImode))
1495 if (register_operand (y, SImode))
1497 tmp = x;
1498 x = y;
1499 y = tmp;
1500 code = swap_condition (code);
1502 else
1503 x = copy_to_mode_reg (SImode, x);
1505 if (GET_CODE (y) == SYMBOL_REF && flag_pic)
1506 y = copy_to_mode_reg (SImode, y);
1508 else
1510 x = force_reg (cmode, x);
1511 y = force_reg (cmode, y);
1513 mode = SELECT_CC_MODE (code, x, y);
1515 cc_reg = gen_rtx_REG (mode, CC_REG);
1517 /* ??? FIXME (x-y)==0, as done by both cmpsfpx_raw and
1518 cmpdfpx_raw, is not a correct comparison for floats:
1519 http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
1521 if (TARGET_ARGONAUT_SET
1522 && ((cmode == SFmode && TARGET_SPFP) || (cmode == DFmode && TARGET_DPFP)))
1524 switch (code)
1526 case NE: case EQ: case LT: case UNGE: case LE: case UNGT:
1527 case UNEQ: case LTGT: case ORDERED: case UNORDERED:
1528 break;
1529 case GT: case UNLE: case GE: case UNLT:
1530 code = swap_condition (code);
1531 tmp = x;
1532 x = y;
1533 y = tmp;
1534 break;
1535 default:
1536 gcc_unreachable ();
1538 if (cmode == SFmode)
1540 emit_insn (gen_cmpsfpx_raw (x, y));
1542 else /* DFmode */
1544 /* Accepts Dx regs directly by insns. */
1545 emit_insn (gen_cmpdfpx_raw (x, y));
1548 if (mode != CC_FPXmode)
1549 emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
1550 gen_rtx_COMPARE (mode,
1551 gen_rtx_REG (CC_FPXmode, 61),
1552 const0_rtx)));
1554 else if (GET_MODE_CLASS (cmode) == MODE_FLOAT && TARGET_OPTFPE)
1556 rtx op0 = gen_rtx_REG (cmode, 0);
1557 rtx op1 = gen_rtx_REG (cmode, GET_MODE_SIZE (cmode) / UNITS_PER_WORD);
1559 switch (code)
1561 case NE: case EQ: case GT: case UNLE: case GE: case UNLT:
1562 case UNEQ: case LTGT: case ORDERED: case UNORDERED:
1563 break;
1564 case LT: case UNGE: case LE: case UNGT:
1565 code = swap_condition (code);
1566 tmp = x;
1567 x = y;
1568 y = tmp;
1569 break;
1570 default:
1571 gcc_unreachable ();
1573 if (currently_expanding_to_rtl)
1575 emit_move_insn (op0, x);
1576 emit_move_insn (op1, y);
1578 else
1580 gcc_assert (rtx_equal_p (op0, x));
1581 gcc_assert (rtx_equal_p (op1, y));
1583 emit_insn (gen_cmp_float (cc_reg, gen_rtx_COMPARE (mode, op0, op1)));
1585 else
1586 emit_insn (gen_rtx_SET (omode, cc_reg,
1587 gen_rtx_COMPARE (mode, x, y)));
1588 return gen_rtx_fmt_ee (code, omode, cc_reg, const0_rtx);
1591 /* Return true if VALUE, a const_double, will fit in a limm (4 byte number).
1592 We assume the value can be either signed or unsigned. */
1594 bool
1595 arc_double_limm_p (rtx value)
1597 HOST_WIDE_INT low, high;
1599 gcc_assert (GET_CODE (value) == CONST_DOUBLE);
1601 if (TARGET_DPFP)
1602 return true;
1604 low = CONST_DOUBLE_LOW (value);
1605 high = CONST_DOUBLE_HIGH (value);
1607 if (low & 0x80000000)
1609 return (((unsigned HOST_WIDE_INT) low <= 0xffffffff && high == 0)
1610 || (((low & - (unsigned HOST_WIDE_INT) 0x80000000)
1611 == - (unsigned HOST_WIDE_INT) 0x80000000)
1612 && high == -1));
1614 else
1616 return (unsigned HOST_WIDE_INT) low <= 0x7fffffff && high == 0;
1620 /* Do any needed setup for a variadic function. For the ARC, we must
1621 create a register parameter block, and then copy any anonymous arguments
1622 in registers to memory.
1624 CUM has not been updated for the last named argument which has type TYPE
1625 and mode MODE, and we rely on this fact. */
1627 static void
1628 arc_setup_incoming_varargs (cumulative_args_t args_so_far,
1629 enum machine_mode mode, tree type,
1630 int *pretend_size, int no_rtl)
1632 int first_anon_arg;
1633 CUMULATIVE_ARGS next_cum;
1635 /* We must treat `__builtin_va_alist' as an anonymous arg. */
1637 next_cum = *get_cumulative_args (args_so_far);
1638 arc_function_arg_advance (pack_cumulative_args (&next_cum), mode, type, 1);
1639 first_anon_arg = next_cum;
1641 if (first_anon_arg < MAX_ARC_PARM_REGS)
1643 /* First anonymous (unnamed) argument is in a reg. */
1645 /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
1646 int first_reg_offset = first_anon_arg;
1648 if (!no_rtl)
1650 rtx regblock
1651 = gen_rtx_MEM (BLKmode, plus_constant (Pmode, arg_pointer_rtx,
1652 FIRST_PARM_OFFSET (0)));
1653 move_block_from_reg (first_reg_offset, regblock,
1654 MAX_ARC_PARM_REGS - first_reg_offset);
1657 *pretend_size
1658 = ((MAX_ARC_PARM_REGS - first_reg_offset ) * UNITS_PER_WORD);
1662 /* Cost functions. */
1664 /* Provide the costs of an addressing mode that contains ADDR.
1665 If ADDR is not a valid address, its cost is irrelevant. */
1668 arc_address_cost (rtx addr, enum machine_mode, addr_space_t, bool speed)
1670 switch (GET_CODE (addr))
1672 case REG :
1673 return speed || satisfies_constraint_Rcq (addr) ? 0 : 1;
1674 case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC:
1675 case PRE_MODIFY: case POST_MODIFY:
1676 return !speed;
1678 case LABEL_REF :
1679 case SYMBOL_REF :
1680 case CONST :
1681 /* Most likely needs a LIMM. */
1682 return COSTS_N_INSNS (1);
1684 case PLUS :
1686 register rtx plus0 = XEXP (addr, 0);
1687 register rtx plus1 = XEXP (addr, 1);
1689 if (GET_CODE (plus0) != REG
1690 && (GET_CODE (plus0) != MULT
1691 || !CONST_INT_P (XEXP (plus0, 1))
1692 || (INTVAL (XEXP (plus0, 1)) != 2
1693 && INTVAL (XEXP (plus0, 1)) != 4)))
1694 break;
1696 switch (GET_CODE (plus1))
1698 case CONST_INT :
1699 return (!RTX_OK_FOR_OFFSET_P (SImode, plus1)
1700 ? COSTS_N_INSNS (1)
1701 : speed
1703 : (satisfies_constraint_Rcq (plus0)
1704 && satisfies_constraint_O (plus1))
1706 : 1);
1707 case REG:
1708 return (speed < 1 ? 0
1709 : (satisfies_constraint_Rcq (plus0)
1710 && satisfies_constraint_Rcq (plus1))
1711 ? 0 : 1);
1712 case CONST :
1713 case SYMBOL_REF :
1714 case LABEL_REF :
1715 return COSTS_N_INSNS (1);
1716 default:
1717 break;
1719 break;
1721 default:
1722 break;
1725 return 4;
1728 /* Emit instruction X with the frame related bit set. */
1730 static rtx
1731 frame_insn (rtx x)
1733 x = emit_insn (x);
1734 RTX_FRAME_RELATED_P (x) = 1;
1735 return x;
1738 /* Emit a frame insn to move SRC to DST. */
1740 static rtx
1741 frame_move (rtx dst, rtx src)
1743 return frame_insn (gen_rtx_SET (VOIDmode, dst, src));
1746 /* Like frame_move, but add a REG_INC note for REG if ADDR contains an
1747 auto increment address, or is zero. */
1749 static rtx
1750 frame_move_inc (rtx dst, rtx src, rtx reg, rtx addr)
1752 rtx insn = frame_move (dst, src);
1754 if (!addr
1755 || GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_INC
1756 || GET_CODE (addr) == PRE_MODIFY || GET_CODE (addr) == POST_MODIFY)
1757 add_reg_note (insn, REG_INC, reg);
1758 return insn;
1761 /* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
1763 static rtx
1764 frame_add (rtx reg, HOST_WIDE_INT offset)
1766 gcc_assert ((offset & 0x3) == 0);
1767 if (!offset)
1768 return NULL_RTX;
1769 return frame_move (reg, plus_constant (Pmode, reg, offset));
1772 /* Emit a frame insn which adjusts stack pointer by OFFSET. */
1774 static rtx
1775 frame_stack_add (HOST_WIDE_INT offset)
1777 return frame_add (stack_pointer_rtx, offset);
1780 /* Traditionally, we push saved registers first in the prologue,
1781 then we allocate the rest of the frame - and reverse in the epilogue.
1782 This has still its merits for ease of debugging, or saving code size
1783 or even execution time if the stack frame is so large that some accesses
1784 can't be encoded anymore with offsets in the instruction code when using
1785 a different scheme.
1786 Also, it would be a good starting point if we got instructions to help
1787 with register save/restore.
1789 However, often stack frames are small, and the pushing / popping has
1790 some costs:
1791 - the stack modification prevents a lot of scheduling.
1792 - frame allocation / deallocation needs extra instructions.
1793 - unless we know that we compile ARC700 user code, we need to put
1794 a memory barrier after frame allocation / before deallocation to
1795 prevent interrupts clobbering our data in the frame.
1796 In particular, we don't have any such guarantees for library functions,
1797 which tend to, on the other hand, to have small frames.
1799 Thus, for small frames, we'd like to use a different scheme:
1800 - The frame is allocated in full with the first prologue instruction,
1801 and deallocated in full with the last epilogue instruction.
1802 Thus, the instructions in-betwen can be freely scheduled.
1803 - If the function has no outgoing arguments on the stack, we can allocate
1804 one register save slot at the top of the stack. This register can then
1805 be saved simultanously with frame allocation, and restored with
1806 frame deallocation.
1807 This register can be picked depending on scheduling considerations,
1808 although same though should go into having some set of registers
1809 to be potentially lingering after a call, and others to be available
1810 immediately - i.e. in the absence of interprocedual optimization, we
1811 can use an ABI-like convention for register allocation to reduce
1812 stalls after function return. */
1813 /* Function prologue/epilogue handlers. */
1815 /* ARCompact stack frames look like:
1817 Before call After call
1818 high +-----------------------+ +-----------------------+
1819 mem | reg parm save area | | reg parm save area |
1820 | only created for | | only created for |
1821 | variable arg fns | | variable arg fns |
1822 AP +-----------------------+ +-----------------------+
1823 | return addr register | | return addr register |
1824 | (if required) | | (if required) |
1825 +-----------------------+ +-----------------------+
1826 | | | |
1827 | reg save area | | reg save area |
1828 | | | |
1829 +-----------------------+ +-----------------------+
1830 | frame pointer | | frame pointer |
1831 | (if required) | | (if required) |
1832 FP +-----------------------+ +-----------------------+
1833 | | | |
1834 | local/temp variables | | local/temp variables |
1835 | | | |
1836 +-----------------------+ +-----------------------+
1837 | | | |
1838 | arguments on stack | | arguments on stack |
1839 | | | |
1840 SP +-----------------------+ +-----------------------+
1841 | reg parm save area |
1842 | only created for |
1843 | variable arg fns |
1844 AP +-----------------------+
1845 | return addr register |
1846 | (if required) |
1847 +-----------------------+
1849 | reg save area |
1851 +-----------------------+
1852 | frame pointer |
1853 | (if required) |
1854 FP +-----------------------+
1856 | local/temp variables |
1858 +-----------------------+
1860 | arguments on stack |
1861 low | |
1862 mem SP +-----------------------+
1864 Notes:
1865 1) The "reg parm save area" does not exist for non variable argument fns.
1866 The "reg parm save area" can be eliminated completely if we created our
1867 own va-arc.h, but that has tradeoffs as well (so it's not done). */
1869 /* Structure to be filled in by arc_compute_frame_size with register
1870 save masks, and offsets for the current function. */
1871 struct GTY (()) arc_frame_info
1873 unsigned int total_size; /* # bytes that the entire frame takes up. */
1874 unsigned int extra_size; /* # bytes of extra stuff. */
1875 unsigned int pretend_size; /* # bytes we push and pretend caller did. */
1876 unsigned int args_size; /* # bytes that outgoing arguments take up. */
1877 unsigned int reg_size; /* # bytes needed to store regs. */
1878 unsigned int var_size; /* # bytes that variables take up. */
1879 unsigned int reg_offset; /* Offset from new sp to store regs. */
1880 unsigned int gmask; /* Mask of saved gp registers. */
1881 int initialized; /* Nonzero if frame size already calculated. */
1882 short millicode_start_reg;
1883 short millicode_end_reg;
1884 bool save_return_addr;
1887 /* Defining data structures for per-function information. */
1889 typedef struct GTY (()) machine_function
1891 enum arc_function_type fn_type;
1892 struct arc_frame_info frame_info;
1893 /* To keep track of unalignment caused by short insns. */
1894 int unalign;
1895 int force_short_suffix; /* Used when disgorging return delay slot insns. */
1896 const char *size_reason;
1897 struct arc_ccfsm ccfsm_current;
1898 /* Map from uid to ccfsm state during branch shortening. */
1899 rtx ccfsm_current_insn;
1900 char arc_reorg_started;
1901 char prescan_initialized;
1902 } machine_function;
1904 /* Type of function DECL.
1906 The result is cached. To reset the cache at the end of a function,
1907 call with DECL = NULL_TREE. */
1909 enum arc_function_type
1910 arc_compute_function_type (struct function *fun)
1912 tree decl = fun->decl;
1913 tree a;
1914 enum arc_function_type fn_type = fun->machine->fn_type;
1916 if (fn_type != ARC_FUNCTION_UNKNOWN)
1917 return fn_type;
1919 /* Assume we have a normal function (not an interrupt handler). */
1920 fn_type = ARC_FUNCTION_NORMAL;
1922 /* Now see if this is an interrupt handler. */
1923 for (a = DECL_ATTRIBUTES (decl);
1925 a = TREE_CHAIN (a))
1927 tree name = TREE_PURPOSE (a), args = TREE_VALUE (a);
1929 if (name == get_identifier ("interrupt")
1930 && list_length (args) == 1
1931 && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
1933 tree value = TREE_VALUE (args);
1935 if (!strcmp (TREE_STRING_POINTER (value), "ilink1"))
1936 fn_type = ARC_FUNCTION_ILINK1;
1937 else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
1938 fn_type = ARC_FUNCTION_ILINK2;
1939 else
1940 gcc_unreachable ();
1941 break;
1945 return fun->machine->fn_type = fn_type;
1948 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
1949 #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
1951 /* Tell prologue and epilogue if register REGNO should be saved / restored.
1952 The return address and frame pointer are treated separately.
1953 Don't consider them here.
1954 Addition for pic: The gp register needs to be saved if the current
1955 function changes it to access gotoff variables.
1956 FIXME: This will not be needed if we used some arbitrary register
1957 instead of r26.
1959 #define MUST_SAVE_REGISTER(regno, interrupt_p) \
1960 (((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
1961 && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p))) \
1962 || (flag_pic && crtl->uses_pic_offset_table \
1963 && regno == PIC_OFFSET_TABLE_REGNUM) )
1965 #define MUST_SAVE_RETURN_ADDR \
1966 (cfun->machine->frame_info.save_return_addr)
1968 /* Return non-zero if there are registers to be saved or loaded using
1969 millicode thunks. We can only use consecutive sequences starting
1970 with r13, and not going beyond r25.
1971 GMASK is a bitmask of registers to save. This function sets
1972 FRAME->millicod_start_reg .. FRAME->millicode_end_reg to the range
1973 of registers to be saved / restored with a millicode call. */
1975 static int
1976 arc_compute_millicode_save_restore_regs (unsigned int gmask,
1977 struct arc_frame_info *frame)
1979 int regno;
1981 int start_reg = 13, end_reg = 25;
1983 for (regno = start_reg; regno <= end_reg && (gmask & (1L << regno));)
1984 regno++;
1985 end_reg = regno - 1;
1986 /* There is no point in using millicode thunks if we don't save/restore
1987 at least three registers. For non-leaf functions we also have the
1988 blink restore. */
1989 if (regno - start_reg >= 3 - (crtl->is_leaf == 0))
1991 frame->millicode_start_reg = 13;
1992 frame->millicode_end_reg = regno - 1;
1993 return 1;
1995 return 0;
1998 /* Return the bytes needed to compute the frame pointer from the current
1999 stack pointer.
2001 SIZE is the size needed for local variables. */
2003 unsigned int
2004 arc_compute_frame_size (int size) /* size = # of var. bytes allocated. */
2006 int regno;
2007 unsigned int total_size, var_size, args_size, pretend_size, extra_size;
2008 unsigned int reg_size, reg_offset;
2009 unsigned int gmask;
2010 enum arc_function_type fn_type;
2011 int interrupt_p;
2012 struct arc_frame_info *frame_info = &cfun->machine->frame_info;
2014 size = ARC_STACK_ALIGN (size);
2016 /* 1) Size of locals and temporaries */
2017 var_size = size;
2019 /* 2) Size of outgoing arguments */
2020 args_size = crtl->outgoing_args_size;
2022 /* 3) Calculate space needed for saved registers.
2023 ??? We ignore the extension registers for now. */
2025 /* See if this is an interrupt handler. Call used registers must be saved
2026 for them too. */
2028 reg_size = 0;
2029 gmask = 0;
2030 fn_type = arc_compute_function_type (cfun);
2031 interrupt_p = ARC_INTERRUPT_P (fn_type);
2033 for (regno = 0; regno <= 31; regno++)
2035 if (MUST_SAVE_REGISTER (regno, interrupt_p))
2037 reg_size += UNITS_PER_WORD;
2038 gmask |= 1 << regno;
2042 /* 4) Space for back trace data structure.
2043 <return addr reg size> (if required) + <fp size> (if required). */
2044 frame_info->save_return_addr
2045 = (!crtl->is_leaf || df_regs_ever_live_p (RETURN_ADDR_REGNUM));
2046 /* Saving blink reg in case of leaf function for millicode thunk calls. */
2047 if (optimize_size && !TARGET_NO_MILLICODE_THUNK_SET)
2049 if (arc_compute_millicode_save_restore_regs (gmask, frame_info))
2050 frame_info->save_return_addr = true;
2053 extra_size = 0;
2054 if (MUST_SAVE_RETURN_ADDR)
2055 extra_size = 4;
2056 if (frame_pointer_needed)
2057 extra_size += 4;
2059 /* 5) Space for variable arguments passed in registers */
2060 pretend_size = crtl->args.pretend_args_size;
2062 /* Ensure everything before the locals is aligned appropriately. */
2064 unsigned int extra_plus_reg_size;
2065 unsigned int extra_plus_reg_size_aligned;
2067 extra_plus_reg_size = extra_size + reg_size;
2068 extra_plus_reg_size_aligned = ARC_STACK_ALIGN(extra_plus_reg_size);
2069 reg_size = extra_plus_reg_size_aligned - extra_size;
2072 /* Compute total frame size. */
2073 total_size = var_size + args_size + extra_size + pretend_size + reg_size;
2075 total_size = ARC_STACK_ALIGN (total_size);
2077 /* Compute offset of register save area from stack pointer:
2078 A5 Frame: pretend_size <blink> reg_size <fp> var_size args_size <--sp
2080 reg_offset = (total_size - (pretend_size + reg_size + extra_size)
2081 + (frame_pointer_needed ? 4 : 0));
2083 /* Save computed information. */
2084 frame_info->total_size = total_size;
2085 frame_info->extra_size = extra_size;
2086 frame_info->pretend_size = pretend_size;
2087 frame_info->var_size = var_size;
2088 frame_info->args_size = args_size;
2089 frame_info->reg_size = reg_size;
2090 frame_info->reg_offset = reg_offset;
2091 frame_info->gmask = gmask;
2092 frame_info->initialized = reload_completed;
2094 /* Ok, we're done. */
2095 return total_size;
2098 /* Common code to save/restore registers. */
2099 /* BASE_REG is the base register to use for addressing and to adjust.
2100 GMASK is a bitmask of general purpose registers to save/restore.
2101 epilogue_p 0: prologue 1:epilogue 2:epilogue, sibling thunk
2102 If *FIRST_OFFSET is non-zero, add it first to BASE_REG - preferably
2103 using a pre-modify for the first memory access. *FIRST_OFFSET is then
2104 zeroed. */
2106 static void
2107 arc_save_restore (rtx base_reg,
2108 unsigned int gmask, int epilogue_p, int *first_offset)
2110 unsigned int offset = 0;
2111 int regno;
2112 struct arc_frame_info *frame = &cfun->machine->frame_info;
2113 rtx sibthunk_insn = NULL_RTX;
2115 if (gmask)
2117 /* Millicode thunks implementation:
2118 Generates calls to millicodes for registers starting from r13 to r25
2119 Present Limitations:
2120 - Only one range supported. The remaining regs will have the ordinary
2121 st and ld instructions for store and loads. Hence a gmask asking
2122 to store r13-14, r16-r25 will only generate calls to store and
2123 load r13 to r14 while store and load insns will be generated for
2124 r16 to r25 in the prologue and epilogue respectively.
2126 - Presently library only supports register ranges starting from r13.
2128 if (epilogue_p == 2 || frame->millicode_end_reg > 14)
2130 int start_call = frame->millicode_start_reg;
2131 int end_call = frame->millicode_end_reg;
2132 int n_regs = end_call - start_call + 1;
2133 int i = 0, r, off = 0;
2134 rtx insn;
2135 rtx ret_addr = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
2137 if (*first_offset)
2139 /* "reg_size" won't be more than 127 . */
2140 gcc_assert (epilogue_p || abs (*first_offset) <= 127);
2141 frame_add (base_reg, *first_offset);
2142 *first_offset = 0;
2144 insn = gen_rtx_PARALLEL
2145 (VOIDmode, rtvec_alloc ((epilogue_p == 2) + n_regs + 1));
2146 if (epilogue_p == 2)
2147 i += 2;
2148 else
2149 XVECEXP (insn, 0, n_regs) = gen_rtx_CLOBBER (VOIDmode, ret_addr);
2150 for (r = start_call; r <= end_call; r++, off += UNITS_PER_WORD, i++)
2152 rtx reg = gen_rtx_REG (SImode, r);
2153 rtx mem
2154 = gen_frame_mem (SImode, plus_constant (Pmode, base_reg, off));
2156 if (epilogue_p)
2157 XVECEXP (insn, 0, i) = gen_rtx_SET (VOIDmode, reg, mem);
2158 else
2159 XVECEXP (insn, 0, i) = gen_rtx_SET (VOIDmode, mem, reg);
2160 gmask = gmask & ~(1L << r);
2162 if (epilogue_p == 2)
2163 sibthunk_insn = insn;
2164 else
2165 frame_insn (insn);
2166 offset += off;
2169 for (regno = 0; regno <= 31; regno++)
2171 if ((gmask & (1L << regno)) != 0)
2173 rtx reg = gen_rtx_REG (SImode, regno);
2174 rtx addr, mem;
2176 if (*first_offset)
2178 gcc_assert (!offset);
2179 addr = plus_constant (Pmode, base_reg, *first_offset);
2180 addr = gen_rtx_PRE_MODIFY (Pmode, base_reg, addr);
2181 *first_offset = 0;
2183 else
2185 gcc_assert (SMALL_INT (offset));
2186 addr = plus_constant (Pmode, base_reg, offset);
2188 mem = gen_frame_mem (SImode, addr);
2189 if (epilogue_p)
2190 frame_move_inc (reg, mem, base_reg, addr);
2191 else
2192 frame_move_inc (mem, reg, base_reg, addr);
2193 offset += UNITS_PER_WORD;
2194 } /* if */
2195 } /* for */
2196 }/* if */
2197 if (sibthunk_insn)
2199 rtx r12 = gen_rtx_REG (Pmode, 12);
2201 frame_insn (gen_rtx_SET (VOIDmode, r12, GEN_INT (offset)));
2202 XVECEXP (sibthunk_insn, 0, 0) = ret_rtx;
2203 XVECEXP (sibthunk_insn, 0, 1)
2204 = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
2205 gen_rtx_PLUS (Pmode, stack_pointer_rtx, r12));
2206 sibthunk_insn = emit_jump_insn (sibthunk_insn);
2207 RTX_FRAME_RELATED_P (sibthunk_insn) = 1;
2209 } /* arc_save_restore */
2212 int arc_return_address_regs[4]
2213 = {0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM};
2215 /* Set up the stack and frame pointer (if desired) for the function. */
2217 void
2218 arc_expand_prologue (void)
2220 int size = get_frame_size ();
2221 unsigned int gmask = cfun->machine->frame_info.gmask;
2222 /* unsigned int frame_pointer_offset;*/
2223 unsigned int frame_size_to_allocate;
2224 /* (FIXME: The first store will use a PRE_MODIFY; this will usually be r13.
2225 Change the stack layout so that we rather store a high register with the
2226 PRE_MODIFY, thus enabling more short insn generation.) */
2227 int first_offset = 0;
2229 size = ARC_STACK_ALIGN (size);
2231 /* Compute/get total frame size. */
2232 size = (!cfun->machine->frame_info.initialized
2233 ? arc_compute_frame_size (size)
2234 : cfun->machine->frame_info.total_size);
2236 if (flag_stack_usage_info)
2237 current_function_static_stack_size = size;
2239 /* Keep track of frame size to be allocated. */
2240 frame_size_to_allocate = size;
2242 /* These cases shouldn't happen. Catch them now. */
2243 gcc_assert (!(size == 0 && gmask));
2245 /* Allocate space for register arguments if this is a variadic function. */
2246 if (cfun->machine->frame_info.pretend_size != 0)
2248 /* Ensure pretend_size is maximum of 8 * word_size. */
2249 gcc_assert (cfun->machine->frame_info.pretend_size <= 32);
2251 frame_stack_add (-(HOST_WIDE_INT)cfun->machine->frame_info.pretend_size);
2252 frame_size_to_allocate -= cfun->machine->frame_info.pretend_size;
2255 /* The home-grown ABI says link register is saved first. */
2256 if (MUST_SAVE_RETURN_ADDR)
2258 rtx ra = gen_rtx_REG (SImode, RETURN_ADDR_REGNUM);
2259 rtx mem = gen_frame_mem (Pmode, gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
2261 frame_move_inc (mem, ra, stack_pointer_rtx, 0);
2262 frame_size_to_allocate -= UNITS_PER_WORD;
2264 } /* MUST_SAVE_RETURN_ADDR */
2266 /* Save any needed call-saved regs (and call-used if this is an
2267 interrupt handler) for ARCompact ISA. */
2268 if (cfun->machine->frame_info.reg_size)
2270 first_offset = -cfun->machine->frame_info.reg_size;
2271 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
2272 arc_save_restore (stack_pointer_rtx, gmask, 0, &first_offset);
2273 frame_size_to_allocate -= cfun->machine->frame_info.reg_size;
2277 /* Save frame pointer if needed. */
2278 if (frame_pointer_needed)
2280 rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2281 GEN_INT (-UNITS_PER_WORD + first_offset));
2282 rtx mem = gen_frame_mem (Pmode, gen_rtx_PRE_MODIFY (Pmode,
2283 stack_pointer_rtx,
2284 addr));
2285 frame_move_inc (mem, frame_pointer_rtx, stack_pointer_rtx, 0);
2286 frame_size_to_allocate -= UNITS_PER_WORD;
2287 first_offset = 0;
2288 frame_move (frame_pointer_rtx, stack_pointer_rtx);
2291 /* ??? We don't handle the case where the saved regs are more than 252
2292 bytes away from sp. This can be handled by decrementing sp once, saving
2293 the regs, and then decrementing it again. The epilogue doesn't have this
2294 problem as the `ld' insn takes reg+limm values (though it would be more
2295 efficient to avoid reg+limm). */
2297 frame_size_to_allocate -= first_offset;
2298 /* Allocate the stack frame. */
2299 if (frame_size_to_allocate > 0)
2300 frame_stack_add ((HOST_WIDE_INT) 0 - frame_size_to_allocate);
2302 /* Setup the gp register, if needed. */
2303 if (crtl->uses_pic_offset_table)
2304 arc_finalize_pic ();
2307 /* Do any necessary cleanup after a function to restore stack, frame,
2308 and regs. */
2310 void
2311 arc_expand_epilogue (int sibcall_p)
2313 int size = get_frame_size ();
2314 enum arc_function_type fn_type = arc_compute_function_type (cfun);
2316 size = ARC_STACK_ALIGN (size);
2317 size = (!cfun->machine->frame_info.initialized
2318 ? arc_compute_frame_size (size)
2319 : cfun->machine->frame_info.total_size);
2321 unsigned int pretend_size = cfun->machine->frame_info.pretend_size;
2322 unsigned int frame_size;
2323 unsigned int size_to_deallocate;
2324 int restored;
2325 int can_trust_sp_p = !cfun->calls_alloca;
2326 int first_offset = 0;
2327 int millicode_p = cfun->machine->frame_info.millicode_end_reg > 0;
2329 size_to_deallocate = size;
2331 frame_size = size - (pretend_size +
2332 cfun->machine->frame_info.reg_size +
2333 cfun->machine->frame_info.extra_size);
2335 /* ??? There are lots of optimizations that can be done here.
2336 EG: Use fp to restore regs if it's closer.
2337 Maybe in time we'll do them all. For now, always restore regs from
2338 sp, but don't restore sp if we don't have to. */
2340 if (!can_trust_sp_p)
2341 gcc_assert (frame_pointer_needed);
2343 /* Restore stack pointer to the beginning of saved register area for
2344 ARCompact ISA. */
2345 if (frame_size)
2347 if (frame_pointer_needed)
2348 frame_move (stack_pointer_rtx, frame_pointer_rtx);
2349 else
2350 first_offset = frame_size;
2351 size_to_deallocate -= frame_size;
2353 else if (!can_trust_sp_p)
2354 frame_stack_add (-frame_size);
2357 /* Restore any saved registers. */
2358 if (frame_pointer_needed)
2360 rtx addr = gen_rtx_POST_INC (Pmode, stack_pointer_rtx);
2362 frame_move_inc (frame_pointer_rtx, gen_frame_mem (Pmode, addr),
2363 stack_pointer_rtx, 0);
2364 size_to_deallocate -= UNITS_PER_WORD;
2367 /* Load blink after the calls to thunk calls in case of optimize size. */
2368 if (millicode_p)
2370 int sibthunk_p = (!sibcall_p
2371 && fn_type == ARC_FUNCTION_NORMAL
2372 && !cfun->machine->frame_info.pretend_size);
2374 gcc_assert (!(cfun->machine->frame_info.gmask
2375 & (FRAME_POINTER_MASK | RETURN_ADDR_MASK)));
2376 arc_save_restore (stack_pointer_rtx,
2377 cfun->machine->frame_info.gmask,
2378 1 + sibthunk_p, &first_offset);
2379 if (sibthunk_p)
2380 goto epilogue_done;
2382 /* If we are to restore registers, and first_offset would require
2383 a limm to be encoded in a PRE_MODIFY, yet we can add it with a
2384 fast add to the stack pointer, do this now. */
2385 if ((!SMALL_INT (first_offset)
2386 && cfun->machine->frame_info.gmask
2387 && ((TARGET_ARC700 && !optimize_size)
2388 ? first_offset <= 0x800
2389 : satisfies_constraint_C2a (GEN_INT (first_offset))))
2390 /* Also do this if we have both gprs and return
2391 address to restore, and they both would need a LIMM. */
2392 || (MUST_SAVE_RETURN_ADDR
2393 && !SMALL_INT ((cfun->machine->frame_info.reg_size + first_offset) >> 2)
2394 && cfun->machine->frame_info.gmask))
2396 frame_stack_add (first_offset);
2397 first_offset = 0;
2399 if (MUST_SAVE_RETURN_ADDR)
2401 rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
2402 int ra_offs = cfun->machine->frame_info.reg_size + first_offset;
2403 rtx addr = plus_constant (Pmode, stack_pointer_rtx, ra_offs);
2405 /* If the load of blink would need a LIMM, but we can add
2406 the offset quickly to sp, do the latter. */
2407 if (!SMALL_INT (ra_offs >> 2)
2408 && !cfun->machine->frame_info.gmask
2409 && ((TARGET_ARC700 && !optimize_size)
2410 ? ra_offs <= 0x800
2411 : satisfies_constraint_C2a (GEN_INT (ra_offs))))
2413 size_to_deallocate -= ra_offs - first_offset;
2414 first_offset = 0;
2415 frame_stack_add (ra_offs);
2416 ra_offs = 0;
2417 addr = stack_pointer_rtx;
2419 /* See if we can combine the load of the return address with the
2420 final stack adjustment.
2421 We need a separate load if there are still registers to
2422 restore. We also want a separate load if the combined insn
2423 would need a limm, but a separate load doesn't. */
2424 if (ra_offs
2425 && !cfun->machine->frame_info.gmask
2426 && (SMALL_INT (ra_offs) || !SMALL_INT (ra_offs >> 2)))
2428 addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx, addr);
2429 first_offset = 0;
2430 size_to_deallocate -= cfun->machine->frame_info.reg_size;
2432 else if (!ra_offs && size_to_deallocate == UNITS_PER_WORD)
2434 addr = gen_rtx_POST_INC (Pmode, addr);
2435 size_to_deallocate = 0;
2437 frame_move_inc (ra, gen_frame_mem (Pmode, addr), stack_pointer_rtx, addr);
2440 if (!millicode_p)
2442 if (cfun->machine->frame_info.reg_size)
2443 arc_save_restore (stack_pointer_rtx,
2444 /* The zeroing of these two bits is unnecessary, but leave this in for clarity. */
2445 cfun->machine->frame_info.gmask
2446 & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK), 1, &first_offset);
2450 /* The rest of this function does the following:
2451 ARCompact : handle epilogue_delay, restore sp (phase-2), return
2454 /* Keep track of how much of the stack pointer we've restored.
2455 It makes the following a lot more readable. */
2456 size_to_deallocate += first_offset;
2457 restored = size - size_to_deallocate;
2459 if (size > restored)
2460 frame_stack_add (size - restored);
2461 /* Emit the return instruction. */
2462 if (sibcall_p == FALSE)
2463 emit_jump_insn (gen_simple_return ());
2464 epilogue_done:
2465 if (!TARGET_EPILOGUE_CFI)
2467 rtx insn;
2469 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2470 RTX_FRAME_RELATED_P (insn) = 0;
2474 /* Return the offset relative to the stack pointer where the return address
2475 is stored, or -1 if it is not stored. */
2478 arc_return_slot_offset ()
2480 struct arc_frame_info *afi = &cfun->machine->frame_info;
2482 return (afi->save_return_addr
2483 ? afi->total_size - afi->pretend_size - afi->extra_size : -1);
2486 /* PIC */
2488 /* Emit special PIC prologues and epilogues. */
2489 /* If the function has any GOTOFF relocations, then the GOTBASE
2490 register has to be setup in the prologue
2491 The instruction needed at the function start for setting up the
2492 GOTBASE register is
2493 add rdest, pc,
2494 ----------------------------------------------------------
2495 The rtl to be emitted for this should be:
2496 set (reg basereg)
2497 (plus (reg pc)
2498 (const (unspec (symref _DYNAMIC) 3)))
2499 ---------------------------------------------------------- */
2501 static void
2502 arc_finalize_pic (void)
2504 rtx pat;
2505 rtx baseptr_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
2507 if (crtl->uses_pic_offset_table == 0)
2508 return;
2510 gcc_assert (flag_pic != 0);
2512 pat = gen_rtx_SYMBOL_REF (Pmode, "_DYNAMIC");
2513 pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, pat), ARC_UNSPEC_GOT);
2514 pat = gen_rtx_CONST (Pmode, pat);
2516 pat = gen_rtx_SET (VOIDmode, baseptr_rtx, pat);
2518 emit_insn (pat);
2521 /* !TARGET_BARREL_SHIFTER support. */
2522 /* Emit a shift insn to set OP0 to OP1 shifted by OP2; CODE specifies what
2523 kind of shift. */
2525 void
2526 emit_shift (enum rtx_code code, rtx op0, rtx op1, rtx op2)
2528 rtx shift = gen_rtx_fmt_ee (code, SImode, op1, op2);
2529 rtx pat
2530 = ((shift4_operator (shift, SImode) ? gen_shift_si3 : gen_shift_si3_loop)
2531 (op0, op1, op2, shift));
2532 emit_insn (pat);
2535 /* Output the assembler code for doing a shift.
2536 We go to a bit of trouble to generate efficient code as the ARC601 only has
2537 single bit shifts. This is taken from the h8300 port. We only have one
2538 mode of shifting and can't access individual bytes like the h8300 can, so
2539 this is greatly simplified (at the expense of not generating hyper-
2540 efficient code).
2542 This function is not used if the variable shift insns are present. */
2544 /* FIXME: This probably can be done using a define_split in arc.md.
2545 Alternately, generate rtx rather than output instructions. */
2547 const char *
2548 output_shift (rtx *operands)
2550 /* static int loopend_lab;*/
2551 rtx shift = operands[3];
2552 enum machine_mode mode = GET_MODE (shift);
2553 enum rtx_code code = GET_CODE (shift);
2554 const char *shift_one;
2556 gcc_assert (mode == SImode);
2558 switch (code)
2560 case ASHIFT: shift_one = "add %0,%1,%1"; break;
2561 case ASHIFTRT: shift_one = "asr %0,%1"; break;
2562 case LSHIFTRT: shift_one = "lsr %0,%1"; break;
2563 default: gcc_unreachable ();
2566 if (GET_CODE (operands[2]) != CONST_INT)
2568 output_asm_insn ("and.f lp_count,%2, 0x1f", operands);
2569 goto shiftloop;
2571 else
2573 int n;
2575 n = INTVAL (operands[2]);
2577 /* Only consider the lower 5 bits of the shift count. */
2578 n = n & 0x1f;
2580 /* First see if we can do them inline. */
2581 /* ??? We could get better scheduling & shorter code (using short insns)
2582 by using splitters. Alas, that'd be even more verbose. */
2583 if (code == ASHIFT && n <= 9 && n > 2
2584 && dest_reg_operand (operands[4], SImode))
2586 output_asm_insn ("mov %4,0\n\tadd3 %0,%4,%1", operands);
2587 for (n -=3 ; n >= 3; n -= 3)
2588 output_asm_insn ("add3 %0,%4,%0", operands);
2589 if (n == 2)
2590 output_asm_insn ("add2 %0,%4,%0", operands);
2591 else if (n)
2592 output_asm_insn ("add %0,%0,%0", operands);
2594 else if (n <= 4)
2596 while (--n >= 0)
2598 output_asm_insn (shift_one, operands);
2599 operands[1] = operands[0];
2602 /* See if we can use a rotate/and. */
2603 else if (n == BITS_PER_WORD - 1)
2605 switch (code)
2607 case ASHIFT :
2608 output_asm_insn ("and %0,%1,1\n\tror %0,%0", operands);
2609 break;
2610 case ASHIFTRT :
2611 /* The ARC doesn't have a rol insn. Use something else. */
2612 output_asm_insn ("add.f 0,%1,%1\n\tsbc %0,%0,%0", operands);
2613 break;
2614 case LSHIFTRT :
2615 /* The ARC doesn't have a rol insn. Use something else. */
2616 output_asm_insn ("add.f 0,%1,%1\n\trlc %0,0", operands);
2617 break;
2618 default:
2619 break;
2622 else if (n == BITS_PER_WORD - 2 && dest_reg_operand (operands[4], SImode))
2624 switch (code)
2626 case ASHIFT :
2627 output_asm_insn ("and %0,%1,3\n\tror %0,%0\n\tror %0,%0", operands);
2628 break;
2629 case ASHIFTRT :
2630 #if 1 /* Need some scheduling comparisons. */
2631 output_asm_insn ("add.f %4,%1,%1\n\tsbc %0,%0,%0\n\t"
2632 "add.f 0,%4,%4\n\trlc %0,%0", operands);
2633 #else
2634 output_asm_insn ("add.f %4,%1,%1\n\tbxor %0,%4,31\n\t"
2635 "sbc.f %0,%0,%4\n\trlc %0,%0", operands);
2636 #endif
2637 break;
2638 case LSHIFTRT :
2639 #if 1
2640 output_asm_insn ("add.f %4,%1,%1\n\trlc %0,0\n\t"
2641 "add.f 0,%4,%4\n\trlc %0,%0", operands);
2642 #else
2643 output_asm_insn ("add.f %0,%1,%1\n\trlc.f %0,0\n\t"
2644 "and %0,%0,1\n\trlc %0,%0", operands);
2645 #endif
2646 break;
2647 default:
2648 break;
2651 else if (n == BITS_PER_WORD - 3 && code == ASHIFT)
2652 output_asm_insn ("and %0,%1,7\n\tror %0,%0\n\tror %0,%0\n\tror %0,%0",
2653 operands);
2654 /* Must loop. */
2655 else
2657 operands[2] = GEN_INT (n);
2658 output_asm_insn ("mov.f lp_count, %2", operands);
2660 shiftloop:
2662 output_asm_insn ("lpnz\t2f", operands);
2663 output_asm_insn (shift_one, operands);
2664 output_asm_insn ("nop", operands);
2665 fprintf (asm_out_file, "2:\t%s end single insn loop\n",
2666 ASM_COMMENT_START);
2671 return "";
2674 /* Nested function support. */
2676 /* Directly store VALUE into memory object BLOCK at OFFSET. */
2678 static void
2679 emit_store_direct (rtx block, int offset, int value)
2681 emit_insn (gen_store_direct (adjust_address (block, SImode, offset),
2682 force_reg (SImode,
2683 gen_int_mode (value, SImode))));
2686 /* Emit RTL insns to initialize the variable parts of a trampoline.
2687 FNADDR is an RTX for the address of the function's pure code.
2688 CXT is an RTX for the static chain value for the function. */
2689 /* With potentially multiple shared objects loaded, and multiple stacks
2690 present for multiple thereds where trampolines might reside, a simple
2691 range check will likely not suffice for the profiler to tell if a callee
2692 is a trampoline. We a speedier check by making the trampoline start at
2693 an address that is not 4-byte aligned.
2694 A trampoline looks like this:
2696 nop_s 0x78e0
2697 entry:
2698 ld_s r12,[pcl,12] 0xd403
2699 ld r11,[pcl,12] 0x170c 700b
2700 j_s [r12] 0x7c00
2701 nop_s 0x78e0
2703 The fastest trampoline to execute for trampolines within +-8KB of CTX
2704 would be:
2705 add2 r11,pcl,s12
2706 j [limm] 0x20200f80 limm
2707 and that would also be faster to write to the stack by computing the offset
2708 from CTX to TRAMP at compile time. However, it would really be better to
2709 get rid of the high cost of cache invalidation when generating trampolines,
2710 which requires that the code part of trampolines stays constant, and
2711 additionally either
2712 - making sure that no executable code but trampolines is on the stack,
2713 no icache entries linger for the area of the stack from when before the
2714 stack was allocated, and allocating trampolines in trampoline-only
2715 cache lines
2717 - allocate trampolines fram a special pool of pre-allocated trampolines. */
2719 static void
2720 arc_initialize_trampoline (rtx tramp, tree fndecl, rtx cxt)
2722 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
2724 emit_store_direct (tramp, 0, TARGET_BIG_ENDIAN ? 0x78e0d403 : 0xd40378e0);
2725 emit_store_direct (tramp, 4, TARGET_BIG_ENDIAN ? 0x170c700b : 0x700b170c);
2726 emit_store_direct (tramp, 8, TARGET_BIG_ENDIAN ? 0x7c0078e0 : 0x78e07c00);
2727 emit_move_insn (adjust_address (tramp, SImode, 12), fnaddr);
2728 emit_move_insn (adjust_address (tramp, SImode, 16), cxt);
2729 emit_insn (gen_flush_icache (adjust_address (tramp, SImode, 0)));
2732 /* Allow the profiler to easily distinguish trampolines from normal
2733 functions. */
2735 static rtx
2736 arc_trampoline_adjust_address (rtx addr)
2738 return plus_constant (Pmode, addr, 2);
2741 /* This is set briefly to 1 when we output a ".as" address modifer, and then
2742 reset when we output the scaled address. */
2743 static int output_scaled = 0;
2745 /* Print operand X (an rtx) in assembler syntax to file FILE.
2746 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2747 For `%' followed by punctuation, CODE is the punctuation and X is null. */
2748 /* In final.c:output_asm_insn:
2749 'l' : label
2750 'a' : address
2751 'c' : constant address if CONSTANT_ADDRESS_P
2752 'n' : negative
2753 Here:
2754 'Z': log2(x+1)-1
2755 'z': log2
2756 'M': log2(~x)
2757 '#': condbranch delay slot suffix
2758 '*': jump delay slot suffix
2759 '?' : nonjump-insn suffix for conditional execution or short instruction
2760 '!' : jump / call suffix for conditional execution or short instruction
2761 '`': fold constant inside unary o-perator, re-recognize, and emit.
2764 'R': Second word
2766 'B': Branch comparison operand - suppress sda reference
2767 'H': Most significant word
2768 'L': Least significant word
2769 'A': ASCII decimal representation of floating point value
2770 'U': Load/store update or scaling indicator
2771 'V': cache bypass indicator for volatile
2775 'O': Operator
2776 'o': original symbol - no @ prepending. */
2778 void
2779 arc_print_operand (FILE *file, rtx x, int code)
2781 switch (code)
2783 case 'Z':
2784 if (GET_CODE (x) == CONST_INT)
2785 fprintf (file, "%d",exact_log2(INTVAL (x) + 1) - 1 );
2786 else
2787 output_operand_lossage ("invalid operand to %%Z code");
2789 return;
2791 case 'z':
2792 if (GET_CODE (x) == CONST_INT)
2793 fprintf (file, "%d",exact_log2(INTVAL (x)) );
2794 else
2795 output_operand_lossage ("invalid operand to %%z code");
2797 return;
2799 case 'M':
2800 if (GET_CODE (x) == CONST_INT)
2801 fprintf (file, "%d",exact_log2(~INTVAL (x)) );
2802 else
2803 output_operand_lossage ("invalid operand to %%M code");
2805 return;
2807 case '#' :
2808 /* Conditional branches depending on condition codes.
2809 Note that this is only for branches that were known to depend on
2810 condition codes before delay slot scheduling;
2811 out-of-range brcc / bbit expansions should use '*'.
2812 This distinction is important because of the different
2813 allowable delay slot insns and the output of the delay suffix
2814 for TARGET_AT_DBR_COND_EXEC. */
2815 case '*' :
2816 /* Unconditional branches / branches not depending on condition codes.
2817 This could also be a CALL_INSN.
2818 Output the appropriate delay slot suffix. */
2819 if (final_sequence && XVECLEN (final_sequence, 0) != 1)
2821 rtx jump = XVECEXP (final_sequence, 0, 0);
2822 rtx delay = XVECEXP (final_sequence, 0, 1);
2824 /* For TARGET_PAD_RETURN we might have grabbed the delay insn. */
2825 if (INSN_DELETED_P (delay))
2826 return;
2827 if (JUMP_P (jump) && INSN_ANNULLED_BRANCH_P (jump))
2828 fputs (INSN_FROM_TARGET_P (delay) ? ".d"
2829 : TARGET_AT_DBR_CONDEXEC && code == '#' ? ".d"
2830 : get_attr_type (jump) == TYPE_RETURN && code == '#' ? ""
2831 : ".nd",
2832 file);
2833 else
2834 fputs (".d", file);
2836 return;
2837 case '?' : /* with leading "." */
2838 case '!' : /* without leading "." */
2839 /* This insn can be conditionally executed. See if the ccfsm machinery
2840 says it should be conditionalized.
2841 If it shouldn't, we'll check the compact attribute if this insn
2842 has a short variant, which may be used depending on code size and
2843 alignment considerations. */
2844 if (current_insn_predicate)
2845 arc_ccfsm_current.cc
2846 = get_arc_condition_code (current_insn_predicate);
2847 if (ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current))
2849 /* Is this insn in a delay slot sequence? */
2850 if (!final_sequence || XVECLEN (final_sequence, 0) < 2
2851 || current_insn_predicate
2852 || CALL_P (XVECEXP (final_sequence, 0, 0))
2853 || simplejump_p (XVECEXP (final_sequence, 0, 0)))
2855 /* This insn isn't in a delay slot sequence, or conditionalized
2856 independently of its position in a delay slot. */
2857 fprintf (file, "%s%s",
2858 code == '?' ? "." : "",
2859 arc_condition_codes[arc_ccfsm_current.cc]);
2860 /* If this is a jump, there are still short variants. However,
2861 only beq_s / bne_s have the same offset range as b_s,
2862 and the only short conditional returns are jeq_s and jne_s. */
2863 if (code == '!'
2864 && (arc_ccfsm_current.cc == ARC_CC_EQ
2865 || arc_ccfsm_current.cc == ARC_CC_NE
2866 || 0 /* FIXME: check if branch in 7 bit range. */))
2867 output_short_suffix (file);
2869 else if (code == '!') /* Jump with delay slot. */
2870 fputs (arc_condition_codes[arc_ccfsm_current.cc], file);
2871 else /* An Instruction in a delay slot of a jump or call. */
2873 rtx jump = XVECEXP (final_sequence, 0, 0);
2874 rtx insn = XVECEXP (final_sequence, 0, 1);
2876 /* If the insn is annulled and is from the target path, we need
2877 to inverse the condition test. */
2878 if (JUMP_P (jump) && INSN_ANNULLED_BRANCH_P (jump))
2880 if (INSN_FROM_TARGET_P (insn))
2881 fprintf (file, "%s%s",
2882 code == '?' ? "." : "",
2883 arc_condition_codes[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current.cc)]);
2884 else
2885 fprintf (file, "%s%s",
2886 code == '?' ? "." : "",
2887 arc_condition_codes[arc_ccfsm_current.cc]);
2888 if (arc_ccfsm_current.state == 5)
2889 arc_ccfsm_current.state = 0;
2891 else
2892 /* This insn is executed for either path, so don't
2893 conditionalize it at all. */
2894 output_short_suffix (file);
2898 else
2899 output_short_suffix (file);
2900 return;
2901 case'`':
2902 /* FIXME: fold constant inside unary operator, re-recognize, and emit. */
2903 gcc_unreachable ();
2904 case 'd' :
2905 fputs (arc_condition_codes[get_arc_condition_code (x)], file);
2906 return;
2907 case 'D' :
2908 fputs (arc_condition_codes[ARC_INVERSE_CONDITION_CODE
2909 (get_arc_condition_code (x))],
2910 file);
2911 return;
2912 case 'R' :
2913 /* Write second word of DImode or DFmode reference,
2914 register or memory. */
2915 if (GET_CODE (x) == REG)
2916 fputs (reg_names[REGNO (x)+1], file);
2917 else if (GET_CODE (x) == MEM)
2919 fputc ('[', file);
2921 /* Handle possible auto-increment. For PRE_INC / PRE_DEC /
2922 PRE_MODIFY, we will have handled the first word already;
2923 For POST_INC / POST_DEC / POST_MODIFY, the access to the
2924 first word will be done later. In either case, the access
2925 to the first word will do the modify, and we only have
2926 to add an offset of four here. */
2927 if (GET_CODE (XEXP (x, 0)) == PRE_INC
2928 || GET_CODE (XEXP (x, 0)) == PRE_DEC
2929 || GET_CODE (XEXP (x, 0)) == PRE_MODIFY
2930 || GET_CODE (XEXP (x, 0)) == POST_INC
2931 || GET_CODE (XEXP (x, 0)) == POST_DEC
2932 || GET_CODE (XEXP (x, 0)) == POST_MODIFY)
2933 output_address (plus_constant (Pmode, XEXP (XEXP (x, 0), 0), 4));
2934 else if (output_scaled)
2936 rtx addr = XEXP (x, 0);
2937 int size = GET_MODE_SIZE (GET_MODE (x));
2939 output_address (plus_constant (Pmode, XEXP (addr, 0),
2940 ((INTVAL (XEXP (addr, 1)) + 4)
2941 >> (size == 2 ? 1 : 2))));
2942 output_scaled = 0;
2944 else
2945 output_address (plus_constant (Pmode, XEXP (x, 0), 4));
2946 fputc (']', file);
2948 else
2949 output_operand_lossage ("invalid operand to %%R code");
2950 return;
2951 case 'S' :
2952 /* FIXME: remove %S option. */
2953 break;
2954 case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
2955 if (CONSTANT_P (x))
2957 output_addr_const (file, x);
2958 return;
2960 break;
2961 case 'H' :
2962 case 'L' :
2963 if (GET_CODE (x) == REG)
2965 /* L = least significant word, H = most significant word. */
2966 if ((WORDS_BIG_ENDIAN != 0) ^ (code == 'L'))
2967 fputs (reg_names[REGNO (x)], file);
2968 else
2969 fputs (reg_names[REGNO (x)+1], file);
2971 else if (GET_CODE (x) == CONST_INT
2972 || GET_CODE (x) == CONST_DOUBLE)
2974 rtx first, second;
2976 split_double (x, &first, &second);
2978 if((WORDS_BIG_ENDIAN) == 0)
2979 fprintf (file, "0x%08lx",
2980 code == 'L' ? INTVAL (first) : INTVAL (second));
2981 else
2982 fprintf (file, "0x%08lx",
2983 code == 'L' ? INTVAL (second) : INTVAL (first));
2987 else
2988 output_operand_lossage ("invalid operand to %%H/%%L code");
2989 return;
2990 case 'A' :
2992 char str[30];
2994 gcc_assert (GET_CODE (x) == CONST_DOUBLE
2995 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT);
2997 real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x), sizeof (str), 0, 1);
2998 fprintf (file, "%s", str);
2999 return;
3001 case 'U' :
3002 /* Output a load/store with update indicator if appropriate. */
3003 if (GET_CODE (x) == MEM)
3005 rtx addr = XEXP (x, 0);
3006 switch (GET_CODE (addr))
3008 case PRE_INC: case PRE_DEC: case PRE_MODIFY:
3009 fputs (".a", file); break;
3010 case POST_INC: case POST_DEC: case POST_MODIFY:
3011 fputs (".ab", file); break;
3012 case PLUS:
3013 /* Are we using a scaled index? */
3014 if (GET_CODE (XEXP (addr, 0)) == MULT)
3015 fputs (".as", file);
3016 /* Can we use a scaled offset? */
3017 else if (CONST_INT_P (XEXP (addr, 1))
3018 && GET_MODE_SIZE (GET_MODE (x)) > 1
3019 && (!(INTVAL (XEXP (addr, 1))
3020 & (GET_MODE_SIZE (GET_MODE (x)) - 1) & 3))
3021 /* Does it make a difference? */
3022 && !SMALL_INT_RANGE(INTVAL (XEXP (addr, 1)),
3023 GET_MODE_SIZE (GET_MODE (x)) - 2, 0))
3025 fputs (".as", file);
3026 output_scaled = 1;
3028 break;
3029 case REG:
3030 break;
3031 default:
3032 gcc_assert (CONSTANT_P (addr)); break;
3035 else
3036 output_operand_lossage ("invalid operand to %%U code");
3037 return;
3038 case 'V' :
3039 /* Output cache bypass indicator for a load/store insn. Volatile memory
3040 refs are defined to use the cache bypass mechanism. */
3041 if (GET_CODE (x) == MEM)
3043 if (MEM_VOLATILE_P (x) && !TARGET_VOLATILE_CACHE_SET )
3044 fputs (".di", file);
3046 else
3047 output_operand_lossage ("invalid operand to %%V code");
3048 return;
3049 /* plt code. */
3050 case 'P':
3051 case 0 :
3052 /* Do nothing special. */
3053 break;
3054 case 'F':
3055 fputs (reg_names[REGNO (x)]+1, file);
3056 return;
3057 case '^':
3058 /* This punctuation character is needed because label references are
3059 printed in the output template using %l. This is a front end
3060 character, and when we want to emit a '@' before it, we have to use
3061 this '^'. */
3063 fputc('@',file);
3064 return;
3065 case 'O':
3066 /* Output an operator. */
3067 switch (GET_CODE (x))
3069 case PLUS: fputs ("add", file); return;
3070 case SS_PLUS: fputs ("adds", file); return;
3071 case AND: fputs ("and", file); return;
3072 case IOR: fputs ("or", file); return;
3073 case XOR: fputs ("xor", file); return;
3074 case MINUS: fputs ("sub", file); return;
3075 case SS_MINUS: fputs ("subs", file); return;
3076 case ASHIFT: fputs ("asl", file); return;
3077 case ASHIFTRT: fputs ("asr", file); return;
3078 case LSHIFTRT: fputs ("lsr", file); return;
3079 case ROTATERT: fputs ("ror", file); return;
3080 case MULT: fputs ("mpy", file); return;
3081 case ABS: fputs ("abs", file); return; /* Unconditional. */
3082 case NEG: fputs ("neg", file); return;
3083 case SS_NEG: fputs ("negs", file); return;
3084 case NOT: fputs ("not", file); return; /* Unconditional. */
3085 case ZERO_EXTEND:
3086 fputs ("ext", file); /* bmsk allows predication. */
3087 goto size_suffix;
3088 case SIGN_EXTEND: /* Unconditional. */
3089 fputs ("sex", file);
3090 size_suffix:
3091 switch (GET_MODE (XEXP (x, 0)))
3093 case QImode: fputs ("b", file); return;
3094 case HImode: fputs ("w", file); return;
3095 default: break;
3097 break;
3098 case SS_TRUNCATE:
3099 if (GET_MODE (x) != HImode)
3100 break;
3101 fputs ("sat16", file);
3102 default: break;
3104 output_operand_lossage ("invalid operand to %%O code"); return;
3105 case 'o':
3106 if (GET_CODE (x) == SYMBOL_REF)
3108 assemble_name (file, XSTR (x, 0));
3109 return;
3111 break;
3112 case '&':
3113 if (TARGET_ANNOTATE_ALIGN && cfun->machine->size_reason)
3114 fprintf (file, "; unalign: %d", cfun->machine->unalign);
3115 return;
3116 default :
3117 /* Unknown flag. */
3118 output_operand_lossage ("invalid operand output code");
3121 switch (GET_CODE (x))
3123 case REG :
3124 fputs (reg_names[REGNO (x)], file);
3125 break;
3126 case MEM :
3128 rtx addr = XEXP (x, 0);
3129 int size = GET_MODE_SIZE (GET_MODE (x));
3131 fputc ('[', file);
3133 switch (GET_CODE (addr))
3135 case PRE_INC: case POST_INC:
3136 output_address (plus_constant (Pmode, XEXP (addr, 0), size)); break;
3137 case PRE_DEC: case POST_DEC:
3138 output_address (plus_constant (Pmode, XEXP (addr, 0), -size));
3139 break;
3140 case PRE_MODIFY: case POST_MODIFY:
3141 output_address (XEXP (addr, 1)); break;
3142 case PLUS:
3143 if (output_scaled)
3145 output_address (plus_constant (Pmode, XEXP (addr, 0),
3146 (INTVAL (XEXP (addr, 1))
3147 >> (size == 2 ? 1 : 2))));
3148 output_scaled = 0;
3150 else
3151 output_address (addr);
3152 break;
3153 default:
3154 if (flag_pic && CONSTANT_ADDRESS_P (addr))
3155 arc_output_pic_addr_const (file, addr, code);
3156 else
3157 output_address (addr);
3158 break;
3160 fputc (']', file);
3161 break;
3163 case CONST_DOUBLE :
3164 /* We handle SFmode constants here as output_addr_const doesn't. */
3165 if (GET_MODE (x) == SFmode)
3167 REAL_VALUE_TYPE d;
3168 long l;
3170 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
3171 REAL_VALUE_TO_TARGET_SINGLE (d, l);
3172 fprintf (file, "0x%08lx", l);
3173 break;
3175 /* Fall through. Let output_addr_const deal with it. */
3176 default :
3177 if (flag_pic)
3178 arc_output_pic_addr_const (file, x, code);
3179 else
3181 /* FIXME: Dirty way to handle @var@sda+const. Shd be handled
3182 with asm_output_symbol_ref */
3183 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
3185 x = XEXP (x, 0);
3186 output_addr_const (file, XEXP (x, 0));
3187 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF && SYMBOL_REF_SMALL_P (XEXP (x, 0)))
3188 fprintf (file, "@sda");
3190 if (GET_CODE (XEXP (x, 1)) != CONST_INT
3191 || INTVAL (XEXP (x, 1)) >= 0)
3192 fprintf (file, "+");
3193 output_addr_const (file, XEXP (x, 1));
3195 else
3196 output_addr_const (file, x);
3198 if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_SMALL_P (x))
3199 fprintf (file, "@sda");
3200 break;
3204 /* Print a memory address as an operand to reference that memory location. */
3206 void
3207 arc_print_operand_address (FILE *file , rtx addr)
3209 register rtx base, index = 0;
3211 switch (GET_CODE (addr))
3213 case REG :
3214 fputs (reg_names[REGNO (addr)], file);
3215 break;
3216 case SYMBOL_REF :
3217 output_addr_const (file, addr);
3218 if (SYMBOL_REF_SMALL_P (addr))
3219 fprintf (file, "@sda");
3220 break;
3221 case PLUS :
3222 if (GET_CODE (XEXP (addr, 0)) == MULT)
3223 index = XEXP (XEXP (addr, 0), 0), base = XEXP (addr, 1);
3224 else if (CONST_INT_P (XEXP (addr, 0)))
3225 index = XEXP (addr, 0), base = XEXP (addr, 1);
3226 else
3227 base = XEXP (addr, 0), index = XEXP (addr, 1);
3229 gcc_assert (OBJECT_P (base));
3230 arc_print_operand_address (file, base);
3231 if (CONSTANT_P (base) && CONST_INT_P (index))
3232 fputc ('+', file);
3233 else
3234 fputc (',', file);
3235 gcc_assert (OBJECT_P (index));
3236 arc_print_operand_address (file, index);
3237 break;
3238 case CONST:
3240 rtx c = XEXP (addr, 0);
3242 gcc_assert (GET_CODE (XEXP (c, 0)) == SYMBOL_REF);
3243 gcc_assert (GET_CODE (XEXP (c, 1)) == CONST_INT);
3245 output_address(XEXP(addr,0));
3247 break;
3249 case PRE_INC :
3250 case PRE_DEC :
3251 /* We shouldn't get here as we've lost the mode of the memory object
3252 (which says how much to inc/dec by. */
3253 gcc_unreachable ();
3254 break;
3255 default :
3256 if (flag_pic)
3257 arc_output_pic_addr_const (file, addr, 0);
3258 else
3259 output_addr_const (file, addr);
3260 break;
3264 /* Called via walk_stores. DATA points to a hash table we can use to
3265 establish a unique SYMBOL_REF for each counter, which corresponds to
3266 a caller-callee pair.
3267 X is a store which we want to examine for an UNSPEC_PROF, which
3268 would be an address loaded into a register, or directly used in a MEM.
3269 If we found an UNSPEC_PROF, if we encounter a new counter the first time,
3270 write out a description and a data allocation for a 32 bit counter.
3271 Also, fill in the appropriate symbol_ref into each UNSPEC_PROF instance. */
3273 static void
3274 write_profile_sections (rtx dest ATTRIBUTE_UNUSED, rtx x, void *data)
3276 rtx *srcp, src;
3277 htab_t htab = (htab_t) data;
3278 rtx *slot;
3280 if (GET_CODE (x) != SET)
3281 return;
3282 srcp = &SET_SRC (x);
3283 if (MEM_P (*srcp))
3284 srcp = &XEXP (*srcp, 0);
3285 else if (MEM_P (SET_DEST (x)))
3286 srcp = &XEXP (SET_DEST (x), 0);
3287 src = *srcp;
3288 if (GET_CODE (src) != CONST)
3289 return;
3290 src = XEXP (src, 0);
3291 if (GET_CODE (src) != UNSPEC || XINT (src, 1) != UNSPEC_PROF)
3292 return;
3294 gcc_assert (XVECLEN (src, 0) == 3);
3295 if (!htab_elements (htab))
3297 output_asm_insn (".section .__arc_profile_desc, \"a\"\n"
3298 "\t.long %0 + 1\n",
3299 &XVECEXP (src, 0, 0));
3301 slot = (rtx *) htab_find_slot (htab, src, INSERT);
3302 if (*slot == HTAB_EMPTY_ENTRY)
3304 static int count_nr;
3305 char buf[24];
3306 rtx count;
3308 *slot = src;
3309 sprintf (buf, "__prof_count%d", count_nr++);
3310 count = gen_rtx_SYMBOL_REF (Pmode, xstrdup (buf));
3311 XVECEXP (src, 0, 2) = count;
3312 output_asm_insn (".section\t.__arc_profile_desc, \"a\"\n"
3313 "\t.long\t%1\n"
3314 "\t.section\t.__arc_profile_counters, \"aw\"\n"
3315 "\t.type\t%o2, @object\n"
3316 "\t.size\t%o2, 4\n"
3317 "%o2:\t.zero 4",
3318 &XVECEXP (src, 0, 0));
3319 *srcp = count;
3321 else
3322 *srcp = XVECEXP (*slot, 0, 2);
3325 /* Hash function for UNSPEC_PROF htab. Use both the caller's name and
3326 the callee's name (if known). */
3328 static hashval_t
3329 unspec_prof_hash (const void *x)
3331 const_rtx u = (const_rtx) x;
3332 const_rtx s1 = XVECEXP (u, 0, 1);
3334 return (htab_hash_string (XSTR (XVECEXP (u, 0, 0), 0))
3335 ^ (s1->code == SYMBOL_REF ? htab_hash_string (XSTR (s1, 0)) : 0));
3338 /* Equality function for UNSPEC_PROF htab. Two pieces of UNSPEC_PROF rtl
3339 shall refer to the same counter if both caller name and callee rtl
3340 are identical. */
3342 static int
3343 unspec_prof_htab_eq (const void *x, const void *y)
3345 const_rtx u0 = (const_rtx) x;
3346 const_rtx u1 = (const_rtx) y;
3347 const_rtx s01 = XVECEXP (u0, 0, 1);
3348 const_rtx s11 = XVECEXP (u1, 0, 1);
3350 return (!strcmp (XSTR (XVECEXP (u0, 0, 0), 0),
3351 XSTR (XVECEXP (u1, 0, 0), 0))
3352 && rtx_equal_p (s01, s11));
3355 /* Conditional execution support.
3357 This is based on the ARM port but for now is much simpler.
3359 A finite state machine takes care of noticing whether or not instructions
3360 can be conditionally executed, and thus decrease execution time and code
3361 size by deleting branch instructions. The fsm is controlled by
3362 arc_ccfsm_advance (called by arc_final_prescan_insn), and controls the
3363 actions of PRINT_OPERAND. The patterns in the .md file for the branch
3364 insns also have a hand in this. */
3365 /* The way we leave dealing with non-anulled or annull-false delay slot
3366 insns to the consumer is awkward. */
3368 /* The state of the fsm controlling condition codes are:
3369 0: normal, do nothing special
3370 1: don't output this insn
3371 2: don't output this insn
3372 3: make insns conditional
3373 4: make insns conditional
3374 5: make insn conditional (only for outputting anulled delay slot insns)
3376 special value for cfun->machine->uid_ccfsm_state:
3377 6: return with but one insn before it since function start / call
3379 State transitions (state->state by whom, under what condition):
3380 0 -> 1 arc_ccfsm_advance, if insn is a conditional branch skipping over
3381 some instructions.
3382 0 -> 2 arc_ccfsm_advance, if insn is a conditional branch followed
3383 by zero or more non-jump insns and an unconditional branch with
3384 the same target label as the condbranch.
3385 1 -> 3 branch patterns, after having not output the conditional branch
3386 2 -> 4 branch patterns, after having not output the conditional branch
3387 0 -> 5 branch patterns, for anulled delay slot insn.
3388 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL, if the `target' label is reached
3389 (the target label has CODE_LABEL_NUMBER equal to
3390 arc_ccfsm_target_label).
3391 4 -> 0 arc_ccfsm_advance, if `target' unconditional branch is reached
3392 3 -> 1 arc_ccfsm_advance, finding an 'else' jump skipping over some insns.
3393 5 -> 0 when outputting the delay slot insn
3395 If the jump clobbers the conditions then we use states 2 and 4.
3397 A similar thing can be done with conditional return insns.
3399 We also handle separating branches from sets of the condition code.
3400 This is done here because knowledge of the ccfsm state is required,
3401 we may not be outputting the branch. */
3403 /* arc_final_prescan_insn calls arc_ccfsm_advance to adjust arc_ccfsm_current,
3404 before letting final output INSN. */
3406 static void
3407 arc_ccfsm_advance (rtx insn, struct arc_ccfsm *state)
3409 /* BODY will hold the body of INSN. */
3410 register rtx body;
3412 /* This will be 1 if trying to repeat the trick (ie: do the `else' part of
3413 an if/then/else), and things need to be reversed. */
3414 int reverse = 0;
3416 /* If we start with a return insn, we only succeed if we find another one. */
3417 int seeking_return = 0;
3419 /* START_INSN will hold the insn from where we start looking. This is the
3420 first insn after the following code_label if REVERSE is true. */
3421 rtx start_insn = insn;
3423 /* Type of the jump_insn. Brcc insns don't affect ccfsm changes,
3424 since they don't rely on a cmp preceding the. */
3425 enum attr_type jump_insn_type;
3427 /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
3428 We can't do this in macro FINAL_PRESCAN_INSN because its called from
3429 final_scan_insn which has `optimize' as a local. */
3430 if (optimize < 2 || TARGET_NO_COND_EXEC)
3431 return;
3433 /* Ignore notes and labels. */
3434 if (!INSN_P (insn))
3435 return;
3436 body = PATTERN (insn);
3437 /* If in state 4, check if the target branch is reached, in order to
3438 change back to state 0. */
3439 if (state->state == 4)
3441 if (insn == state->target_insn)
3443 state->target_insn = NULL;
3444 state->state = 0;
3446 return;
3449 /* If in state 3, it is possible to repeat the trick, if this insn is an
3450 unconditional branch to a label, and immediately following this branch
3451 is the previous target label which is only used once, and the label this
3452 branch jumps to is not too far off. Or in other words "we've done the
3453 `then' part, see if we can do the `else' part." */
3454 if (state->state == 3)
3456 if (simplejump_p (insn))
3458 start_insn = next_nonnote_insn (start_insn);
3459 if (GET_CODE (start_insn) == BARRIER)
3461 /* ??? Isn't this always a barrier? */
3462 start_insn = next_nonnote_insn (start_insn);
3464 if (GET_CODE (start_insn) == CODE_LABEL
3465 && CODE_LABEL_NUMBER (start_insn) == state->target_label
3466 && LABEL_NUSES (start_insn) == 1)
3467 reverse = TRUE;
3468 else
3469 return;
3471 else if (GET_CODE (body) == SIMPLE_RETURN)
3473 start_insn = next_nonnote_insn (start_insn);
3474 if (GET_CODE (start_insn) == BARRIER)
3475 start_insn = next_nonnote_insn (start_insn);
3476 if (GET_CODE (start_insn) == CODE_LABEL
3477 && CODE_LABEL_NUMBER (start_insn) == state->target_label
3478 && LABEL_NUSES (start_insn) == 1)
3480 reverse = TRUE;
3481 seeking_return = 1;
3483 else
3484 return;
3486 else
3487 return;
3490 if (GET_CODE (insn) != JUMP_INSN
3491 || GET_CODE (PATTERN (insn)) == ADDR_VEC
3492 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
3493 return;
3495 /* We can't predicate BRCC or loop ends.
3496 Also, when generating PIC code, and considering a medium range call,
3497 we can't predicate the call. */
3498 jump_insn_type = get_attr_type (insn);
3499 if (jump_insn_type == TYPE_BRCC
3500 || jump_insn_type == TYPE_BRCC_NO_DELAY_SLOT
3501 || jump_insn_type == TYPE_LOOP_END
3502 || (jump_insn_type == TYPE_CALL && !get_attr_predicable (insn)))
3503 return;
3505 /* This jump might be paralleled with a clobber of the condition codes,
3506 the jump should always come first. */
3507 if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0)
3508 body = XVECEXP (body, 0, 0);
3510 if (reverse
3511 || (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == PC
3512 && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE))
3514 int insns_skipped = 0, fail = FALSE, succeed = FALSE;
3515 /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
3516 int then_not_else = TRUE;
3517 /* Nonzero if next insn must be the target label. */
3518 int next_must_be_target_label_p;
3519 rtx this_insn = start_insn, label = 0;
3521 /* Register the insn jumped to. */
3522 if (reverse)
3524 if (!seeking_return)
3525 label = XEXP (SET_SRC (body), 0);
3527 else if (GET_CODE (XEXP (SET_SRC (body), 1)) == LABEL_REF)
3528 label = XEXP (XEXP (SET_SRC (body), 1), 0);
3529 else if (GET_CODE (XEXP (SET_SRC (body), 2)) == LABEL_REF)
3531 label = XEXP (XEXP (SET_SRC (body), 2), 0);
3532 then_not_else = FALSE;
3534 else if (GET_CODE (XEXP (SET_SRC (body), 1)) == SIMPLE_RETURN)
3535 seeking_return = 1;
3536 else if (GET_CODE (XEXP (SET_SRC (body), 2)) == SIMPLE_RETURN)
3538 seeking_return = 1;
3539 then_not_else = FALSE;
3541 else
3542 gcc_unreachable ();
3544 /* If this is a non-annulled branch with a delay slot, there is
3545 no need to conditionalize the delay slot. */
3546 if (NEXT_INSN (PREV_INSN (insn)) != insn
3547 && state->state == 0 && !INSN_ANNULLED_BRANCH_P (insn))
3549 this_insn = NEXT_INSN (this_insn);
3550 gcc_assert (NEXT_INSN (NEXT_INSN (PREV_INSN (start_insn)))
3551 == NEXT_INSN (this_insn));
3553 /* See how many insns this branch skips, and what kind of insns. If all
3554 insns are okay, and the label or unconditional branch to the same
3555 label is not too far away, succeed. */
3556 for (insns_skipped = 0, next_must_be_target_label_p = FALSE;
3557 !fail && !succeed && insns_skipped < MAX_INSNS_SKIPPED;
3558 insns_skipped++)
3560 rtx scanbody;
3562 this_insn = next_nonnote_insn (this_insn);
3563 if (!this_insn)
3564 break;
3566 if (next_must_be_target_label_p)
3568 if (GET_CODE (this_insn) == BARRIER)
3569 continue;
3570 if (GET_CODE (this_insn) == CODE_LABEL
3571 && this_insn == label)
3573 state->state = 1;
3574 succeed = TRUE;
3576 else
3577 fail = TRUE;
3578 break;
3581 scanbody = PATTERN (this_insn);
3583 switch (GET_CODE (this_insn))
3585 case CODE_LABEL:
3586 /* Succeed if it is the target label, otherwise fail since
3587 control falls in from somewhere else. */
3588 if (this_insn == label)
3590 state->state = 1;
3591 succeed = TRUE;
3593 else
3594 fail = TRUE;
3595 break;
3597 case BARRIER:
3598 /* Succeed if the following insn is the target label.
3599 Otherwise fail.
3600 If return insns are used then the last insn in a function
3601 will be a barrier. */
3602 next_must_be_target_label_p = TRUE;
3603 break;
3605 case CALL_INSN:
3606 /* Can handle a call insn if there are no insns after it.
3607 IE: The next "insn" is the target label. We don't have to
3608 worry about delay slots as such insns are SEQUENCE's inside
3609 INSN's. ??? It is possible to handle such insns though. */
3610 if (get_attr_cond (this_insn) == COND_CANUSE)
3611 next_must_be_target_label_p = TRUE;
3612 else
3613 fail = TRUE;
3614 break;
3616 case JUMP_INSN:
3617 /* If this is an unconditional branch to the same label, succeed.
3618 If it is to another label, do nothing. If it is conditional,
3619 fail. */
3620 /* ??? Probably, the test for the SET and the PC are
3621 unnecessary. */
3623 if (GET_CODE (scanbody) == SET
3624 && GET_CODE (SET_DEST (scanbody)) == PC)
3626 if (GET_CODE (SET_SRC (scanbody)) == LABEL_REF
3627 && XEXP (SET_SRC (scanbody), 0) == label && !reverse)
3629 state->state = 2;
3630 succeed = TRUE;
3632 else if (GET_CODE (SET_SRC (scanbody)) == IF_THEN_ELSE)
3633 fail = TRUE;
3634 else if (get_attr_cond (this_insn) != COND_CANUSE)
3635 fail = TRUE;
3637 else if (GET_CODE (scanbody) == SIMPLE_RETURN
3638 && seeking_return)
3640 state->state = 2;
3641 succeed = TRUE;
3643 else if (GET_CODE (scanbody) == PARALLEL)
3645 if (get_attr_cond (this_insn) != COND_CANUSE)
3646 fail = TRUE;
3648 break;
3650 case INSN:
3651 /* We can only do this with insns that can use the condition
3652 codes (and don't set them). */
3653 if (GET_CODE (scanbody) == SET
3654 || GET_CODE (scanbody) == PARALLEL)
3656 if (get_attr_cond (this_insn) != COND_CANUSE)
3657 fail = TRUE;
3659 /* We can't handle other insns like sequences. */
3660 else
3661 fail = TRUE;
3662 break;
3664 default:
3665 break;
3669 if (succeed)
3671 if ((!seeking_return) && (state->state == 1 || reverse))
3672 state->target_label = CODE_LABEL_NUMBER (label);
3673 else if (seeking_return || state->state == 2)
3675 while (this_insn && GET_CODE (PATTERN (this_insn)) == USE)
3677 this_insn = next_nonnote_insn (this_insn);
3679 gcc_assert (!this_insn ||
3680 (GET_CODE (this_insn) != BARRIER
3681 && GET_CODE (this_insn) != CODE_LABEL));
3683 if (!this_insn)
3685 /* Oh dear! we ran off the end, give up. */
3686 extract_insn_cached (insn);
3687 state->state = 0;
3688 state->target_insn = NULL;
3689 return;
3691 state->target_insn = this_insn;
3693 else
3694 gcc_unreachable ();
3696 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
3697 what it was. */
3698 if (!reverse)
3700 state->cond = XEXP (SET_SRC (body), 0);
3701 state->cc = get_arc_condition_code (XEXP (SET_SRC (body), 0));
3704 if (reverse || then_not_else)
3705 state->cc = ARC_INVERSE_CONDITION_CODE (state->cc);
3708 /* Restore recog_operand. Getting the attributes of other insns can
3709 destroy this array, but final.c assumes that it remains intact
3710 across this call; since the insn has been recognized already we
3711 call insn_extract direct. */
3712 extract_insn_cached (insn);
3716 /* Record that we are currently outputting label NUM with prefix PREFIX.
3717 It it's the label we're looking for, reset the ccfsm machinery.
3719 Called from ASM_OUTPUT_INTERNAL_LABEL. */
3721 static void
3722 arc_ccfsm_at_label (const char *prefix, int num, struct arc_ccfsm *state)
3724 if (state->state == 3 && state->target_label == num
3725 && !strcmp (prefix, "L"))
3727 state->state = 0;
3728 state->target_insn = NULL_RTX;
3732 /* We are considering a conditional branch with the condition COND.
3733 Check if we want to conditionalize a delay slot insn, and if so modify
3734 the ccfsm state accordingly.
3735 REVERSE says branch will branch when the condition is false. */
3736 void
3737 arc_ccfsm_record_condition (rtx cond, bool reverse, rtx jump,
3738 struct arc_ccfsm *state)
3740 rtx seq_insn = NEXT_INSN (PREV_INSN (jump));
3741 if (!state)
3742 state = &arc_ccfsm_current;
3744 gcc_assert (state->state == 0);
3745 if (seq_insn != jump)
3747 rtx insn = XVECEXP (PATTERN (seq_insn), 0, 1);
3749 if (!INSN_DELETED_P (insn)
3750 && INSN_ANNULLED_BRANCH_P (jump)
3751 && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (insn)))
3753 state->cond = cond;
3754 state->cc = get_arc_condition_code (cond);
3755 if (!reverse)
3756 arc_ccfsm_current.cc
3757 = ARC_INVERSE_CONDITION_CODE (state->cc);
3758 rtx pat = PATTERN (insn);
3759 if (GET_CODE (pat) == COND_EXEC)
3760 gcc_assert ((INSN_FROM_TARGET_P (insn)
3761 ? ARC_INVERSE_CONDITION_CODE (state->cc) : state->cc)
3762 == get_arc_condition_code (XEXP (pat, 0)));
3763 else
3764 state->state = 5;
3769 /* Update *STATE as we would when we emit INSN. */
3771 static void
3772 arc_ccfsm_post_advance (rtx insn, struct arc_ccfsm *state)
3774 enum attr_type type;
3776 if (LABEL_P (insn))
3777 arc_ccfsm_at_label ("L", CODE_LABEL_NUMBER (insn), state);
3778 else if (JUMP_P (insn)
3779 && GET_CODE (PATTERN (insn)) != ADDR_VEC
3780 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
3781 && ((type = get_attr_type (insn)) == TYPE_BRANCH
3782 || (type == TYPE_UNCOND_BRANCH
3783 /* ??? Maybe should also handle TYPE_RETURN here,
3784 but we don't have a testcase for that. */
3785 && ARC_CCFSM_BRANCH_DELETED_P (state))))
3787 if (ARC_CCFSM_BRANCH_DELETED_P (state))
3788 ARC_CCFSM_RECORD_BRANCH_DELETED (state);
3789 else
3791 rtx src = SET_SRC (PATTERN (insn));
3792 arc_ccfsm_record_condition (XEXP (src, 0), XEXP (src, 1) == pc_rtx,
3793 insn, state);
3796 else if (arc_ccfsm_current.state == 5)
3797 arc_ccfsm_current.state = 0;
3800 /* Return true if the current insn, which is a conditional branch, is to be
3801 deleted. */
3803 bool
3804 arc_ccfsm_branch_deleted_p (void)
3806 return ARC_CCFSM_BRANCH_DELETED_P (&arc_ccfsm_current);
3809 /* Record a branch isn't output because subsequent insns can be
3810 conditionalized. */
3812 void
3813 arc_ccfsm_record_branch_deleted (void)
3815 ARC_CCFSM_RECORD_BRANCH_DELETED (&arc_ccfsm_current);
3818 /* During insn output, indicate if the current insn is predicated. */
3820 bool
3821 arc_ccfsm_cond_exec_p (void)
3823 return (cfun->machine->prescan_initialized
3824 && ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current));
3827 /* Like next_active_insn, but return NULL if we find an ADDR_(DIFF_)VEC,
3828 and look inside SEQUENCEs. */
3830 static rtx
3831 arc_next_active_insn (rtx insn, struct arc_ccfsm *statep)
3833 rtx pat;
3837 if (statep)
3838 arc_ccfsm_post_advance (insn, statep);
3839 insn = NEXT_INSN (insn);
3840 if (!insn || BARRIER_P (insn))
3841 return NULL_RTX;
3842 if (statep)
3843 arc_ccfsm_advance (insn, statep);
3845 while (NOTE_P (insn)
3846 || (cfun->machine->arc_reorg_started
3847 && LABEL_P (insn) && !label_to_alignment (insn))
3848 || (NONJUMP_INSN_P (insn)
3849 && (GET_CODE (PATTERN (insn)) == USE
3850 || GET_CODE (PATTERN (insn)) == CLOBBER)));
3851 if (!LABEL_P (insn))
3853 gcc_assert (INSN_P (insn));
3854 pat = PATTERN (insn);
3855 if (GET_CODE (pat) == ADDR_VEC || GET_CODE (pat) == ADDR_DIFF_VEC)
3856 return NULL_RTX;
3857 if (GET_CODE (pat) == SEQUENCE)
3858 return XVECEXP (pat, 0, 0);
3860 return insn;
3863 /* When deciding if an insn should be output short, we want to know something
3864 about the following insns:
3865 - if another insn follows which we know we can output as a short insn
3866 before an alignment-sensitive point, we can output this insn short:
3867 the decision about the eventual alignment can be postponed.
3868 - if a to-be-aligned label comes next, we should output this insn such
3869 as to get / preserve 4-byte alignment.
3870 - if a likely branch without delay slot insn, or a call with an immediately
3871 following short insn comes next, we should out output this insn such as to
3872 get / preserve 2 mod 4 unalignment.
3873 - do the same for a not completely unlikely branch with a short insn
3874 following before any other branch / label.
3875 - in order to decide if we are actually looking at a branch, we need to
3876 call arc_ccfsm_advance.
3877 - in order to decide if we are looking at a short insn, we should know
3878 if it is conditionalized. To a first order of approximation this is
3879 the case if the state from arc_ccfsm_advance from before this insn
3880 indicates the insn is conditionalized. However, a further refinement
3881 could be to not conditionalize an insn if the destination register(s)
3882 is/are dead in the non-executed case. */
3883 /* Return non-zero if INSN should be output as a short insn. UNALIGN is
3884 zero if the current insn is aligned to a 4-byte-boundary, two otherwise.
3885 If CHECK_ATTR is greater than 0, check the iscompact attribute first. */
3888 arc_verify_short (rtx insn, int, int check_attr)
3890 enum attr_iscompact iscompact;
3891 struct machine_function *machine;
3893 if (check_attr > 0)
3895 iscompact = get_attr_iscompact (insn);
3896 if (iscompact == ISCOMPACT_FALSE)
3897 return 0;
3899 machine = cfun->machine;
3901 if (machine->force_short_suffix >= 0)
3902 return machine->force_short_suffix;
3904 return (get_attr_length (insn) & 2) != 0;
3907 /* When outputting an instruction (alternative) that can potentially be short,
3908 output the short suffix if the insn is in fact short, and update
3909 cfun->machine->unalign accordingly. */
3911 static void
3912 output_short_suffix (FILE *file)
3914 rtx insn = current_output_insn;
3916 if (arc_verify_short (insn, cfun->machine->unalign, 1))
3918 fprintf (file, "_s");
3919 cfun->machine->unalign ^= 2;
3921 /* Restore recog_operand. */
3922 extract_insn_cached (insn);
3925 /* Implement FINAL_PRESCAN_INSN. */
3927 void
3928 arc_final_prescan_insn (rtx insn, rtx *opvec ATTRIBUTE_UNUSED,
3929 int noperands ATTRIBUTE_UNUSED)
3931 if (TARGET_DUMPISIZE)
3932 fprintf (asm_out_file, "\n; at %04x\n", INSN_ADDRESSES (INSN_UID (insn)));
3934 /* Output a nop if necessary to prevent a hazard.
3935 Don't do this for delay slots: inserting a nop would
3936 alter semantics, and the only time we would find a hazard is for a
3937 call function result - and in that case, the hazard is spurious to
3938 start with. */
3939 if (PREV_INSN (insn)
3940 && PREV_INSN (NEXT_INSN (insn)) == insn
3941 && arc_hazard (prev_real_insn (insn), insn))
3943 current_output_insn =
3944 emit_insn_before (gen_nop (), NEXT_INSN (PREV_INSN (insn)));
3945 final_scan_insn (current_output_insn, asm_out_file, optimize, 1, NULL);
3946 current_output_insn = insn;
3948 /* Restore extraction data which might have been clobbered by arc_hazard. */
3949 extract_constrain_insn_cached (insn);
3951 if (!cfun->machine->prescan_initialized)
3953 /* Clear lingering state from branch shortening. */
3954 memset (&arc_ccfsm_current, 0, sizeof arc_ccfsm_current);
3955 cfun->machine->prescan_initialized = 1;
3957 arc_ccfsm_advance (insn, &arc_ccfsm_current);
3959 cfun->machine->size_reason = 0;
3962 /* Given FROM and TO register numbers, say whether this elimination is allowed.
3963 Frame pointer elimination is automatically handled.
3965 All eliminations are permissible. If we need a frame
3966 pointer, we must eliminate ARG_POINTER_REGNUM into
3967 FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */
3969 static bool
3970 arc_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
3972 return to == FRAME_POINTER_REGNUM || !arc_frame_pointer_required ();
3975 /* Define the offset between two registers, one to be eliminated, and
3976 the other its replacement, at the start of a routine. */
3979 arc_initial_elimination_offset (int from, int to)
3981 if (! cfun->machine->frame_info.initialized)
3982 arc_compute_frame_size (get_frame_size ());
3984 if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
3986 return (cfun->machine->frame_info.extra_size
3987 + cfun->machine->frame_info.reg_size);
3990 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
3992 return (cfun->machine->frame_info.total_size
3993 - cfun->machine->frame_info.pretend_size);
3996 if ((from == FRAME_POINTER_REGNUM) && (to == STACK_POINTER_REGNUM))
3998 return (cfun->machine->frame_info.total_size
3999 - (cfun->machine->frame_info.pretend_size
4000 + cfun->machine->frame_info.extra_size
4001 + cfun->machine->frame_info.reg_size));
4004 gcc_unreachable ();
4007 static bool
4008 arc_frame_pointer_required (void)
4010 return cfun->calls_alloca;
4014 /* Return the destination address of a branch. */
4017 branch_dest (rtx branch)
4019 rtx pat = PATTERN (branch);
4020 rtx dest = (GET_CODE (pat) == PARALLEL
4021 ? SET_SRC (XVECEXP (pat, 0, 0)) : SET_SRC (pat));
4022 int dest_uid;
4024 if (GET_CODE (dest) == IF_THEN_ELSE)
4025 dest = XEXP (dest, XEXP (dest, 1) == pc_rtx ? 2 : 1);
4027 dest = XEXP (dest, 0);
4028 dest_uid = INSN_UID (dest);
4030 return INSN_ADDRESSES (dest_uid);
4034 /* Implement TARGET_ENCODE_SECTION_INFO hook. */
4036 static void
4037 arc_encode_section_info (tree decl, rtx rtl, int first)
4039 /* For sdata, SYMBOL_FLAG_LOCAL and SYMBOL_FLAG_FUNCTION.
4040 This clears machine specific flags, so has to come first. */
4041 default_encode_section_info (decl, rtl, first);
4043 /* Check if it is a function, and whether it has the
4044 [long/medium/short]_call attribute specified. */
4045 if (TREE_CODE (decl) == FUNCTION_DECL)
4047 rtx symbol = XEXP (rtl, 0);
4048 int flags = SYMBOL_REF_FLAGS (symbol);
4050 tree attr = (TREE_TYPE (decl) != error_mark_node
4051 ? TYPE_ATTRIBUTES (TREE_TYPE (decl)) : NULL_TREE);
4052 tree long_call_attr = lookup_attribute ("long_call", attr);
4053 tree medium_call_attr = lookup_attribute ("medium_call", attr);
4054 tree short_call_attr = lookup_attribute ("short_call", attr);
4056 if (long_call_attr != NULL_TREE)
4057 flags |= SYMBOL_FLAG_LONG_CALL;
4058 else if (medium_call_attr != NULL_TREE)
4059 flags |= SYMBOL_FLAG_MEDIUM_CALL;
4060 else if (short_call_attr != NULL_TREE)
4061 flags |= SYMBOL_FLAG_SHORT_CALL;
4063 SYMBOL_REF_FLAGS (symbol) = flags;
4067 /* This is how to output a definition of an internal numbered label where
4068 PREFIX is the class of label and NUM is the number within the class. */
4070 static void arc_internal_label (FILE *stream, const char *prefix, unsigned long labelno)
4072 if (cfun)
4073 arc_ccfsm_at_label (prefix, labelno, &arc_ccfsm_current);
4074 default_internal_label (stream, prefix, labelno);
4077 /* Set the cpu type and print out other fancy things,
4078 at the top of the file. */
4080 static void arc_file_start (void)
4082 default_file_start ();
4083 fprintf (asm_out_file, "\t.cpu %s\n", arc_cpu_string);
4086 /* Cost functions. */
4088 /* Compute a (partial) cost for rtx X. Return true if the complete
4089 cost has been computed, and false if subexpressions should be
4090 scanned. In either case, *TOTAL contains the cost result. */
4092 static bool
4093 arc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
4094 int *total, bool speed)
4096 switch (code)
4098 /* Small integers are as cheap as registers. */
4099 case CONST_INT:
4101 bool nolimm = false; /* Can we do without long immediate? */
4102 bool fast = false; /* Is the result available immediately? */
4103 bool condexec = false; /* Does this allow conditiobnal execution? */
4104 bool compact = false; /* Is a 16 bit opcode available? */
4105 /* CONDEXEC also implies that we can have an unconditional
4106 3-address operation. */
4108 nolimm = compact = condexec = false;
4109 if (UNSIGNED_INT6 (INTVAL (x)))
4110 nolimm = condexec = compact = true;
4111 else
4113 if (SMALL_INT (INTVAL (x)))
4114 nolimm = fast = true;
4115 switch (outer_code)
4117 case AND: /* bclr, bmsk, ext[bw] */
4118 if (satisfies_constraint_Ccp (x) /* bclr */
4119 || satisfies_constraint_C1p (x) /* bmsk */)
4120 nolimm = fast = condexec = compact = true;
4121 break;
4122 case IOR: /* bset */
4123 if (satisfies_constraint_C0p (x)) /* bset */
4124 nolimm = fast = condexec = compact = true;
4125 break;
4126 case XOR:
4127 if (satisfies_constraint_C0p (x)) /* bxor */
4128 nolimm = fast = condexec = true;
4129 break;
4130 case SET:
4131 if (satisfies_constraint_Crr (x)) /* ror b,u6 */
4132 nolimm = true;
4133 default:
4134 break;
4137 /* FIXME: Add target options to attach a small cost if
4138 condexec / compact is not true. */
4139 if (nolimm)
4141 *total = 0;
4142 return true;
4145 /* FALLTHRU */
4147 /* 4 byte values can be fetched as immediate constants -
4148 let's give that the cost of an extra insn. */
4149 case CONST:
4150 case LABEL_REF:
4151 case SYMBOL_REF:
4152 *total = COSTS_N_INSNS (1);
4153 return true;
4155 case CONST_DOUBLE:
4157 rtx high, low;
4159 if (TARGET_DPFP)
4161 *total = COSTS_N_INSNS (1);
4162 return true;
4164 /* FIXME: correct the order of high,low */
4165 split_double (x, &high, &low);
4166 *total = COSTS_N_INSNS (!SMALL_INT (INTVAL (high))
4167 + !SMALL_INT (INTVAL (low)));
4168 return true;
4171 /* Encourage synth_mult to find a synthetic multiply when reasonable.
4172 If we need more than 12 insns to do a multiply, then go out-of-line,
4173 since the call overhead will be < 10% of the cost of the multiply. */
4174 case ASHIFT:
4175 case ASHIFTRT:
4176 case LSHIFTRT:
4177 if (TARGET_BARREL_SHIFTER)
4179 /* If we want to shift a constant, we need a LIMM. */
4180 /* ??? when the optimizers want to know if a constant should be
4181 hoisted, they ask for the cost of the constant. OUTER_CODE is
4182 insufficient context for shifts since we don't know which operand
4183 we are looking at. */
4184 if (CONSTANT_P (XEXP (x, 0)))
4186 *total += (COSTS_N_INSNS (2)
4187 + rtx_cost (XEXP (x, 1), (enum rtx_code) code, 0, speed));
4188 return true;
4190 *total = COSTS_N_INSNS (1);
4192 else if (GET_CODE (XEXP (x, 1)) != CONST_INT)
4193 *total = COSTS_N_INSNS (16);
4194 else
4196 *total = COSTS_N_INSNS (INTVAL (XEXP ((x), 1)));
4197 /* ??? want_to_gcse_p can throw negative shift counts at us,
4198 and then panics when it gets a negative cost as result.
4199 Seen for gcc.c-torture/compile/20020710-1.c -Os . */
4200 if (*total < 0)
4201 *total = 0;
4203 return false;
4205 case DIV:
4206 case UDIV:
4207 if (speed)
4208 *total = COSTS_N_INSNS(30);
4209 else
4210 *total = COSTS_N_INSNS(1);
4211 return false;
4213 case MULT:
4214 if ((TARGET_DPFP && GET_MODE (x) == DFmode))
4215 *total = COSTS_N_INSNS (1);
4216 else if (speed)
4217 *total= arc_multcost;
4218 /* We do not want synth_mult sequences when optimizing
4219 for size. */
4220 else if (TARGET_MUL64_SET || (TARGET_ARC700 && !TARGET_NOMPY_SET))
4221 *total = COSTS_N_INSNS (1);
4222 else
4223 *total = COSTS_N_INSNS (2);
4224 return false;
4225 case PLUS:
4226 if (GET_CODE (XEXP (x, 0)) == MULT
4227 && _2_4_8_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
4229 *total += (rtx_cost (XEXP (x, 1), PLUS, 0, speed)
4230 + rtx_cost (XEXP (XEXP (x, 0), 0), PLUS, 1, speed));
4231 return true;
4233 return false;
4234 case MINUS:
4235 if (GET_CODE (XEXP (x, 1)) == MULT
4236 && _2_4_8_operand (XEXP (XEXP (x, 1), 1), VOIDmode))
4238 *total += (rtx_cost (XEXP (x, 0), PLUS, 0, speed)
4239 + rtx_cost (XEXP (XEXP (x, 1), 0), PLUS, 1, speed));
4240 return true;
4242 return false;
4243 case COMPARE:
4245 rtx op0 = XEXP (x, 0);
4246 rtx op1 = XEXP (x, 1);
4248 if (GET_CODE (op0) == ZERO_EXTRACT && op1 == const0_rtx
4249 && XEXP (op0, 1) == const1_rtx)
4251 /* btst / bbit0 / bbit1:
4252 Small integers and registers are free; everything else can
4253 be put in a register. */
4254 *total = (rtx_cost (XEXP (op0, 0), SET, 1, speed)
4255 + rtx_cost (XEXP (op0, 2), SET, 1, speed));
4256 return true;
4258 if (GET_CODE (op0) == AND && op1 == const0_rtx
4259 && satisfies_constraint_C1p (XEXP (op0, 1)))
4261 /* bmsk.f */
4262 *total = rtx_cost (XEXP (op0, 0), SET, 1, speed);
4263 return true;
4265 /* add.f */
4266 if (GET_CODE (op1) == NEG)
4268 /* op0 might be constant, the inside of op1 is rather
4269 unlikely to be so. So swapping the operands might lower
4270 the cost. */
4271 *total = (rtx_cost (op0, PLUS, 1, speed)
4272 + rtx_cost (XEXP (op1, 0), PLUS, 0, speed));
4274 return false;
4276 case EQ: case NE:
4277 if (outer_code == IF_THEN_ELSE
4278 && GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT
4279 && XEXP (x, 1) == const0_rtx
4280 && XEXP (XEXP (x, 0), 1) == const1_rtx)
4282 /* btst / bbit0 / bbit1:
4283 Small integers and registers are free; everything else can
4284 be put in a register. */
4285 rtx op0 = XEXP (x, 0);
4287 *total = (rtx_cost (XEXP (op0, 0), SET, 1, speed)
4288 + rtx_cost (XEXP (op0, 2), SET, 1, speed));
4289 return true;
4291 /* Fall through. */
4292 /* scc_insn expands into two insns. */
4293 case GTU: case GEU: case LEU:
4294 if (GET_MODE (x) == SImode)
4295 *total += COSTS_N_INSNS (1);
4296 return false;
4297 case LTU: /* might use adc. */
4298 if (GET_MODE (x) == SImode)
4299 *total += COSTS_N_INSNS (1) - 1;
4300 return false;
4301 default:
4302 return false;
4306 /* Return true if ADDR is an address that needs to be expressed as an
4307 explicit sum of pcl + offset. */
4309 bool
4310 arc_legitimate_pc_offset_p (rtx addr)
4312 if (GET_CODE (addr) != CONST)
4313 return false;
4314 addr = XEXP (addr, 0);
4315 if (GET_CODE (addr) == PLUS)
4317 if (GET_CODE (XEXP (addr, 1)) != CONST_INT)
4318 return false;
4319 addr = XEXP (addr, 0);
4321 return (GET_CODE (addr) == UNSPEC
4322 && XVECLEN (addr, 0) == 1
4323 && XINT (addr, 1) == ARC_UNSPEC_GOT
4324 && GET_CODE (XVECEXP (addr, 0, 0)) == SYMBOL_REF);
4327 /* Return true if ADDR is a valid pic address.
4328 A valid pic address on arc should look like
4329 const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT)) */
4331 bool
4332 arc_legitimate_pic_addr_p (rtx addr)
4334 if (GET_CODE (addr) == LABEL_REF)
4335 return true;
4336 if (GET_CODE (addr) != CONST)
4337 return false;
4339 addr = XEXP (addr, 0);
4342 if (GET_CODE (addr) == PLUS)
4344 if (GET_CODE (XEXP (addr, 1)) != CONST_INT)
4345 return false;
4346 addr = XEXP (addr, 0);
4349 if (GET_CODE (addr) != UNSPEC
4350 || XVECLEN (addr, 0) != 1)
4351 return false;
4353 /* Must be @GOT or @GOTOFF. */
4354 if (XINT (addr, 1) != ARC_UNSPEC_GOT
4355 && XINT (addr, 1) != ARC_UNSPEC_GOTOFF)
4356 return false;
4358 if (GET_CODE (XVECEXP (addr, 0, 0)) != SYMBOL_REF
4359 && GET_CODE (XVECEXP (addr, 0, 0)) != LABEL_REF)
4360 return false;
4362 return true;
4367 /* Return true if OP contains a symbol reference. */
4369 static bool
4370 symbolic_reference_mentioned_p (rtx op)
4372 register const char *fmt;
4373 register int i;
4375 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
4376 return true;
4378 fmt = GET_RTX_FORMAT (GET_CODE (op));
4379 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
4381 if (fmt[i] == 'E')
4383 register int j;
4385 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
4386 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
4387 return true;
4390 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
4391 return true;
4394 return false;
4397 /* Return true if OP contains a SYMBOL_REF that is not wrapped in an unspec.
4398 If SKIP_LOCAL is true, skip symbols that bind locally.
4399 This is used further down in this file, and, without SKIP_LOCAL,
4400 in the addsi3 / subsi3 expanders when generating PIC code. */
4402 bool
4403 arc_raw_symbolic_reference_mentioned_p (rtx op, bool skip_local)
4405 register const char *fmt;
4406 register int i;
4408 if (GET_CODE(op) == UNSPEC)
4409 return false;
4411 if (GET_CODE (op) == SYMBOL_REF)
4413 tree decl = SYMBOL_REF_DECL (op);
4414 return !skip_local || !decl || !default_binds_local_p (decl);
4417 fmt = GET_RTX_FORMAT (GET_CODE (op));
4418 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
4420 if (fmt[i] == 'E')
4422 register int j;
4424 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
4425 if (arc_raw_symbolic_reference_mentioned_p (XVECEXP (op, i, j),
4426 skip_local))
4427 return true;
4430 else if (fmt[i] == 'e'
4431 && arc_raw_symbolic_reference_mentioned_p (XEXP (op, i),
4432 skip_local))
4433 return true;
4436 return false;
4439 /* Legitimize a pic address reference in ORIG.
4440 The return value is the legitimated address.
4441 If OLDX is non-zero, it is the target to assign the address to first. */
4444 arc_legitimize_pic_address (rtx orig, rtx oldx)
4446 rtx addr = orig;
4447 rtx pat = orig;
4448 rtx base;
4450 if (oldx == orig)
4451 oldx = NULL;
4453 if (GET_CODE (addr) == LABEL_REF)
4454 ; /* Do nothing. */
4455 else if (GET_CODE (addr) == SYMBOL_REF
4456 && (CONSTANT_POOL_ADDRESS_P (addr)
4457 || SYMBOL_REF_LOCAL_P (addr)))
4459 /* This symbol may be referenced via a displacement from the PIC
4460 base address (@GOTOFF). */
4462 /* FIXME: if we had a way to emit pc-relative adds that don't
4463 create a GOT entry, we could do without the use of the gp register. */
4464 crtl->uses_pic_offset_table = 1;
4465 pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOTOFF);
4466 pat = gen_rtx_CONST (Pmode, pat);
4467 pat = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pat);
4469 if (oldx == NULL)
4470 oldx = gen_reg_rtx (Pmode);
4472 if (oldx != 0)
4474 emit_move_insn (oldx, pat);
4475 pat = oldx;
4479 else if (GET_CODE (addr) == SYMBOL_REF)
4481 /* This symbol must be referenced via a load from the
4482 Global Offset Table (@GOTPC). */
4484 pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOT);
4485 pat = gen_rtx_CONST (Pmode, pat);
4486 pat = gen_const_mem (Pmode, pat);
4488 if (oldx == 0)
4489 oldx = gen_reg_rtx (Pmode);
4491 emit_move_insn (oldx, pat);
4492 pat = oldx;
4494 else
4496 if (GET_CODE (addr) == CONST)
4498 addr = XEXP (addr, 0);
4499 if (GET_CODE (addr) == UNSPEC)
4501 /* Check that the unspec is one of the ones we generate? */
4503 else
4504 gcc_assert (GET_CODE (addr) == PLUS);
4507 if (GET_CODE (addr) == PLUS)
4509 rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
4511 /* Check first to see if this is a constant offset from a @GOTOFF
4512 symbol reference. */
4513 if ((GET_CODE (op0) == LABEL_REF
4514 || (GET_CODE (op0) == SYMBOL_REF
4515 && (CONSTANT_POOL_ADDRESS_P (op0)
4516 || SYMBOL_REF_LOCAL_P (op0))))
4517 && GET_CODE (op1) == CONST_INT)
4519 /* FIXME: like above, could do without gp reference. */
4520 crtl->uses_pic_offset_table = 1;
4522 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), ARC_UNSPEC_GOTOFF);
4523 pat = gen_rtx_PLUS (Pmode, pat, op1);
4524 pat = gen_rtx_CONST (Pmode, pat);
4525 pat = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pat);
4527 if (oldx != 0)
4529 emit_move_insn (oldx, pat);
4530 pat = oldx;
4533 else
4535 base = arc_legitimize_pic_address (XEXP (addr, 0), oldx);
4536 pat = arc_legitimize_pic_address (XEXP (addr, 1),
4537 base == oldx ? NULL_RTX : oldx);
4539 if (GET_CODE (pat) == CONST_INT)
4540 pat = plus_constant (Pmode, base, INTVAL (pat));
4541 else
4543 if (GET_CODE (pat) == PLUS && CONSTANT_P (XEXP (pat, 1)))
4545 base = gen_rtx_PLUS (Pmode, base, XEXP (pat, 0));
4546 pat = XEXP (pat, 1);
4548 pat = gen_rtx_PLUS (Pmode, base, pat);
4554 return pat;
4557 /* Output address constant X to FILE, taking PIC into account. */
4559 void
4560 arc_output_pic_addr_const (FILE * file, rtx x, int code)
4562 char buf[256];
4564 restart:
4565 switch (GET_CODE (x))
4567 case PC:
4568 if (flag_pic)
4569 putc ('.', file);
4570 else
4571 gcc_unreachable ();
4572 break;
4574 case SYMBOL_REF:
4575 output_addr_const (file, x);
4577 /* Local functions do not get references through the PLT. */
4578 if (code == 'P' && ! SYMBOL_REF_LOCAL_P (x))
4579 fputs ("@plt", file);
4580 break;
4582 case LABEL_REF:
4583 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
4584 assemble_name (file, buf);
4585 break;
4587 case CODE_LABEL:
4588 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
4589 assemble_name (file, buf);
4590 break;
4592 case CONST_INT:
4593 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
4594 break;
4596 case CONST:
4597 arc_output_pic_addr_const (file, XEXP (x, 0), code);
4598 break;
4600 case CONST_DOUBLE:
4601 if (GET_MODE (x) == VOIDmode)
4603 /* We can use %d if the number is one word and positive. */
4604 if (CONST_DOUBLE_HIGH (x))
4605 fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
4606 CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
4607 else if (CONST_DOUBLE_LOW (x) < 0)
4608 fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
4609 else
4610 fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x));
4612 else
4613 /* We can't handle floating point constants;
4614 PRINT_OPERAND must handle them. */
4615 output_operand_lossage ("floating constant misused");
4616 break;
4618 case PLUS:
4619 /* FIXME: Not needed here. */
4620 /* Some assemblers need integer constants to appear last (eg masm). */
4621 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
4623 arc_output_pic_addr_const (file, XEXP (x, 1), code);
4624 fprintf (file, "+");
4625 arc_output_pic_addr_const (file, XEXP (x, 0), code);
4627 else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
4629 arc_output_pic_addr_const (file, XEXP (x, 0), code);
4630 if (INTVAL (XEXP (x, 1)) >= 0)
4631 fprintf (file, "+");
4632 arc_output_pic_addr_const (file, XEXP (x, 1), code);
4634 else
4635 gcc_unreachable();
4636 break;
4638 case MINUS:
4639 /* Avoid outputting things like x-x or x+5-x,
4640 since some assemblers can't handle that. */
4641 x = simplify_subtraction (x);
4642 if (GET_CODE (x) != MINUS)
4643 goto restart;
4645 arc_output_pic_addr_const (file, XEXP (x, 0), code);
4646 fprintf (file, "-");
4647 if (GET_CODE (XEXP (x, 1)) == CONST_INT
4648 && INTVAL (XEXP (x, 1)) < 0)
4650 fprintf (file, "(");
4651 arc_output_pic_addr_const (file, XEXP (x, 1), code);
4652 fprintf (file, ")");
4654 else
4655 arc_output_pic_addr_const (file, XEXP (x, 1), code);
4656 break;
4658 case ZERO_EXTEND:
4659 case SIGN_EXTEND:
4660 arc_output_pic_addr_const (file, XEXP (x, 0), code);
4661 break;
4664 case UNSPEC:
4665 gcc_assert (XVECLEN (x, 0) == 1);
4666 if (XINT (x, 1) == ARC_UNSPEC_GOT)
4667 fputs ("pcl,", file);
4668 arc_output_pic_addr_const (file, XVECEXP (x, 0, 0), code);
4669 switch (XINT (x, 1))
4671 case ARC_UNSPEC_GOT:
4672 fputs ("@gotpc", file);
4673 break;
4674 case ARC_UNSPEC_GOTOFF:
4675 fputs ("@gotoff", file);
4676 break;
4677 case ARC_UNSPEC_PLT:
4678 fputs ("@plt", file);
4679 break;
4680 default:
4681 output_operand_lossage ("invalid UNSPEC as operand: %d", XINT (x,1));
4682 break;
4684 break;
4686 default:
4687 output_operand_lossage ("invalid expression as operand");
4691 #define SYMBOLIC_CONST(X) \
4692 (GET_CODE (X) == SYMBOL_REF \
4693 || GET_CODE (X) == LABEL_REF \
4694 || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
4696 /* Emit insns to move operands[1] into operands[0]. */
4698 void
4699 emit_pic_move (rtx *operands, enum machine_mode)
4701 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
4703 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
4704 operands[1] = force_reg (Pmode, operands[1]);
4705 else
4706 operands[1] = arc_legitimize_pic_address (operands[1], temp);
4710 /* The function returning the number of words, at the beginning of an
4711 argument, must be put in registers. The returned value must be
4712 zero for arguments that are passed entirely in registers or that
4713 are entirely pushed on the stack.
4715 On some machines, certain arguments must be passed partially in
4716 registers and partially in memory. On these machines, typically
4717 the first N words of arguments are passed in registers, and the
4718 rest on the stack. If a multi-word argument (a `double' or a
4719 structure) crosses that boundary, its first few words must be
4720 passed in registers and the rest must be pushed. This function
4721 tells the compiler when this occurs, and how many of the words
4722 should go in registers.
4724 `FUNCTION_ARG' for these arguments should return the first register
4725 to be used by the caller for this argument; likewise
4726 `FUNCTION_INCOMING_ARG', for the called function.
4728 The function is used to implement macro FUNCTION_ARG_PARTIAL_NREGS. */
4730 /* If REGNO is the least arg reg available then what is the total number of arg
4731 regs available. */
4732 #define GPR_REST_ARG_REGS(REGNO) \
4733 ((REGNO) <= MAX_ARC_PARM_REGS ? MAX_ARC_PARM_REGS - (REGNO) : 0 )
4735 /* Since arc parm regs are contiguous. */
4736 #define ARC_NEXT_ARG_REG(REGNO) ( (REGNO) + 1 )
4738 /* Implement TARGET_ARG_PARTIAL_BYTES. */
4740 static int
4741 arc_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode,
4742 tree type, bool named ATTRIBUTE_UNUSED)
4744 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
4745 int bytes = (mode == BLKmode
4746 ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode));
4747 int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
4748 int arg_num = *cum;
4749 int ret;
4751 arg_num = ROUND_ADVANCE_CUM (arg_num, mode, type);
4752 ret = GPR_REST_ARG_REGS (arg_num);
4754 /* ICEd at function.c:2361, and ret is copied to data->partial */
4755 ret = (ret >= words ? 0 : ret * UNITS_PER_WORD);
4757 return ret;
4762 /* This function is used to control a function argument is passed in a
4763 register, and which register.
4765 The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes
4766 (in a way defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE)
4767 all of the previous arguments so far passed in registers; MODE, the
4768 machine mode of the argument; TYPE, the data type of the argument
4769 as a tree node or 0 if that is not known (which happens for C
4770 support library functions); and NAMED, which is 1 for an ordinary
4771 argument and 0 for nameless arguments that correspond to `...' in
4772 the called function's prototype.
4774 The returned value should either be a `reg' RTX for the hard
4775 register in which to pass the argument, or zero to pass the
4776 argument on the stack.
4778 For machines like the Vax and 68000, where normally all arguments
4779 are pushed, zero suffices as a definition.
4781 The usual way to make the ANSI library `stdarg.h' work on a machine
4782 where some arguments are usually passed in registers, is to cause
4783 nameless arguments to be passed on the stack instead. This is done
4784 by making the function return 0 whenever NAMED is 0.
4786 You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the
4787 definition of this function to determine if this argument is of a
4788 type that must be passed in the stack. If `REG_PARM_STACK_SPACE'
4789 is not defined and the function returns non-zero for such an
4790 argument, the compiler will abort. If `REG_PARM_STACK_SPACE' is
4791 defined, the argument will be computed in the stack and then loaded
4792 into a register.
4794 The function is used to implement macro FUNCTION_ARG. */
4795 /* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers
4796 and the rest are pushed. */
4798 static rtx
4799 arc_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
4800 const_tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
4802 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
4803 int arg_num = *cum;
4804 rtx ret;
4805 const char *debstr ATTRIBUTE_UNUSED;
4807 arg_num = ROUND_ADVANCE_CUM (arg_num, mode, type);
4808 /* Return a marker for use in the call instruction. */
4809 if (mode == VOIDmode)
4811 ret = const0_rtx;
4812 debstr = "<0>";
4814 else if (GPR_REST_ARG_REGS (arg_num) > 0)
4816 ret = gen_rtx_REG (mode, arg_num);
4817 debstr = reg_names [arg_num];
4819 else
4821 ret = NULL_RTX;
4822 debstr = "memory";
4824 return ret;
4827 /* The function to update the summarizer variable *CUM to advance past
4828 an argument in the argument list. The values MODE, TYPE and NAMED
4829 describe that argument. Once this is done, the variable *CUM is
4830 suitable for analyzing the *following* argument with
4831 `FUNCTION_ARG', etc.
4833 This function need not do anything if the argument in question was
4834 passed on the stack. The compiler knows how to track the amount of
4835 stack space used for arguments without any special help.
4837 The function is used to implement macro FUNCTION_ARG_ADVANCE. */
4838 /* For the ARC: the cum set here is passed on to function_arg where we
4839 look at its value and say which reg to use. Strategy: advance the
4840 regnumber here till we run out of arg regs, then set *cum to last
4841 reg. In function_arg, since *cum > last arg reg we would return 0
4842 and thus the arg will end up on the stack. For straddling args of
4843 course function_arg_partial_nregs will come into play. */
4845 static void
4846 arc_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
4847 const_tree type, bool named ATTRIBUTE_UNUSED)
4849 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
4850 int bytes = (mode == BLKmode
4851 ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode));
4852 int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
4853 int i;
4855 if (words)
4856 *cum = ROUND_ADVANCE_CUM (*cum, mode, type);
4857 for (i = 0; i < words; i++)
4858 *cum = ARC_NEXT_ARG_REG (*cum);
4862 /* Define how to find the value returned by a function.
4863 VALTYPE is the data type of the value (as a tree).
4864 If the precise function being called is known, FN_DECL_OR_TYPE is its
4865 FUNCTION_DECL; otherwise, FN_DECL_OR_TYPE is its type. */
4867 static rtx
4868 arc_function_value (const_tree valtype,
4869 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
4870 bool outgoing ATTRIBUTE_UNUSED)
4872 enum machine_mode mode = TYPE_MODE (valtype);
4873 int unsignedp ATTRIBUTE_UNUSED;
4875 unsignedp = TYPE_UNSIGNED (valtype);
4876 if (INTEGRAL_TYPE_P (valtype) || TREE_CODE (valtype) == OFFSET_TYPE)
4877 PROMOTE_MODE (mode, unsignedp, valtype);
4878 return gen_rtx_REG (mode, 0);
4881 /* Returns the return address that is used by builtin_return_address. */
4884 arc_return_addr_rtx (int count, ATTRIBUTE_UNUSED rtx frame)
4886 if (count != 0)
4887 return const0_rtx;
4889 return get_hard_reg_initial_val (Pmode , RETURN_ADDR_REGNUM);
4892 /* Nonzero if the constant value X is a legitimate general operand
4893 when generating PIC code. It is given that flag_pic is on and
4894 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
4896 bool
4897 arc_legitimate_pic_operand_p (rtx x)
4899 return !arc_raw_symbolic_reference_mentioned_p (x, true);
4902 /* Determine if a given RTX is a valid constant. We already know this
4903 satisfies CONSTANT_P. */
4905 bool
4906 arc_legitimate_constant_p (enum machine_mode, rtx x)
4908 if (!flag_pic)
4909 return true;
4911 switch (GET_CODE (x))
4913 case CONST:
4914 x = XEXP (x, 0);
4916 if (GET_CODE (x) == PLUS)
4918 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
4919 return false;
4920 x = XEXP (x, 0);
4923 /* Only some unspecs are valid as "constants". */
4924 if (GET_CODE (x) == UNSPEC)
4925 switch (XINT (x, 1))
4927 case ARC_UNSPEC_PLT:
4928 case ARC_UNSPEC_GOTOFF:
4929 case ARC_UNSPEC_GOT:
4930 case UNSPEC_PROF:
4931 return true;
4933 default:
4934 gcc_unreachable ();
4937 /* We must have drilled down to a symbol. */
4938 if (arc_raw_symbolic_reference_mentioned_p (x, false))
4939 return false;
4941 /* Return true. */
4942 break;
4944 case LABEL_REF:
4945 case SYMBOL_REF:
4946 return false;
4948 default:
4949 break;
4952 /* Otherwise we handle everything else in the move patterns. */
4953 return true;
4956 static bool
4957 arc_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
4959 if (RTX_OK_FOR_BASE_P (x, strict))
4960 return true;
4961 if (LEGITIMATE_OFFSET_ADDRESS_P (mode, x, TARGET_INDEXED_LOADS, strict))
4962 return true;
4963 if (LEGITIMATE_SCALED_ADDRESS_P (mode, x, strict))
4964 return true;
4965 if (LEGITIMATE_SMALL_DATA_ADDRESS_P (x))
4966 return true;
4967 if (GET_CODE (x) == CONST_INT && LARGE_INT (INTVAL (x)))
4968 return true;
4969 if ((GET_MODE_SIZE (mode) != 16)
4970 && (GET_CODE (x) == SYMBOL_REF
4971 || GET_CODE (x) == LABEL_REF
4972 || GET_CODE (x) == CONST))
4974 if (!flag_pic || arc_legitimate_pic_addr_p (x))
4975 return true;
4977 if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == PRE_INC
4978 || GET_CODE (x) == POST_DEC || GET_CODE (x) == POST_INC)
4979 && RTX_OK_FOR_BASE_P (XEXP (x, 0), strict))
4980 return true;
4981 /* We're restricted here by the `st' insn. */
4982 if ((GET_CODE (x) == PRE_MODIFY || GET_CODE (x) == POST_MODIFY)
4983 && GET_CODE (XEXP ((x), 1)) == PLUS
4984 && rtx_equal_p (XEXP ((x), 0), XEXP (XEXP (x, 1), 0))
4985 && LEGITIMATE_OFFSET_ADDRESS_P (QImode, XEXP (x, 1),
4986 TARGET_AUTO_MODIFY_REG, strict))
4987 return true;
4988 return false;
4991 /* Return true iff ADDR (a legitimate address expression)
4992 has an effect that depends on the machine mode it is used for. */
4994 static bool
4995 arc_mode_dependent_address_p (const_rtx addr, addr_space_t)
4997 /* SYMBOL_REF is not mode dependent: it is either a small data reference,
4998 which is valid for loads and stores, or a limm offset, which is valid for
4999 loads. */
5000 /* Scaled indices are scaled by the access mode; likewise for scaled
5001 offsets, which are needed for maximum offset stores. */
5002 if (GET_CODE (addr) == PLUS
5003 && (GET_CODE (XEXP ((addr), 0)) == MULT
5004 || (CONST_INT_P (XEXP ((addr), 1))
5005 && !SMALL_INT (INTVAL (XEXP ((addr), 1))))))
5006 return true;
5007 return false;
5010 /* Determine if it's legal to put X into the constant pool. */
5012 static bool
5013 arc_cannot_force_const_mem (enum machine_mode mode, rtx x)
5015 return !arc_legitimate_constant_p (mode, x);
5019 /* Generic function to define a builtin. */
5020 #define def_mbuiltin(MASK, NAME, TYPE, CODE) \
5021 do \
5023 if (MASK) \
5024 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE); \
5026 while (0)
5029 static void
5030 arc_init_builtins (void)
5032 tree endlink = void_list_node;
5034 tree void_ftype_void
5035 = build_function_type (void_type_node,
5036 endlink);
5038 tree int_ftype_int
5039 = build_function_type (integer_type_node,
5040 tree_cons (NULL_TREE, integer_type_node, endlink));
5042 tree pcvoid_type_node
5043 = build_pointer_type (build_qualified_type (void_type_node, TYPE_QUAL_CONST));
5044 tree int_ftype_pcvoid_int
5045 = build_function_type (integer_type_node,
5046 tree_cons (NULL_TREE, pcvoid_type_node,
5047 tree_cons (NULL_TREE, integer_type_node,
5048 endlink)));
5050 tree int_ftype_short_int
5051 = build_function_type (integer_type_node,
5052 tree_cons (NULL_TREE, short_integer_type_node, endlink));
5054 tree void_ftype_int_int
5055 = build_function_type (void_type_node,
5056 tree_cons (NULL_TREE, integer_type_node,
5057 tree_cons (NULL_TREE, integer_type_node, endlink)));
5058 tree void_ftype_usint_usint
5059 = build_function_type (void_type_node,
5060 tree_cons (NULL_TREE, long_unsigned_type_node,
5061 tree_cons (NULL_TREE, long_unsigned_type_node, endlink)));
5063 tree int_ftype_int_int
5064 = build_function_type (integer_type_node,
5065 tree_cons (NULL_TREE, integer_type_node,
5066 tree_cons (NULL_TREE, integer_type_node, endlink)));
5068 tree usint_ftype_usint
5069 = build_function_type (long_unsigned_type_node,
5070 tree_cons (NULL_TREE, long_unsigned_type_node, endlink));
5072 tree void_ftype_usint
5073 = build_function_type (void_type_node,
5074 tree_cons (NULL_TREE, long_unsigned_type_node, endlink));
5076 /* Add the builtins. */
5077 def_mbuiltin (1,"__builtin_arc_nop", void_ftype_void, ARC_BUILTIN_NOP);
5078 def_mbuiltin (TARGET_NORM, "__builtin_arc_norm", int_ftype_int, ARC_BUILTIN_NORM);
5079 def_mbuiltin (TARGET_NORM, "__builtin_arc_normw", int_ftype_short_int, ARC_BUILTIN_NORMW);
5080 def_mbuiltin (TARGET_SWAP, "__builtin_arc_swap", int_ftype_int, ARC_BUILTIN_SWAP);
5081 def_mbuiltin (TARGET_MUL64_SET,"__builtin_arc_mul64", void_ftype_int_int, ARC_BUILTIN_MUL64);
5082 def_mbuiltin (TARGET_MUL64_SET,"__builtin_arc_mulu64", void_ftype_usint_usint, ARC_BUILTIN_MULU64);
5083 def_mbuiltin (1,"__builtin_arc_rtie", void_ftype_void, ARC_BUILTIN_RTIE);
5084 def_mbuiltin (TARGET_ARC700,"__builtin_arc_sync", void_ftype_void, ARC_BUILTIN_SYNC);
5085 def_mbuiltin ((TARGET_EA_SET),"__builtin_arc_divaw", int_ftype_int_int, ARC_BUILTIN_DIVAW);
5086 def_mbuiltin (1,"__builtin_arc_brk", void_ftype_void, ARC_BUILTIN_BRK);
5087 def_mbuiltin (1,"__builtin_arc_flag", void_ftype_usint, ARC_BUILTIN_FLAG);
5088 def_mbuiltin (1,"__builtin_arc_sleep", void_ftype_usint, ARC_BUILTIN_SLEEP);
5089 def_mbuiltin (1,"__builtin_arc_swi", void_ftype_void, ARC_BUILTIN_SWI);
5090 def_mbuiltin (1,"__builtin_arc_core_read", usint_ftype_usint, ARC_BUILTIN_CORE_READ);
5091 def_mbuiltin (1,"__builtin_arc_core_write", void_ftype_usint_usint, ARC_BUILTIN_CORE_WRITE);
5092 def_mbuiltin (1,"__builtin_arc_lr", usint_ftype_usint, ARC_BUILTIN_LR);
5093 def_mbuiltin (1,"__builtin_arc_sr", void_ftype_usint_usint, ARC_BUILTIN_SR);
5094 def_mbuiltin (TARGET_ARC700,"__builtin_arc_trap_s", void_ftype_usint, ARC_BUILTIN_TRAP_S);
5095 def_mbuiltin (TARGET_ARC700,"__builtin_arc_unimp_s", void_ftype_void, ARC_BUILTIN_UNIMP_S);
5096 def_mbuiltin (1,"__builtin_arc_aligned", int_ftype_pcvoid_int, ARC_BUILTIN_ALIGNED);
5098 if (TARGET_SIMD_SET)
5099 arc_init_simd_builtins ();
5102 static rtx arc_expand_simd_builtin (tree, rtx, rtx, enum machine_mode, int);
5104 /* Expand an expression EXP that calls a built-in function,
5105 with result going to TARGET if that's convenient
5106 (and in mode MODE if that's convenient).
5107 SUBTARGET may be used as the target for computing one of EXP's operands.
5108 IGNORE is nonzero if the value is to be ignored. */
5110 static rtx
5111 arc_expand_builtin (tree exp,
5112 rtx target,
5113 rtx subtarget,
5114 enum machine_mode mode,
5115 int ignore)
5117 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
5118 tree arg0;
5119 tree arg1;
5120 rtx op0;
5121 rtx op1;
5122 int fcode = DECL_FUNCTION_CODE (fndecl);
5123 int icode;
5124 enum machine_mode mode0;
5125 enum machine_mode mode1;
5127 if (fcode > ARC_SIMD_BUILTIN_BEGIN && fcode < ARC_SIMD_BUILTIN_END)
5128 return arc_expand_simd_builtin (exp, target, subtarget, mode, ignore);
5130 switch (fcode)
5132 case ARC_BUILTIN_NOP:
5133 emit_insn (gen_nop ());
5134 return NULL_RTX;
5136 case ARC_BUILTIN_NORM:
5137 icode = CODE_FOR_clrsbsi2;
5138 arg0 = CALL_EXPR_ARG (exp, 0);
5139 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5140 mode0 = insn_data[icode].operand[1].mode;
5141 target = gen_reg_rtx (SImode);
5143 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5144 op0 = copy_to_mode_reg (mode0, op0);
5146 emit_insn (gen_clrsbsi2 (target, op0));
5147 return target;
5149 case ARC_BUILTIN_NORMW:
5151 /* FIXME : This should all be HImode, not SImode. */
5152 icode = CODE_FOR_normw;
5153 arg0 = CALL_EXPR_ARG (exp, 0);
5154 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5155 mode0 = insn_data[icode].operand[1].mode;
5156 target = gen_reg_rtx (SImode);
5158 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5159 op0 = copy_to_mode_reg (mode0, convert_to_mode (mode0, op0,0));
5161 emit_insn (gen_normw (target, op0));
5162 return target;
5164 case ARC_BUILTIN_MUL64:
5165 icode = CODE_FOR_mul64;
5166 arg0 = CALL_EXPR_ARG (exp, 0);
5167 arg1 = CALL_EXPR_ARG (exp, 1);
5168 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5169 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5171 mode0 = insn_data[icode].operand[0].mode;
5172 mode1 = insn_data[icode].operand[1].mode;
5174 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
5175 op0 = copy_to_mode_reg (mode0, op0);
5177 if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
5178 op1 = copy_to_mode_reg (mode1, op1);
5180 emit_insn (gen_mul64 (op0,op1));
5181 return NULL_RTX;
5183 case ARC_BUILTIN_MULU64:
5184 icode = CODE_FOR_mulu64;
5185 arg0 = CALL_EXPR_ARG (exp, 0);
5186 arg1 = CALL_EXPR_ARG (exp, 1);
5187 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5188 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5190 mode0 = insn_data[icode].operand[0].mode;
5191 mode1 = insn_data[icode].operand[1].mode;
5193 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
5194 op0 = copy_to_mode_reg (mode0, op0);
5196 if (! (*insn_data[icode].operand[0].predicate) (op1, mode1))
5197 op1 = copy_to_mode_reg (mode1, op1);
5199 emit_insn (gen_mulu64 (op0,op1));
5200 return NULL_RTX;
5202 case ARC_BUILTIN_RTIE:
5203 icode = CODE_FOR_rtie;
5204 emit_insn (gen_rtie (const1_rtx));
5205 return NULL_RTX;
5207 case ARC_BUILTIN_SYNC:
5208 icode = CODE_FOR_sync;
5209 emit_insn (gen_sync (const1_rtx));
5210 return NULL_RTX;
5212 case ARC_BUILTIN_SWAP:
5213 icode = CODE_FOR_swap;
5214 arg0 = CALL_EXPR_ARG (exp, 0);
5215 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5216 mode0 = insn_data[icode].operand[1].mode;
5217 target = gen_reg_rtx (SImode);
5219 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5220 op0 = copy_to_mode_reg (mode0, op0);
5222 emit_insn (gen_swap (target, op0));
5223 return target;
5225 case ARC_BUILTIN_DIVAW:
5226 icode = CODE_FOR_divaw;
5227 arg0 = CALL_EXPR_ARG (exp, 0);
5228 arg1 = CALL_EXPR_ARG (exp, 1);
5230 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5231 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5232 target = gen_reg_rtx (SImode);
5234 mode0 = insn_data[icode].operand[0].mode;
5235 mode1 = insn_data[icode].operand[1].mode;
5237 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
5238 op0 = copy_to_mode_reg (mode0, op0);
5240 if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
5241 op1 = copy_to_mode_reg (mode1, op1);
5243 emit_insn (gen_divaw (target, op0, op1));
5244 return target;
5246 case ARC_BUILTIN_BRK:
5247 icode = CODE_FOR_brk;
5248 emit_insn (gen_brk (const1_rtx));
5249 return NULL_RTX;
5251 case ARC_BUILTIN_SLEEP:
5252 icode = CODE_FOR_sleep;
5253 arg0 = CALL_EXPR_ARG (exp, 0);
5255 fold (arg0);
5257 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5258 mode0 = insn_data[icode].operand[1].mode;
5260 emit_insn (gen_sleep (op0));
5261 return NULL_RTX;
5263 case ARC_BUILTIN_SWI:
5264 icode = CODE_FOR_swi;
5265 emit_insn (gen_swi (const1_rtx));
5266 return NULL_RTX;
5268 case ARC_BUILTIN_FLAG:
5269 icode = CODE_FOR_flag;
5270 arg0 = CALL_EXPR_ARG (exp, 0);
5271 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5272 mode0 = insn_data[icode].operand[0].mode;
5274 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
5275 op0 = copy_to_mode_reg (mode0, op0);
5277 emit_insn (gen_flag (op0));
5278 return NULL_RTX;
5280 case ARC_BUILTIN_CORE_READ:
5281 icode = CODE_FOR_core_read;
5282 arg0 = CALL_EXPR_ARG (exp, 0);
5283 target = gen_reg_rtx (SImode);
5285 fold (arg0);
5287 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5288 mode0 = insn_data[icode].operand[1].mode;
5290 emit_insn (gen_core_read (target, op0));
5291 return target;
5293 case ARC_BUILTIN_CORE_WRITE:
5294 icode = CODE_FOR_core_write;
5295 arg0 = CALL_EXPR_ARG (exp, 0);
5296 arg1 = CALL_EXPR_ARG (exp, 1);
5298 fold (arg1);
5300 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5301 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5303 mode0 = insn_data[icode].operand[0].mode;
5304 mode1 = insn_data[icode].operand[1].mode;
5306 emit_insn (gen_core_write (op0, op1));
5307 return NULL_RTX;
5309 case ARC_BUILTIN_LR:
5310 icode = CODE_FOR_lr;
5311 arg0 = CALL_EXPR_ARG (exp, 0);
5312 target = gen_reg_rtx (SImode);
5314 fold (arg0);
5316 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5317 mode0 = insn_data[icode].operand[1].mode;
5319 emit_insn (gen_lr (target, op0));
5320 return target;
5322 case ARC_BUILTIN_SR:
5323 icode = CODE_FOR_sr;
5324 arg0 = CALL_EXPR_ARG (exp, 0);
5325 arg1 = CALL_EXPR_ARG (exp, 1);
5327 fold (arg1);
5329 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5330 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5332 mode0 = insn_data[icode].operand[0].mode;
5333 mode1 = insn_data[icode].operand[1].mode;
5335 emit_insn (gen_sr (op0, op1));
5336 return NULL_RTX;
5338 case ARC_BUILTIN_TRAP_S:
5339 icode = CODE_FOR_trap_s;
5340 arg0 = CALL_EXPR_ARG (exp, 0);
5342 fold (arg0);
5344 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5345 mode0 = insn_data[icode].operand[1].mode;
5347 /* We don't give an error for non-cost values here because
5348 we still want to allow things to be fixed up by later inlining /
5349 constant folding / dead code elimination. */
5350 if (CONST_INT_P (op0) && !satisfies_constraint_L (op0))
5352 /* Keep this message in sync with the one in arc.md:trap_s,
5353 because *.md files don't get scanned by exgettext. */
5354 error ("operand to trap_s should be an unsigned 6-bit value");
5356 emit_insn (gen_trap_s (op0));
5357 return NULL_RTX;
5359 case ARC_BUILTIN_UNIMP_S:
5360 icode = CODE_FOR_unimp_s;
5361 emit_insn (gen_unimp_s (const1_rtx));
5362 return NULL_RTX;
5364 case ARC_BUILTIN_ALIGNED:
5365 /* __builtin_arc_aligned (void* val, int alignval) */
5366 arg0 = CALL_EXPR_ARG (exp, 0);
5367 arg1 = CALL_EXPR_ARG (exp, 1);
5368 fold (arg1);
5369 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5370 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5371 target = gen_reg_rtx (SImode);
5373 if (!CONST_INT_P (op1))
5375 /* If we can't fold the alignment to a constant integer
5376 whilst optimizing, this is probably a user error. */
5377 if (optimize)
5378 warning (0, "__builtin_arc_aligned with non-constant alignment");
5380 else
5382 HOST_WIDE_INT alignTest = INTVAL (op1);
5383 /* Check alignTest is positive, and a power of two. */
5384 if (alignTest <= 0 || alignTest != (alignTest & -alignTest))
5386 error ("invalid alignment value for __builtin_arc_aligned");
5387 return NULL_RTX;
5390 if (CONST_INT_P (op0))
5392 HOST_WIDE_INT pnt = INTVAL (op0);
5394 if ((pnt & (alignTest - 1)) == 0)
5395 return const1_rtx;
5397 else
5399 unsigned align = get_pointer_alignment (arg0);
5400 unsigned numBits = alignTest * BITS_PER_UNIT;
5402 if (align && align >= numBits)
5403 return const1_rtx;
5404 /* Another attempt to ascertain alignment. Check the type
5405 we are pointing to. */
5406 if (POINTER_TYPE_P (TREE_TYPE (arg0))
5407 && TYPE_ALIGN (TREE_TYPE (TREE_TYPE (arg0))) >= numBits)
5408 return const1_rtx;
5412 /* Default to false. */
5413 return const0_rtx;
5415 default:
5416 break;
5419 /* @@@ Should really do something sensible here. */
5420 return NULL_RTX;
5423 /* Returns true if the operands[opno] is a valid compile-time constant to be
5424 used as register number in the code for builtins. Else it flags an error
5425 and returns false. */
5427 bool
5428 check_if_valid_regno_const (rtx *operands, int opno)
5431 switch (GET_CODE (operands[opno]))
5433 case SYMBOL_REF :
5434 case CONST :
5435 case CONST_INT :
5436 return true;
5437 default:
5438 error ("register number must be a compile-time constant. Try giving higher optimization levels");
5439 break;
5441 return false;
5444 /* Check that after all the constant folding, whether the operand to
5445 __builtin_arc_sleep is an unsigned int of 6 bits. If not, flag an error. */
5447 bool
5448 check_if_valid_sleep_operand (rtx *operands, int opno)
5450 switch (GET_CODE (operands[opno]))
5452 case CONST :
5453 case CONST_INT :
5454 if( UNSIGNED_INT6 (INTVAL (operands[opno])))
5455 return true;
5456 default:
5457 fatal_error("operand for sleep instruction must be an unsigned 6 bit compile-time constant");
5458 break;
5460 return false;
5463 /* Return true if it is ok to make a tail-call to DECL. */
5465 static bool
5466 arc_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
5467 tree exp ATTRIBUTE_UNUSED)
5469 /* Never tailcall from an ISR routine - it needs a special exit sequence. */
5470 if (ARC_INTERRUPT_P (arc_compute_function_type (cfun)))
5471 return false;
5473 /* Everything else is ok. */
5474 return true;
5477 /* Output code to add DELTA to the first argument, and then jump
5478 to FUNCTION. Used for C++ multiple inheritance. */
5480 static void
5481 arc_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
5482 HOST_WIDE_INT delta,
5483 HOST_WIDE_INT vcall_offset,
5484 tree function)
5486 int mi_delta = delta;
5487 const char *const mi_op = mi_delta < 0 ? "sub" : "add";
5488 int shift = 0;
5489 int this_regno
5490 = aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function) ? 1 : 0;
5491 rtx fnaddr;
5493 if (mi_delta < 0)
5494 mi_delta = - mi_delta;
5496 /* Add DELTA. When possible use a plain add, otherwise load it into
5497 a register first. */
5499 while (mi_delta != 0)
5501 if ((mi_delta & (3 << shift)) == 0)
5502 shift += 2;
5503 else
5505 asm_fprintf (file, "\t%s\t%s, %s, %d\n",
5506 mi_op, reg_names[this_regno], reg_names[this_regno],
5507 mi_delta & (0xff << shift));
5508 mi_delta &= ~(0xff << shift);
5509 shift += 8;
5513 /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
5514 if (vcall_offset != 0)
5516 /* ld r12,[this] --> temp = *this
5517 add r12,r12,vcall_offset --> temp = *(*this + vcall_offset)
5518 ld r12,[r12]
5519 add this,this,r12 --> this+ = *(*this + vcall_offset) */
5520 asm_fprintf (file, "\tld\t%s, [%s]\n",
5521 ARC_TEMP_SCRATCH_REG, reg_names[this_regno]);
5522 asm_fprintf (file, "\tadd\t%s, %s, %ld\n",
5523 ARC_TEMP_SCRATCH_REG, ARC_TEMP_SCRATCH_REG, vcall_offset);
5524 asm_fprintf (file, "\tld\t%s, [%s]\n",
5525 ARC_TEMP_SCRATCH_REG, ARC_TEMP_SCRATCH_REG);
5526 asm_fprintf (file, "\tadd\t%s, %s, %s\n", reg_names[this_regno],
5527 reg_names[this_regno], ARC_TEMP_SCRATCH_REG);
5530 fnaddr = XEXP (DECL_RTL (function), 0);
5532 if (arc_is_longcall_p (fnaddr))
5533 fputs ("\tj\t", file);
5534 else
5535 fputs ("\tb\t", file);
5536 assemble_name (file, XSTR (fnaddr, 0));
5537 fputc ('\n', file);
5540 /* Return true if a 32 bit "long_call" should be generated for
5541 this calling SYM_REF. We generate a long_call if the function:
5543 a. has an __attribute__((long call))
5544 or b. the -mlong-calls command line switch has been specified
5546 However we do not generate a long call if the function has an
5547 __attribute__ ((short_call)) or __attribute__ ((medium_call))
5549 This function will be called by C fragments contained in the machine
5550 description file. */
5552 bool
5553 arc_is_longcall_p (rtx sym_ref)
5555 if (GET_CODE (sym_ref) != SYMBOL_REF)
5556 return false;
5558 return (SYMBOL_REF_LONG_CALL_P (sym_ref)
5559 || (TARGET_LONG_CALLS_SET
5560 && !SYMBOL_REF_SHORT_CALL_P (sym_ref)
5561 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref)));
5565 /* Likewise for short calls. */
5567 bool
5568 arc_is_shortcall_p (rtx sym_ref)
5570 if (GET_CODE (sym_ref) != SYMBOL_REF)
5571 return false;
5573 return (SYMBOL_REF_SHORT_CALL_P (sym_ref)
5574 || (!TARGET_LONG_CALLS_SET && !TARGET_MEDIUM_CALLS
5575 && !SYMBOL_REF_LONG_CALL_P (sym_ref)
5576 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref)));
5580 /* Emit profiling code for calling CALLEE. Return true if a special
5581 call pattern needs to be generated. */
5583 bool
5584 arc_profile_call (rtx callee)
5586 rtx from = XEXP (DECL_RTL (current_function_decl), 0);
5588 if (TARGET_UCB_MCOUNT)
5589 /* Profiling is done by instrumenting the callee. */
5590 return false;
5592 if (CONSTANT_P (callee))
5594 rtx count_ptr
5595 = gen_rtx_CONST (Pmode,
5596 gen_rtx_UNSPEC (Pmode,
5597 gen_rtvec (3, from, callee,
5598 CONST0_RTX (Pmode)),
5599 UNSPEC_PROF));
5600 rtx counter = gen_rtx_MEM (SImode, count_ptr);
5601 /* ??? The increment would better be done atomically, but as there is
5602 no proper hardware support, that would be too expensive. */
5603 emit_move_insn (counter,
5604 force_reg (SImode, plus_constant (SImode, counter, 1)));
5605 return false;
5607 else
5609 rtx count_list_ptr
5610 = gen_rtx_CONST (Pmode,
5611 gen_rtx_UNSPEC (Pmode,
5612 gen_rtvec (3, from, CONST0_RTX (Pmode),
5613 CONST0_RTX (Pmode)),
5614 UNSPEC_PROF));
5615 emit_move_insn (gen_rtx_REG (Pmode, 8), count_list_ptr);
5616 emit_move_insn (gen_rtx_REG (Pmode, 9), callee);
5617 return true;
5621 /* Worker function for TARGET_RETURN_IN_MEMORY. */
5623 static bool
5624 arc_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
5626 if (AGGREGATE_TYPE_P (type) || TREE_ADDRESSABLE (type))
5627 return true;
5628 else
5630 HOST_WIDE_INT size = int_size_in_bytes (type);
5631 return (size == -1 || size > 8);
5636 /* This was in rtlanal.c, and can go in there when we decide we want
5637 to submit the change for inclusion in the GCC tree. */
5638 /* Like note_stores, but allow the callback to have side effects on the rtl
5639 (like the note_stores of yore):
5640 Call FUN on each register or MEM that is stored into or clobbered by X.
5641 (X would be the pattern of an insn). DATA is an arbitrary pointer,
5642 ignored by note_stores, but passed to FUN.
5643 FUN may alter parts of the RTL.
5645 FUN receives three arguments:
5646 1. the REG, MEM, CC0 or PC being stored in or clobbered,
5647 2. the SET or CLOBBER rtx that does the store,
5648 3. the pointer DATA provided to note_stores.
5650 If the item being stored in or clobbered is a SUBREG of a hard register,
5651 the SUBREG will be passed. */
5653 /* For now. */ static
5654 void
5655 walk_stores (rtx x, void (*fun) (rtx, rtx, void *), void *data)
5657 int i;
5659 if (GET_CODE (x) == COND_EXEC)
5660 x = COND_EXEC_CODE (x);
5662 if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
5664 rtx dest = SET_DEST (x);
5666 while ((GET_CODE (dest) == SUBREG
5667 && (!REG_P (SUBREG_REG (dest))
5668 || REGNO (SUBREG_REG (dest)) >= FIRST_PSEUDO_REGISTER))
5669 || GET_CODE (dest) == ZERO_EXTRACT
5670 || GET_CODE (dest) == STRICT_LOW_PART)
5671 dest = XEXP (dest, 0);
5673 /* If we have a PARALLEL, SET_DEST is a list of EXPR_LIST expressions,
5674 each of whose first operand is a register. */
5675 if (GET_CODE (dest) == PARALLEL)
5677 for (i = XVECLEN (dest, 0) - 1; i >= 0; i--)
5678 if (XEXP (XVECEXP (dest, 0, i), 0) != 0)
5679 (*fun) (XEXP (XVECEXP (dest, 0, i), 0), x, data);
5681 else
5682 (*fun) (dest, x, data);
5685 else if (GET_CODE (x) == PARALLEL)
5686 for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
5687 walk_stores (XVECEXP (x, 0, i), fun, data);
5690 static bool
5691 arc_pass_by_reference (cumulative_args_t ca_v ATTRIBUTE_UNUSED,
5692 enum machine_mode mode ATTRIBUTE_UNUSED,
5693 const_tree type,
5694 bool named ATTRIBUTE_UNUSED)
5696 return (type != 0
5697 && (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
5698 || TREE_ADDRESSABLE (type)));
5701 /* Implement TARGET_CAN_USE_DOLOOP_P. */
5703 static bool
5704 arc_can_use_doloop_p (const widest_int &iterations, const widest_int &,
5705 unsigned int loop_depth, bool entered_at_top)
5707 if (loop_depth > 1)
5708 return false;
5709 /* Setting up the loop with two sr instructions costs 6 cycles. */
5710 if (TARGET_ARC700
5711 && !entered_at_top
5712 && wi::gtu_p (iterations, 0)
5713 && wi::leu_p (iterations, flag_pic ? 6 : 3))
5714 return false;
5715 return true;
5718 /* NULL if INSN insn is valid within a low-overhead loop.
5719 Otherwise return why doloop cannot be applied. */
5721 static const char *
5722 arc_invalid_within_doloop (const_rtx insn)
5724 if (CALL_P (insn))
5725 return "Function call in the loop.";
5726 return NULL;
5729 static int arc_reorg_in_progress = 0;
5731 /* ARC's machince specific reorg function. */
5733 static void
5734 arc_reorg (void)
5736 rtx insn, pattern;
5737 rtx pc_target;
5738 long offset;
5739 int changed;
5741 cfun->machine->arc_reorg_started = 1;
5742 arc_reorg_in_progress = 1;
5744 /* Emit special sections for profiling. */
5745 if (crtl->profile)
5747 section *save_text_section;
5748 rtx insn;
5749 int size = get_max_uid () >> 4;
5750 htab_t htab = htab_create (size, unspec_prof_hash, unspec_prof_htab_eq,
5751 NULL);
5753 save_text_section = in_section;
5754 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5755 if (NONJUMP_INSN_P (insn))
5756 walk_stores (PATTERN (insn), write_profile_sections, htab);
5757 if (htab_elements (htab))
5758 in_section = 0;
5759 switch_to_section (save_text_section);
5760 htab_delete (htab);
5763 /* Link up loop ends with their loop start. */
5765 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5766 if (GET_CODE (insn) == JUMP_INSN
5767 && recog_memoized (insn) == CODE_FOR_doloop_end_i)
5769 rtx top_label
5770 = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0);
5771 rtx num = GEN_INT (CODE_LABEL_NUMBER (top_label));
5772 rtx lp, prev = prev_nonnote_insn (top_label);
5773 rtx lp_simple = NULL_RTX;
5774 rtx next = NULL_RTX;
5775 rtx op0 = XEXP (XVECEXP (PATTERN (insn), 0, 1), 0);
5776 HOST_WIDE_INT loop_end_id
5777 = -INTVAL (XEXP (XVECEXP (PATTERN (insn), 0, 4), 0));
5778 int seen_label = 0;
5780 for (lp = prev;
5781 (lp && NONJUMP_INSN_P (lp)
5782 && recog_memoized (lp) != CODE_FOR_doloop_begin_i);
5783 lp = prev_nonnote_insn (lp))
5785 if (!lp || !NONJUMP_INSN_P (lp)
5786 || dead_or_set_regno_p (lp, LP_COUNT))
5788 for (prev = next = insn, lp = NULL_RTX ; prev || next;)
5790 if (prev)
5792 if (NONJUMP_INSN_P (prev)
5793 && recog_memoized (prev) == CODE_FOR_doloop_begin_i
5794 && (INTVAL (XEXP (XVECEXP (PATTERN (prev), 0, 5), 0))
5795 == loop_end_id))
5797 lp = prev;
5798 break;
5800 else if (LABEL_P (prev))
5801 seen_label = 1;
5802 prev = prev_nonnote_insn (prev);
5804 if (next)
5806 if (NONJUMP_INSN_P (next)
5807 && recog_memoized (next) == CODE_FOR_doloop_begin_i
5808 && (INTVAL (XEXP (XVECEXP (PATTERN (next), 0, 5), 0))
5809 == loop_end_id))
5811 lp = next;
5812 break;
5814 next = next_nonnote_insn (next);
5817 prev = NULL_RTX;
5819 else
5820 lp_simple = lp;
5821 if (lp && !dead_or_set_regno_p (lp, LP_COUNT))
5823 rtx begin_cnt = XEXP (XVECEXP (PATTERN (lp), 0 ,3), 0);
5824 if (INTVAL (XEXP (XVECEXP (PATTERN (lp), 0, 4), 0)))
5825 /* The loop end insn has been duplicated. That can happen
5826 when there is a conditional block at the very end of
5827 the loop. */
5828 goto failure;
5829 /* If Register allocation failed to allocate to the right
5830 register, There is no point into teaching reload to
5831 fix this up with reloads, as that would cost more
5832 than using an ordinary core register with the
5833 doloop_fallback pattern. */
5834 if ((true_regnum (op0) != LP_COUNT || !REG_P (begin_cnt))
5835 /* Likewise, if the loop setup is evidently inside the loop,
5836 we loose. */
5837 || (!lp_simple && lp != next && !seen_label))
5839 remove_insn (lp);
5840 goto failure;
5842 /* It is common that the optimizers copy the loop count from
5843 another register, and doloop_begin_i is stuck with the
5844 source of the move. Making doloop_begin_i only accept "l"
5845 is nonsentical, as this then makes reload evict the pseudo
5846 used for the loop end. The underlying cause is that the
5847 optimizers don't understand that the register allocation for
5848 doloop_begin_i should be treated as part of the loop.
5849 Try to work around this problem by verifying the previous
5850 move exists. */
5851 if (true_regnum (begin_cnt) != LP_COUNT)
5853 rtx mov, set, note;
5855 for (mov = prev_nonnote_insn (lp); mov;
5856 mov = prev_nonnote_insn (mov))
5858 if (!NONJUMP_INSN_P (mov))
5859 mov = 0;
5860 else if ((set = single_set (mov))
5861 && rtx_equal_p (SET_SRC (set), begin_cnt)
5862 && rtx_equal_p (SET_DEST (set), op0))
5863 break;
5865 if (mov)
5867 XEXP (XVECEXP (PATTERN (lp), 0 ,3), 0) = op0;
5868 note = find_regno_note (lp, REG_DEAD, REGNO (begin_cnt));
5869 if (note)
5870 remove_note (lp, note);
5872 else
5874 remove_insn (lp);
5875 goto failure;
5878 XEXP (XVECEXP (PATTERN (insn), 0, 4), 0) = num;
5879 XEXP (XVECEXP (PATTERN (lp), 0, 4), 0) = num;
5880 if (next == lp)
5881 XEXP (XVECEXP (PATTERN (lp), 0, 6), 0) = const2_rtx;
5882 else if (!lp_simple)
5883 XEXP (XVECEXP (PATTERN (lp), 0, 6), 0) = const1_rtx;
5884 else if (prev != lp)
5886 remove_insn (lp);
5887 add_insn_after (lp, prev, NULL);
5889 if (!lp_simple)
5891 XEXP (XVECEXP (PATTERN (lp), 0, 7), 0)
5892 = gen_rtx_LABEL_REF (Pmode, top_label);
5893 add_reg_note (lp, REG_LABEL_OPERAND, top_label);
5894 LABEL_NUSES (top_label)++;
5896 /* We can avoid tedious loop start / end setting for empty loops
5897 be merely setting the loop count to its final value. */
5898 if (next_active_insn (top_label) == insn)
5900 rtx lc_set
5901 = gen_rtx_SET (VOIDmode,
5902 XEXP (XVECEXP (PATTERN (lp), 0, 3), 0),
5903 const0_rtx);
5905 lc_set = emit_insn_before (lc_set, insn);
5906 delete_insn (lp);
5907 delete_insn (insn);
5908 insn = lc_set;
5910 /* If the loop is non-empty with zero length, we can't make it
5911 a zero-overhead loop. That can happen for empty asms. */
5912 else
5914 rtx scan;
5916 for (scan = top_label;
5917 (scan && scan != insn
5918 && (!NONJUMP_INSN_P (scan) || !get_attr_length (scan)));
5919 scan = NEXT_INSN (scan));
5920 if (scan == insn)
5922 remove_insn (lp);
5923 goto failure;
5927 else
5929 /* Sometimes the loop optimizer makes a complete hash of the
5930 loop. If it were only that the loop is not entered at the
5931 top, we could fix this up by setting LP_START with SR .
5932 However, if we can't find the loop begin were it should be,
5933 chances are that it does not even dominate the loop, but is
5934 inside the loop instead. Using SR there would kill
5935 performance.
5936 We use the doloop_fallback pattern here, which executes
5937 in two cycles on the ARC700 when predicted correctly. */
5938 failure:
5939 if (!REG_P (op0))
5941 rtx op3 = XEXP (XVECEXP (PATTERN (insn), 0, 5), 0);
5943 emit_insn_before (gen_move_insn (op3, op0), insn);
5944 PATTERN (insn)
5945 = gen_doloop_fallback_m (op3, JUMP_LABEL (insn), op0);
5947 else
5948 XVEC (PATTERN (insn), 0)
5949 = gen_rtvec (2, XVECEXP (PATTERN (insn), 0, 0),
5950 XVECEXP (PATTERN (insn), 0, 1));
5951 INSN_CODE (insn) = -1;
5956 /* FIXME: should anticipate ccfsm action, generate special patterns for
5957 to-be-deleted branches that have no delay slot and have at least the
5958 length of the size increase forced on other insns that are conditionalized.
5959 This can also have an insn_list inside that enumerates insns which are
5960 not actually conditionalized because the destinations are dead in the
5961 not-execute case.
5962 Could also tag branches that we want to be unaligned if they get no delay
5963 slot, or even ones that we don't want to do delay slot sheduling for
5964 because we can unalign them.
5966 However, there are cases when conditional execution is only possible after
5967 delay slot scheduling:
5969 - If a delay slot is filled with a nocond/set insn from above, the previous
5970 basic block can become elegible for conditional execution.
5971 - If a delay slot is filled with a nocond insn from the fall-through path,
5972 the branch with that delay slot can become eligble for conditional
5973 execution (however, with the same sort of data flow analysis that dbr
5974 does, we could have figured out before that we don't need to
5975 conditionalize this insn.)
5976 - If a delay slot insn is filled with an insn from the target, the
5977 target label gets its uses decremented (even deleted if falling to zero),
5978 thus possibly creating more condexec opportunities there.
5979 Therefore, we should still be prepared to apply condexec optimization on
5980 non-prepared branches if the size increase of conditionalized insns is no
5981 more than the size saved from eliminating the branch. An invocation option
5982 could also be used to reserve a bit of extra size for condbranches so that
5983 this'll work more often (could also test in arc_reorg if the block is
5984 'close enough' to be eligible for condexec to make this likely, and
5985 estimate required size increase). */
5986 /* Generate BRcc insns, by combining cmp and Bcc insns wherever possible. */
5987 if (TARGET_NO_BRCC_SET)
5988 return;
5992 init_insn_lengths();
5993 changed = 0;
5995 if (optimize > 1 && !TARGET_NO_COND_EXEC)
5997 arc_ifcvt ();
5998 unsigned int flags = pass_data_arc_ifcvt.todo_flags_finish;
5999 df_finish_pass ((flags & TODO_df_verify) != 0);
6002 /* Call shorten_branches to calculate the insn lengths. */
6003 shorten_branches (get_insns());
6004 cfun->machine->ccfsm_current_insn = NULL_RTX;
6006 if (!INSN_ADDRESSES_SET_P())
6007 fatal_error ("Insn addresses not set after shorten_branches");
6009 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
6011 rtx label;
6012 enum attr_type insn_type;
6014 /* If a non-jump insn (or a casesi jump table), continue. */
6015 if (GET_CODE (insn) != JUMP_INSN ||
6016 GET_CODE (PATTERN (insn)) == ADDR_VEC
6017 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
6018 continue;
6020 /* If we already have a brcc, note if it is suitable for brcc_s.
6021 Be a bit generous with the brcc_s range so that we can take
6022 advantage of any code shortening from delay slot scheduling. */
6023 if (recog_memoized (insn) == CODE_FOR_cbranchsi4_scratch)
6025 rtx pat = PATTERN (insn);
6026 rtx op = XEXP (SET_SRC (XVECEXP (pat, 0, 0)), 0);
6027 rtx *ccp = &XEXP (XVECEXP (pat, 0, 1), 0);
6029 offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
6030 if ((offset >= -140 && offset < 140)
6031 && rtx_equal_p (XEXP (op, 1), const0_rtx)
6032 && compact_register_operand (XEXP (op, 0), VOIDmode)
6033 && equality_comparison_operator (op, VOIDmode))
6034 PUT_MODE (*ccp, CC_Zmode);
6035 else if (GET_MODE (*ccp) == CC_Zmode)
6036 PUT_MODE (*ccp, CC_ZNmode);
6037 continue;
6039 if ((insn_type = get_attr_type (insn)) == TYPE_BRCC
6040 || insn_type == TYPE_BRCC_NO_DELAY_SLOT)
6041 continue;
6043 /* OK. so we have a jump insn. */
6044 /* We need to check that it is a bcc. */
6045 /* Bcc => set (pc) (if_then_else ) */
6046 pattern = PATTERN (insn);
6047 if (GET_CODE (pattern) != SET
6048 || GET_CODE (SET_SRC (pattern)) != IF_THEN_ELSE
6049 || ANY_RETURN_P (XEXP (SET_SRC (pattern), 1)))
6050 continue;
6052 /* Now check if the jump is beyond the s9 range. */
6053 if (CROSSING_JUMP_P (insn))
6054 continue;
6055 offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
6057 if(offset > 253 || offset < -254)
6058 continue;
6060 pc_target = SET_SRC (pattern);
6062 /* Now go back and search for the set cc insn. */
6064 label = XEXP (pc_target, 1);
6067 rtx pat, scan, link_insn = NULL;
6069 for (scan = PREV_INSN (insn);
6070 scan && GET_CODE (scan) != CODE_LABEL;
6071 scan = PREV_INSN (scan))
6073 if (! INSN_P (scan))
6074 continue;
6075 pat = PATTERN (scan);
6076 if (GET_CODE (pat) == SET
6077 && cc_register (SET_DEST (pat), VOIDmode))
6079 link_insn = scan;
6080 break;
6083 if (! link_insn)
6084 continue;
6085 else
6086 /* Check if this is a data dependency. */
6088 rtx op, cc_clob_rtx, op0, op1, brcc_insn, note;
6089 rtx cmp0, cmp1;
6091 /* Ok this is the set cc. copy args here. */
6092 op = XEXP (pc_target, 0);
6094 op0 = cmp0 = XEXP (SET_SRC (pat), 0);
6095 op1 = cmp1 = XEXP (SET_SRC (pat), 1);
6096 if (GET_CODE (op0) == ZERO_EXTRACT
6097 && XEXP (op0, 1) == const1_rtx
6098 && (GET_CODE (op) == EQ
6099 || GET_CODE (op) == NE))
6101 /* btst / b{eq,ne} -> bbit{0,1} */
6102 op0 = XEXP (cmp0, 0);
6103 op1 = XEXP (cmp0, 2);
6105 else if (!register_operand (op0, VOIDmode)
6106 || !general_operand (op1, VOIDmode))
6107 continue;
6108 /* Be careful not to break what cmpsfpx_raw is
6109 trying to create for checking equality of
6110 single-precision floats. */
6111 else if (TARGET_SPFP
6112 && GET_MODE (op0) == SFmode
6113 && GET_MODE (op1) == SFmode)
6114 continue;
6116 /* None of the two cmp operands should be set between the
6117 cmp and the branch. */
6118 if (reg_set_between_p (op0, link_insn, insn))
6119 continue;
6121 if (reg_set_between_p (op1, link_insn, insn))
6122 continue;
6124 /* Since the MODE check does not work, check that this is
6125 CC reg's last set location before insn, and also no
6126 instruction between the cmp and branch uses the
6127 condition codes. */
6128 if ((reg_set_between_p (SET_DEST (pat), link_insn, insn))
6129 || (reg_used_between_p (SET_DEST (pat), link_insn, insn)))
6130 continue;
6132 /* CC reg should be dead after insn. */
6133 if (!find_regno_note (insn, REG_DEAD, CC_REG))
6134 continue;
6136 op = gen_rtx_fmt_ee (GET_CODE (op),
6137 GET_MODE (op), cmp0, cmp1);
6138 /* If we create a LIMM where there was none before,
6139 we only benefit if we can avoid a scheduling bubble
6140 for the ARC600. Otherwise, we'd only forgo chances
6141 at short insn generation, and risk out-of-range
6142 branches. */
6143 if (!brcc_nolimm_operator (op, VOIDmode)
6144 && !long_immediate_operand (op1, VOIDmode)
6145 && (TARGET_ARC700
6146 || next_active_insn (link_insn) != insn))
6147 continue;
6149 /* Emit bbit / brcc (or brcc_s if possible).
6150 CC_Zmode indicates that brcc_s is possible. */
6152 if (op0 != cmp0)
6153 cc_clob_rtx = gen_rtx_REG (CC_ZNmode, CC_REG);
6154 else if ((offset >= -140 && offset < 140)
6155 && rtx_equal_p (op1, const0_rtx)
6156 && compact_register_operand (op0, VOIDmode)
6157 && (GET_CODE (op) == EQ
6158 || GET_CODE (op) == NE))
6159 cc_clob_rtx = gen_rtx_REG (CC_Zmode, CC_REG);
6160 else
6161 cc_clob_rtx = gen_rtx_REG (CCmode, CC_REG);
6163 brcc_insn
6164 = gen_rtx_IF_THEN_ELSE (VOIDmode, op, label, pc_rtx);
6165 brcc_insn = gen_rtx_SET (VOIDmode, pc_rtx, brcc_insn);
6166 cc_clob_rtx = gen_rtx_CLOBBER (VOIDmode, cc_clob_rtx);
6167 brcc_insn
6168 = gen_rtx_PARALLEL
6169 (VOIDmode, gen_rtvec (2, brcc_insn, cc_clob_rtx));
6170 brcc_insn = emit_jump_insn_before (brcc_insn, insn);
6172 JUMP_LABEL (brcc_insn) = JUMP_LABEL (insn);
6173 note = find_reg_note (insn, REG_BR_PROB, 0);
6174 if (note)
6176 XEXP (note, 1) = REG_NOTES (brcc_insn);
6177 REG_NOTES (brcc_insn) = note;
6179 note = find_reg_note (link_insn, REG_DEAD, op0);
6180 if (note)
6182 remove_note (link_insn, note);
6183 XEXP (note, 1) = REG_NOTES (brcc_insn);
6184 REG_NOTES (brcc_insn) = note;
6186 note = find_reg_note (link_insn, REG_DEAD, op1);
6187 if (note)
6189 XEXP (note, 1) = REG_NOTES (brcc_insn);
6190 REG_NOTES (brcc_insn) = note;
6193 changed = 1;
6195 /* Delete the bcc insn. */
6196 set_insn_deleted (insn);
6198 /* Delete the cmp insn. */
6199 set_insn_deleted (link_insn);
6204 /* Clear out insn_addresses. */
6205 INSN_ADDRESSES_FREE ();
6207 } while (changed);
6209 if (INSN_ADDRESSES_SET_P())
6210 fatal_error ("insn addresses not freed");
6212 arc_reorg_in_progress = 0;
6215 /* Check if the operands are valid for BRcc.d generation
6216 Valid Brcc.d patterns are
6217 Brcc.d b, c, s9
6218 Brcc.d b, u6, s9
6220 For cc={GT, LE, GTU, LEU}, u6=63 can not be allowed,
6221 since they are encoded by the assembler as {GE, LT, HS, LS} 64, which
6222 does not have a delay slot
6224 Assumed precondition: Second operand is either a register or a u6 value. */
6226 bool
6227 valid_brcc_with_delay_p (rtx *operands)
6229 if (optimize_size && GET_MODE (operands[4]) == CC_Zmode)
6230 return false;
6231 return brcc_nolimm_operator (operands[0], VOIDmode);
6234 /* ??? Hack. This should no really be here. See PR32143. */
6235 static bool
6236 arc_decl_anon_ns_mem_p (const_tree decl)
6238 while (1)
6240 if (decl == NULL_TREE || decl == error_mark_node)
6241 return false;
6242 if (TREE_CODE (decl) == NAMESPACE_DECL
6243 && DECL_NAME (decl) == NULL_TREE)
6244 return true;
6245 /* Classes and namespaces inside anonymous namespaces have
6246 TREE_PUBLIC == 0, so we can shortcut the search. */
6247 else if (TYPE_P (decl))
6248 return (TREE_PUBLIC (TYPE_NAME (decl)) == 0);
6249 else if (TREE_CODE (decl) == NAMESPACE_DECL)
6250 return (TREE_PUBLIC (decl) == 0);
6251 else
6252 decl = DECL_CONTEXT (decl);
6256 /* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
6257 access DECL using %gp_rel(...)($gp). */
6259 static bool
6260 arc_in_small_data_p (const_tree decl)
6262 HOST_WIDE_INT size;
6264 if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL)
6265 return false;
6268 /* We don't yet generate small-data references for -mabicalls. See related
6269 -G handling in override_options. */
6270 if (TARGET_NO_SDATA_SET)
6271 return false;
6273 if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0)
6275 const char *name;
6277 /* Reject anything that isn't in a known small-data section. */
6278 name = DECL_SECTION_NAME (decl);
6279 if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0)
6280 return false;
6282 /* If a symbol is defined externally, the assembler will use the
6283 usual -G rules when deciding how to implement macros. */
6284 if (!DECL_EXTERNAL (decl))
6285 return true;
6287 /* Only global variables go into sdata section for now. */
6288 else if (1)
6290 /* Don't put constants into the small data section: we want them
6291 to be in ROM rather than RAM. */
6292 if (TREE_CODE (decl) != VAR_DECL)
6293 return false;
6295 if (TREE_READONLY (decl)
6296 && !TREE_SIDE_EFFECTS (decl)
6297 && (!DECL_INITIAL (decl) || TREE_CONSTANT (DECL_INITIAL (decl))))
6298 return false;
6300 /* TREE_PUBLIC might change after the first call, because of the patch
6301 for PR19238. */
6302 if (default_binds_local_p_1 (decl, 1)
6303 || arc_decl_anon_ns_mem_p (decl))
6304 return false;
6306 /* To ensure -mvolatile-cache works
6307 ld.di does not have a gp-relative variant. */
6308 if (TREE_THIS_VOLATILE (decl))
6309 return false;
6312 /* Disable sdata references to weak variables. */
6313 if (DECL_WEAK (decl))
6314 return false;
6316 size = int_size_in_bytes (TREE_TYPE (decl));
6318 /* if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) */
6319 /* return false; */
6321 /* Allow only <=4B long data types into sdata. */
6322 return (size > 0 && size <= 4);
6325 /* Return true if X is a small data address that can be rewritten
6326 as a gp+symref. */
6328 static bool
6329 arc_rewrite_small_data_p (rtx x)
6331 if (GET_CODE (x) == CONST)
6332 x = XEXP (x, 0);
6334 if (GET_CODE (x) == PLUS)
6336 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
6337 x = XEXP (x, 0);
6340 return (GET_CODE (x) == SYMBOL_REF
6341 && SYMBOL_REF_SMALL_P(x));
6344 /* A for_each_rtx callback, used by arc_rewrite_small_data. */
6346 static int
6347 arc_rewrite_small_data_1 (rtx *loc, void *data)
6349 if (arc_rewrite_small_data_p (*loc))
6351 rtx top;
6353 gcc_assert (SDATA_BASE_REGNUM == PIC_OFFSET_TABLE_REGNUM);
6354 *loc = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, *loc);
6355 if (loc == data)
6356 return -1;
6357 top = *(rtx*) data;
6358 if (GET_CODE (top) == MEM && &XEXP (top, 0) == loc)
6359 ; /* OK. */
6360 else if (GET_CODE (top) == MEM
6361 && GET_CODE (XEXP (top, 0)) == PLUS
6362 && GET_CODE (XEXP (XEXP (top, 0), 0)) == MULT)
6363 *loc = force_reg (Pmode, *loc);
6364 else
6365 gcc_unreachable ();
6366 return -1;
6369 if (GET_CODE (*loc) == PLUS
6370 && rtx_equal_p (XEXP (*loc, 0), pic_offset_table_rtx))
6371 return -1;
6373 return 0;
6376 /* If possible, rewrite OP so that it refers to small data using
6377 explicit relocations. */
6380 arc_rewrite_small_data (rtx op)
6382 op = copy_insn (op);
6383 for_each_rtx (&op, arc_rewrite_small_data_1, &op);
6384 return op;
6387 /* A for_each_rtx callback for small_data_pattern. */
6389 static int
6390 small_data_pattern_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
6392 if (GET_CODE (*loc) == PLUS
6393 && rtx_equal_p (XEXP (*loc, 0), pic_offset_table_rtx))
6394 return -1;
6396 return arc_rewrite_small_data_p (*loc);
6399 /* Return true if OP refers to small data symbols directly, not through
6400 a PLUS. */
6402 bool
6403 small_data_pattern (rtx op, enum machine_mode)
6405 return (GET_CODE (op) != SEQUENCE
6406 && for_each_rtx (&op, small_data_pattern_1, 0));
6409 /* Return true if OP is an acceptable memory operand for ARCompact
6410 16-bit gp-relative load instructions.
6411 op shd look like : [r26, symref@sda]
6412 i.e. (mem (plus (reg 26) (symref with smalldata flag set))
6414 /* volatile cache option still to be handled. */
6416 bool
6417 compact_sda_memory_operand (rtx op, enum machine_mode mode)
6419 rtx addr;
6420 int size;
6422 /* Eliminate non-memory operations. */
6423 if (GET_CODE (op) != MEM)
6424 return false;
6426 if (mode == VOIDmode)
6427 mode = GET_MODE (op);
6429 size = GET_MODE_SIZE (mode);
6431 /* dword operations really put out 2 instructions, so eliminate them. */
6432 if (size > UNITS_PER_WORD)
6433 return false;
6435 /* Decode the address now. */
6436 addr = XEXP (op, 0);
6438 return LEGITIMATE_SMALL_DATA_ADDRESS_P (addr);
6441 /* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */
6443 void
6444 arc_asm_output_aligned_decl_local (FILE * stream, tree decl, const char * name,
6445 unsigned HOST_WIDE_INT size,
6446 unsigned HOST_WIDE_INT align,
6447 unsigned HOST_WIDE_INT globalize_p)
6449 int in_small_data = arc_in_small_data_p (decl);
6451 if (in_small_data)
6452 switch_to_section (get_named_section (NULL, ".sbss", 0));
6453 /* named_section (0,".sbss",0); */
6454 else
6455 switch_to_section (bss_section);
6457 if (globalize_p)
6458 (*targetm.asm_out.globalize_label) (stream, name);
6460 ASM_OUTPUT_ALIGN (stream, floor_log2 ((align) / BITS_PER_UNIT));
6461 ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "object");
6462 ASM_OUTPUT_SIZE_DIRECTIVE (stream, name, size);
6463 ASM_OUTPUT_LABEL (stream, name);
6465 if (size != 0)
6466 ASM_OUTPUT_SKIP (stream, size);
6502 /* SIMD builtins support. */
6503 enum simd_insn_args_type {
6504 Va_Vb_Vc,
6505 Va_Vb_rlimm,
6506 Va_Vb_Ic,
6507 Va_Vb_u6,
6508 Va_Vb_u8,
6509 Va_rlimm_u8,
6511 Va_Vb,
6513 void_rlimm,
6514 void_u6,
6516 Da_u3_rlimm,
6517 Da_rlimm_rlimm,
6519 Va_Ib_u8,
6520 void_Va_Ib_u8,
6522 Va_Vb_Ic_u8,
6523 void_Va_u3_Ib_u8
6526 struct builtin_description
6528 enum simd_insn_args_type args_type;
6529 const enum insn_code icode;
6530 const char * const name;
6531 const enum arc_builtins code;
6534 static const struct builtin_description arc_simd_builtin_desc_list[] =
6536 /* VVV builtins go first. */
6537 #define SIMD_BUILTIN(type, code, string, builtin) \
6538 { type,CODE_FOR_##code, "__builtin_arc_" string, \
6539 ARC_SIMD_BUILTIN_##builtin },
6541 SIMD_BUILTIN (Va_Vb_Vc, vaddaw_insn, "vaddaw", VADDAW)
6542 SIMD_BUILTIN (Va_Vb_Vc, vaddw_insn, "vaddw", VADDW)
6543 SIMD_BUILTIN (Va_Vb_Vc, vavb_insn, "vavb", VAVB)
6544 SIMD_BUILTIN (Va_Vb_Vc, vavrb_insn, "vavrb", VAVRB)
6545 SIMD_BUILTIN (Va_Vb_Vc, vdifaw_insn, "vdifaw", VDIFAW)
6546 SIMD_BUILTIN (Va_Vb_Vc, vdifw_insn, "vdifw", VDIFW)
6547 SIMD_BUILTIN (Va_Vb_Vc, vmaxaw_insn, "vmaxaw", VMAXAW)
6548 SIMD_BUILTIN (Va_Vb_Vc, vmaxw_insn, "vmaxw", VMAXW)
6549 SIMD_BUILTIN (Va_Vb_Vc, vminaw_insn, "vminaw", VMINAW)
6550 SIMD_BUILTIN (Va_Vb_Vc, vminw_insn, "vminw", VMINW)
6551 SIMD_BUILTIN (Va_Vb_Vc, vmulaw_insn, "vmulaw", VMULAW)
6552 SIMD_BUILTIN (Va_Vb_Vc, vmulfaw_insn, "vmulfaw", VMULFAW)
6553 SIMD_BUILTIN (Va_Vb_Vc, vmulfw_insn, "vmulfw", VMULFW)
6554 SIMD_BUILTIN (Va_Vb_Vc, vmulw_insn, "vmulw", VMULW)
6555 SIMD_BUILTIN (Va_Vb_Vc, vsubaw_insn, "vsubaw", VSUBAW)
6556 SIMD_BUILTIN (Va_Vb_Vc, vsubw_insn, "vsubw", VSUBW)
6557 SIMD_BUILTIN (Va_Vb_Vc, vsummw_insn, "vsummw", VSUMMW)
6558 SIMD_BUILTIN (Va_Vb_Vc, vand_insn, "vand", VAND)
6559 SIMD_BUILTIN (Va_Vb_Vc, vandaw_insn, "vandaw", VANDAW)
6560 SIMD_BUILTIN (Va_Vb_Vc, vbic_insn, "vbic", VBIC)
6561 SIMD_BUILTIN (Va_Vb_Vc, vbicaw_insn, "vbicaw", VBICAW)
6562 SIMD_BUILTIN (Va_Vb_Vc, vor_insn, "vor", VOR)
6563 SIMD_BUILTIN (Va_Vb_Vc, vxor_insn, "vxor", VXOR)
6564 SIMD_BUILTIN (Va_Vb_Vc, vxoraw_insn, "vxoraw", VXORAW)
6565 SIMD_BUILTIN (Va_Vb_Vc, veqw_insn, "veqw", VEQW)
6566 SIMD_BUILTIN (Va_Vb_Vc, vlew_insn, "vlew", VLEW)
6567 SIMD_BUILTIN (Va_Vb_Vc, vltw_insn, "vltw", VLTW)
6568 SIMD_BUILTIN (Va_Vb_Vc, vnew_insn, "vnew", VNEW)
6569 SIMD_BUILTIN (Va_Vb_Vc, vmr1aw_insn, "vmr1aw", VMR1AW)
6570 SIMD_BUILTIN (Va_Vb_Vc, vmr1w_insn, "vmr1w", VMR1W)
6571 SIMD_BUILTIN (Va_Vb_Vc, vmr2aw_insn, "vmr2aw", VMR2AW)
6572 SIMD_BUILTIN (Va_Vb_Vc, vmr2w_insn, "vmr2w", VMR2W)
6573 SIMD_BUILTIN (Va_Vb_Vc, vmr3aw_insn, "vmr3aw", VMR3AW)
6574 SIMD_BUILTIN (Va_Vb_Vc, vmr3w_insn, "vmr3w", VMR3W)
6575 SIMD_BUILTIN (Va_Vb_Vc, vmr4aw_insn, "vmr4aw", VMR4AW)
6576 SIMD_BUILTIN (Va_Vb_Vc, vmr4w_insn, "vmr4w", VMR4W)
6577 SIMD_BUILTIN (Va_Vb_Vc, vmr5aw_insn, "vmr5aw", VMR5AW)
6578 SIMD_BUILTIN (Va_Vb_Vc, vmr5w_insn, "vmr5w", VMR5W)
6579 SIMD_BUILTIN (Va_Vb_Vc, vmr6aw_insn, "vmr6aw", VMR6AW)
6580 SIMD_BUILTIN (Va_Vb_Vc, vmr6w_insn, "vmr6w", VMR6W)
6581 SIMD_BUILTIN (Va_Vb_Vc, vmr7aw_insn, "vmr7aw", VMR7AW)
6582 SIMD_BUILTIN (Va_Vb_Vc, vmr7w_insn, "vmr7w", VMR7W)
6583 SIMD_BUILTIN (Va_Vb_Vc, vmrb_insn, "vmrb", VMRB)
6584 SIMD_BUILTIN (Va_Vb_Vc, vh264f_insn, "vh264f", VH264F)
6585 SIMD_BUILTIN (Va_Vb_Vc, vh264ft_insn, "vh264ft", VH264FT)
6586 SIMD_BUILTIN (Va_Vb_Vc, vh264fw_insn, "vh264fw", VH264FW)
6587 SIMD_BUILTIN (Va_Vb_Vc, vvc1f_insn, "vvc1f", VVC1F)
6588 SIMD_BUILTIN (Va_Vb_Vc, vvc1ft_insn, "vvc1ft", VVC1FT)
6590 SIMD_BUILTIN (Va_Vb_rlimm, vbaddw_insn, "vbaddw", VBADDW)
6591 SIMD_BUILTIN (Va_Vb_rlimm, vbmaxw_insn, "vbmaxw", VBMAXW)
6592 SIMD_BUILTIN (Va_Vb_rlimm, vbminw_insn, "vbminw", VBMINW)
6593 SIMD_BUILTIN (Va_Vb_rlimm, vbmulaw_insn, "vbmulaw", VBMULAW)
6594 SIMD_BUILTIN (Va_Vb_rlimm, vbmulfw_insn, "vbmulfw", VBMULFW)
6595 SIMD_BUILTIN (Va_Vb_rlimm, vbmulw_insn, "vbmulw", VBMULW)
6596 SIMD_BUILTIN (Va_Vb_rlimm, vbrsubw_insn, "vbrsubw", VBRSUBW)
6597 SIMD_BUILTIN (Va_Vb_rlimm, vbsubw_insn, "vbsubw", VBSUBW)
6599 /* Va, Vb, Ic instructions. */
6600 SIMD_BUILTIN (Va_Vb_Ic, vasrw_insn, "vasrw", VASRW)
6601 SIMD_BUILTIN (Va_Vb_Ic, vsr8_insn, "vsr8", VSR8)
6602 SIMD_BUILTIN (Va_Vb_Ic, vsr8aw_insn, "vsr8aw", VSR8AW)
6604 /* Va, Vb, u6 instructions. */
6605 SIMD_BUILTIN (Va_Vb_u6, vasrrwi_insn, "vasrrwi", VASRRWi)
6606 SIMD_BUILTIN (Va_Vb_u6, vasrsrwi_insn, "vasrsrwi", VASRSRWi)
6607 SIMD_BUILTIN (Va_Vb_u6, vasrwi_insn, "vasrwi", VASRWi)
6608 SIMD_BUILTIN (Va_Vb_u6, vasrpwbi_insn, "vasrpwbi", VASRPWBi)
6609 SIMD_BUILTIN (Va_Vb_u6, vasrrpwbi_insn,"vasrrpwbi", VASRRPWBi)
6610 SIMD_BUILTIN (Va_Vb_u6, vsr8awi_insn, "vsr8awi", VSR8AWi)
6611 SIMD_BUILTIN (Va_Vb_u6, vsr8i_insn, "vsr8i", VSR8i)
6613 /* Va, Vb, u8 (simm) instructions. */
6614 SIMD_BUILTIN (Va_Vb_u8, vmvaw_insn, "vmvaw", VMVAW)
6615 SIMD_BUILTIN (Va_Vb_u8, vmvw_insn, "vmvw", VMVW)
6616 SIMD_BUILTIN (Va_Vb_u8, vmvzw_insn, "vmvzw", VMVZW)
6617 SIMD_BUILTIN (Va_Vb_u8, vd6tapf_insn, "vd6tapf", VD6TAPF)
6619 /* Va, rlimm, u8 (simm) instructions. */
6620 SIMD_BUILTIN (Va_rlimm_u8, vmovaw_insn, "vmovaw", VMOVAW)
6621 SIMD_BUILTIN (Va_rlimm_u8, vmovw_insn, "vmovw", VMOVW)
6622 SIMD_BUILTIN (Va_rlimm_u8, vmovzw_insn, "vmovzw", VMOVZW)
6624 /* Va, Vb instructions. */
6625 SIMD_BUILTIN (Va_Vb, vabsaw_insn, "vabsaw", VABSAW)
6626 SIMD_BUILTIN (Va_Vb, vabsw_insn, "vabsw", VABSW)
6627 SIMD_BUILTIN (Va_Vb, vaddsuw_insn, "vaddsuw", VADDSUW)
6628 SIMD_BUILTIN (Va_Vb, vsignw_insn, "vsignw", VSIGNW)
6629 SIMD_BUILTIN (Va_Vb, vexch1_insn, "vexch1", VEXCH1)
6630 SIMD_BUILTIN (Va_Vb, vexch2_insn, "vexch2", VEXCH2)
6631 SIMD_BUILTIN (Va_Vb, vexch4_insn, "vexch4", VEXCH4)
6632 SIMD_BUILTIN (Va_Vb, vupbaw_insn, "vupbaw", VUPBAW)
6633 SIMD_BUILTIN (Va_Vb, vupbw_insn, "vupbw", VUPBW)
6634 SIMD_BUILTIN (Va_Vb, vupsbaw_insn, "vupsbaw", VUPSBAW)
6635 SIMD_BUILTIN (Va_Vb, vupsbw_insn, "vupsbw", VUPSBW)
6637 /* DIb, rlimm, rlimm instructions. */
6638 SIMD_BUILTIN (Da_rlimm_rlimm, vdirun_insn, "vdirun", VDIRUN)
6639 SIMD_BUILTIN (Da_rlimm_rlimm, vdorun_insn, "vdorun", VDORUN)
6641 /* DIb, limm, rlimm instructions. */
6642 SIMD_BUILTIN (Da_u3_rlimm, vdiwr_insn, "vdiwr", VDIWR)
6643 SIMD_BUILTIN (Da_u3_rlimm, vdowr_insn, "vdowr", VDOWR)
6645 /* rlimm instructions. */
6646 SIMD_BUILTIN (void_rlimm, vrec_insn, "vrec", VREC)
6647 SIMD_BUILTIN (void_rlimm, vrun_insn, "vrun", VRUN)
6648 SIMD_BUILTIN (void_rlimm, vrecrun_insn, "vrecrun", VRECRUN)
6649 SIMD_BUILTIN (void_rlimm, vendrec_insn, "vendrec", VENDREC)
6651 /* Va, [Ib,u8] instructions. */
6652 SIMD_BUILTIN (Va_Vb_Ic_u8, vld32wh_insn, "vld32wh", VLD32WH)
6653 SIMD_BUILTIN (Va_Vb_Ic_u8, vld32wl_insn, "vld32wl", VLD32WL)
6654 SIMD_BUILTIN (Va_Vb_Ic_u8, vld64_insn, "vld64", VLD64)
6655 SIMD_BUILTIN (Va_Vb_Ic_u8, vld32_insn, "vld32", VLD32)
6657 SIMD_BUILTIN (Va_Ib_u8, vld64w_insn, "vld64w", VLD64W)
6658 SIMD_BUILTIN (Va_Ib_u8, vld128_insn, "vld128", VLD128)
6659 SIMD_BUILTIN (void_Va_Ib_u8, vst128_insn, "vst128", VST128)
6660 SIMD_BUILTIN (void_Va_Ib_u8, vst64_insn, "vst64", VST64)
6662 /* Va, [Ib, u8] instructions. */
6663 SIMD_BUILTIN (void_Va_u3_Ib_u8, vst16_n_insn, "vst16_n", VST16_N)
6664 SIMD_BUILTIN (void_Va_u3_Ib_u8, vst32_n_insn, "vst32_n", VST32_N)
6666 SIMD_BUILTIN (void_u6, vinti_insn, "vinti", VINTI)
6669 static void
6670 arc_init_simd_builtins (void)
6672 int i;
6673 tree endlink = void_list_node;
6674 tree V8HI_type_node = build_vector_type_for_mode (intHI_type_node, V8HImode);
6676 tree v8hi_ftype_v8hi_v8hi
6677 = build_function_type (V8HI_type_node,
6678 tree_cons (NULL_TREE, V8HI_type_node,
6679 tree_cons (NULL_TREE, V8HI_type_node,
6680 endlink)));
6681 tree v8hi_ftype_v8hi_int
6682 = build_function_type (V8HI_type_node,
6683 tree_cons (NULL_TREE, V8HI_type_node,
6684 tree_cons (NULL_TREE, integer_type_node,
6685 endlink)));
6687 tree v8hi_ftype_v8hi_int_int
6688 = build_function_type (V8HI_type_node,
6689 tree_cons (NULL_TREE, V8HI_type_node,
6690 tree_cons (NULL_TREE, integer_type_node,
6691 tree_cons (NULL_TREE,
6692 integer_type_node,
6693 endlink))));
6695 tree void_ftype_v8hi_int_int
6696 = build_function_type (void_type_node,
6697 tree_cons (NULL_TREE, V8HI_type_node,
6698 tree_cons (NULL_TREE, integer_type_node,
6699 tree_cons (NULL_TREE,
6700 integer_type_node,
6701 endlink))));
6703 tree void_ftype_v8hi_int_int_int
6704 = (build_function_type
6705 (void_type_node,
6706 tree_cons (NULL_TREE, V8HI_type_node,
6707 tree_cons (NULL_TREE, integer_type_node,
6708 tree_cons (NULL_TREE, integer_type_node,
6709 tree_cons (NULL_TREE,
6710 integer_type_node,
6711 endlink))))));
6713 tree v8hi_ftype_int_int
6714 = build_function_type (V8HI_type_node,
6715 tree_cons (NULL_TREE, integer_type_node,
6716 tree_cons (NULL_TREE, integer_type_node,
6717 endlink)));
6719 tree void_ftype_int_int
6720 = build_function_type (void_type_node,
6721 tree_cons (NULL_TREE, integer_type_node,
6722 tree_cons (NULL_TREE, integer_type_node,
6723 endlink)));
6725 tree void_ftype_int
6726 = build_function_type (void_type_node,
6727 tree_cons (NULL_TREE, integer_type_node, endlink));
6729 tree v8hi_ftype_v8hi
6730 = build_function_type (V8HI_type_node, tree_cons (NULL_TREE, V8HI_type_node,
6731 endlink));
6733 /* These asserts have been introduced to ensure that the order of builtins
6734 does not get messed up, else the initialization goes wrong. */
6735 gcc_assert (arc_simd_builtin_desc_list [0].args_type == Va_Vb_Vc);
6736 for (i=0; arc_simd_builtin_desc_list [i].args_type == Va_Vb_Vc; i++)
6737 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6738 v8hi_ftype_v8hi_v8hi, arc_simd_builtin_desc_list[i].code);
6740 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_rlimm);
6741 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_rlimm; i++)
6742 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6743 v8hi_ftype_v8hi_int, arc_simd_builtin_desc_list[i].code);
6745 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_Ic);
6746 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_Ic; i++)
6747 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6748 v8hi_ftype_v8hi_int, arc_simd_builtin_desc_list[i].code);
6750 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_u6);
6751 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_u6; i++)
6752 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6753 v8hi_ftype_v8hi_int, arc_simd_builtin_desc_list[i].code);
6755 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_u8);
6756 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_u8; i++)
6757 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6758 v8hi_ftype_v8hi_int, arc_simd_builtin_desc_list[i].code);
6760 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_rlimm_u8);
6761 for (; arc_simd_builtin_desc_list [i].args_type == Va_rlimm_u8; i++)
6762 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6763 v8hi_ftype_int_int, arc_simd_builtin_desc_list[i].code);
6765 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb);
6766 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb; i++)
6767 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6768 v8hi_ftype_v8hi, arc_simd_builtin_desc_list[i].code);
6770 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Da_rlimm_rlimm);
6771 for (; arc_simd_builtin_desc_list [i].args_type == Da_rlimm_rlimm; i++)
6772 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list [i].name,
6773 void_ftype_int_int, arc_simd_builtin_desc_list[i].code);
6775 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Da_u3_rlimm);
6776 for (; arc_simd_builtin_desc_list [i].args_type == Da_u3_rlimm; i++)
6777 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6778 void_ftype_int_int, arc_simd_builtin_desc_list[i].code);
6780 gcc_assert (arc_simd_builtin_desc_list [i].args_type == void_rlimm);
6781 for (; arc_simd_builtin_desc_list [i].args_type == void_rlimm; i++)
6782 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6783 void_ftype_int, arc_simd_builtin_desc_list[i].code);
6785 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_Ic_u8);
6786 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_Ic_u8; i++)
6787 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6788 v8hi_ftype_v8hi_int_int, arc_simd_builtin_desc_list[i].code);
6790 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Ib_u8);
6791 for (; arc_simd_builtin_desc_list [i].args_type == Va_Ib_u8; i++)
6792 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6793 v8hi_ftype_int_int, arc_simd_builtin_desc_list[i].code);
6795 gcc_assert (arc_simd_builtin_desc_list [i].args_type == void_Va_Ib_u8);
6796 for (; arc_simd_builtin_desc_list [i].args_type == void_Va_Ib_u8; i++)
6797 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list [i].name,
6798 void_ftype_v8hi_int_int, arc_simd_builtin_desc_list[i].code);
6800 gcc_assert (arc_simd_builtin_desc_list [i].args_type == void_Va_u3_Ib_u8);
6801 for (; arc_simd_builtin_desc_list [i].args_type == void_Va_u3_Ib_u8; i++)
6802 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6803 void_ftype_v8hi_int_int_int,
6804 arc_simd_builtin_desc_list[i].code);
6806 gcc_assert (arc_simd_builtin_desc_list [i].args_type == void_u6);
6807 for (; arc_simd_builtin_desc_list [i].args_type == void_u6; i++)
6808 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6809 void_ftype_int, arc_simd_builtin_desc_list[i].code);
6811 gcc_assert(i == ARRAY_SIZE (arc_simd_builtin_desc_list));
6814 /* Helper function of arc_expand_builtin; has the same parameters,
6815 except that EXP is now known to be a call to a simd builtin. */
6817 static rtx
6818 arc_expand_simd_builtin (tree exp,
6819 rtx target,
6820 rtx subtarget ATTRIBUTE_UNUSED,
6821 enum machine_mode mode ATTRIBUTE_UNUSED,
6822 int ignore ATTRIBUTE_UNUSED)
6824 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
6825 tree arg0;
6826 tree arg1;
6827 tree arg2;
6828 tree arg3;
6829 rtx op0;
6830 rtx op1;
6831 rtx op2;
6832 rtx op3;
6833 rtx op4;
6834 rtx pat;
6835 unsigned int i;
6836 int fcode = DECL_FUNCTION_CODE (fndecl);
6837 int icode;
6838 enum machine_mode mode0;
6839 enum machine_mode mode1;
6840 enum machine_mode mode2;
6841 enum machine_mode mode3;
6842 enum machine_mode mode4;
6843 const struct builtin_description * d;
6845 for (i = 0, d = arc_simd_builtin_desc_list;
6846 i < ARRAY_SIZE (arc_simd_builtin_desc_list); i++, d++)
6847 if (d->code == (const enum arc_builtins) fcode)
6848 break;
6850 /* We must get an entry here. */
6851 gcc_assert (i < ARRAY_SIZE (arc_simd_builtin_desc_list));
6853 switch (d->args_type)
6855 case Va_Vb_rlimm:
6856 icode = d->icode;
6857 arg0 = CALL_EXPR_ARG (exp, 0);
6858 arg1 = CALL_EXPR_ARG (exp, 1);
6859 op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
6860 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
6862 target = gen_reg_rtx (V8HImode);
6863 mode0 = insn_data[icode].operand[1].mode;
6864 mode1 = insn_data[icode].operand[2].mode;
6866 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6867 op0 = copy_to_mode_reg (mode0, op0);
6869 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
6870 op1 = copy_to_mode_reg (mode1, op1);
6872 pat = GEN_FCN (icode) (target, op0, op1);
6873 if (! pat)
6874 return 0;
6876 emit_insn (pat);
6877 return target;
6879 case Va_Vb_u6:
6880 case Va_Vb_u8:
6881 icode = d->icode;
6882 arg0 = CALL_EXPR_ARG (exp, 0);
6883 arg1 = CALL_EXPR_ARG (exp, 1);
6884 op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
6885 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
6887 target = gen_reg_rtx (V8HImode);
6888 mode0 = insn_data[icode].operand[1].mode;
6889 mode1 = insn_data[icode].operand[2].mode;
6891 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6892 op0 = copy_to_mode_reg (mode0, op0);
6894 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)
6895 || (d->args_type == Va_Vb_u6 && !UNSIGNED_INT6 (INTVAL (op1)))
6896 || (d->args_type == Va_Vb_u8 && !UNSIGNED_INT8 (INTVAL (op1))))
6897 error ("operand 2 of %s instruction should be an unsigned %d-bit value",
6898 d->name,
6899 (d->args_type == Va_Vb_u6)? 6: 8);
6901 pat = GEN_FCN (icode) (target, op0, op1);
6902 if (! pat)
6903 return 0;
6905 emit_insn (pat);
6906 return target;
6908 case Va_rlimm_u8:
6909 icode = d->icode;
6910 arg0 = CALL_EXPR_ARG (exp, 0);
6911 arg1 = CALL_EXPR_ARG (exp, 1);
6912 op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
6913 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
6915 target = gen_reg_rtx (V8HImode);
6916 mode0 = insn_data[icode].operand[1].mode;
6917 mode1 = insn_data[icode].operand[2].mode;
6919 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6920 op0 = copy_to_mode_reg (mode0, op0);
6922 if ( (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
6923 || !(UNSIGNED_INT8 (INTVAL (op1))))
6924 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
6925 d->name);
6927 pat = GEN_FCN (icode) (target, op0, op1);
6928 if (! pat)
6929 return 0;
6931 emit_insn (pat);
6932 return target;
6934 case Va_Vb_Ic:
6935 icode = d->icode;
6936 arg0 = CALL_EXPR_ARG (exp, 0);
6937 arg1 = CALL_EXPR_ARG (exp, 1);
6938 op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
6939 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
6940 op2 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG);
6942 target = gen_reg_rtx (V8HImode);
6943 mode0 = insn_data[icode].operand[1].mode;
6944 mode1 = insn_data[icode].operand[2].mode;
6946 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6947 op0 = copy_to_mode_reg (mode0, op0);
6949 if ( (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
6950 || !(UNSIGNED_INT3 (INTVAL (op1))))
6951 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
6952 d->name);
6954 pat = GEN_FCN (icode) (target, op0, op1, op2);
6955 if (! pat)
6956 return 0;
6958 emit_insn (pat);
6959 return target;
6961 case Va_Vb_Vc:
6962 icode = d->icode;
6963 arg0 = CALL_EXPR_ARG (exp, 0);
6964 arg1 = CALL_EXPR_ARG (exp, 1);
6965 op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
6966 op1 = expand_expr (arg1, NULL_RTX, V8HImode, EXPAND_NORMAL);
6968 target = gen_reg_rtx (V8HImode);
6969 mode0 = insn_data[icode].operand[1].mode;
6970 mode1 = insn_data[icode].operand[2].mode;
6972 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6973 op0 = copy_to_mode_reg (mode0, op0);
6975 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
6976 op1 = copy_to_mode_reg (mode1, op1);
6978 pat = GEN_FCN (icode) (target, op0, op1);
6979 if (! pat)
6980 return 0;
6982 emit_insn (pat);
6983 return target;
6985 case Va_Vb:
6986 icode = d->icode;
6987 arg0 = CALL_EXPR_ARG (exp, 0);
6988 op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
6990 target = gen_reg_rtx (V8HImode);
6991 mode0 = insn_data[icode].operand[1].mode;
6993 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6994 op0 = copy_to_mode_reg (mode0, op0);
6996 pat = GEN_FCN (icode) (target, op0);
6997 if (! pat)
6998 return 0;
7000 emit_insn (pat);
7001 return target;
7003 case Da_rlimm_rlimm:
7004 icode = d->icode;
7005 arg0 = CALL_EXPR_ARG (exp, 0);
7006 arg1 = CALL_EXPR_ARG (exp, 1);
7007 op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
7008 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
7011 if (icode == CODE_FOR_vdirun_insn)
7012 target = gen_rtx_REG (SImode, 131);
7013 else if (icode == CODE_FOR_vdorun_insn)
7014 target = gen_rtx_REG (SImode, 139);
7015 else
7016 gcc_unreachable ();
7018 mode0 = insn_data[icode].operand[1].mode;
7019 mode1 = insn_data[icode].operand[2].mode;
7021 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
7022 op0 = copy_to_mode_reg (mode0, op0);
7024 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
7025 op1 = copy_to_mode_reg (mode1, op1);
7028 pat = GEN_FCN (icode) (target, op0, op1);
7029 if (! pat)
7030 return 0;
7032 emit_insn (pat);
7033 return NULL_RTX;
7035 case Da_u3_rlimm:
7036 icode = d->icode;
7037 arg0 = CALL_EXPR_ARG (exp, 0);
7038 arg1 = CALL_EXPR_ARG (exp, 1);
7039 op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
7040 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
7043 if (! (GET_CODE (op0) == CONST_INT)
7044 || !(UNSIGNED_INT3 (INTVAL (op0))))
7045 error ("operand 1 of %s instruction should be an unsigned 3-bit value (DR0-DR7)",
7046 d->name);
7048 mode1 = insn_data[icode].operand[1].mode;
7050 if (icode == CODE_FOR_vdiwr_insn)
7051 target = gen_rtx_REG (SImode,
7052 ARC_FIRST_SIMD_DMA_CONFIG_IN_REG + INTVAL (op0));
7053 else if (icode == CODE_FOR_vdowr_insn)
7054 target = gen_rtx_REG (SImode,
7055 ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG + INTVAL (op0));
7056 else
7057 gcc_unreachable ();
7059 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
7060 op1 = copy_to_mode_reg (mode1, op1);
7062 pat = GEN_FCN (icode) (target, op1);
7063 if (! pat)
7064 return 0;
7066 emit_insn (pat);
7067 return NULL_RTX;
7069 case void_u6:
7070 icode = d->icode;
7071 arg0 = CALL_EXPR_ARG (exp, 0);
7073 fold (arg0);
7075 op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
7076 mode0 = insn_data[icode].operand[0].mode;
7078 /* op0 should be u6. */
7079 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)
7080 || !(UNSIGNED_INT6 (INTVAL (op0))))
7081 error ("operand of %s instruction should be an unsigned 6-bit value",
7082 d->name);
7084 pat = GEN_FCN (icode) (op0);
7085 if (! pat)
7086 return 0;
7088 emit_insn (pat);
7089 return NULL_RTX;
7091 case void_rlimm:
7092 icode = d->icode;
7093 arg0 = CALL_EXPR_ARG (exp, 0);
7095 fold (arg0);
7097 op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
7098 mode0 = insn_data[icode].operand[0].mode;
7100 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
7101 op0 = copy_to_mode_reg (mode0, op0);
7103 pat = GEN_FCN (icode) (op0);
7104 if (! pat)
7105 return 0;
7107 emit_insn (pat);
7108 return NULL_RTX;
7110 case Va_Vb_Ic_u8:
7112 rtx src_vreg;
7113 icode = d->icode;
7114 arg0 = CALL_EXPR_ARG (exp, 0); /* source vreg */
7115 arg1 = CALL_EXPR_ARG (exp, 1); /* [I]0-7 */
7116 arg2 = CALL_EXPR_ARG (exp, 2); /* u8 */
7118 src_vreg = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
7119 op0 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL); /* [I]0-7 */
7120 op1 = expand_expr (arg2, NULL_RTX, SImode, EXPAND_NORMAL); /* u8 */
7121 op2 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG); /* VR0 */
7123 /* target <- src vreg */
7124 emit_insn (gen_move_insn (target, src_vreg));
7126 /* target <- vec_concat: target, mem(Ib, u8) */
7127 mode0 = insn_data[icode].operand[3].mode;
7128 mode1 = insn_data[icode].operand[1].mode;
7130 if ( (!(*insn_data[icode].operand[3].predicate) (op0, mode0))
7131 || !(UNSIGNED_INT3 (INTVAL (op0))))
7132 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7133 d->name);
7135 if ( (!(*insn_data[icode].operand[1].predicate) (op1, mode1))
7136 || !(UNSIGNED_INT8 (INTVAL (op1))))
7137 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7138 d->name);
7140 pat = GEN_FCN (icode) (target, op1, op2, op0);
7141 if (! pat)
7142 return 0;
7144 emit_insn (pat);
7145 return target;
7148 case void_Va_Ib_u8:
7149 icode = d->icode;
7150 arg0 = CALL_EXPR_ARG (exp, 0); /* src vreg */
7151 arg1 = CALL_EXPR_ARG (exp, 1); /* [I]0-7 */
7152 arg2 = CALL_EXPR_ARG (exp, 2); /* u8 */
7154 op0 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG); /* VR0 */
7155 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL); /* I[0-7] */
7156 op2 = expand_expr (arg2, NULL_RTX, SImode, EXPAND_NORMAL); /* u8 */
7157 op3 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL); /* Vdest */
7159 mode0 = insn_data[icode].operand[0].mode;
7160 mode1 = insn_data[icode].operand[1].mode;
7161 mode2 = insn_data[icode].operand[2].mode;
7162 mode3 = insn_data[icode].operand[3].mode;
7164 if ( (!(*insn_data[icode].operand[1].predicate) (op1, mode1))
7165 || !(UNSIGNED_INT3 (INTVAL (op1))))
7166 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7167 d->name);
7169 if ( (!(*insn_data[icode].operand[2].predicate) (op2, mode2))
7170 || !(UNSIGNED_INT8 (INTVAL (op2))))
7171 error ("operand 3 of %s instruction should be an unsigned 8-bit value",
7172 d->name);
7174 if (!(*insn_data[icode].operand[3].predicate) (op3, mode3))
7175 op3 = copy_to_mode_reg (mode3, op3);
7177 pat = GEN_FCN (icode) (op0, op1, op2, op3);
7178 if (! pat)
7179 return 0;
7181 emit_insn (pat);
7182 return NULL_RTX;
7184 case Va_Ib_u8:
7185 icode = d->icode;
7186 arg0 = CALL_EXPR_ARG (exp, 0); /* dest vreg */
7187 arg1 = CALL_EXPR_ARG (exp, 1); /* [I]0-7 */
7189 op0 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG); /* VR0 */
7190 op1 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL); /* I[0-7] */
7191 op2 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL); /* u8 */
7193 /* target <- src vreg */
7194 target = gen_reg_rtx (V8HImode);
7196 /* target <- vec_concat: target, mem(Ib, u8) */
7197 mode0 = insn_data[icode].operand[1].mode;
7198 mode1 = insn_data[icode].operand[2].mode;
7199 mode2 = insn_data[icode].operand[3].mode;
7201 if ( (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
7202 || !(UNSIGNED_INT3 (INTVAL (op1))))
7203 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7204 d->name);
7206 if ( (!(*insn_data[icode].operand[3].predicate) (op2, mode2))
7207 || !(UNSIGNED_INT8 (INTVAL (op2))))
7208 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7209 d->name);
7211 pat = GEN_FCN (icode) (target, op0, op1, op2);
7212 if (! pat)
7213 return 0;
7215 emit_insn (pat);
7216 return target;
7218 case void_Va_u3_Ib_u8:
7219 icode = d->icode;
7220 arg0 = CALL_EXPR_ARG (exp, 0); /* source vreg */
7221 arg1 = CALL_EXPR_ARG (exp, 1); /* u3 */
7222 arg2 = CALL_EXPR_ARG (exp, 2); /* [I]0-7 */
7223 arg3 = CALL_EXPR_ARG (exp, 3); /* u8 */
7225 op0 = expand_expr (arg3, NULL_RTX, SImode, EXPAND_NORMAL); /* u8 */
7226 op1 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG); /* VR */
7227 op2 = expand_expr (arg2, NULL_RTX, SImode, EXPAND_NORMAL); /* [I]0-7 */
7228 op3 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);/* vreg to be stored */
7229 op4 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL); /* vreg 0-7 subreg no. */
7231 mode0 = insn_data[icode].operand[0].mode;
7232 mode2 = insn_data[icode].operand[2].mode;
7233 mode3 = insn_data[icode].operand[3].mode;
7234 mode4 = insn_data[icode].operand[4].mode;
7236 /* Do some correctness checks for the operands. */
7237 if ( (!(*insn_data[icode].operand[0].predicate) (op0, mode0))
7238 || !(UNSIGNED_INT8 (INTVAL (op0))))
7239 error ("operand 4 of %s instruction should be an unsigned 8-bit value (0-255)",
7240 d->name);
7242 if ( (!(*insn_data[icode].operand[2].predicate) (op2, mode2))
7243 || !(UNSIGNED_INT3 (INTVAL (op2))))
7244 error ("operand 3 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7245 d->name);
7247 if (!(*insn_data[icode].operand[3].predicate) (op3, mode3))
7248 op3 = copy_to_mode_reg (mode3, op3);
7250 if ( (!(*insn_data[icode].operand[4].predicate) (op4, mode4))
7251 || !(UNSIGNED_INT3 (INTVAL (op4))))
7252 error ("operand 2 of %s instruction should be an unsigned 3-bit value (subreg 0-7)",
7253 d->name);
7254 else if (icode == CODE_FOR_vst32_n_insn
7255 && ((INTVAL(op4) % 2 ) != 0))
7256 error ("operand 2 of %s instruction should be an even 3-bit value (subreg 0,2,4,6)",
7257 d->name);
7259 pat = GEN_FCN (icode) (op0, op1, op2, op3, op4);
7260 if (! pat)
7261 return 0;
7263 emit_insn (pat);
7264 return NULL_RTX;
7266 default:
7267 gcc_unreachable ();
7269 return NULL_RTX;
7272 static bool
7273 arc_preserve_reload_p (rtx in)
7275 return (GET_CODE (in) == PLUS
7276 && RTX_OK_FOR_BASE_P (XEXP (in, 0), true)
7277 && CONST_INT_P (XEXP (in, 1))
7278 && !((INTVAL (XEXP (in, 1)) & 511)));
7282 arc_register_move_cost (enum machine_mode,
7283 enum reg_class from_class, enum reg_class to_class)
7285 /* The ARC600 has no bypass for extension registers, hence a nop might be
7286 needed to be inserted after a write so that reads are safe. */
7287 if (TARGET_ARC600)
7289 if (to_class == MPY_WRITABLE_CORE_REGS)
7290 return 3;
7291 /* Instructions modifying LP_COUNT need 4 additional cycles before
7292 the register will actually contain the value. */
7293 else if (to_class == LPCOUNT_REG)
7294 return 6;
7295 else if (to_class == WRITABLE_CORE_REGS)
7296 return 6;
7299 /* The ARC700 stalls for 3 cycles when *reading* from lp_count. */
7300 if (TARGET_ARC700
7301 && (from_class == LPCOUNT_REG || from_class == ALL_CORE_REGS
7302 || from_class == WRITABLE_CORE_REGS))
7303 return 8;
7305 /* Force an attempt to 'mov Dy,Dx' to spill. */
7306 if (TARGET_ARC700 && TARGET_DPFP
7307 && from_class == DOUBLE_REGS && to_class == DOUBLE_REGS)
7308 return 100;
7310 return 2;
7313 /* Emit code for an addsi3 instruction with OPERANDS.
7314 COND_P indicates if this will use conditional execution.
7315 Return the length of the instruction.
7316 If OUTPUT_P is false, don't actually output the instruction, just return
7317 its length. */
7319 arc_output_addsi (rtx *operands, bool cond_p, bool output_p)
7321 char format[32];
7323 int match = operands_match_p (operands[0], operands[1]);
7324 int match2 = operands_match_p (operands[0], operands[2]);
7325 int intval = (REG_P (operands[2]) ? 1
7326 : CONST_INT_P (operands[2]) ? INTVAL (operands[2]) : 0xbadc057);
7327 int neg_intval = -intval;
7328 int short_0 = satisfies_constraint_Rcq (operands[0]);
7329 int short_p = (!cond_p && short_0 && satisfies_constraint_Rcq (operands[1]));
7330 int ret = 0;
7332 #define ADDSI_OUTPUT1(FORMAT) do {\
7333 if (output_p) \
7334 output_asm_insn (FORMAT, operands);\
7335 return ret; \
7336 } while (0)
7337 #define ADDSI_OUTPUT(LIST) do {\
7338 if (output_p) \
7339 sprintf LIST;\
7340 ADDSI_OUTPUT1 (format);\
7341 return ret; \
7342 } while (0)
7344 /* First try to emit a 16 bit insn. */
7345 ret = 2;
7346 if (!cond_p
7347 /* If we are actually about to output this insn, don't try a 16 bit
7348 variant if we already decided that we don't want that
7349 (I.e. we upsized this insn to align some following insn.)
7350 E.g. add_s r0,sp,70 is 16 bit, but add r0,sp,70 requires a LIMM -
7351 but add1 r0,sp,35 doesn't. */
7352 && (!output_p || (get_attr_length (current_output_insn) & 2)))
7354 if (short_p
7355 && (REG_P (operands[2])
7356 ? (match || satisfies_constraint_Rcq (operands[2]))
7357 : (unsigned) intval <= (match ? 127 : 7)))
7358 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7359 if (short_0 && REG_P (operands[1]) && match2)
7360 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7361 if ((short_0 || REGNO (operands[0]) == STACK_POINTER_REGNUM)
7362 && REGNO (operands[1]) == STACK_POINTER_REGNUM && !(intval & ~124))
7363 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7365 if ((short_p && (unsigned) neg_intval <= (match ? 31 : 7))
7366 || (REGNO (operands[0]) == STACK_POINTER_REGNUM
7367 && match && !(neg_intval & ~124)))
7368 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7371 /* Now try to emit a 32 bit insn without long immediate. */
7372 ret = 4;
7373 if (!match && match2 && REG_P (operands[1]))
7374 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7375 if (match || !cond_p)
7377 int limit = (match && !cond_p) ? 0x7ff : 0x3f;
7378 int range_factor = neg_intval & intval;
7379 int shift;
7381 if (intval == -1 << 31)
7382 ADDSI_OUTPUT1 ("bxor%? %0,%1,31");
7384 /* If we can use a straight add / sub instead of a {add,sub}[123] of
7385 same size, do, so - the insn latency is lower. */
7386 /* -0x800 is a 12-bit constant for add /add3 / sub / sub3, but
7387 0x800 is not. */
7388 if ((intval >= 0 && intval <= limit)
7389 || (intval == -0x800 && limit == 0x7ff))
7390 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7391 else if ((intval < 0 && neg_intval <= limit)
7392 || (intval == 0x800 && limit == 0x7ff))
7393 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7394 shift = range_factor >= 8 ? 3 : (range_factor >> 1);
7395 gcc_assert (shift == 0 || shift == 1 || shift == 2 || shift == 3);
7396 gcc_assert ((((1 << shift) - 1) & intval) == 0);
7397 if (((intval < 0 && intval != -0x4000)
7398 /* sub[123] is slower than add_s / sub, only use it if it
7399 avoids a long immediate. */
7400 && neg_intval <= limit << shift)
7401 || (intval == 0x4000 && limit == 0x7ff))
7402 ADDSI_OUTPUT ((format, "sub%d%%? %%0,%%1,%d",
7403 shift, neg_intval >> shift));
7404 else if ((intval >= 0 && intval <= limit << shift)
7405 || (intval == -0x4000 && limit == 0x7ff))
7406 ADDSI_OUTPUT ((format, "add%d%%? %%0,%%1,%d", shift, intval >> shift));
7408 /* Try to emit a 16 bit opcode with long immediate. */
7409 ret = 6;
7410 if (short_p && match)
7411 ADDSI_OUTPUT1 ("add%? %0,%1,%S2");
7413 /* We have to use a 32 bit opcode, and with a long immediate. */
7414 ret = 8;
7415 ADDSI_OUTPUT1 (intval < 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%S2");
7418 /* Emit code for an commutative_cond_exec instruction with OPERANDS.
7419 Return the length of the instruction.
7420 If OUTPUT_P is false, don't actually output the instruction, just return
7421 its length. */
7423 arc_output_commutative_cond_exec (rtx *operands, bool output_p)
7425 enum rtx_code commutative_op = GET_CODE (operands[3]);
7426 const char *pat = NULL;
7428 /* Canonical rtl should not have a constant in the first operand position. */
7429 gcc_assert (!CONSTANT_P (operands[1]));
7431 switch (commutative_op)
7433 case AND:
7434 if (satisfies_constraint_C1p (operands[2]))
7435 pat = "bmsk%? %0,%1,%Z2";
7436 else if (satisfies_constraint_Ccp (operands[2]))
7437 pat = "bclr%? %0,%1,%M2";
7438 else if (satisfies_constraint_CnL (operands[2]))
7439 pat = "bic%? %0,%1,%n2-1";
7440 break;
7441 case IOR:
7442 if (satisfies_constraint_C0p (operands[2]))
7443 pat = "bset%? %0,%1,%z2";
7444 break;
7445 case XOR:
7446 if (satisfies_constraint_C0p (operands[2]))
7447 pat = "bxor%? %0,%1,%z2";
7448 break;
7449 case PLUS:
7450 return arc_output_addsi (operands, true, output_p);
7451 default: break;
7453 if (output_p)
7454 output_asm_insn (pat ? pat : "%O3.%d5 %0,%1,%2", operands);
7455 if (pat || REG_P (operands[2]) || satisfies_constraint_L (operands[2]))
7456 return 4;
7457 return 8;
7460 /* Helper function of arc_expand_movmem. ADDR points to a chunk of memory.
7461 Emit code and return an potentially modified address such that offsets
7462 up to SIZE are can be added to yield a legitimate address.
7463 if REUSE is set, ADDR is a register that may be modified. */
7465 static rtx
7466 force_offsettable (rtx addr, HOST_WIDE_INT size, bool reuse)
7468 rtx base = addr;
7469 rtx offs = const0_rtx;
7471 if (GET_CODE (base) == PLUS)
7473 offs = XEXP (base, 1);
7474 base = XEXP (base, 0);
7476 if (!REG_P (base)
7477 || (REGNO (base) != STACK_POINTER_REGNUM
7478 && REGNO_PTR_FRAME_P (REGNO (addr)))
7479 || !CONST_INT_P (offs) || !SMALL_INT (INTVAL (offs))
7480 || !SMALL_INT (INTVAL (offs) + size))
7482 if (reuse)
7483 emit_insn (gen_add2_insn (addr, offs));
7484 else
7485 addr = copy_to_mode_reg (Pmode, addr);
7487 return addr;
7490 /* Like move_by_pieces, but take account of load latency,
7491 and actual offset ranges.
7492 Return true on success. */
7494 bool
7495 arc_expand_movmem (rtx *operands)
7497 rtx dst = operands[0];
7498 rtx src = operands[1];
7499 rtx dst_addr, src_addr;
7500 HOST_WIDE_INT size;
7501 int align = INTVAL (operands[3]);
7502 unsigned n_pieces;
7503 int piece = align;
7504 rtx store[2];
7505 rtx tmpx[2];
7506 int i;
7508 if (!CONST_INT_P (operands[2]))
7509 return false;
7510 size = INTVAL (operands[2]);
7511 /* move_by_pieces_ninsns is static, so we can't use it. */
7512 if (align >= 4)
7513 n_pieces = (size + 2) / 4U + (size & 1);
7514 else if (align == 2)
7515 n_pieces = (size + 1) / 2U;
7516 else
7517 n_pieces = size;
7518 if (n_pieces >= (unsigned int) (optimize_size ? 3 : 15))
7519 return false;
7520 if (piece > 4)
7521 piece = 4;
7522 dst_addr = force_offsettable (XEXP (operands[0], 0), size, 0);
7523 src_addr = force_offsettable (XEXP (operands[1], 0), size, 0);
7524 store[0] = store[1] = NULL_RTX;
7525 tmpx[0] = tmpx[1] = NULL_RTX;
7526 for (i = 0; size > 0; i ^= 1, size -= piece)
7528 rtx tmp;
7529 enum machine_mode mode;
7531 if (piece > size)
7532 piece = size & -size;
7533 mode = smallest_mode_for_size (piece * BITS_PER_UNIT, MODE_INT);
7534 /* If we don't re-use temporaries, the scheduler gets carried away,
7535 and the register pressure gets unnecessarily high. */
7536 if (0 && tmpx[i] && GET_MODE (tmpx[i]) == mode)
7537 tmp = tmpx[i];
7538 else
7539 tmpx[i] = tmp = gen_reg_rtx (mode);
7540 dst_addr = force_offsettable (dst_addr, piece, 1);
7541 src_addr = force_offsettable (src_addr, piece, 1);
7542 if (store[i])
7543 emit_insn (store[i]);
7544 emit_move_insn (tmp, change_address (src, mode, src_addr));
7545 store[i] = gen_move_insn (change_address (dst, mode, dst_addr), tmp);
7546 dst_addr = plus_constant (Pmode, dst_addr, piece);
7547 src_addr = plus_constant (Pmode, src_addr, piece);
7549 if (store[i])
7550 emit_insn (store[i]);
7551 if (store[i^1])
7552 emit_insn (store[i^1]);
7553 return true;
7556 /* Prepare operands for move in MODE. Return true iff the move has
7557 been emitted. */
7559 bool
7560 prepare_move_operands (rtx *operands, enum machine_mode mode)
7562 /* We used to do this only for MODE_INT Modes, but addresses to floating
7563 point variables may well be in the small data section. */
7564 if (1)
7566 if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[0], Pmode))
7567 operands[0] = arc_rewrite_small_data (operands[0]);
7568 else if (mode == SImode && flag_pic && SYMBOLIC_CONST (operands[1]))
7570 emit_pic_move (operands, SImode);
7572 /* Disable any REG_EQUALs associated with the symref
7573 otherwise the optimization pass undoes the work done
7574 here and references the variable directly. */
7576 else if (GET_CODE (operands[0]) != MEM
7577 && !TARGET_NO_SDATA_SET
7578 && small_data_pattern (operands[1], Pmode))
7580 /* This is to take care of address calculations involving sdata
7581 variables. */
7582 operands[1] = arc_rewrite_small_data (operands[1]);
7584 emit_insn (gen_rtx_SET (mode, operands[0],operands[1]));
7585 /* ??? This note is useless, since it only restates the set itself.
7586 We should rather use the original SYMBOL_REF. However, there is
7587 the problem that we are lying to the compiler about these
7588 SYMBOL_REFs to start with. symbol@sda should be encoded specially
7589 so that we can tell it apart from an actual symbol. */
7590 set_unique_reg_note (get_last_insn (), REG_EQUAL, operands[1]);
7592 /* Take care of the REG_EQUAL note that will be attached to mark the
7593 output reg equal to the initial symbol_ref after this code is
7594 executed. */
7595 emit_move_insn (operands[0], operands[0]);
7596 return true;
7600 if (MEM_P (operands[0])
7601 && !(reload_in_progress || reload_completed))
7603 operands[1] = force_reg (mode, operands[1]);
7604 if (!move_dest_operand (operands[0], mode))
7606 rtx addr = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
7607 /* This is like change_address_1 (operands[0], mode, 0, 1) ,
7608 except that we can't use that function because it is static. */
7609 rtx pat = change_address (operands[0], mode, addr);
7610 MEM_COPY_ATTRIBUTES (pat, operands[0]);
7611 operands[0] = pat;
7613 if (!cse_not_expected)
7615 rtx pat = XEXP (operands[0], 0);
7617 pat = arc_legitimize_address_0 (pat, pat, mode);
7618 if (pat)
7620 pat = change_address (operands[0], mode, pat);
7621 MEM_COPY_ATTRIBUTES (pat, operands[0]);
7622 operands[0] = pat;
7627 if (MEM_P (operands[1]) && !cse_not_expected)
7629 rtx pat = XEXP (operands[1], 0);
7631 pat = arc_legitimize_address_0 (pat, pat, mode);
7632 if (pat)
7634 pat = change_address (operands[1], mode, pat);
7635 MEM_COPY_ATTRIBUTES (pat, operands[1]);
7636 operands[1] = pat;
7640 return false;
7643 /* Prepare OPERANDS for an extension using CODE to OMODE.
7644 Return true iff the move has been emitted. */
7646 bool
7647 prepare_extend_operands (rtx *operands, enum rtx_code code,
7648 enum machine_mode omode)
7650 if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[1], Pmode))
7652 /* This is to take care of address calculations involving sdata
7653 variables. */
7654 operands[1]
7655 = gen_rtx_fmt_e (code, omode, arc_rewrite_small_data (operands[1]));
7656 emit_insn (gen_rtx_SET (omode, operands[0], operands[1]));
7657 set_unique_reg_note (get_last_insn (), REG_EQUAL, operands[1]);
7659 /* Take care of the REG_EQUAL note that will be attached to mark the
7660 output reg equal to the initial extension after this code is
7661 executed. */
7662 emit_move_insn (operands[0], operands[0]);
7663 return true;
7665 return false;
7668 /* Output a library call to a function called FNAME that has been arranged
7669 to be local to any dso. */
7671 const char *
7672 arc_output_libcall (const char *fname)
7674 unsigned len = strlen (fname);
7675 static char buf[64];
7677 gcc_assert (len < sizeof buf - 35);
7678 if (TARGET_LONG_CALLS_SET
7679 || (TARGET_MEDIUM_CALLS && arc_ccfsm_cond_exec_p ()))
7681 if (flag_pic)
7682 sprintf (buf, "add r12,pcl,@%s-(.&-4)\n\tjl%%!%%* [r12]", fname);
7683 else
7684 sprintf (buf, "jl%%! @%s", fname);
7686 else
7687 sprintf (buf, "bl%%!%%* @%s", fname);
7688 return buf;
7691 /* Return the SImode highpart of the DImode value IN. */
7694 disi_highpart (rtx in)
7696 return simplify_gen_subreg (SImode, in, DImode, TARGET_BIG_ENDIAN ? 0 : 4);
7699 /* Called by arc600_corereg_hazard via for_each_rtx.
7700 If a hazard is found, return a conservative estimate of the required
7701 length adjustment to accomodate a nop. */
7703 static int
7704 arc600_corereg_hazard_1 (rtx *xp, void *data)
7706 rtx x = *xp;
7707 rtx dest;
7708 rtx pat = (rtx) data;
7710 switch (GET_CODE (x))
7712 case SET: case POST_INC: case POST_DEC: case PRE_INC: case PRE_DEC:
7713 break;
7714 default:
7715 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
7716 return 0;
7718 dest = XEXP (x, 0);
7719 /* Check if this sets a an extension register. N.B. we use 61 for the
7720 condition codes, which is definitely not an extension register. */
7721 if (REG_P (dest) && REGNO (dest) >= 32 && REGNO (dest) < 61
7722 /* Check if the same register is used by the PAT. */
7723 && (refers_to_regno_p
7724 (REGNO (dest),
7725 REGNO (dest) + (GET_MODE_SIZE (GET_MODE (dest)) + 3) / 4U, pat, 0)))
7726 return 4;
7728 return 0;
7731 /* Return length adjustment for INSN.
7732 For ARC600:
7733 A write to a core reg greater or equal to 32 must not be immediately
7734 followed by a use. Anticipate the length requirement to insert a nop
7735 between PRED and SUCC to prevent a hazard. */
7737 static int
7738 arc600_corereg_hazard (rtx pred, rtx succ)
7740 if (!TARGET_ARC600)
7741 return 0;
7742 /* If SUCC is a doloop_end_i with a preceding label, we must output a nop
7743 in front of SUCC anyway, so there will be separation between PRED and
7744 SUCC. */
7745 if (recog_memoized (succ) == CODE_FOR_doloop_end_i
7746 && LABEL_P (prev_nonnote_insn (succ)))
7747 return 0;
7748 if (recog_memoized (succ) == CODE_FOR_doloop_begin_i)
7749 return 0;
7750 if (GET_CODE (PATTERN (pred)) == SEQUENCE)
7751 pred = XVECEXP (PATTERN (pred), 0, 1);
7752 if (GET_CODE (PATTERN (succ)) == SEQUENCE)
7753 succ = XVECEXP (PATTERN (succ), 0, 0);
7754 if (recog_memoized (pred) == CODE_FOR_mulsi_600
7755 || recog_memoized (pred) == CODE_FOR_umul_600
7756 || recog_memoized (pred) == CODE_FOR_mac_600
7757 || recog_memoized (pred) == CODE_FOR_mul64_600
7758 || recog_memoized (pred) == CODE_FOR_mac64_600
7759 || recog_memoized (pred) == CODE_FOR_umul64_600
7760 || recog_memoized (pred) == CODE_FOR_umac64_600)
7761 return 0;
7762 return for_each_rtx (&PATTERN (pred), arc600_corereg_hazard_1,
7763 PATTERN (succ));
7766 /* For ARC600:
7767 A write to a core reg greater or equal to 32 must not be immediately
7768 followed by a use. Anticipate the length requirement to insert a nop
7769 between PRED and SUCC to prevent a hazard. */
7772 arc_hazard (rtx pred, rtx succ)
7774 if (!TARGET_ARC600)
7775 return 0;
7776 if (!pred || !INSN_P (pred) || !succ || !INSN_P (succ))
7777 return 0;
7778 /* We might have a CALL to a non-returning function before a loop end.
7779 ??? Although the manual says that's OK (the target is outside the loop,
7780 and the loop counter unused there), the assembler barfs on this, so we
7781 must instert a nop before such a call too. */
7782 if (recog_memoized (succ) == CODE_FOR_doloop_end_i
7783 && (JUMP_P (pred) || CALL_P (pred)
7784 || GET_CODE (PATTERN (pred)) == SEQUENCE))
7785 return 4;
7786 return arc600_corereg_hazard (pred, succ);
7789 /* Return length adjustment for INSN. */
7792 arc_adjust_insn_length (rtx insn, int len, bool)
7794 if (!INSN_P (insn))
7795 return len;
7796 /* We already handle sequences by ignoring the delay sequence flag. */
7797 if (GET_CODE (PATTERN (insn)) == SEQUENCE)
7798 return len;
7800 /* It is impossible to jump to the very end of a Zero-Overhead Loop, as
7801 the ZOL mechanism only triggers when advancing to the end address,
7802 so if there's a label at the end of a ZOL, we need to insert a nop.
7803 The ARC600 ZOL also has extra restrictions on jumps at the end of a
7804 loop. */
7805 if (recog_memoized (insn) == CODE_FOR_doloop_end_i)
7807 rtx prev = prev_nonnote_insn (insn);
7809 return ((LABEL_P (prev)
7810 || (TARGET_ARC600
7811 && (JUMP_P (prev)
7812 || CALL_P (prev) /* Could be a noreturn call. */
7813 || (NONJUMP_INSN_P (prev)
7814 && GET_CODE (PATTERN (prev)) == SEQUENCE))))
7815 ? len + 4 : len);
7818 /* Check for return with but one preceding insn since function
7819 start / call. */
7820 if (TARGET_PAD_RETURN
7821 && JUMP_P (insn)
7822 && GET_CODE (PATTERN (insn)) != ADDR_VEC
7823 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
7824 && get_attr_type (insn) == TYPE_RETURN)
7826 rtx prev = prev_active_insn (insn);
7828 if (!prev || !(prev = prev_active_insn (prev))
7829 || ((NONJUMP_INSN_P (prev)
7830 && GET_CODE (PATTERN (prev)) == SEQUENCE)
7831 ? CALL_ATTR (XVECEXP (PATTERN (prev), 0, 0), NON_SIBCALL)
7832 : CALL_ATTR (prev, NON_SIBCALL)))
7833 return len + 4;
7835 if (TARGET_ARC600)
7837 rtx succ = next_real_insn (insn);
7839 /* One the ARC600, a write to an extension register must be separated
7840 from a read. */
7841 if (succ && INSN_P (succ))
7842 len += arc600_corereg_hazard (insn, succ);
7845 /* Restore extracted operands - otherwise splitters like the addsi3_mixed one
7846 can go awry. */
7847 extract_constrain_insn_cached (insn);
7849 return len;
7852 /* Values for length_sensitive. */
7853 enum
7855 ARC_LS_NONE,// Jcc
7856 ARC_LS_25, // 25 bit offset, B
7857 ARC_LS_21, // 21 bit offset, Bcc
7858 ARC_LS_U13,// 13 bit unsigned offset, LP
7859 ARC_LS_10, // 10 bit offset, B_s, Beq_s, Bne_s
7860 ARC_LS_9, // 9 bit offset, BRcc
7861 ARC_LS_8, // 8 bit offset, BRcc_s
7862 ARC_LS_U7, // 7 bit unsigned offset, LPcc
7863 ARC_LS_7 // 7 bit offset, Bcc_s
7866 /* While the infrastructure patch is waiting for review, duplicate the
7867 struct definitions, to allow this file to compile. */
7868 #if 1
7869 typedef struct
7871 unsigned align_set;
7872 /* Cost as a branch / call target or call return address. */
7873 int target_cost;
7874 int fallthrough_cost;
7875 int branch_cost;
7876 int length;
7877 /* 0 for not length sensitive, 1 for largest offset range,
7878 * 2 for next smaller etc. */
7879 unsigned length_sensitive : 8;
7880 bool enabled;
7881 } insn_length_variant_t;
7883 typedef struct insn_length_parameters_s
7885 int align_unit_log;
7886 int align_base_log;
7887 int max_variants;
7888 int (*get_variants) (rtx, int, bool, bool, insn_length_variant_t *);
7889 } insn_length_parameters_t;
7891 static void
7892 arc_insn_length_parameters (insn_length_parameters_t *ilp) ATTRIBUTE_UNUSED;
7893 #endif
7895 static int
7896 arc_get_insn_variants (rtx insn, int len, bool, bool target_p,
7897 insn_length_variant_t *ilv)
7899 if (!NONDEBUG_INSN_P (insn))
7900 return 0;
7901 enum attr_type type;
7902 /* shorten_branches doesn't take optimize_size into account yet for the
7903 get_variants mechanism, so turn this off for now. */
7904 if (optimize_size)
7905 return 0;
7906 if (GET_CODE (PATTERN (insn)) == SEQUENCE)
7908 /* The interaction of a short delay slot insn with a short branch is
7909 too weird for shorten_branches to piece together, so describe the
7910 entire SEQUENCE. */
7911 rtx pat, inner;
7912 if (TARGET_UPSIZE_DBR
7913 && get_attr_length (XVECEXP ((pat = PATTERN (insn)), 0, 1)) <= 2
7914 && (((type = get_attr_type (inner = XVECEXP (pat, 0, 0)))
7915 == TYPE_UNCOND_BRANCH)
7916 || type == TYPE_BRANCH)
7917 && get_attr_delay_slot_filled (inner) == DELAY_SLOT_FILLED_YES)
7919 int n_variants
7920 = arc_get_insn_variants (inner, get_attr_length (inner), true,
7921 target_p, ilv+1);
7922 /* The short variant gets split into a higher-cost aligned
7923 and a lower cost unaligned variant. */
7924 gcc_assert (n_variants);
7925 gcc_assert (ilv[1].length_sensitive == ARC_LS_7
7926 || ilv[1].length_sensitive == ARC_LS_10);
7927 gcc_assert (ilv[1].align_set == 3);
7928 ilv[0] = ilv[1];
7929 ilv[0].align_set = 1;
7930 ilv[0].branch_cost += 1;
7931 ilv[1].align_set = 2;
7932 n_variants++;
7933 for (int i = 0; i < n_variants; i++)
7934 ilv[i].length += 2;
7935 /* In case an instruction with aligned size is wanted, and
7936 the short variants are unavailable / too expensive, add
7937 versions of long branch + long delay slot. */
7938 for (int i = 2, end = n_variants; i < end; i++, n_variants++)
7940 ilv[n_variants] = ilv[i];
7941 ilv[n_variants].length += 2;
7943 return n_variants;
7945 return 0;
7947 insn_length_variant_t *first_ilv = ilv;
7948 type = get_attr_type (insn);
7949 bool delay_filled
7950 = (get_attr_delay_slot_filled (insn) == DELAY_SLOT_FILLED_YES);
7951 int branch_align_cost = delay_filled ? 0 : 1;
7952 int branch_unalign_cost = delay_filled ? 0 : TARGET_UNALIGN_BRANCH ? 0 : 1;
7953 /* If the previous instruction is an sfunc call, this insn is always
7954 a target, even though the middle-end is unaware of this. */
7955 bool force_target = false;
7956 rtx prev = prev_active_insn (insn);
7957 if (prev && arc_next_active_insn (prev, 0) == insn
7958 && ((NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE)
7959 ? CALL_ATTR (XVECEXP (PATTERN (prev), 0, 0), NON_SIBCALL)
7960 : (CALL_ATTR (prev, NON_SIBCALL)
7961 && NEXT_INSN (PREV_INSN (prev)) == prev)))
7962 force_target = true;
7964 switch (type)
7966 case TYPE_BRCC:
7967 /* Short BRCC only comes in no-delay-slot version, and without limm */
7968 if (!delay_filled)
7970 ilv->align_set = 3;
7971 ilv->length = 2;
7972 ilv->branch_cost = 1;
7973 ilv->enabled = (len == 2);
7974 ilv->length_sensitive = ARC_LS_8;
7975 ilv++;
7977 /* Fall through. */
7978 case TYPE_BRCC_NO_DELAY_SLOT:
7979 /* doloop_fallback* patterns are TYPE_BRCC_NO_DELAY_SLOT for
7980 (delay slot) scheduling purposes, but they are longer. */
7981 if (GET_CODE (PATTERN (insn)) == PARALLEL
7982 && GET_CODE (XVECEXP (PATTERN (insn), 0, 1)) == SET)
7983 return 0;
7984 /* Standard BRCC: 4 bytes, or 8 bytes with limm. */
7985 ilv->length = ((type == TYPE_BRCC) ? 4 : 8);
7986 ilv->align_set = 3;
7987 ilv->branch_cost = branch_align_cost;
7988 ilv->enabled = (len <= ilv->length);
7989 ilv->length_sensitive = ARC_LS_9;
7990 if ((target_p || force_target)
7991 || (!delay_filled && TARGET_UNALIGN_BRANCH))
7993 ilv[1] = *ilv;
7994 ilv->align_set = 1;
7995 ilv++;
7996 ilv->align_set = 2;
7997 ilv->target_cost = 1;
7998 ilv->branch_cost = branch_unalign_cost;
8000 ilv++;
8002 rtx op, op0;
8003 op = XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 0);
8004 op0 = XEXP (op, 0);
8006 if (GET_CODE (op0) == ZERO_EXTRACT
8007 && satisfies_constraint_L (XEXP (op0, 2)))
8008 op0 = XEXP (op0, 0);
8009 if (satisfies_constraint_Rcq (op0))
8011 ilv->length = ((type == TYPE_BRCC) ? 6 : 10);
8012 ilv->align_set = 3;
8013 ilv->branch_cost = 1 + branch_align_cost;
8014 ilv->fallthrough_cost = 1;
8015 ilv->enabled = true;
8016 ilv->length_sensitive = ARC_LS_21;
8017 if (!delay_filled && TARGET_UNALIGN_BRANCH)
8019 ilv[1] = *ilv;
8020 ilv->align_set = 1;
8021 ilv++;
8022 ilv->align_set = 2;
8023 ilv->branch_cost = 1 + branch_unalign_cost;
8025 ilv++;
8027 ilv->length = ((type == TYPE_BRCC) ? 8 : 12);
8028 ilv->align_set = 3;
8029 ilv->branch_cost = 1 + branch_align_cost;
8030 ilv->fallthrough_cost = 1;
8031 ilv->enabled = true;
8032 ilv->length_sensitive = ARC_LS_21;
8033 if ((target_p || force_target)
8034 || (!delay_filled && TARGET_UNALIGN_BRANCH))
8036 ilv[1] = *ilv;
8037 ilv->align_set = 1;
8038 ilv++;
8039 ilv->align_set = 2;
8040 ilv->target_cost = 1;
8041 ilv->branch_cost = 1 + branch_unalign_cost;
8043 ilv++;
8044 break;
8046 case TYPE_SFUNC:
8047 ilv->length = 12;
8048 goto do_call;
8049 case TYPE_CALL_NO_DELAY_SLOT:
8050 ilv->length = 8;
8051 goto do_call;
8052 case TYPE_CALL:
8053 ilv->length = 4;
8054 ilv->length_sensitive
8055 = GET_CODE (PATTERN (insn)) == COND_EXEC ? ARC_LS_21 : ARC_LS_25;
8056 do_call:
8057 ilv->align_set = 3;
8058 ilv->fallthrough_cost = branch_align_cost;
8059 ilv->enabled = true;
8060 if ((target_p || force_target)
8061 || (!delay_filled && TARGET_UNALIGN_BRANCH))
8063 ilv[1] = *ilv;
8064 ilv->align_set = 1;
8065 ilv++;
8066 ilv->align_set = 2;
8067 ilv->target_cost = 1;
8068 ilv->fallthrough_cost = branch_unalign_cost;
8070 ilv++;
8071 break;
8072 case TYPE_UNCOND_BRANCH:
8073 /* Strictly speaking, this should be ARC_LS_10 for equality comparisons,
8074 but that makes no difference at the moment. */
8075 ilv->length_sensitive = ARC_LS_7;
8076 ilv[1].length_sensitive = ARC_LS_25;
8077 goto do_branch;
8078 case TYPE_BRANCH:
8079 ilv->length_sensitive = ARC_LS_10;
8080 ilv[1].length_sensitive = ARC_LS_21;
8081 do_branch:
8082 ilv->align_set = 3;
8083 ilv->length = 2;
8084 ilv->branch_cost = branch_align_cost;
8085 ilv->enabled = (len == ilv->length);
8086 ilv++;
8087 ilv->length = 4;
8088 ilv->align_set = 3;
8089 ilv->branch_cost = branch_align_cost;
8090 ilv->enabled = true;
8091 if ((target_p || force_target)
8092 || (!delay_filled && TARGET_UNALIGN_BRANCH))
8094 ilv[1] = *ilv;
8095 ilv->align_set = 1;
8096 ilv++;
8097 ilv->align_set = 2;
8098 ilv->target_cost = 1;
8099 ilv->branch_cost = branch_unalign_cost;
8101 ilv++;
8102 break;
8103 case TYPE_JUMP:
8104 return 0;
8105 default:
8106 /* For every short insn, there is generally also a long insn.
8107 trap_s is an exception. */
8108 if ((len & 2) == 0 || recog_memoized (insn) == CODE_FOR_trap_s)
8109 return 0;
8110 ilv->align_set = 3;
8111 ilv->length = len;
8112 ilv->enabled = 1;
8113 ilv++;
8114 ilv->align_set = 3;
8115 ilv->length = len + 2;
8116 ilv->enabled = 1;
8117 if (target_p || force_target)
8119 ilv[1] = *ilv;
8120 ilv->align_set = 1;
8121 ilv++;
8122 ilv->align_set = 2;
8123 ilv->target_cost = 1;
8125 ilv++;
8127 /* If the previous instruction is an sfunc call, this insn is always
8128 a target, even though the middle-end is unaware of this.
8129 Therefore, if we have a call predecessor, transfer the target cost
8130 to the fallthrough and branch costs. */
8131 if (force_target)
8133 for (insn_length_variant_t *p = first_ilv; p < ilv; p++)
8135 p->fallthrough_cost += p->target_cost;
8136 p->branch_cost += p->target_cost;
8137 p->target_cost = 0;
8141 return ilv - first_ilv;
8144 static void
8145 arc_insn_length_parameters (insn_length_parameters_t *ilp)
8147 ilp->align_unit_log = 1;
8148 ilp->align_base_log = 1;
8149 ilp->max_variants = 7;
8150 ilp->get_variants = arc_get_insn_variants;
8153 /* Return a copy of COND from *STATEP, inverted if that is indicated by the
8154 CC field of *STATEP. */
8156 static rtx
8157 arc_get_ccfsm_cond (struct arc_ccfsm *statep, bool reverse)
8159 rtx cond = statep->cond;
8160 int raw_cc = get_arc_condition_code (cond);
8161 if (reverse)
8162 raw_cc = ARC_INVERSE_CONDITION_CODE (raw_cc);
8164 if (statep->cc == raw_cc)
8165 return copy_rtx (cond);
8167 gcc_assert (ARC_INVERSE_CONDITION_CODE (raw_cc) == statep->cc);
8169 enum machine_mode ccm = GET_MODE (XEXP (cond, 0));
8170 enum rtx_code code = reverse_condition (GET_CODE (cond));
8171 if (code == UNKNOWN || ccm == CC_FP_GTmode || ccm == CC_FP_GEmode)
8172 code = reverse_condition_maybe_unordered (GET_CODE (cond));
8174 return gen_rtx_fmt_ee (code, GET_MODE (cond),
8175 copy_rtx (XEXP (cond, 0)), copy_rtx (XEXP (cond, 1)));
8178 /* Return version of PAT conditionalized with COND, which is part of INSN.
8179 ANNULLED indicates if INSN is an annulled delay-slot insn.
8180 Register further changes if necessary. */
8181 static rtx
8182 conditionalize_nonjump (rtx pat, rtx cond, rtx insn, bool annulled)
8184 /* For commutative operators, we generally prefer to have
8185 the first source match the destination. */
8186 if (GET_CODE (pat) == SET)
8188 rtx src = SET_SRC (pat);
8190 if (COMMUTATIVE_P (src))
8192 rtx src0 = XEXP (src, 0);
8193 rtx src1 = XEXP (src, 1);
8194 rtx dst = SET_DEST (pat);
8196 if (rtx_equal_p (src1, dst) && !rtx_equal_p (src0, dst)
8197 /* Leave add_n alone - the canonical form is to
8198 have the complex summand first. */
8199 && REG_P (src0))
8200 pat = gen_rtx_SET (VOIDmode, dst,
8201 gen_rtx_fmt_ee (GET_CODE (src), GET_MODE (src),
8202 src1, src0));
8206 /* dwarf2out.c:dwarf2out_frame_debug_expr doesn't know
8207 what to do with COND_EXEC. */
8208 if (RTX_FRAME_RELATED_P (insn))
8210 /* If this is the delay slot insn of an anulled branch,
8211 dwarf2out.c:scan_trace understands the anulling semantics
8212 without the COND_EXEC. */
8213 gcc_assert (annulled);
8214 rtx note = alloc_reg_note (REG_FRAME_RELATED_EXPR, pat,
8215 REG_NOTES (insn));
8216 validate_change (insn, &REG_NOTES (insn), note, 1);
8218 pat = gen_rtx_COND_EXEC (VOIDmode, cond, pat);
8219 return pat;
8222 /* Use the ccfsm machinery to do if conversion. */
8224 static unsigned
8225 arc_ifcvt (void)
8227 struct arc_ccfsm *statep = &cfun->machine->ccfsm_current;
8228 basic_block merge_bb = 0;
8230 memset (statep, 0, sizeof *statep);
8231 for (rtx insn = get_insns (); insn; insn = next_insn (insn))
8233 arc_ccfsm_advance (insn, statep);
8235 switch (statep->state)
8237 case 0:
8238 if (JUMP_P (insn))
8239 merge_bb = 0;
8240 break;
8241 case 1: case 2:
8243 /* Deleted branch. */
8244 gcc_assert (!merge_bb);
8245 merge_bb = BLOCK_FOR_INSN (insn);
8246 basic_block succ_bb
8247 = BLOCK_FOR_INSN (NEXT_INSN (NEXT_INSN (PREV_INSN (insn))));
8248 arc_ccfsm_post_advance (insn, statep);
8249 gcc_assert (!IN_RANGE (statep->state, 1, 2));
8250 rtx seq = NEXT_INSN (PREV_INSN (insn));
8251 if (seq != insn)
8253 rtx slot = XVECEXP (PATTERN (seq), 0, 1);
8254 rtx pat = PATTERN (slot);
8255 if (INSN_ANNULLED_BRANCH_P (insn))
8257 rtx cond
8258 = arc_get_ccfsm_cond (statep, INSN_FROM_TARGET_P (slot));
8259 pat = gen_rtx_COND_EXEC (VOIDmode, cond, pat);
8261 if (!validate_change (seq, &PATTERN (seq), pat, 0))
8262 gcc_unreachable ();
8263 PUT_CODE (slot, NOTE);
8264 NOTE_KIND (slot) = NOTE_INSN_DELETED;
8265 if (merge_bb && succ_bb)
8266 merge_blocks (merge_bb, succ_bb);
8268 else if (merge_bb && succ_bb)
8270 set_insn_deleted (insn);
8271 merge_blocks (merge_bb, succ_bb);
8273 else
8275 PUT_CODE (insn, NOTE);
8276 NOTE_KIND (insn) = NOTE_INSN_DELETED;
8278 continue;
8280 case 3:
8281 if (LABEL_P (insn)
8282 && statep->target_label == CODE_LABEL_NUMBER (insn))
8284 arc_ccfsm_post_advance (insn, statep);
8285 basic_block succ_bb = BLOCK_FOR_INSN (insn);
8286 if (merge_bb && succ_bb)
8287 merge_blocks (merge_bb, succ_bb);
8288 else if (--LABEL_NUSES (insn) == 0)
8290 const char *name = LABEL_NAME (insn);
8291 PUT_CODE (insn, NOTE);
8292 NOTE_KIND (insn) = NOTE_INSN_DELETED_LABEL;
8293 NOTE_DELETED_LABEL_NAME (insn) = name;
8295 merge_bb = 0;
8296 continue;
8298 /* Fall through. */
8299 case 4: case 5:
8300 if (!NONDEBUG_INSN_P (insn))
8301 break;
8303 /* Conditionalized insn. */
8305 rtx prev, pprev, *patp, pat, cond;
8306 bool annulled; annulled = false;
8308 /* If this is a delay slot insn in a non-annulled branch,
8309 don't conditionalize it. N.B., this should be fine for
8310 conditional return too. However, don't do this for
8311 unconditional branches, as these would be encountered when
8312 processing an 'else' part. */
8313 prev = PREV_INSN (insn);
8314 pprev = PREV_INSN (prev);
8315 if (pprev && NEXT_INSN (NEXT_INSN (pprev)) == NEXT_INSN (insn)
8316 && JUMP_P (prev) && get_attr_cond (prev) == COND_USE)
8318 if (!INSN_ANNULLED_BRANCH_P (prev))
8319 break;
8320 annulled = true;
8323 patp = &PATTERN (insn);
8324 pat = *patp;
8325 cond = arc_get_ccfsm_cond (statep, INSN_FROM_TARGET_P (insn));
8326 if (NONJUMP_INSN_P (insn) || CALL_P (insn))
8328 /* ??? don't conditionalize if all side effects are dead
8329 in the not-execute case. */
8331 pat = conditionalize_nonjump (pat, cond, insn, annulled);
8333 else if (simplejump_p (insn))
8335 patp = &SET_SRC (pat);
8336 pat = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, *patp, pc_rtx);
8338 else if (JUMP_P (insn) && ANY_RETURN_P (PATTERN (insn)))
8340 pat = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, pat, pc_rtx);
8341 pat = gen_rtx_SET (VOIDmode, pc_rtx, pat);
8343 else
8344 gcc_unreachable ();
8345 validate_change (insn, patp, pat, 1);
8346 if (!apply_change_group ())
8347 gcc_unreachable ();
8348 if (JUMP_P (insn))
8350 rtx next = next_nonnote_insn (insn);
8351 if (GET_CODE (next) == BARRIER)
8352 delete_insn (next);
8353 if (statep->state == 3)
8354 continue;
8356 break;
8357 default:
8358 gcc_unreachable ();
8360 arc_ccfsm_post_advance (insn, statep);
8362 return 0;
8365 /* Find annulled delay insns and convert them to use the appropriate predicate.
8366 This allows branch shortening to size up these insns properly. */
8368 static unsigned
8369 arc_predicate_delay_insns (void)
8371 for (rtx insn = get_insns (); insn; insn = NEXT_INSN (insn))
8373 rtx pat, jump, dlay, src, cond, *patp;
8374 int reverse;
8376 if (!NONJUMP_INSN_P (insn)
8377 || GET_CODE (pat = PATTERN (insn)) != SEQUENCE)
8378 continue;
8379 jump = XVECEXP (pat, 0, 0);
8380 dlay = XVECEXP (pat, 0, 1);
8381 if (!JUMP_P (jump) || !INSN_ANNULLED_BRANCH_P (jump))
8382 continue;
8383 /* If the branch insn does the annulling, leave the delay insn alone. */
8384 if (!TARGET_AT_DBR_CONDEXEC && !INSN_FROM_TARGET_P (dlay))
8385 continue;
8386 /* ??? Could also leave DLAY un-conditionalized if its target is dead
8387 on the other path. */
8388 gcc_assert (GET_CODE (PATTERN (jump)) == SET);
8389 gcc_assert (SET_DEST (PATTERN (jump)) == pc_rtx);
8390 src = SET_SRC (PATTERN (jump));
8391 gcc_assert (GET_CODE (src) == IF_THEN_ELSE);
8392 cond = XEXP (src, 0);
8393 if (XEXP (src, 2) == pc_rtx)
8394 reverse = 0;
8395 else if (XEXP (src, 1) == pc_rtx)
8396 reverse = 1;
8397 else
8398 gcc_unreachable ();
8399 if (!INSN_FROM_TARGET_P (dlay) != reverse)
8401 enum machine_mode ccm = GET_MODE (XEXP (cond, 0));
8402 enum rtx_code code = reverse_condition (GET_CODE (cond));
8403 if (code == UNKNOWN || ccm == CC_FP_GTmode || ccm == CC_FP_GEmode)
8404 code = reverse_condition_maybe_unordered (GET_CODE (cond));
8406 cond = gen_rtx_fmt_ee (code, GET_MODE (cond),
8407 copy_rtx (XEXP (cond, 0)),
8408 copy_rtx (XEXP (cond, 1)));
8410 else
8411 cond = copy_rtx (cond);
8412 patp = &PATTERN (dlay);
8413 pat = *patp;
8414 pat = conditionalize_nonjump (pat, cond, dlay, true);
8415 validate_change (dlay, patp, pat, 1);
8416 if (!apply_change_group ())
8417 gcc_unreachable ();
8419 return 0;
8422 /* For ARC600: If a write to a core reg >=32 appears in a delay slot
8423 (other than of a forward brcc), it creates a hazard when there is a read
8424 of the same register at the branch target. We can't know what is at the
8425 branch target of calls, and for branches, we don't really know before the
8426 end of delay slot scheduling, either. Not only can individual instruction
8427 be hoisted out into a delay slot, a basic block can also be emptied this
8428 way, and branch and/or fall through targets be redirected. Hence we don't
8429 want such writes in a delay slot. */
8430 /* Called by arc_write_ext_corereg via for_each_rtx. */
8432 static int
8433 write_ext_corereg_1 (rtx *xp, void *data ATTRIBUTE_UNUSED)
8435 rtx x = *xp;
8436 rtx dest;
8438 switch (GET_CODE (x))
8440 case SET: case POST_INC: case POST_DEC: case PRE_INC: case PRE_DEC:
8441 break;
8442 default:
8443 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
8444 return 0;
8446 dest = XEXP (x, 0);
8447 if (REG_P (dest) && REGNO (dest) >= 32 && REGNO (dest) < 61)
8448 return 1;
8449 return 0;
8452 /* Return nonzreo iff INSN writes to an extension core register. */
8455 arc_write_ext_corereg (rtx insn)
8457 return for_each_rtx (&PATTERN (insn), write_ext_corereg_1, 0);
8460 /* This is like the hook, but returns NULL when it can't / won't generate
8461 a legitimate address. */
8463 static rtx
8464 arc_legitimize_address_0 (rtx x, rtx oldx ATTRIBUTE_UNUSED,
8465 enum machine_mode mode)
8467 rtx addr, inner;
8469 if (flag_pic && SYMBOLIC_CONST (x))
8470 (x) = arc_legitimize_pic_address (x, 0);
8471 addr = x;
8472 if (GET_CODE (addr) == CONST)
8473 addr = XEXP (addr, 0);
8474 if (GET_CODE (addr) == PLUS
8475 && CONST_INT_P (XEXP (addr, 1))
8476 && ((GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
8477 && !SYMBOL_REF_FUNCTION_P (XEXP (addr, 0)))
8478 || (REG_P (XEXP (addr, 0))
8479 && (INTVAL (XEXP (addr, 1)) & 252))))
8481 HOST_WIDE_INT offs, upper;
8482 int size = GET_MODE_SIZE (mode);
8484 offs = INTVAL (XEXP (addr, 1));
8485 upper = (offs + 256 * size) & ~511 * size;
8486 inner = plus_constant (Pmode, XEXP (addr, 0), upper);
8487 #if 0 /* ??? this produces worse code for EEMBC idctrn01 */
8488 if (GET_CODE (x) == CONST)
8489 inner = gen_rtx_CONST (Pmode, inner);
8490 #endif
8491 addr = plus_constant (Pmode, force_reg (Pmode, inner), offs - upper);
8492 x = addr;
8494 else if (GET_CODE (addr) == SYMBOL_REF && !SYMBOL_REF_FUNCTION_P (addr))
8495 x = force_reg (Pmode, x);
8496 if (memory_address_p ((enum machine_mode) mode, x))
8497 return x;
8498 return NULL_RTX;
8501 static rtx
8502 arc_legitimize_address (rtx orig_x, rtx oldx, enum machine_mode mode)
8504 rtx new_x = arc_legitimize_address_0 (orig_x, oldx, mode);
8506 if (new_x)
8507 return new_x;
8508 return orig_x;
8511 static rtx
8512 arc_delegitimize_address_0 (rtx x)
8514 rtx u, gp;
8516 if (GET_CODE (x) == CONST && GET_CODE (u = XEXP (x, 0)) == UNSPEC)
8518 if (XINT (u, 1) == ARC_UNSPEC_GOT)
8519 return XVECEXP (u, 0, 0);
8521 else if (GET_CODE (x) == PLUS
8522 && ((REG_P (gp = XEXP (x, 0))
8523 && REGNO (gp) == PIC_OFFSET_TABLE_REGNUM)
8524 || (GET_CODE (gp) == CONST
8525 && GET_CODE (u = XEXP (gp, 0)) == UNSPEC
8526 && XINT (u, 1) == ARC_UNSPEC_GOT
8527 && GET_CODE (XVECEXP (u, 0, 0)) == SYMBOL_REF
8528 && !strcmp (XSTR (XVECEXP (u, 0, 0), 0), "_DYNAMIC")))
8529 && GET_CODE (XEXP (x, 1)) == CONST
8530 && GET_CODE (u = XEXP (XEXP (x, 1), 0)) == UNSPEC
8531 && XINT (u, 1) == ARC_UNSPEC_GOTOFF)
8532 return XVECEXP (u, 0, 0);
8533 else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
8534 && ((REG_P (gp = XEXP (XEXP (x, 0), 1))
8535 && REGNO (gp) == PIC_OFFSET_TABLE_REGNUM)
8536 || (GET_CODE (gp) == CONST
8537 && GET_CODE (u = XEXP (gp, 0)) == UNSPEC
8538 && XINT (u, 1) == ARC_UNSPEC_GOT
8539 && GET_CODE (XVECEXP (u, 0, 0)) == SYMBOL_REF
8540 && !strcmp (XSTR (XVECEXP (u, 0, 0), 0), "_DYNAMIC")))
8541 && GET_CODE (XEXP (x, 1)) == CONST
8542 && GET_CODE (u = XEXP (XEXP (x, 1), 0)) == UNSPEC
8543 && XINT (u, 1) == ARC_UNSPEC_GOTOFF)
8544 return gen_rtx_PLUS (GET_MODE (x), XEXP (XEXP (x, 0), 0),
8545 XVECEXP (u, 0, 0));
8546 else if (GET_CODE (x) == PLUS
8547 && (u = arc_delegitimize_address_0 (XEXP (x, 1))))
8548 return gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0), u);
8549 return NULL_RTX;
8552 static rtx
8553 arc_delegitimize_address (rtx x)
8555 rtx orig_x = x = delegitimize_mem_from_attrs (x);
8556 if (GET_CODE (x) == MEM)
8557 x = XEXP (x, 0);
8558 x = arc_delegitimize_address_0 (x);
8559 if (x)
8561 if (MEM_P (orig_x))
8562 x = replace_equiv_address_nv (orig_x, x);
8563 return x;
8565 return orig_x;
8568 /* Return a REG rtx for acc1. N.B. the gcc-internal representation may
8569 differ from the hardware register number in order to allow the generic
8570 code to correctly split the concatenation of acc1 and acc2. */
8573 gen_acc1 (void)
8575 return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 56: 57);
8578 /* Return a REG rtx for acc2. N.B. the gcc-internal representation may
8579 differ from the hardware register number in order to allow the generic
8580 code to correctly split the concatenation of acc1 and acc2. */
8583 gen_acc2 (void)
8585 return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 57: 56);
8588 /* Return a REG rtx for mlo. N.B. the gcc-internal representation may
8589 differ from the hardware register number in order to allow the generic
8590 code to correctly split the concatenation of mhi and mlo. */
8593 gen_mlo (void)
8595 return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 59: 58);
8598 /* Return a REG rtx for mhi. N.B. the gcc-internal representation may
8599 differ from the hardware register number in order to allow the generic
8600 code to correctly split the concatenation of mhi and mlo. */
8603 gen_mhi (void)
8605 return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 58: 59);
8608 /* FIXME: a parameter should be added, and code added to final.c,
8609 to reproduce this functionality in shorten_branches. */
8610 #if 0
8611 /* Return nonzero iff BRANCH should be unaligned if possible by upsizing
8612 a previous instruction. */
8614 arc_unalign_branch_p (rtx branch)
8616 rtx note;
8618 if (!TARGET_UNALIGN_BRANCH)
8619 return 0;
8620 /* Do not do this if we have a filled delay slot. */
8621 if (get_attr_delay_slot_filled (branch) == DELAY_SLOT_FILLED_YES
8622 && !INSN_DELETED_P (NEXT_INSN (branch)))
8623 return 0;
8624 note = find_reg_note (branch, REG_BR_PROB, 0);
8625 return (!note
8626 || (arc_unalign_prob_threshold && !br_prob_note_reliable_p (note))
8627 || INTVAL (XEXP (note, 0)) < arc_unalign_prob_threshold);
8629 #endif
8631 /* When estimating sizes during arc_reorg, when optimizing for speed, there
8632 are three reasons why we need to consider branches to be length 6:
8633 - annull-false delay slot insns are implemented using conditional execution,
8634 thus preventing short insn formation where used.
8635 - for ARC600: annul-true delay slot insns are implemented where possible
8636 using conditional execution, preventing short insn formation where used.
8637 - for ARC700: likely or somewhat likely taken branches are made long and
8638 unaligned if possible to avoid branch penalty. */
8640 bool
8641 arc_branch_size_unknown_p (void)
8643 return !optimize_size && arc_reorg_in_progress;
8646 /* We are about to output a return insn. Add padding if necessary to avoid
8647 a mispredict. A return could happen immediately after the function
8648 start, but after a call we know that there will be at least a blink
8649 restore. */
8651 void
8652 arc_pad_return (void)
8654 rtx insn = current_output_insn;
8655 rtx prev = prev_active_insn (insn);
8656 int want_long;
8658 if (!prev)
8660 fputs ("\tnop_s\n", asm_out_file);
8661 cfun->machine->unalign ^= 2;
8662 want_long = 1;
8664 /* If PREV is a sequence, we know it must be a branch / jump or a tailcall,
8665 because after a call, we'd have to restore blink first. */
8666 else if (GET_CODE (PATTERN (prev)) == SEQUENCE)
8667 return;
8668 else
8670 want_long = (get_attr_length (prev) == 2);
8671 prev = prev_active_insn (prev);
8673 if (!prev
8674 || ((NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE)
8675 ? CALL_ATTR (XVECEXP (PATTERN (prev), 0, 0), NON_SIBCALL)
8676 : CALL_ATTR (prev, NON_SIBCALL)))
8678 if (want_long)
8679 cfun->machine->size_reason
8680 = "call/return and return/return must be 6 bytes apart to avoid mispredict";
8681 else if (TARGET_UNALIGN_BRANCH && cfun->machine->unalign)
8683 cfun->machine->size_reason
8684 = "Long unaligned jump avoids non-delay slot penalty";
8685 want_long = 1;
8687 /* Disgorge delay insn, if there is any, and it may be moved. */
8688 if (final_sequence
8689 /* ??? Annulled would be OK if we can and do conditionalize
8690 the delay slot insn accordingly. */
8691 && !INSN_ANNULLED_BRANCH_P (insn)
8692 && (get_attr_cond (insn) != COND_USE
8693 || !reg_set_p (gen_rtx_REG (CCmode, CC_REG),
8694 XVECEXP (final_sequence, 0, 1))))
8696 prev = XVECEXP (final_sequence, 0, 1);
8697 gcc_assert (!prev_real_insn (insn)
8698 || !arc_hazard (prev_real_insn (insn), prev));
8699 cfun->machine->force_short_suffix = !want_long;
8700 rtx save_pred = current_insn_predicate;
8701 final_scan_insn (prev, asm_out_file, optimize, 1, NULL);
8702 cfun->machine->force_short_suffix = -1;
8703 INSN_DELETED_P (prev) = 1;
8704 current_output_insn = insn;
8705 current_insn_predicate = save_pred;
8707 else if (want_long)
8708 fputs ("\tnop\n", asm_out_file);
8709 else
8711 fputs ("\tnop_s\n", asm_out_file);
8712 cfun->machine->unalign ^= 2;
8715 return;
8718 /* The usual; we set up our machine_function data. */
8720 static struct machine_function *
8721 arc_init_machine_status (void)
8723 struct machine_function *machine;
8724 machine = ggc_cleared_alloc<machine_function> ();
8725 machine->fn_type = ARC_FUNCTION_UNKNOWN;
8726 machine->force_short_suffix = -1;
8728 return machine;
8731 /* Implements INIT_EXPANDERS. We just set up to call the above
8732 function. */
8734 void
8735 arc_init_expanders (void)
8737 init_machine_status = arc_init_machine_status;
8740 /* Check if OP is a proper parallel of a millicode call pattern. OFFSET
8741 indicates a number of elements to ignore - that allows to have a
8742 sibcall pattern that starts with (return). LOAD_P is zero for store
8743 multiple (for prologues), and one for load multiples (for epilogues),
8744 and two for load multiples where no final clobber of blink is required.
8745 We also skip the first load / store element since this is supposed to
8746 be checked in the instruction pattern. */
8749 arc_check_millicode (rtx op, int offset, int load_p)
8751 int len = XVECLEN (op, 0) - offset;
8752 int i;
8754 if (load_p == 2)
8756 if (len < 2 || len > 13)
8757 return 0;
8758 load_p = 1;
8760 else
8762 rtx elt = XVECEXP (op, 0, --len);
8764 if (GET_CODE (elt) != CLOBBER
8765 || !REG_P (XEXP (elt, 0))
8766 || REGNO (XEXP (elt, 0)) != RETURN_ADDR_REGNUM
8767 || len < 3 || len > 13)
8768 return 0;
8770 for (i = 1; i < len; i++)
8772 rtx elt = XVECEXP (op, 0, i + offset);
8773 rtx reg, mem, addr;
8775 if (GET_CODE (elt) != SET)
8776 return 0;
8777 mem = XEXP (elt, load_p);
8778 reg = XEXP (elt, 1-load_p);
8779 if (!REG_P (reg) || REGNO (reg) != 13U+i || !MEM_P (mem))
8780 return 0;
8781 addr = XEXP (mem, 0);
8782 if (GET_CODE (addr) != PLUS
8783 || !rtx_equal_p (stack_pointer_rtx, XEXP (addr, 0))
8784 || !CONST_INT_P (XEXP (addr, 1)) || INTVAL (XEXP (addr, 1)) != i*4)
8785 return 0;
8787 return 1;
8790 /* Accessor functions for cfun->machine->unalign. */
8793 arc_get_unalign (void)
8795 return cfun->machine->unalign;
8798 void
8799 arc_clear_unalign (void)
8801 if (cfun)
8802 cfun->machine->unalign = 0;
8805 void
8806 arc_toggle_unalign (void)
8808 cfun->machine->unalign ^= 2;
8811 /* Operands 0..2 are the operands of a addsi which uses a 12 bit
8812 constant in operand 2, but which would require a LIMM because of
8813 operand mismatch.
8814 operands 3 and 4 are new SET_SRCs for operands 0. */
8816 void
8817 split_addsi (rtx *operands)
8819 int val = INTVAL (operands[2]);
8821 /* Try for two short insns first. Lengths being equal, we prefer
8822 expansions with shorter register lifetimes. */
8823 if (val > 127 && val <= 255
8824 && satisfies_constraint_Rcq (operands[0]))
8826 operands[3] = operands[2];
8827 operands[4] = gen_rtx_PLUS (SImode, operands[0], operands[1]);
8829 else
8831 operands[3] = operands[1];
8832 operands[4] = gen_rtx_PLUS (SImode, operands[0], operands[2]);
8836 /* Operands 0..2 are the operands of a subsi which uses a 12 bit
8837 constant in operand 1, but which would require a LIMM because of
8838 operand mismatch.
8839 operands 3 and 4 are new SET_SRCs for operands 0. */
8841 void
8842 split_subsi (rtx *operands)
8844 int val = INTVAL (operands[1]);
8846 /* Try for two short insns first. Lengths being equal, we prefer
8847 expansions with shorter register lifetimes. */
8848 if (satisfies_constraint_Rcq (operands[0])
8849 && satisfies_constraint_Rcq (operands[2]))
8851 if (val >= -31 && val <= 127)
8853 operands[3] = gen_rtx_NEG (SImode, operands[2]);
8854 operands[4] = gen_rtx_PLUS (SImode, operands[0], operands[1]);
8855 return;
8857 else if (val >= 0 && val < 255)
8859 operands[3] = operands[1];
8860 operands[4] = gen_rtx_MINUS (SImode, operands[0], operands[2]);
8861 return;
8864 /* If the destination is not an ARCompact16 register, we might
8865 still have a chance to make a short insn if the source is;
8866 we need to start with a reg-reg move for this. */
8867 operands[3] = operands[2];
8868 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[0]);
8871 /* Handle DOUBLE_REGS uses.
8872 Operand 0: destination register
8873 Operand 1: source register */
8875 static rtx
8876 arc_process_double_reg_moves (rtx *operands)
8878 rtx dest = operands[0];
8879 rtx src = operands[1];
8880 rtx val;
8882 enum usesDxState { none, srcDx, destDx, maxDx };
8883 enum usesDxState state = none;
8885 if (refers_to_regno_p (40, 44, src, 0))
8886 state = srcDx;
8887 if (refers_to_regno_p (40, 44, dest, 0))
8889 /* Via arc_register_move_cost, we should never see D,D moves. */
8890 gcc_assert (state == none);
8891 state = destDx;
8894 if (state == none)
8895 return NULL_RTX;
8897 start_sequence ();
8899 if (state == srcDx)
8901 /* Without the LR insn, we need to split this into a
8902 sequence of insns which will use the DEXCLx and DADDHxy
8903 insns to be able to read the Dx register in question. */
8904 if (TARGET_DPFP_DISABLE_LRSR)
8906 /* gen *movdf_insn_nolrsr */
8907 rtx set = gen_rtx_SET (VOIDmode, dest, src);
8908 rtx use1 = gen_rtx_USE (VOIDmode, const1_rtx);
8909 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, use1)));
8911 else
8913 /* When we have 'mov D, r' or 'mov D, D' then get the target
8914 register pair for use with LR insn. */
8915 rtx destHigh = simplify_gen_subreg(SImode, dest, DFmode, 4);
8916 rtx destLow = simplify_gen_subreg(SImode, dest, DFmode, 0);
8918 /* Produce the two LR insns to get the high and low parts. */
8919 emit_insn (gen_rtx_SET (VOIDmode,
8920 destHigh,
8921 gen_rtx_UNSPEC_VOLATILE (Pmode, gen_rtvec (1, src),
8922 VUNSPEC_LR_HIGH)));
8923 emit_insn (gen_rtx_SET (VOIDmode,
8924 destLow,
8925 gen_rtx_UNSPEC_VOLATILE (Pmode, gen_rtvec (1, src),
8926 VUNSPEC_LR)));
8929 else if (state == destDx)
8931 /* When we have 'mov r, D' or 'mov D, D' and we have access to the
8932 LR insn get the target register pair. */
8933 rtx srcHigh = simplify_gen_subreg(SImode, src, DFmode, 4);
8934 rtx srcLow = simplify_gen_subreg(SImode, src, DFmode, 0);
8936 emit_insn (gen_rtx_UNSPEC_VOLATILE (Pmode,
8937 gen_rtvec (3, dest, srcHigh, srcLow),
8938 VUNSPEC_DEXCL_NORES));
8941 else
8942 gcc_unreachable ();
8944 val = get_insns ();
8945 end_sequence ();
8946 return val;
8949 /* operands 0..1 are the operands of a 64 bit move instruction.
8950 split it into two moves with operands 2/3 and 4/5. */
8953 arc_split_move (rtx *operands)
8955 enum machine_mode mode = GET_MODE (operands[0]);
8956 int i;
8957 int swap = 0;
8958 rtx xop[4];
8959 rtx val;
8961 if (TARGET_DPFP)
8963 val = arc_process_double_reg_moves (operands);
8964 if (val)
8965 return val;
8968 for (i = 0; i < 2; i++)
8970 if (MEM_P (operands[i]) && auto_inc_p (XEXP (operands[i], 0)))
8972 rtx addr = XEXP (operands[i], 0);
8973 rtx r, o;
8974 enum rtx_code code;
8976 gcc_assert (!reg_overlap_mentioned_p (operands[0], addr));
8977 switch (GET_CODE (addr))
8979 case PRE_DEC: o = GEN_INT (-8); goto pre_modify;
8980 case PRE_INC: o = GEN_INT (8); goto pre_modify;
8981 case PRE_MODIFY: o = XEXP (XEXP (addr, 1), 1);
8982 pre_modify:
8983 code = PRE_MODIFY;
8984 break;
8985 case POST_DEC: o = GEN_INT (-8); goto post_modify;
8986 case POST_INC: o = GEN_INT (8); goto post_modify;
8987 case POST_MODIFY: o = XEXP (XEXP (addr, 1), 1);
8988 post_modify:
8989 code = POST_MODIFY;
8990 swap = 2;
8991 break;
8992 default:
8993 gcc_unreachable ();
8995 r = XEXP (addr, 0);
8996 xop[0+i] = adjust_automodify_address_nv
8997 (operands[i], SImode,
8998 gen_rtx_fmt_ee (code, Pmode, r,
8999 gen_rtx_PLUS (Pmode, r, o)),
9001 xop[2+i] = adjust_automodify_address_nv
9002 (operands[i], SImode, plus_constant (Pmode, r, 4), 4);
9004 else
9006 xop[0+i] = operand_subword (operands[i], 0, 0, mode);
9007 xop[2+i] = operand_subword (operands[i], 1, 0, mode);
9010 if (reg_overlap_mentioned_p (xop[0], xop[3]))
9012 swap = 2;
9013 gcc_assert (!reg_overlap_mentioned_p (xop[2], xop[1]));
9015 operands[2+swap] = xop[0];
9016 operands[3+swap] = xop[1];
9017 operands[4-swap] = xop[2];
9018 operands[5-swap] = xop[3];
9020 start_sequence ();
9021 emit_insn (gen_rtx_SET (VOIDmode, operands[2], operands[3]));
9022 emit_insn (gen_rtx_SET (VOIDmode, operands[4], operands[5]));
9023 val = get_insns ();
9024 end_sequence ();
9026 return val;
9029 /* Select between the instruction output templates s_tmpl (for short INSNs)
9030 and l_tmpl (for long INSNs). */
9032 const char *
9033 arc_short_long (rtx insn, const char *s_tmpl, const char *l_tmpl)
9035 int is_short = arc_verify_short (insn, cfun->machine->unalign, -1);
9037 extract_constrain_insn_cached (insn);
9038 return is_short ? s_tmpl : l_tmpl;
9041 /* Searches X for any reference to REGNO, returning the rtx of the
9042 reference found if any. Otherwise, returns NULL_RTX. */
9045 arc_regno_use_in (unsigned int regno, rtx x)
9047 const char *fmt;
9048 int i, j;
9049 rtx tem;
9051 if (REG_P (x) && refers_to_regno_p (regno, regno+1, x, (rtx *) 0))
9052 return x;
9054 fmt = GET_RTX_FORMAT (GET_CODE (x));
9055 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
9057 if (fmt[i] == 'e')
9059 if ((tem = regno_use_in (regno, XEXP (x, i))))
9060 return tem;
9062 else if (fmt[i] == 'E')
9063 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
9064 if ((tem = regno_use_in (regno , XVECEXP (x, i, j))))
9065 return tem;
9068 return NULL_RTX;
9071 /* Return the integer value of the "type" attribute for INSN, or -1 if
9072 INSN can't have attributes. */
9075 arc_attr_type (rtx insn)
9077 if (NONJUMP_INSN_P (insn)
9078 ? (GET_CODE (PATTERN (insn)) == USE
9079 || GET_CODE (PATTERN (insn)) == CLOBBER)
9080 : JUMP_P (insn)
9081 ? (GET_CODE (PATTERN (insn)) == ADDR_VEC
9082 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
9083 : !CALL_P (insn))
9084 return -1;
9085 return get_attr_type (insn);
9088 /* Return true if insn sets the condition codes. */
9090 bool
9091 arc_sets_cc_p (rtx insn)
9093 if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
9094 insn = XVECEXP (PATTERN (insn), 0, XVECLEN (PATTERN (insn), 0) - 1);
9095 return arc_attr_type (insn) == TYPE_COMPARE;
9098 /* Return true if INSN is an instruction with a delay slot we may want
9099 to fill. */
9101 bool
9102 arc_need_delay (rtx insn)
9104 rtx next;
9106 if (!flag_delayed_branch)
9107 return false;
9108 /* The return at the end of a function needs a delay slot. */
9109 if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
9110 && (!(next = next_active_insn (insn))
9111 || ((!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) != SEQUENCE)
9112 && arc_attr_type (next) == TYPE_RETURN))
9113 && (!TARGET_PAD_RETURN
9114 || (prev_active_insn (insn)
9115 && prev_active_insn (prev_active_insn (insn))
9116 && prev_active_insn (prev_active_insn (prev_active_insn (insn))))))
9117 return true;
9118 if (NONJUMP_INSN_P (insn)
9119 ? (GET_CODE (PATTERN (insn)) == USE
9120 || GET_CODE (PATTERN (insn)) == CLOBBER
9121 || GET_CODE (PATTERN (insn)) == SEQUENCE)
9122 : JUMP_P (insn)
9123 ? (GET_CODE (PATTERN (insn)) == ADDR_VEC
9124 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
9125 : !CALL_P (insn))
9126 return false;
9127 return num_delay_slots (insn) != 0;
9130 /* Return true if the scheduling pass(es) has/have already run,
9131 i.e. where possible, we should try to mitigate high latencies
9132 by different instruction selection. */
9134 bool
9135 arc_scheduling_not_expected (void)
9137 return cfun->machine->arc_reorg_started;
9140 /* Oddly enough, sometimes we get a zero overhead loop that branch
9141 shortening doesn't think is a loop - observed with compile/pr24883.c
9142 -O3 -fomit-frame-pointer -funroll-loops. Make sure to include the
9143 alignment visible for branch shortening (we actually align the loop
9144 insn before it, but that is equivalent since the loop insn is 4 byte
9145 long.) */
9148 arc_label_align (rtx label)
9150 int loop_align = LOOP_ALIGN (LABEL);
9152 if (loop_align > align_labels_log)
9154 rtx prev = prev_nonnote_insn (label);
9156 if (prev && NONJUMP_INSN_P (prev)
9157 && GET_CODE (PATTERN (prev)) == PARALLEL
9158 && recog_memoized (prev) == CODE_FOR_doloop_begin_i)
9159 return loop_align;
9161 /* Code has a minimum p2 alignment of 1, which we must restore after an
9162 ADDR_DIFF_VEC. */
9163 if (align_labels_log < 1)
9165 rtx next = next_nonnote_nondebug_insn (label);
9166 if (INSN_P (next) && recog_memoized (next) >= 0)
9167 return 1;
9169 return align_labels_log;
9172 /* Return true if LABEL is in executable code. */
9174 bool
9175 arc_text_label (rtx label)
9177 rtx next;
9179 /* ??? We use deleted labels like they were still there, see
9180 gcc.c-torture/compile/20000326-2.c . */
9181 gcc_assert (GET_CODE (label) == CODE_LABEL
9182 || (GET_CODE (label) == NOTE
9183 && NOTE_KIND (label) == NOTE_INSN_DELETED_LABEL));
9184 next = next_nonnote_insn (label);
9185 if (next)
9186 return (!JUMP_TABLE_DATA_P (next)
9187 || GET_CODE (PATTERN (next)) != ADDR_VEC);
9188 else if (!PREV_INSN (label))
9189 /* ??? sometimes text labels get inserted very late, see
9190 gcc.dg/torture/stackalign/comp-goto-1.c */
9191 return true;
9192 return false;
9195 /* Return the size of the pretend args for DECL. */
9198 arc_decl_pretend_args (tree decl)
9200 /* struct function is in DECL_STRUCT_FUNCTION (decl), but no
9201 pretend_args there... See PR38391. */
9202 gcc_assert (decl == current_function_decl);
9203 return crtl->args.pretend_args_size;
9206 /* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
9207 when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
9208 -D_PROFILE_USE; delay branch scheduling then follows a crossing jump
9209 to redirect two breqs. */
9211 static bool
9212 arc_can_follow_jump (const_rtx follower, const_rtx followee)
9214 /* ??? get_attr_type is declared to take an rtx. */
9215 union { const_rtx c; rtx r; } u;
9217 u.c = follower;
9218 if (CROSSING_JUMP_P (followee))
9219 switch (get_attr_type (u.r))
9221 case TYPE_BRCC:
9222 case TYPE_BRCC_NO_DELAY_SLOT:
9223 return false;
9224 default:
9225 return true;
9227 return true;
9230 /* Implement EPILOGUE__USES.
9231 Return true if REGNO should be added to the deemed uses of the epilogue.
9233 We use the return address
9234 arc_return_address_regs[arc_compute_function_type (cfun)] .
9235 But also, we have to make sure all the register restore instructions
9236 are known to be live in interrupt functions. */
9238 bool
9239 arc_epilogue_uses (int regno)
9241 if (reload_completed)
9243 if (ARC_INTERRUPT_P (cfun->machine->fn_type))
9245 if (!fixed_regs[regno])
9246 return true;
9247 return regno == arc_return_address_regs[cfun->machine->fn_type];
9249 else
9250 return regno == RETURN_ADDR_REGNUM;
9252 else
9253 return regno == arc_return_address_regs[arc_compute_function_type (cfun)];
9256 #ifndef TARGET_NO_LRA
9257 #define TARGET_NO_LRA !TARGET_LRA
9258 #endif
9260 static bool
9261 arc_lra_p (void)
9263 return !TARGET_NO_LRA;
9266 /* ??? Should we define TARGET_REGISTER_PRIORITY? We might perfer to use
9267 Rcq registers, because some insn are shorter with them. OTOH we already
9268 have separate alternatives for this purpose, and other insns don't
9269 mind, so maybe we should rather prefer the other registers?
9270 We need more data, and we can only get that if we allow people to
9271 try all options. */
9272 static int
9273 arc_register_priority (int r)
9275 switch (arc_lra_priority_tag)
9277 case ARC_LRA_PRIORITY_NONE:
9278 return 0;
9279 case ARC_LRA_PRIORITY_NONCOMPACT:
9280 return ((((r & 7) ^ 4) - 4) & 15) != r;
9281 case ARC_LRA_PRIORITY_COMPACT:
9282 return ((((r & 7) ^ 4) - 4) & 15) == r;
9283 default:
9284 gcc_unreachable ();
9288 static reg_class_t
9289 arc_spill_class (reg_class_t /* orig_class */, enum machine_mode)
9291 return GENERAL_REGS;
9294 bool
9295 arc_legitimize_reload_address (rtx *p, enum machine_mode mode, int opnum,
9296 int itype)
9298 rtx x = *p;
9299 enum reload_type type = (enum reload_type) itype;
9301 if (GET_CODE (x) == PLUS
9302 && CONST_INT_P (XEXP (x, 1))
9303 && (RTX_OK_FOR_BASE_P (XEXP (x, 0), true)
9304 || (REG_P (XEXP (x, 0))
9305 && reg_equiv_constant (REGNO (XEXP (x, 0))))))
9307 int scale = GET_MODE_SIZE (mode);
9308 int shift;
9309 rtx index_rtx = XEXP (x, 1);
9310 HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base;
9311 rtx reg, sum, sum2;
9313 if (scale > 4)
9314 scale = 4;
9315 if ((scale-1) & offset)
9316 scale = 1;
9317 shift = scale >> 1;
9318 offset_base = (offset + (256 << shift)) & (-512 << shift);
9319 /* Sometimes the normal form does not suit DImode. We
9320 could avoid that by using smaller ranges, but that
9321 would give less optimized code when SImode is
9322 prevalent. */
9323 if (GET_MODE_SIZE (mode) + offset - offset_base <= (256 << shift))
9325 int regno;
9327 reg = XEXP (x, 0);
9328 regno = REGNO (reg);
9329 sum2 = sum = plus_constant (Pmode, reg, offset_base);
9331 if (reg_equiv_constant (regno))
9333 sum2 = plus_constant (Pmode, reg_equiv_constant (regno),
9334 offset_base);
9335 if (GET_CODE (sum2) == PLUS)
9336 sum2 = gen_rtx_CONST (Pmode, sum2);
9338 *p = gen_rtx_PLUS (Pmode, sum, GEN_INT (offset - offset_base));
9339 push_reload (sum2, NULL_RTX, &XEXP (*p, 0), NULL,
9340 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, opnum,
9341 type);
9342 return true;
9345 /* We must re-recognize what we created before. */
9346 else if (GET_CODE (x) == PLUS
9347 && GET_CODE (XEXP (x, 0)) == PLUS
9348 && CONST_INT_P (XEXP (XEXP (x, 0), 1))
9349 && REG_P (XEXP (XEXP (x, 0), 0))
9350 && CONST_INT_P (XEXP (x, 1)))
9352 /* Because this address is so complex, we know it must have
9353 been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,
9354 it is already unshared, and needs no further unsharing. */
9355 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
9356 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, opnum, type);
9357 return true;
9359 return false;
9362 struct gcc_target targetm = TARGET_INITIALIZER;
9364 #include "gt-arc.h"