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