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