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