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