]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arc/arc.c
Add crtfastmath for AArch64.
[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"
9b2b7279 69#include "builtins.h"
526b7aee
SV
70
71/* Which cpu we're compiling for (A5, ARC600, ARC601, ARC700). */
72static const char *arc_cpu_string = "";
73
74/* ??? Loads can handle any constant, stores can only handle small ones. */
75/* OTOH, LIMMs cost extra, so their usefulness is limited. */
76#define RTX_OK_FOR_OFFSET_P(MODE, X) \
77(GET_CODE (X) == CONST_INT \
78 && SMALL_INT_RANGE (INTVAL (X), (GET_MODE_SIZE (MODE) - 1) & -4, \
79 (INTVAL (X) & (GET_MODE_SIZE (MODE) - 1) & 3 \
80 ? 0 \
81 : -(-GET_MODE_SIZE (MODE) | -4) >> 1)))
82
83#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X, INDEX, STRICT) \
84(GET_CODE (X) == PLUS \
85 && RTX_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
86 && ((INDEX && RTX_OK_FOR_INDEX_P (XEXP (X, 1), (STRICT)) \
87 && GET_MODE_SIZE ((MODE)) <= 4) \
88 || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
89
90#define LEGITIMATE_SCALED_ADDRESS_P(MODE, X, STRICT) \
91(GET_CODE (X) == PLUS \
92 && GET_CODE (XEXP (X, 0)) == MULT \
93 && RTX_OK_FOR_INDEX_P (XEXP (XEXP (X, 0), 0), (STRICT)) \
94 && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
95 && ((GET_MODE_SIZE (MODE) == 2 && INTVAL (XEXP (XEXP (X, 0), 1)) == 2) \
96 || (GET_MODE_SIZE (MODE) == 4 && INTVAL (XEXP (XEXP (X, 0), 1)) == 4)) \
97 && (RTX_OK_FOR_BASE_P (XEXP (X, 1), (STRICT)) \
98 || (flag_pic ? CONST_INT_P (XEXP (X, 1)) : CONSTANT_P (XEXP (X, 1)))))
99
100#define LEGITIMATE_SMALL_DATA_ADDRESS_P(X) \
101 (GET_CODE (X) == PLUS \
102 && (REG_P (XEXP ((X), 0)) && REGNO (XEXP ((X), 0)) == SDATA_BASE_REGNUM) \
103 && ((GET_CODE (XEXP((X),1)) == SYMBOL_REF \
104 && SYMBOL_REF_SMALL_P (XEXP ((X), 1))) \
105 || (GET_CODE (XEXP ((X), 1)) == CONST \
106 && GET_CODE (XEXP (XEXP ((X), 1), 0)) == PLUS \
107 && GET_CODE (XEXP (XEXP (XEXP ((X), 1), 0), 0)) == SYMBOL_REF \
108 && SYMBOL_REF_SMALL_P (XEXP (XEXP (XEXP ((X), 1), 0), 0)) \
109 && GET_CODE (XEXP(XEXP (XEXP ((X), 1), 0), 1)) == CONST_INT)))
110
111/* Array of valid operand punctuation characters. */
112char arc_punct_chars[256];
113
114/* State used by arc_ccfsm_advance to implement conditional execution. */
115struct GTY (()) arc_ccfsm
116{
117 int state;
118 int cc;
119 rtx cond;
b3458f61 120 rtx_insn *target_insn;
526b7aee
SV
121 int target_label;
122};
123
124#define arc_ccfsm_current cfun->machine->ccfsm_current
125
126#define ARC_CCFSM_BRANCH_DELETED_P(STATE) \
127 ((STATE)->state == 1 || (STATE)->state == 2)
128
129/* Indicate we're conditionalizing insns now. */
130#define ARC_CCFSM_RECORD_BRANCH_DELETED(STATE) \
131 ((STATE)->state += 2)
132
133#define ARC_CCFSM_COND_EXEC_P(STATE) \
134 ((STATE)->state == 3 || (STATE)->state == 4 || (STATE)->state == 5 \
135 || current_insn_predicate)
136
137/* Check if INSN has a 16 bit opcode considering struct arc_ccfsm *STATE. */
138#define CCFSM_ISCOMPACT(INSN,STATE) \
139 (ARC_CCFSM_COND_EXEC_P (STATE) \
140 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
141 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
142 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
143
144/* Likewise, but also consider that INSN might be in a delay slot of JUMP. */
145#define CCFSM_DBR_ISCOMPACT(INSN,JUMP,STATE) \
146 ((ARC_CCFSM_COND_EXEC_P (STATE) \
147 || (JUMP_P (JUMP) \
148 && INSN_ANNULLED_BRANCH_P (JUMP) \
149 && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (INSN)))) \
150 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
151 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
152 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
153
154/* The maximum number of insns skipped which will be conditionalised if
155 possible. */
156/* When optimizing for speed:
157 Let p be the probability that the potentially skipped insns need to
158 be executed, pn the cost of a correctly predicted non-taken branch,
159 mt the cost of a mis/non-predicted taken branch,
160 mn mispredicted non-taken, pt correctly predicted taken ;
161 costs expressed in numbers of instructions like the ones considered
162 skipping.
163 Unfortunately we don't have a measure of predictability - this
164 is linked to probability only in that in the no-eviction-scenario
165 there is a lower bound 1 - 2 * min (p, 1-p), and a somewhat larger
166 value that can be assumed *if* the distribution is perfectly random.
167 A predictability of 1 is perfectly plausible not matter what p is,
168 because the decision could be dependent on an invocation parameter
169 of the program.
170 For large p, we want MAX_INSNS_SKIPPED == pn/(1-p) + mt - pn
171 For small p, we want MAX_INSNS_SKIPPED == pt
172
173 When optimizing for size:
174 We want to skip insn unless we could use 16 opcodes for the
175 non-conditionalized insn to balance the branch length or more.
176 Performance can be tie-breaker. */
177/* If the potentially-skipped insns are likely to be executed, we'll
178 generally save one non-taken branch
179 o
180 this to be no less than the 1/p */
181#define MAX_INSNS_SKIPPED 3
182
183/* The values of unspec's first field. */
184enum {
185 ARC_UNSPEC_PLT = 3,
186 ARC_UNSPEC_GOT,
187 ARC_UNSPEC_GOTOFF
188} ;
189
190
191enum arc_builtins {
192 ARC_BUILTIN_NOP = 2,
193 ARC_BUILTIN_NORM = 3,
194 ARC_BUILTIN_NORMW = 4,
195 ARC_BUILTIN_SWAP = 5,
196 ARC_BUILTIN_BRK = 6,
197 ARC_BUILTIN_DIVAW = 7,
198 ARC_BUILTIN_EX = 8,
199 ARC_BUILTIN_MUL64 = 9,
200 ARC_BUILTIN_MULU64 = 10,
201 ARC_BUILTIN_RTIE = 11,
202 ARC_BUILTIN_SYNC = 12,
203 ARC_BUILTIN_CORE_READ = 13,
204 ARC_BUILTIN_CORE_WRITE = 14,
205 ARC_BUILTIN_FLAG = 15,
206 ARC_BUILTIN_LR = 16,
207 ARC_BUILTIN_SR = 17,
208 ARC_BUILTIN_SLEEP = 18,
209 ARC_BUILTIN_SWI = 19,
210 ARC_BUILTIN_TRAP_S = 20,
211 ARC_BUILTIN_UNIMP_S = 21,
212 ARC_BUILTIN_ALIGNED = 22,
213
214 /* Sentinel to mark start of simd builtins. */
215 ARC_SIMD_BUILTIN_BEGIN = 1000,
216
217 ARC_SIMD_BUILTIN_VADDAW = 1001,
218 ARC_SIMD_BUILTIN_VADDW = 1002,
219 ARC_SIMD_BUILTIN_VAVB = 1003,
220 ARC_SIMD_BUILTIN_VAVRB = 1004,
221 ARC_SIMD_BUILTIN_VDIFAW = 1005,
222 ARC_SIMD_BUILTIN_VDIFW = 1006,
223 ARC_SIMD_BUILTIN_VMAXAW = 1007,
224 ARC_SIMD_BUILTIN_VMAXW = 1008,
225 ARC_SIMD_BUILTIN_VMINAW = 1009,
226 ARC_SIMD_BUILTIN_VMINW = 1010,
227 ARC_SIMD_BUILTIN_VMULAW = 1011,
228 ARC_SIMD_BUILTIN_VMULFAW = 1012,
229 ARC_SIMD_BUILTIN_VMULFW = 1013,
230 ARC_SIMD_BUILTIN_VMULW = 1014,
231 ARC_SIMD_BUILTIN_VSUBAW = 1015,
232 ARC_SIMD_BUILTIN_VSUBW = 1016,
233 ARC_SIMD_BUILTIN_VSUMMW = 1017,
234 ARC_SIMD_BUILTIN_VAND = 1018,
235 ARC_SIMD_BUILTIN_VANDAW = 1019,
236 ARC_SIMD_BUILTIN_VBIC = 1020,
237 ARC_SIMD_BUILTIN_VBICAW = 1021,
238 ARC_SIMD_BUILTIN_VOR = 1022,
239 ARC_SIMD_BUILTIN_VXOR = 1023,
240 ARC_SIMD_BUILTIN_VXORAW = 1024,
241 ARC_SIMD_BUILTIN_VEQW = 1025,
242 ARC_SIMD_BUILTIN_VLEW = 1026,
243 ARC_SIMD_BUILTIN_VLTW = 1027,
244 ARC_SIMD_BUILTIN_VNEW = 1028,
245 ARC_SIMD_BUILTIN_VMR1AW = 1029,
246 ARC_SIMD_BUILTIN_VMR1W = 1030,
247 ARC_SIMD_BUILTIN_VMR2AW = 1031,
248 ARC_SIMD_BUILTIN_VMR2W = 1032,
249 ARC_SIMD_BUILTIN_VMR3AW = 1033,
250 ARC_SIMD_BUILTIN_VMR3W = 1034,
251 ARC_SIMD_BUILTIN_VMR4AW = 1035,
252 ARC_SIMD_BUILTIN_VMR4W = 1036,
253 ARC_SIMD_BUILTIN_VMR5AW = 1037,
254 ARC_SIMD_BUILTIN_VMR5W = 1038,
255 ARC_SIMD_BUILTIN_VMR6AW = 1039,
256 ARC_SIMD_BUILTIN_VMR6W = 1040,
257 ARC_SIMD_BUILTIN_VMR7AW = 1041,
258 ARC_SIMD_BUILTIN_VMR7W = 1042,
259 ARC_SIMD_BUILTIN_VMRB = 1043,
260 ARC_SIMD_BUILTIN_VH264F = 1044,
261 ARC_SIMD_BUILTIN_VH264FT = 1045,
262 ARC_SIMD_BUILTIN_VH264FW = 1046,
263 ARC_SIMD_BUILTIN_VVC1F = 1047,
264 ARC_SIMD_BUILTIN_VVC1FT = 1048,
265
266 /* Va, Vb, rlimm instructions. */
267 ARC_SIMD_BUILTIN_VBADDW = 1050,
268 ARC_SIMD_BUILTIN_VBMAXW = 1051,
269 ARC_SIMD_BUILTIN_VBMINW = 1052,
270 ARC_SIMD_BUILTIN_VBMULAW = 1053,
271 ARC_SIMD_BUILTIN_VBMULFW = 1054,
272 ARC_SIMD_BUILTIN_VBMULW = 1055,
273 ARC_SIMD_BUILTIN_VBRSUBW = 1056,
274 ARC_SIMD_BUILTIN_VBSUBW = 1057,
275
276 /* Va, Vb, Ic instructions. */
277 ARC_SIMD_BUILTIN_VASRW = 1060,
278 ARC_SIMD_BUILTIN_VSR8 = 1061,
279 ARC_SIMD_BUILTIN_VSR8AW = 1062,
280
281 /* Va, Vb, u6 instructions. */
282 ARC_SIMD_BUILTIN_VASRRWi = 1065,
283 ARC_SIMD_BUILTIN_VASRSRWi = 1066,
284 ARC_SIMD_BUILTIN_VASRWi = 1067,
285 ARC_SIMD_BUILTIN_VASRPWBi = 1068,
286 ARC_SIMD_BUILTIN_VASRRPWBi = 1069,
287 ARC_SIMD_BUILTIN_VSR8AWi = 1070,
288 ARC_SIMD_BUILTIN_VSR8i = 1071,
289
290 /* Va, Vb, u8 (simm) instructions. */
291 ARC_SIMD_BUILTIN_VMVAW = 1075,
292 ARC_SIMD_BUILTIN_VMVW = 1076,
293 ARC_SIMD_BUILTIN_VMVZW = 1077,
294 ARC_SIMD_BUILTIN_VD6TAPF = 1078,
295
296 /* Va, rlimm, u8 (simm) instructions. */
297 ARC_SIMD_BUILTIN_VMOVAW = 1080,
298 ARC_SIMD_BUILTIN_VMOVW = 1081,
299 ARC_SIMD_BUILTIN_VMOVZW = 1082,
300
301 /* Va, Vb instructions. */
302 ARC_SIMD_BUILTIN_VABSAW = 1085,
303 ARC_SIMD_BUILTIN_VABSW = 1086,
304 ARC_SIMD_BUILTIN_VADDSUW = 1087,
305 ARC_SIMD_BUILTIN_VSIGNW = 1088,
306 ARC_SIMD_BUILTIN_VEXCH1 = 1089,
307 ARC_SIMD_BUILTIN_VEXCH2 = 1090,
308 ARC_SIMD_BUILTIN_VEXCH4 = 1091,
309 ARC_SIMD_BUILTIN_VUPBAW = 1092,
310 ARC_SIMD_BUILTIN_VUPBW = 1093,
311 ARC_SIMD_BUILTIN_VUPSBAW = 1094,
312 ARC_SIMD_BUILTIN_VUPSBW = 1095,
313
314 ARC_SIMD_BUILTIN_VDIRUN = 1100,
315 ARC_SIMD_BUILTIN_VDORUN = 1101,
316 ARC_SIMD_BUILTIN_VDIWR = 1102,
317 ARC_SIMD_BUILTIN_VDOWR = 1103,
318
319 ARC_SIMD_BUILTIN_VREC = 1105,
320 ARC_SIMD_BUILTIN_VRUN = 1106,
321 ARC_SIMD_BUILTIN_VRECRUN = 1107,
322 ARC_SIMD_BUILTIN_VENDREC = 1108,
323
324 ARC_SIMD_BUILTIN_VLD32WH = 1110,
325 ARC_SIMD_BUILTIN_VLD32WL = 1111,
326 ARC_SIMD_BUILTIN_VLD64 = 1112,
327 ARC_SIMD_BUILTIN_VLD32 = 1113,
328 ARC_SIMD_BUILTIN_VLD64W = 1114,
329 ARC_SIMD_BUILTIN_VLD128 = 1115,
330 ARC_SIMD_BUILTIN_VST128 = 1116,
331 ARC_SIMD_BUILTIN_VST64 = 1117,
332
333 ARC_SIMD_BUILTIN_VST16_N = 1120,
334 ARC_SIMD_BUILTIN_VST32_N = 1121,
335
336 ARC_SIMD_BUILTIN_VINTI = 1201,
337
338 ARC_SIMD_BUILTIN_END
339};
340
341/* A nop is needed between a 4 byte insn that sets the condition codes and
342 a branch that uses them (the same isn't true for an 8 byte insn that sets
343 the condition codes). Set by arc_ccfsm_advance. Used by
344 arc_print_operand. */
345
346static int get_arc_condition_code (rtx);
347
348static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
349
350/* Initialized arc_attribute_table to NULL since arc doesnot have any
351 machine specific supported attributes. */
352const struct attribute_spec arc_attribute_table[] =
353{
354 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
355 affects_type_identity } */
356 { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute, true },
357 /* Function calls made to this symbol must be done indirectly, because
358 it may lie outside of the 21/25 bit addressing range of a normal function
359 call. */
360 { "long_call", 0, 0, false, true, true, NULL, false },
361 /* Whereas these functions are always known to reside within the 25 bit
362 addressing range of unconditionalized bl. */
363 { "medium_call", 0, 0, false, true, true, NULL, false },
364 /* And these functions are always known to reside within the 21 bit
365 addressing range of blcc. */
366 { "short_call", 0, 0, false, true, true, NULL, false },
367 { NULL, 0, 0, false, false, false, NULL, false }
368};
369static int arc_comp_type_attributes (const_tree, const_tree);
370static void arc_file_start (void);
371static void arc_internal_label (FILE *, const char *, unsigned long);
372static void arc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
373 tree);
374static int arc_address_cost (rtx, enum machine_mode, addr_space_t, bool);
375static void arc_encode_section_info (tree decl, rtx rtl, int first);
376
377static void arc_init_builtins (void);
378static rtx arc_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
379
380static int branch_dest (rtx);
381
382static void arc_output_pic_addr_const (FILE *, rtx, int);
383void emit_pic_move (rtx *, enum machine_mode);
384bool arc_legitimate_pic_operand_p (rtx);
385static bool arc_function_ok_for_sibcall (tree, tree);
386static rtx arc_function_value (const_tree, const_tree, bool);
387const char * output_shift (rtx *);
388static void arc_reorg (void);
389static bool arc_in_small_data_p (const_tree);
390
391static void arc_init_reg_tables (void);
392static bool arc_return_in_memory (const_tree, const_tree);
393static void arc_init_simd_builtins (void);
394static bool arc_vector_mode_supported_p (enum machine_mode);
395
807e902e
KZ
396static bool arc_can_use_doloop_p (const widest_int &, const widest_int &,
397 unsigned int, bool);
ac44248e 398static const char *arc_invalid_within_doloop (const rtx_insn *);
526b7aee
SV
399
400static void output_short_suffix (FILE *file);
401
402static bool arc_frame_pointer_required (void);
403
404/* Implements target hook vector_mode_supported_p. */
405
406static bool
407arc_vector_mode_supported_p (enum machine_mode mode)
408{
409 if (!TARGET_SIMD_SET)
410 return false;
411
412 if ((mode == V4SImode)
413 || (mode == V8HImode))
414 return true;
415
416 return false;
417}
418
419
420/* TARGET_PRESERVE_RELOAD_P is still awaiting patch re-evaluation / review. */
421static bool arc_preserve_reload_p (rtx in) ATTRIBUTE_UNUSED;
422static rtx arc_delegitimize_address (rtx);
423static bool arc_can_follow_jump (const_rtx follower, const_rtx followee);
424
425static rtx frame_insn (rtx);
426static void arc_function_arg_advance (cumulative_args_t, enum machine_mode,
427 const_tree, bool);
428static rtx arc_legitimize_address_0 (rtx, rtx, enum machine_mode mode);
429
430static void arc_finalize_pic (void);
431
432/* initialize the GCC target structure. */
433#undef TARGET_COMP_TYPE_ATTRIBUTES
434#define TARGET_COMP_TYPE_ATTRIBUTES arc_comp_type_attributes
435#undef TARGET_ASM_FILE_START
436#define TARGET_ASM_FILE_START arc_file_start
437#undef TARGET_ATTRIBUTE_TABLE
438#define TARGET_ATTRIBUTE_TABLE arc_attribute_table
439#undef TARGET_ASM_INTERNAL_LABEL
440#define TARGET_ASM_INTERNAL_LABEL arc_internal_label
441#undef TARGET_RTX_COSTS
442#define TARGET_RTX_COSTS arc_rtx_costs
443#undef TARGET_ADDRESS_COST
444#define TARGET_ADDRESS_COST arc_address_cost
445
446#undef TARGET_ENCODE_SECTION_INFO
447#define TARGET_ENCODE_SECTION_INFO arc_encode_section_info
448
449#undef TARGET_CANNOT_FORCE_CONST_MEM
450#define TARGET_CANNOT_FORCE_CONST_MEM arc_cannot_force_const_mem
451
452#undef TARGET_INIT_BUILTINS
453#define TARGET_INIT_BUILTINS arc_init_builtins
454
455#undef TARGET_EXPAND_BUILTIN
456#define TARGET_EXPAND_BUILTIN arc_expand_builtin
457
458#undef TARGET_ASM_OUTPUT_MI_THUNK
459#define TARGET_ASM_OUTPUT_MI_THUNK arc_output_mi_thunk
460
461#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
462#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
463
464#undef TARGET_FUNCTION_OK_FOR_SIBCALL
465#define TARGET_FUNCTION_OK_FOR_SIBCALL arc_function_ok_for_sibcall
466
467#undef TARGET_MACHINE_DEPENDENT_REORG
468#define TARGET_MACHINE_DEPENDENT_REORG arc_reorg
469
470#undef TARGET_IN_SMALL_DATA_P
471#define TARGET_IN_SMALL_DATA_P arc_in_small_data_p
472
473#undef TARGET_PROMOTE_FUNCTION_MODE
474#define TARGET_PROMOTE_FUNCTION_MODE \
475 default_promote_function_mode_always_promote
476
477#undef TARGET_PROMOTE_PROTOTYPES
478#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
479
480#undef TARGET_RETURN_IN_MEMORY
481#define TARGET_RETURN_IN_MEMORY arc_return_in_memory
482#undef TARGET_PASS_BY_REFERENCE
483#define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
484
485#undef TARGET_SETUP_INCOMING_VARARGS
486#define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
487
488#undef TARGET_ARG_PARTIAL_BYTES
489#define TARGET_ARG_PARTIAL_BYTES arc_arg_partial_bytes
490
491#undef TARGET_MUST_PASS_IN_STACK
492#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
493
494#undef TARGET_FUNCTION_VALUE
495#define TARGET_FUNCTION_VALUE arc_function_value
496
497#undef TARGET_SCHED_ADJUST_PRIORITY
498#define TARGET_SCHED_ADJUST_PRIORITY arc_sched_adjust_priority
499
500#undef TARGET_VECTOR_MODE_SUPPORTED_P
501#define TARGET_VECTOR_MODE_SUPPORTED_P arc_vector_mode_supported_p
502
1d0216c8
RS
503#undef TARGET_CAN_USE_DOLOOP_P
504#define TARGET_CAN_USE_DOLOOP_P arc_can_use_doloop_p
505
526b7aee
SV
506#undef TARGET_INVALID_WITHIN_DOLOOP
507#define TARGET_INVALID_WITHIN_DOLOOP arc_invalid_within_doloop
508
509#undef TARGET_PRESERVE_RELOAD_P
510#define TARGET_PRESERVE_RELOAD_P arc_preserve_reload_p
511
512#undef TARGET_CAN_FOLLOW_JUMP
513#define TARGET_CAN_FOLLOW_JUMP arc_can_follow_jump
514
515#undef TARGET_DELEGITIMIZE_ADDRESS
516#define TARGET_DELEGITIMIZE_ADDRESS arc_delegitimize_address
517
518/* Usually, we will be able to scale anchor offsets.
519 When this fails, we want LEGITIMIZE_ADDRESS to kick in. */
520#undef TARGET_MIN_ANCHOR_OFFSET
521#define TARGET_MIN_ANCHOR_OFFSET (-1024)
522#undef TARGET_MAX_ANCHOR_OFFSET
523#define TARGET_MAX_ANCHOR_OFFSET (1020)
524
525#undef TARGET_SECONDARY_RELOAD
526#define TARGET_SECONDARY_RELOAD arc_secondary_reload
527
528#define TARGET_OPTION_OVERRIDE arc_override_options
529
530#define TARGET_CONDITIONAL_REGISTER_USAGE arc_conditional_register_usage
531
532#define TARGET_TRAMPOLINE_INIT arc_initialize_trampoline
533
534#define TARGET_TRAMPOLINE_ADJUST_ADDRESS arc_trampoline_adjust_address
535
536#define TARGET_CAN_ELIMINATE arc_can_eliminate
537
538#define TARGET_FRAME_POINTER_REQUIRED arc_frame_pointer_required
539
540#define TARGET_FUNCTION_ARG arc_function_arg
541
542#define TARGET_FUNCTION_ARG_ADVANCE arc_function_arg_advance
543
544#define TARGET_LEGITIMATE_CONSTANT_P arc_legitimate_constant_p
545
546#define TARGET_LEGITIMATE_ADDRESS_P arc_legitimate_address_p
547
548#define TARGET_MODE_DEPENDENT_ADDRESS_P arc_mode_dependent_address_p
549
550#define TARGET_LEGITIMIZE_ADDRESS arc_legitimize_address
551
552#define TARGET_ADJUST_INSN_LENGTH arc_adjust_insn_length
553
554#define TARGET_INSN_LENGTH_PARAMETERS arc_insn_length_parameters
555
53c8d5a7 556#undef TARGET_LRA_P
526b7aee
SV
557#define TARGET_LRA_P arc_lra_p
558#define TARGET_REGISTER_PRIORITY arc_register_priority
559/* Stores with scaled offsets have different displacement ranges. */
560#define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
561#define TARGET_SPILL_CLASS arc_spill_class
562
563#include "target-def.h"
564
565#undef TARGET_ASM_ALIGNED_HI_OP
566#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
567#undef TARGET_ASM_ALIGNED_SI_OP
568#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
569
570/* Try to keep the (mov:DF _, reg) as early as possible so
571 that the d<add/sub/mul>h-lr insns appear together and can
572 use the peephole2 pattern. */
573
574static int
ac44248e 575arc_sched_adjust_priority (rtx_insn *insn, int priority)
526b7aee
SV
576{
577 rtx set = single_set (insn);
578 if (set
579 && GET_MODE (SET_SRC(set)) == DFmode
580 && GET_CODE (SET_SRC(set)) == REG)
581 {
582 /* Incrementing priority by 20 (empirically derived). */
583 return priority + 20;
584 }
585
586 return priority;
587}
588
589static reg_class_t
590arc_secondary_reload (bool in_p, rtx x, reg_class_t cl, enum machine_mode,
591 secondary_reload_info *)
592{
593 if (cl == DOUBLE_REGS)
594 return GENERAL_REGS;
595
596 /* The loop counter register can be stored, but not loaded directly. */
597 if ((cl == LPCOUNT_REG || cl == WRITABLE_CORE_REGS)
598 && in_p && MEM_P (x))
599 return GENERAL_REGS;
600 return NO_REGS;
601}
602
603static unsigned arc_ifcvt (void);
604
605namespace {
606
607const pass_data pass_data_arc_ifcvt =
608{
609 RTL_PASS,
610 "arc_ifcvt", /* name */
611 OPTGROUP_NONE, /* optinfo_flags */
526b7aee
SV
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 TV_IFCVT2, /* tv_id */
650 0, /* properties_required */
651 0, /* properties_provided */
652 0, /* properties_destroyed */
653 0, /* todo_flags_start */
654 TODO_df_finish /* todo_flags_finish */
655};
656
657class pass_arc_predicate_delay_insns : public rtl_opt_pass
658{
659public:
660 pass_arc_predicate_delay_insns(gcc::context *ctxt)
661 : rtl_opt_pass(pass_data_arc_predicate_delay_insns, ctxt)
662 {}
663
664 /* opt_pass methods: */
be55bfe6
TS
665 virtual unsigned int execute (function *)
666 {
667 return arc_predicate_delay_insns ();
668 }
0bc69b81
JR
669};
670
671} // anon namespace
672
673rtl_opt_pass *
674make_pass_arc_predicate_delay_insns (gcc::context *ctxt)
675{
676 return new pass_arc_predicate_delay_insns (ctxt);
677}
678
526b7aee
SV
679/* Called by OVERRIDE_OPTIONS to initialize various things. */
680
681void
682arc_init (void)
683{
684 enum attr_tune tune_dflt = TUNE_NONE;
685
686 if (TARGET_A5)
687 {
688 arc_cpu_string = "A5";
689 }
690 else if (TARGET_ARC600)
691 {
692 arc_cpu_string = "ARC600";
693 tune_dflt = TUNE_ARC600;
694 }
695 else if (TARGET_ARC601)
696 {
697 arc_cpu_string = "ARC601";
698 tune_dflt = TUNE_ARC600;
699 }
700 else if (TARGET_ARC700)
701 {
702 arc_cpu_string = "ARC700";
703 tune_dflt = TUNE_ARC700_4_2_STD;
704 }
705 else
706 gcc_unreachable ();
707 if (arc_tune == TUNE_NONE)
708 arc_tune = tune_dflt;
709 /* Note: arc_multcost is only used in rtx_cost if speed is true. */
710 if (arc_multcost < 0)
711 switch (arc_tune)
712 {
713 case TUNE_ARC700_4_2_STD:
714 /* latency 7;
715 max throughput (1 multiply + 4 other insns) / 5 cycles. */
716 arc_multcost = COSTS_N_INSNS (4);
717 if (TARGET_NOMPY_SET)
718 arc_multcost = COSTS_N_INSNS (30);
719 break;
720 case TUNE_ARC700_4_2_XMAC:
721 /* latency 5;
722 max throughput (1 multiply + 2 other insns) / 3 cycles. */
723 arc_multcost = COSTS_N_INSNS (3);
724 if (TARGET_NOMPY_SET)
725 arc_multcost = COSTS_N_INSNS (30);
726 break;
727 case TUNE_ARC600:
728 if (TARGET_MUL64_SET)
729 {
730 arc_multcost = COSTS_N_INSNS (4);
731 break;
732 }
733 /* Fall through. */
734 default:
735 arc_multcost = COSTS_N_INSNS (30);
736 break;
737 }
738
739 /* Support mul64 generation only for A5 and ARC600. */
740 if (TARGET_MUL64_SET && TARGET_ARC700)
741 error ("-mmul64 not supported for ARC700");
742
743 /* MPY instructions valid only for ARC700. */
744 if (TARGET_NOMPY_SET && !TARGET_ARC700)
745 error ("-mno-mpy supported only for ARC700");
746
747 /* mul/mac instructions only for ARC600. */
748 if (TARGET_MULMAC_32BY16_SET && !(TARGET_ARC600 || TARGET_ARC601))
749 error ("-mmul32x16 supported only for ARC600 or ARC601");
750
751 if (!TARGET_DPFP && TARGET_DPFP_DISABLE_LRSR)
2236746b 752 error ("-mno-dpfp-lrsr supported only with -mdpfp");
526b7aee
SV
753
754 /* FPX-1. No fast and compact together. */
755 if ((TARGET_DPFP_FAST_SET && TARGET_DPFP_COMPACT_SET)
756 || (TARGET_SPFP_FAST_SET && TARGET_SPFP_COMPACT_SET))
757 error ("FPX fast and compact options cannot be specified together");
758
759 /* FPX-2. No fast-spfp for arc600 or arc601. */
760 if (TARGET_SPFP_FAST_SET && (TARGET_ARC600 || TARGET_ARC601))
761 error ("-mspfp_fast not available on ARC600 or ARC601");
762
763 /* FPX-3. No FPX extensions on pre-ARC600 cores. */
764 if ((TARGET_DPFP || TARGET_SPFP)
765 && !(TARGET_ARC600 || TARGET_ARC601 || TARGET_ARC700))
766 error ("FPX extensions not available on pre-ARC600 cores");
767
768 /* Warn for unimplemented PIC in pre-ARC700 cores, and disable flag_pic. */
769 if (flag_pic && !TARGET_ARC700)
770 {
771 warning (DK_WARNING, "PIC is not supported for %s. Generating non-PIC code only..", arc_cpu_string);
772 flag_pic = 0;
773 }
774
775 arc_init_reg_tables ();
776
777 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
778 memset (arc_punct_chars, 0, sizeof (arc_punct_chars));
779 arc_punct_chars['#'] = 1;
780 arc_punct_chars['*'] = 1;
781 arc_punct_chars['?'] = 1;
782 arc_punct_chars['!'] = 1;
783 arc_punct_chars['^'] = 1;
784 arc_punct_chars['&'] = 1;
785
786 if (optimize > 1 && !TARGET_NO_COND_EXEC)
787 {
788 /* There are two target-independent ifcvt passes, and arc_reorg may do
789 one or more arc_ifcvt calls. */
790 opt_pass *pass_arc_ifcvt_4 = make_pass_arc_ifcvt (g);
791 struct register_pass_info arc_ifcvt4_info
792 = { pass_arc_ifcvt_4, "dbr", 1, PASS_POS_INSERT_AFTER };
793 struct register_pass_info arc_ifcvt5_info
794 = { pass_arc_ifcvt_4->clone (), "shorten", 1, PASS_POS_INSERT_BEFORE };
795
796 register_pass (&arc_ifcvt4_info);
797 register_pass (&arc_ifcvt5_info);
798 }
0bc69b81
JR
799
800 if (flag_delayed_branch)
801 {
802 opt_pass *pass_arc_predicate_delay_insns
803 = make_pass_arc_predicate_delay_insns (g);
804 struct register_pass_info arc_predicate_delay_info
805 = { pass_arc_predicate_delay_insns, "dbr", 1, PASS_POS_INSERT_AFTER };
806
807 register_pass (&arc_predicate_delay_info);
808 }
526b7aee
SV
809}
810
811/* Check ARC options, generate derived target attributes. */
812
813static void
814arc_override_options (void)
815{
816 if (arc_cpu == PROCESSOR_NONE)
817 arc_cpu = PROCESSOR_ARC700;
818
819 if (arc_size_opt_level == 3)
820 optimize_size = 1;
821
822 if (flag_pic)
823 target_flags |= MASK_NO_SDATA_SET;
824
825 if (flag_no_common == 255)
826 flag_no_common = !TARGET_NO_SDATA_SET;
827
828 /* TARGET_COMPACT_CASESI needs the "q" register class. */ \
829 if (TARGET_MIXED_CODE)
830 TARGET_Q_CLASS = 1;
831 if (!TARGET_Q_CLASS)
832 TARGET_COMPACT_CASESI = 0;
833 if (TARGET_COMPACT_CASESI)
834 TARGET_CASE_VECTOR_PC_RELATIVE = 1;
835
836 /* These need to be done at start up. It's convenient to do them here. */
837 arc_init ();
838}
839
840/* The condition codes of the ARC, and the inverse function. */
841/* For short branches, the "c" / "nc" names are not defined in the ARC
842 Programmers manual, so we have to use "lo" / "hs"" instead. */
843static const char *arc_condition_codes[] =
844{
845 "al", 0, "eq", "ne", "p", "n", "lo", "hs", "v", "nv",
846 "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
847};
848
849enum arc_cc_code_index
850{
851 ARC_CC_AL, ARC_CC_EQ = ARC_CC_AL+2, ARC_CC_NE, ARC_CC_P, ARC_CC_N,
852 ARC_CC_C, ARC_CC_NC, ARC_CC_V, ARC_CC_NV,
853 ARC_CC_GT, ARC_CC_LE, ARC_CC_GE, ARC_CC_LT, ARC_CC_HI, ARC_CC_LS, ARC_CC_PNZ,
854 ARC_CC_LO = ARC_CC_C, ARC_CC_HS = ARC_CC_NC
855};
856
857#define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
858
859/* Returns the index of the ARC condition code string in
860 `arc_condition_codes'. COMPARISON should be an rtx like
861 `(eq (...) (...))'. */
862
863static int
864get_arc_condition_code (rtx comparison)
865{
866 switch (GET_MODE (XEXP (comparison, 0)))
867 {
868 case CCmode:
869 case SImode: /* For BRcc. */
870 switch (GET_CODE (comparison))
871 {
872 case EQ : return ARC_CC_EQ;
873 case NE : return ARC_CC_NE;
874 case GT : return ARC_CC_GT;
875 case LE : return ARC_CC_LE;
876 case GE : return ARC_CC_GE;
877 case LT : return ARC_CC_LT;
878 case GTU : return ARC_CC_HI;
879 case LEU : return ARC_CC_LS;
880 case LTU : return ARC_CC_LO;
881 case GEU : return ARC_CC_HS;
882 default : gcc_unreachable ();
883 }
884 case CC_ZNmode:
885 switch (GET_CODE (comparison))
886 {
887 case EQ : return ARC_CC_EQ;
888 case NE : return ARC_CC_NE;
889 case GE: return ARC_CC_P;
890 case LT: return ARC_CC_N;
891 case GT : return ARC_CC_PNZ;
892 default : gcc_unreachable ();
893 }
894 case CC_Zmode:
895 switch (GET_CODE (comparison))
896 {
897 case EQ : return ARC_CC_EQ;
898 case NE : return ARC_CC_NE;
899 default : gcc_unreachable ();
900 }
901 case CC_Cmode:
902 switch (GET_CODE (comparison))
903 {
904 case LTU : return ARC_CC_C;
905 case GEU : return ARC_CC_NC;
906 default : gcc_unreachable ();
907 }
908 case CC_FP_GTmode:
909 if (TARGET_ARGONAUT_SET && TARGET_SPFP)
910 switch (GET_CODE (comparison))
911 {
912 case GT : return ARC_CC_N;
913 case UNLE: return ARC_CC_P;
914 default : gcc_unreachable ();
915 }
916 else
917 switch (GET_CODE (comparison))
918 {
919 case GT : return ARC_CC_HI;
920 case UNLE : return ARC_CC_LS;
921 default : gcc_unreachable ();
922 }
923 case CC_FP_GEmode:
924 /* Same for FPX and non-FPX. */
925 switch (GET_CODE (comparison))
926 {
927 case GE : return ARC_CC_HS;
928 case UNLT : return ARC_CC_LO;
929 default : gcc_unreachable ();
930 }
931 case CC_FP_UNEQmode:
932 switch (GET_CODE (comparison))
933 {
934 case UNEQ : return ARC_CC_EQ;
935 case LTGT : return ARC_CC_NE;
936 default : gcc_unreachable ();
937 }
938 case CC_FP_ORDmode:
939 switch (GET_CODE (comparison))
940 {
941 case UNORDERED : return ARC_CC_C;
942 case ORDERED : return ARC_CC_NC;
943 default : gcc_unreachable ();
944 }
945 case CC_FPXmode:
946 switch (GET_CODE (comparison))
947 {
948 case EQ : return ARC_CC_EQ;
949 case NE : return ARC_CC_NE;
950 case UNORDERED : return ARC_CC_C;
951 case ORDERED : return ARC_CC_NC;
952 case LTGT : return ARC_CC_HI;
953 case UNEQ : return ARC_CC_LS;
954 default : gcc_unreachable ();
955 }
956 default : gcc_unreachable ();
957 }
958 /*NOTREACHED*/
959 return (42);
960}
961
962/* Return true if COMPARISON has a short form that can accomodate OFFSET. */
963
964bool
965arc_short_comparison_p (rtx comparison, int offset)
966{
967 gcc_assert (ARC_CC_NC == ARC_CC_HS);
968 gcc_assert (ARC_CC_C == ARC_CC_LO);
969 switch (get_arc_condition_code (comparison))
970 {
971 case ARC_CC_EQ: case ARC_CC_NE:
972 return offset >= -512 && offset <= 506;
973 case ARC_CC_GT: case ARC_CC_LE: case ARC_CC_GE: case ARC_CC_LT:
974 case ARC_CC_HI: case ARC_CC_LS: case ARC_CC_LO: case ARC_CC_HS:
975 return offset >= -64 && offset <= 58;
976 default:
977 return false;
978 }
979}
980
981/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
982 return the mode to be used for the comparison. */
983
984enum machine_mode
985arc_select_cc_mode (enum rtx_code op, rtx x, rtx y)
986{
987 enum machine_mode mode = GET_MODE (x);
988 rtx x1;
989
990 /* For an operation that sets the condition codes as a side-effect, the
991 C and V flags is not set as for cmp, so we can only use comparisons where
992 this doesn't matter. (For LT and GE we can use "mi" and "pl"
993 instead.) */
994 /* ??? We could use "pnz" for greater than zero, however, we could then
995 get into trouble because the comparison could not be reversed. */
996 if (GET_MODE_CLASS (mode) == MODE_INT
997 && y == const0_rtx
998 && (op == EQ || op == NE
486c559b 999 || ((op == LT || op == GE) && GET_MODE_SIZE (GET_MODE (x)) <= 4)))
526b7aee
SV
1000 return CC_ZNmode;
1001
1002 /* add.f for if (a+b) */
1003 if (mode == SImode
1004 && GET_CODE (y) == NEG
1005 && (op == EQ || op == NE))
1006 return CC_ZNmode;
1007
1008 /* Check if this is a test suitable for bxor.f . */
1009 if (mode == SImode && (op == EQ || op == NE) && CONST_INT_P (y)
1010 && ((INTVAL (y) - 1) & INTVAL (y)) == 0
1011 && INTVAL (y))
1012 return CC_Zmode;
1013
1014 /* Check if this is a test suitable for add / bmsk.f . */
1015 if (mode == SImode && (op == EQ || op == NE) && CONST_INT_P (y)
1016 && GET_CODE (x) == AND && CONST_INT_P ((x1 = XEXP (x, 1)))
1017 && ((INTVAL (x1) + 1) & INTVAL (x1)) == 0
1018 && (~INTVAL (x1) | INTVAL (y)) < 0
1019 && (~INTVAL (x1) | INTVAL (y)) > -0x800)
1020 return CC_Zmode;
1021
1022 if (GET_MODE (x) == SImode && (op == LTU || op == GEU)
1023 && GET_CODE (x) == PLUS
1024 && (rtx_equal_p (XEXP (x, 0), y) || rtx_equal_p (XEXP (x, 1), y)))
1025 return CC_Cmode;
1026
1027 if (TARGET_ARGONAUT_SET
1028 && ((mode == SFmode && TARGET_SPFP) || (mode == DFmode && TARGET_DPFP)))
1029 switch (op)
1030 {
1031 case EQ: case NE: case UNEQ: case LTGT: case ORDERED: case UNORDERED:
1032 return CC_FPXmode;
1033 case LT: case UNGE: case GT: case UNLE:
1034 return CC_FP_GTmode;
1035 case LE: case UNGT: case GE: case UNLT:
1036 return CC_FP_GEmode;
1037 default: gcc_unreachable ();
1038 }
1039 else if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_OPTFPE)
1040 switch (op)
1041 {
1042 case EQ: case NE: return CC_Zmode;
1043 case LT: case UNGE:
1044 case GT: case UNLE: return CC_FP_GTmode;
1045 case LE: case UNGT:
1046 case GE: case UNLT: return CC_FP_GEmode;
1047 case UNEQ: case LTGT: return CC_FP_UNEQmode;
1048 case ORDERED: case UNORDERED: return CC_FP_ORDmode;
1049 default: gcc_unreachable ();
1050 }
1051
1052 return CCmode;
1053}
1054
1055/* Vectors to keep interesting information about registers where it can easily
1056 be got. We use to use the actual mode value as the bit number, but there
1057 is (or may be) more than 32 modes now. Instead we use two tables: one
1058 indexed by hard register number, and one indexed by mode. */
1059
1060/* The purpose of arc_mode_class is to shrink the range of modes so that
1061 they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
1062 mapped into one arc_mode_class mode. */
1063
1064enum arc_mode_class {
1065 C_MODE,
1066 S_MODE, D_MODE, T_MODE, O_MODE,
1067 SF_MODE, DF_MODE, TF_MODE, OF_MODE,
1068 V_MODE
1069};
1070
1071/* Modes for condition codes. */
1072#define C_MODES (1 << (int) C_MODE)
1073
1074/* Modes for single-word and smaller quantities. */
1075#define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
1076
1077/* Modes for double-word and smaller quantities. */
1078#define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
1079
1080/* Mode for 8-byte DF values only. */
1081#define DF_MODES (1 << DF_MODE)
1082
1083/* Modes for quad-word and smaller quantities. */
1084#define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
1085
1086/* Modes for 128-bit vectors. */
1087#define V_MODES (1 << (int) V_MODE)
1088
1089/* Value is 1 if register/mode pair is acceptable on arc. */
1090
1091unsigned int arc_hard_regno_mode_ok[] = {
1092 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
1093 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
1094 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, D_MODES,
1095 D_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
1096
1097 /* ??? Leave these as S_MODES for now. */
1098 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
1099 DF_MODES, 0, DF_MODES, 0, S_MODES, S_MODES, S_MODES, S_MODES,
1100 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
1101 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, C_MODES, S_MODES,
1102
1103 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1104 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1105 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1106 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1107
1108 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1109 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1110 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1111 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1112
1113 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
1114 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES
1115};
1116
1117unsigned int arc_mode_class [NUM_MACHINE_MODES];
1118
1119enum reg_class arc_regno_reg_class[FIRST_PSEUDO_REGISTER];
1120
1121enum reg_class
1122arc_preferred_reload_class (rtx, enum reg_class cl)
1123{
1124 if ((cl) == CHEAP_CORE_REGS || (cl) == WRITABLE_CORE_REGS)
1125 return GENERAL_REGS;
1126 return cl;
1127}
1128
1129/* Initialize the arc_mode_class array. */
1130
1131static void
1132arc_init_reg_tables (void)
1133{
1134 int i;
1135
1136 for (i = 0; i < NUM_MACHINE_MODES; i++)
1137 {
f8d91e80
NC
1138 enum machine_mode m = (enum machine_mode) i;
1139
1140 switch (GET_MODE_CLASS (m))
526b7aee
SV
1141 {
1142 case MODE_INT:
1143 case MODE_PARTIAL_INT:
1144 case MODE_COMPLEX_INT:
f8d91e80 1145 if (GET_MODE_SIZE (m) <= 4)
526b7aee 1146 arc_mode_class[i] = 1 << (int) S_MODE;
f8d91e80 1147 else if (GET_MODE_SIZE (m) == 8)
526b7aee 1148 arc_mode_class[i] = 1 << (int) D_MODE;
f8d91e80 1149 else if (GET_MODE_SIZE (m) == 16)
526b7aee 1150 arc_mode_class[i] = 1 << (int) T_MODE;
f8d91e80 1151 else if (GET_MODE_SIZE (m) == 32)
526b7aee
SV
1152 arc_mode_class[i] = 1 << (int) O_MODE;
1153 else
1154 arc_mode_class[i] = 0;
1155 break;
1156 case MODE_FLOAT:
1157 case MODE_COMPLEX_FLOAT:
f8d91e80 1158 if (GET_MODE_SIZE (m) <= 4)
526b7aee 1159 arc_mode_class[i] = 1 << (int) SF_MODE;
f8d91e80 1160 else if (GET_MODE_SIZE (m) == 8)
526b7aee 1161 arc_mode_class[i] = 1 << (int) DF_MODE;
f8d91e80 1162 else if (GET_MODE_SIZE (m) == 16)
526b7aee 1163 arc_mode_class[i] = 1 << (int) TF_MODE;
f8d91e80 1164 else if (GET_MODE_SIZE (m) == 32)
526b7aee
SV
1165 arc_mode_class[i] = 1 << (int) OF_MODE;
1166 else
1167 arc_mode_class[i] = 0;
1168 break;
1169 case MODE_VECTOR_INT:
1170 arc_mode_class [i] = (1<< (int) V_MODE);
1171 break;
1172 case MODE_CC:
1173 default:
1174 /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
1175 we must explicitly check for them here. */
1176 if (i == (int) CCmode || i == (int) CC_ZNmode || i == (int) CC_Zmode
1177 || i == (int) CC_Cmode
1178 || i == CC_FP_GTmode || i == CC_FP_GEmode || i == CC_FP_ORDmode)
1179 arc_mode_class[i] = 1 << (int) C_MODE;
1180 else
1181 arc_mode_class[i] = 0;
1182 break;
1183 }
1184 }
1185}
1186
1187/* Core registers 56..59 are used for multiply extension options.
1188 The dsp option uses r56 and r57, these are then named acc1 and acc2.
1189 acc1 is the highpart, and acc2 the lowpart, so which register gets which
1190 number depends on endianness.
1191 The mul64 multiplier options use r57 for mlo, r58 for mmid and r59 for mhi.
1192 Because mlo / mhi form a 64 bit value, we use different gcc internal
1193 register numbers to make them form a register pair as the gcc internals
1194 know it. mmid gets number 57, if still available, and mlo / mhi get
1195 number 58 and 59, depending on endianness. We use DBX_REGISTER_NUMBER
1196 to map this back. */
1197 char rname56[5] = "r56";
1198 char rname57[5] = "r57";
1199 char rname58[5] = "r58";
1200 char rname59[5] = "r59";
1201
1202static void
1203arc_conditional_register_usage (void)
1204{
1205 int regno;
1206 int i;
1207 int fix_start = 60, fix_end = 55;
1208
1209 if (TARGET_MUL64_SET)
1210 {
1211 fix_start = 57;
1212 fix_end = 59;
1213
1214 /* We don't provide a name for mmed. In rtl / assembly resource lists,
1215 you are supposed to refer to it as mlo & mhi, e.g
1216 (zero_extract:SI (reg:DI 58) (const_int 32) (16)) .
1217 In an actual asm instruction, you are of course use mmed.
1218 The point of avoiding having a separate register for mmed is that
1219 this way, we don't have to carry clobbers of that reg around in every
1220 isntruction that modifies mlo and/or mhi. */
1221 strcpy (rname57, "");
1222 strcpy (rname58, TARGET_BIG_ENDIAN ? "mhi" : "mlo");
1223 strcpy (rname59, TARGET_BIG_ENDIAN ? "mlo" : "mhi");
1224 }
1225 if (TARGET_MULMAC_32BY16_SET)
1226 {
1227 fix_start = 56;
1228 fix_end = fix_end > 57 ? fix_end : 57;
1229 strcpy (rname56, TARGET_BIG_ENDIAN ? "acc1" : "acc2");
1230 strcpy (rname57, TARGET_BIG_ENDIAN ? "acc2" : "acc1");
1231 }
1232 for (regno = fix_start; regno <= fix_end; regno++)
1233 {
1234 if (!fixed_regs[regno])
1235 warning (0, "multiply option implies r%d is fixed", regno);
1236 fixed_regs [regno] = call_used_regs[regno] = 1;
1237 }
1238 if (TARGET_Q_CLASS)
1239 {
1240 reg_alloc_order[2] = 12;
1241 reg_alloc_order[3] = 13;
1242 reg_alloc_order[4] = 14;
1243 reg_alloc_order[5] = 15;
1244 reg_alloc_order[6] = 1;
1245 reg_alloc_order[7] = 0;
1246 reg_alloc_order[8] = 4;
1247 reg_alloc_order[9] = 5;
1248 reg_alloc_order[10] = 6;
1249 reg_alloc_order[11] = 7;
1250 reg_alloc_order[12] = 8;
1251 reg_alloc_order[13] = 9;
1252 reg_alloc_order[14] = 10;
1253 reg_alloc_order[15] = 11;
1254 }
1255 if (TARGET_SIMD_SET)
1256 {
1257 int i;
6462fab0
JR
1258 for (i = ARC_FIRST_SIMD_VR_REG; i <= ARC_LAST_SIMD_VR_REG; i++)
1259 reg_alloc_order [i] = i;
1260 for (i = ARC_FIRST_SIMD_DMA_CONFIG_REG;
1261 i <= ARC_LAST_SIMD_DMA_CONFIG_REG; i++)
526b7aee
SV
1262 reg_alloc_order [i] = i;
1263 }
1264 /* For Arctangent-A5 / ARC600, lp_count may not be read in an instruction
1265 following immediately after another one setting it to a new value.
1266 There was some discussion on how to enforce scheduling constraints for
1267 processors with missing interlocks on the gcc mailing list:
1268 http://gcc.gnu.org/ml/gcc/2008-05/msg00021.html .
1269 However, we can't actually use this approach, because for ARC the
1270 delay slot scheduling pass is active, which runs after
1271 machine_dependent_reorg. */
1272 if (TARGET_ARC600)
1273 CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], LP_COUNT);
1274 else if (!TARGET_ARC700)
1275 fixed_regs[LP_COUNT] = 1;
1276 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1277 if (!call_used_regs[regno])
1278 CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno);
1279 for (regno = 32; regno < 60; regno++)
1280 if (!fixed_regs[regno])
1281 SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], regno);
1282 if (TARGET_ARC700)
1283 {
1284 for (regno = 32; regno <= 60; regno++)
1285 CLEAR_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], regno);
1286
1287 /* If they have used -ffixed-lp_count, make sure it takes
1288 effect. */
1289 if (fixed_regs[LP_COUNT])
1290 {
1291 CLEAR_HARD_REG_BIT (reg_class_contents[LPCOUNT_REG], LP_COUNT);
1292 CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], LP_COUNT);
1293 CLEAR_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], LP_COUNT);
1294
1295 /* Instead of taking out SF_MODE like below, forbid it outright. */
1296 arc_hard_regno_mode_ok[60] = 0;
1297 }
1298 else
1299 arc_hard_regno_mode_ok[60] = 1 << (int) S_MODE;
1300 }
1301
1302 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1303 {
1304 if (i < 29)
1305 {
1306 if (TARGET_Q_CLASS && ((i <= 3) || ((i >= 12) && (i <= 15))))
1307 arc_regno_reg_class[i] = ARCOMPACT16_REGS;
1308 else
1309 arc_regno_reg_class[i] = GENERAL_REGS;
1310 }
1311 else if (i < 60)
1312 arc_regno_reg_class[i]
1313 = (fixed_regs[i]
1314 ? (TEST_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], i)
1315 ? CHEAP_CORE_REGS : ALL_CORE_REGS)
1316 : ((TARGET_ARC700
1317 && TEST_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], i))
1318 ? CHEAP_CORE_REGS : WRITABLE_CORE_REGS));
1319 else
1320 arc_regno_reg_class[i] = NO_REGS;
1321 }
1322
1323 /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS has not been activated. */
1324 if (!TARGET_Q_CLASS)
1325 {
1326 CLEAR_HARD_REG_SET(reg_class_contents [ARCOMPACT16_REGS]);
1327 CLEAR_HARD_REG_SET(reg_class_contents [AC16_BASE_REGS]);
1328 }
1329
1330 gcc_assert (FIRST_PSEUDO_REGISTER >= 144);
1331
1332 /* Handle Special Registers. */
1333 arc_regno_reg_class[29] = LINK_REGS; /* ilink1 register. */
1334 arc_regno_reg_class[30] = LINK_REGS; /* ilink2 register. */
1335 arc_regno_reg_class[31] = LINK_REGS; /* blink register. */
1336 arc_regno_reg_class[60] = LPCOUNT_REG;
1337 arc_regno_reg_class[61] = NO_REGS; /* CC_REG: must be NO_REGS. */
1338 arc_regno_reg_class[62] = GENERAL_REGS;
1339
1340 if (TARGET_DPFP)
1341 {
1342 for (i = 40; i < 44; ++i)
1343 {
1344 arc_regno_reg_class[i] = DOUBLE_REGS;
1345
1346 /* Unless they want us to do 'mov d1, 0x00000000' make sure
1347 no attempt is made to use such a register as a destination
1348 operand in *movdf_insn. */
1349 if (!TARGET_ARGONAUT_SET)
1350 {
1351 /* Make sure no 'c', 'w', 'W', or 'Rac' constraint is
1352 interpreted to mean they can use D1 or D2 in their insn. */
1353 CLEAR_HARD_REG_BIT(reg_class_contents[CHEAP_CORE_REGS ], i);
1354 CLEAR_HARD_REG_BIT(reg_class_contents[ALL_CORE_REGS ], i);
1355 CLEAR_HARD_REG_BIT(reg_class_contents[WRITABLE_CORE_REGS ], i);
1356 CLEAR_HARD_REG_BIT(reg_class_contents[MPY_WRITABLE_CORE_REGS], i);
1357 }
1358 }
1359 }
1360 else
1361 {
1362 /* Disable all DOUBLE_REGISTER settings,
1363 if not generating DPFP code. */
1364 arc_regno_reg_class[40] = ALL_REGS;
1365 arc_regno_reg_class[41] = ALL_REGS;
1366 arc_regno_reg_class[42] = ALL_REGS;
1367 arc_regno_reg_class[43] = ALL_REGS;
1368
1369 arc_hard_regno_mode_ok[40] = 0;
1370 arc_hard_regno_mode_ok[42] = 0;
1371
1372 CLEAR_HARD_REG_SET(reg_class_contents [DOUBLE_REGS]);
1373 }
1374
1375 if (TARGET_SIMD_SET)
1376 {
1377 gcc_assert (ARC_FIRST_SIMD_VR_REG == 64);
1378 gcc_assert (ARC_LAST_SIMD_VR_REG == 127);
1379
1380 for (i = ARC_FIRST_SIMD_VR_REG; i <= ARC_LAST_SIMD_VR_REG; i++)
1381 arc_regno_reg_class [i] = SIMD_VR_REGS;
1382
1383 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_REG == 128);
1384 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_IN_REG == 128);
1385 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG == 136);
1386 gcc_assert (ARC_LAST_SIMD_DMA_CONFIG_REG == 143);
1387
1388 for (i = ARC_FIRST_SIMD_DMA_CONFIG_REG;
1389 i <= ARC_LAST_SIMD_DMA_CONFIG_REG; i++)
1390 arc_regno_reg_class [i] = SIMD_DMA_CONFIG_REGS;
1391 }
1392
1393 /* pc : r63 */
1394 arc_regno_reg_class[PROGRAM_COUNTER_REGNO] = GENERAL_REGS;
1395}
1396
1397/* Handle an "interrupt" attribute; arguments as in
1398 struct attribute_spec.handler. */
1399
1400static tree
1401arc_handle_interrupt_attribute (tree *, tree name, tree args, int,
1402 bool *no_add_attrs)
1403{
1404 gcc_assert (args);
1405
1406 tree value = TREE_VALUE (args);
1407
1408 if (TREE_CODE (value) != STRING_CST)
1409 {
1410 warning (OPT_Wattributes,
1411 "argument of %qE attribute is not a string constant",
1412 name);
1413 *no_add_attrs = true;
1414 }
1415 else if (strcmp (TREE_STRING_POINTER (value), "ilink1")
1416 && strcmp (TREE_STRING_POINTER (value), "ilink2"))
1417 {
1418 warning (OPT_Wattributes,
1419 "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
1420 name);
1421 *no_add_attrs = true;
1422 }
1423 return NULL_TREE;
1424}
1425
1426/* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
1427 and two if they are nearly compatible (which causes a warning to be
1428 generated). */
1429
1430static int
1431arc_comp_type_attributes (const_tree type1,
1432 const_tree type2)
1433{
1434 int l1, l2, m1, m2, s1, s2;
1435
1436 /* Check for mismatch of non-default calling convention. */
1437 if (TREE_CODE (type1) != FUNCTION_TYPE)
1438 return 1;
1439
1440 /* Check for mismatched call attributes. */
1441 l1 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1)) != NULL;
1442 l2 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2)) != NULL;
1443 m1 = lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type1)) != NULL;
1444 m2 = lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type2)) != NULL;
1445 s1 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1)) != NULL;
1446 s2 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2)) != NULL;
1447
1448 /* Only bother to check if an attribute is defined. */
1449 if (l1 | l2 | m1 | m2 | s1 | s2)
1450 {
1451 /* If one type has an attribute, the other must have the same attribute. */
1452 if ((l1 != l2) || (m1 != m2) || (s1 != s2))
1453 return 0;
1454
1455 /* Disallow mixed attributes. */
1456 if (l1 + m1 + s1 > 1)
1457 return 0;
1458 }
1459
1460
1461 return 1;
1462}
1463
1464/* Set the default attributes for TYPE. */
1465
1466void
1467arc_set_default_type_attributes (tree type ATTRIBUTE_UNUSED)
1468{
1469 gcc_unreachable();
1470}
1471
1472/* Misc. utilities. */
1473
1474/* X and Y are two things to compare using CODE. Emit the compare insn and
1475 return the rtx for the cc reg in the proper mode. */
1476
1477rtx
1478gen_compare_reg (rtx comparison, enum machine_mode omode)
1479{
1480 enum rtx_code code = GET_CODE (comparison);
1481 rtx x = XEXP (comparison, 0);
1482 rtx y = XEXP (comparison, 1);
1483 rtx tmp, cc_reg;
1484 enum machine_mode mode, cmode;
1485
1486
1487 cmode = GET_MODE (x);
1488 if (cmode == VOIDmode)
1489 cmode = GET_MODE (y);
1490 gcc_assert (cmode == SImode || cmode == SFmode || cmode == DFmode);
1491 if (cmode == SImode)
1492 {
1493 if (!register_operand (x, SImode))
1494 {
1495 if (register_operand (y, SImode))
1496 {
1497 tmp = x;
1498 x = y;
1499 y = tmp;
1500 code = swap_condition (code);
1501 }
1502 else
1503 x = copy_to_mode_reg (SImode, x);
1504 }
1505 if (GET_CODE (y) == SYMBOL_REF && flag_pic)
1506 y = copy_to_mode_reg (SImode, y);
1507 }
1508 else
1509 {
1510 x = force_reg (cmode, x);
1511 y = force_reg (cmode, y);
1512 }
1513 mode = SELECT_CC_MODE (code, x, y);
1514
1515 cc_reg = gen_rtx_REG (mode, CC_REG);
1516
1517 /* ??? FIXME (x-y)==0, as done by both cmpsfpx_raw and
1518 cmpdfpx_raw, is not a correct comparison for floats:
1519 http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
1520 */
1521 if (TARGET_ARGONAUT_SET
1522 && ((cmode == SFmode && TARGET_SPFP) || (cmode == DFmode && TARGET_DPFP)))
1523 {
1524 switch (code)
1525 {
1526 case NE: case EQ: case LT: case UNGE: case LE: case UNGT:
1527 case UNEQ: case LTGT: case ORDERED: case UNORDERED:
1528 break;
1529 case GT: case UNLE: case GE: case UNLT:
1530 code = swap_condition (code);
1531 tmp = x;
1532 x = y;
1533 y = tmp;
1534 break;
1535 default:
1536 gcc_unreachable ();
1537 }
1538 if (cmode == SFmode)
1539 {
1540 emit_insn (gen_cmpsfpx_raw (x, y));
1541 }
1542 else /* DFmode */
1543 {
1544 /* Accepts Dx regs directly by insns. */
1545 emit_insn (gen_cmpdfpx_raw (x, y));
1546 }
1547
1548 if (mode != CC_FPXmode)
1549 emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
1550 gen_rtx_COMPARE (mode,
1551 gen_rtx_REG (CC_FPXmode, 61),
1552 const0_rtx)));
1553 }
1554 else if (GET_MODE_CLASS (cmode) == MODE_FLOAT && TARGET_OPTFPE)
1555 {
1556 rtx op0 = gen_rtx_REG (cmode, 0);
1557 rtx op1 = gen_rtx_REG (cmode, GET_MODE_SIZE (cmode) / UNITS_PER_WORD);
1558
1559 switch (code)
1560 {
1561 case NE: case EQ: case GT: case UNLE: case GE: case UNLT:
1562 case UNEQ: case LTGT: case ORDERED: case UNORDERED:
1563 break;
1564 case LT: case UNGE: case LE: case UNGT:
1565 code = swap_condition (code);
1566 tmp = x;
1567 x = y;
1568 y = tmp;
1569 break;
1570 default:
1571 gcc_unreachable ();
1572 }
1573 if (currently_expanding_to_rtl)
1574 {
1575 emit_move_insn (op0, x);
1576 emit_move_insn (op1, y);
1577 }
1578 else
1579 {
1580 gcc_assert (rtx_equal_p (op0, x));
1581 gcc_assert (rtx_equal_p (op1, y));
1582 }
1583 emit_insn (gen_cmp_float (cc_reg, gen_rtx_COMPARE (mode, op0, op1)));
1584 }
1585 else
1586 emit_insn (gen_rtx_SET (omode, cc_reg,
1587 gen_rtx_COMPARE (mode, x, y)));
1588 return gen_rtx_fmt_ee (code, omode, cc_reg, const0_rtx);
1589}
1590
1591/* Return true if VALUE, a const_double, will fit in a limm (4 byte number).
1592 We assume the value can be either signed or unsigned. */
1593
1594bool
1595arc_double_limm_p (rtx value)
1596{
1597 HOST_WIDE_INT low, high;
1598
1599 gcc_assert (GET_CODE (value) == CONST_DOUBLE);
1600
1601 if (TARGET_DPFP)
1602 return true;
1603
1604 low = CONST_DOUBLE_LOW (value);
1605 high = CONST_DOUBLE_HIGH (value);
1606
1607 if (low & 0x80000000)
1608 {
1609 return (((unsigned HOST_WIDE_INT) low <= 0xffffffff && high == 0)
1610 || (((low & - (unsigned HOST_WIDE_INT) 0x80000000)
1611 == - (unsigned HOST_WIDE_INT) 0x80000000)
1612 && high == -1));
1613 }
1614 else
1615 {
1616 return (unsigned HOST_WIDE_INT) low <= 0x7fffffff && high == 0;
1617 }
1618}
1619
1620/* Do any needed setup for a variadic function. For the ARC, we must
1621 create a register parameter block, and then copy any anonymous arguments
1622 in registers to memory.
1623
1624 CUM has not been updated for the last named argument which has type TYPE
1625 and mode MODE, and we rely on this fact. */
1626
1627static void
1628arc_setup_incoming_varargs (cumulative_args_t args_so_far,
1629 enum machine_mode mode, tree type,
1630 int *pretend_size, int no_rtl)
1631{
1632 int first_anon_arg;
1633 CUMULATIVE_ARGS next_cum;
1634
1635 /* We must treat `__builtin_va_alist' as an anonymous arg. */
1636
1637 next_cum = *get_cumulative_args (args_so_far);
1638 arc_function_arg_advance (pack_cumulative_args (&next_cum), mode, type, 1);
1639 first_anon_arg = next_cum;
1640
1641 if (first_anon_arg < MAX_ARC_PARM_REGS)
1642 {
1643 /* First anonymous (unnamed) argument is in a reg. */
1644
1645 /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
1646 int first_reg_offset = first_anon_arg;
1647
1648 if (!no_rtl)
1649 {
1650 rtx regblock
1651 = gen_rtx_MEM (BLKmode, plus_constant (Pmode, arg_pointer_rtx,
1652 FIRST_PARM_OFFSET (0)));
1653 move_block_from_reg (first_reg_offset, regblock,
1654 MAX_ARC_PARM_REGS - first_reg_offset);
1655 }
1656
1657 *pretend_size
1658 = ((MAX_ARC_PARM_REGS - first_reg_offset ) * UNITS_PER_WORD);
1659 }
1660}
1661
1662/* Cost functions. */
1663
1664/* Provide the costs of an addressing mode that contains ADDR.
1665 If ADDR is not a valid address, its cost is irrelevant. */
1666
1667int
1668arc_address_cost (rtx addr, enum machine_mode, addr_space_t, bool speed)
1669{
1670 switch (GET_CODE (addr))
1671 {
1672 case REG :
1673 return speed || satisfies_constraint_Rcq (addr) ? 0 : 1;
1674 case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC:
1675 case PRE_MODIFY: case POST_MODIFY:
1676 return !speed;
1677
1678 case LABEL_REF :
1679 case SYMBOL_REF :
1680 case CONST :
1681 /* Most likely needs a LIMM. */
1682 return COSTS_N_INSNS (1);
1683
1684 case PLUS :
1685 {
1686 register rtx plus0 = XEXP (addr, 0);
1687 register rtx plus1 = XEXP (addr, 1);
1688
1689 if (GET_CODE (plus0) != REG
1690 && (GET_CODE (plus0) != MULT
1691 || !CONST_INT_P (XEXP (plus0, 1))
1692 || (INTVAL (XEXP (plus0, 1)) != 2
1693 && INTVAL (XEXP (plus0, 1)) != 4)))
1694 break;
1695
1696 switch (GET_CODE (plus1))
1697 {
1698 case CONST_INT :
1699 return (!RTX_OK_FOR_OFFSET_P (SImode, plus1)
1700 ? COSTS_N_INSNS (1)
1701 : speed
1702 ? 0
1703 : (satisfies_constraint_Rcq (plus0)
1704 && satisfies_constraint_O (plus1))
1705 ? 0
1706 : 1);
1707 case REG:
1708 return (speed < 1 ? 0
1709 : (satisfies_constraint_Rcq (plus0)
1710 && satisfies_constraint_Rcq (plus1))
1711 ? 0 : 1);
1712 case CONST :
1713 case SYMBOL_REF :
1714 case LABEL_REF :
1715 return COSTS_N_INSNS (1);
1716 default:
1717 break;
1718 }
1719 break;
1720 }
1721 default:
1722 break;
1723 }
1724
1725 return 4;
1726}
1727
1728/* Emit instruction X with the frame related bit set. */
1729
1730static rtx
1731frame_insn (rtx x)
1732{
1733 x = emit_insn (x);
1734 RTX_FRAME_RELATED_P (x) = 1;
1735 return x;
1736}
1737
1738/* Emit a frame insn to move SRC to DST. */
1739
1740static rtx
1741frame_move (rtx dst, rtx src)
1742{
1743 return frame_insn (gen_rtx_SET (VOIDmode, dst, src));
1744}
1745
1746/* Like frame_move, but add a REG_INC note for REG if ADDR contains an
1747 auto increment address, or is zero. */
1748
1749static rtx
1750frame_move_inc (rtx dst, rtx src, rtx reg, rtx addr)
1751{
1752 rtx insn = frame_move (dst, src);
1753
1754 if (!addr
1755 || GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_INC
1756 || GET_CODE (addr) == PRE_MODIFY || GET_CODE (addr) == POST_MODIFY)
1757 add_reg_note (insn, REG_INC, reg);
1758 return insn;
1759}
1760
1761/* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
1762
1763static rtx
1764frame_add (rtx reg, HOST_WIDE_INT offset)
1765{
1766 gcc_assert ((offset & 0x3) == 0);
1767 if (!offset)
1768 return NULL_RTX;
1769 return frame_move (reg, plus_constant (Pmode, reg, offset));
1770}
1771
1772/* Emit a frame insn which adjusts stack pointer by OFFSET. */
1773
1774static rtx
1775frame_stack_add (HOST_WIDE_INT offset)
1776{
1777 return frame_add (stack_pointer_rtx, offset);
1778}
1779
1780/* Traditionally, we push saved registers first in the prologue,
1781 then we allocate the rest of the frame - and reverse in the epilogue.
1782 This has still its merits for ease of debugging, or saving code size
1783 or even execution time if the stack frame is so large that some accesses
1784 can't be encoded anymore with offsets in the instruction code when using
1785 a different scheme.
1786 Also, it would be a good starting point if we got instructions to help
1787 with register save/restore.
1788
1789 However, often stack frames are small, and the pushing / popping has
1790 some costs:
1791 - the stack modification prevents a lot of scheduling.
1792 - frame allocation / deallocation needs extra instructions.
1793 - unless we know that we compile ARC700 user code, we need to put
1794 a memory barrier after frame allocation / before deallocation to
1795 prevent interrupts clobbering our data in the frame.
1796 In particular, we don't have any such guarantees for library functions,
1797 which tend to, on the other hand, to have small frames.
1798
1799 Thus, for small frames, we'd like to use a different scheme:
1800 - The frame is allocated in full with the first prologue instruction,
1801 and deallocated in full with the last epilogue instruction.
1802 Thus, the instructions in-betwen can be freely scheduled.
1803 - If the function has no outgoing arguments on the stack, we can allocate
1804 one register save slot at the top of the stack. This register can then
1805 be saved simultanously with frame allocation, and restored with
1806 frame deallocation.
1807 This register can be picked depending on scheduling considerations,
1808 although same though should go into having some set of registers
1809 to be potentially lingering after a call, and others to be available
1810 immediately - i.e. in the absence of interprocedual optimization, we
1811 can use an ABI-like convention for register allocation to reduce
1812 stalls after function return. */
1813/* Function prologue/epilogue handlers. */
1814
1815/* ARCompact stack frames look like:
1816
1817 Before call After call
1818 high +-----------------------+ +-----------------------+
1819 mem | reg parm save area | | reg parm save area |
1820 | only created for | | only created for |
1821 | variable arg fns | | variable arg fns |
1822 AP +-----------------------+ +-----------------------+
1823 | return addr register | | return addr register |
1824 | (if required) | | (if required) |
1825 +-----------------------+ +-----------------------+
1826 | | | |
1827 | reg save area | | reg save area |
1828 | | | |
1829 +-----------------------+ +-----------------------+
1830 | frame pointer | | frame pointer |
1831 | (if required) | | (if required) |
1832 FP +-----------------------+ +-----------------------+
1833 | | | |
1834 | local/temp variables | | local/temp variables |
1835 | | | |
1836 +-----------------------+ +-----------------------+
1837 | | | |
1838 | arguments on stack | | arguments on stack |
1839 | | | |
1840 SP +-----------------------+ +-----------------------+
1841 | reg parm save area |
1842 | only created for |
1843 | variable arg fns |
1844 AP +-----------------------+
1845 | return addr register |
1846 | (if required) |
1847 +-----------------------+
1848 | |
1849 | reg save area |
1850 | |
1851 +-----------------------+
1852 | frame pointer |
1853 | (if required) |
1854 FP +-----------------------+
1855 | |
1856 | local/temp variables |
1857 | |
1858 +-----------------------+
1859 | |
1860 | arguments on stack |
1861 low | |
1862 mem SP +-----------------------+
1863
1864Notes:
18651) The "reg parm save area" does not exist for non variable argument fns.
1866 The "reg parm save area" can be eliminated completely if we created our
1867 own va-arc.h, but that has tradeoffs as well (so it's not done). */
1868
1869/* Structure to be filled in by arc_compute_frame_size with register
1870 save masks, and offsets for the current function. */
6cdfeeb4 1871struct GTY (()) arc_frame_info
526b7aee
SV
1872{
1873 unsigned int total_size; /* # bytes that the entire frame takes up. */
1874 unsigned int extra_size; /* # bytes of extra stuff. */
1875 unsigned int pretend_size; /* # bytes we push and pretend caller did. */
1876 unsigned int args_size; /* # bytes that outgoing arguments take up. */
1877 unsigned int reg_size; /* # bytes needed to store regs. */
1878 unsigned int var_size; /* # bytes that variables take up. */
1879 unsigned int reg_offset; /* Offset from new sp to store regs. */
1880 unsigned int gmask; /* Mask of saved gp registers. */
1881 int initialized; /* Nonzero if frame size already calculated. */
1882 short millicode_start_reg;
1883 short millicode_end_reg;
1884 bool save_return_addr;
1885};
1886
1887/* Defining data structures for per-function information. */
1888
1889typedef struct GTY (()) machine_function
1890{
1891 enum arc_function_type fn_type;
1892 struct arc_frame_info frame_info;
1893 /* To keep track of unalignment caused by short insns. */
1894 int unalign;
1895 int force_short_suffix; /* Used when disgorging return delay slot insns. */
1896 const char *size_reason;
1897 struct arc_ccfsm ccfsm_current;
1898 /* Map from uid to ccfsm state during branch shortening. */
1899 rtx ccfsm_current_insn;
1900 char arc_reorg_started;
1901 char prescan_initialized;
1902} machine_function;
1903
1904/* Type of function DECL.
1905
1906 The result is cached. To reset the cache at the end of a function,
1907 call with DECL = NULL_TREE. */
1908
1909enum arc_function_type
1910arc_compute_function_type (struct function *fun)
1911{
1912 tree decl = fun->decl;
1913 tree a;
1914 enum arc_function_type fn_type = fun->machine->fn_type;
1915
1916 if (fn_type != ARC_FUNCTION_UNKNOWN)
1917 return fn_type;
1918
1919 /* Assume we have a normal function (not an interrupt handler). */
1920 fn_type = ARC_FUNCTION_NORMAL;
1921
1922 /* Now see if this is an interrupt handler. */
1923 for (a = DECL_ATTRIBUTES (decl);
1924 a;
1925 a = TREE_CHAIN (a))
1926 {
1927 tree name = TREE_PURPOSE (a), args = TREE_VALUE (a);
1928
1929 if (name == get_identifier ("interrupt")
1930 && list_length (args) == 1
1931 && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
1932 {
1933 tree value = TREE_VALUE (args);
1934
1935 if (!strcmp (TREE_STRING_POINTER (value), "ilink1"))
1936 fn_type = ARC_FUNCTION_ILINK1;
1937 else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
1938 fn_type = ARC_FUNCTION_ILINK2;
1939 else
1940 gcc_unreachable ();
1941 break;
1942 }
1943 }
1944
1945 return fun->machine->fn_type = fn_type;
1946}
1947
1948#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
1949#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
1950
1951/* Tell prologue and epilogue if register REGNO should be saved / restored.
1952 The return address and frame pointer are treated separately.
1953 Don't consider them here.
1954 Addition for pic: The gp register needs to be saved if the current
1955 function changes it to access gotoff variables.
1956 FIXME: This will not be needed if we used some arbitrary register
1957 instead of r26.
1958*/
1959#define MUST_SAVE_REGISTER(regno, interrupt_p) \
1960(((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
1961 && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p))) \
1962 || (flag_pic && crtl->uses_pic_offset_table \
1963 && regno == PIC_OFFSET_TABLE_REGNUM) )
1964
1965#define MUST_SAVE_RETURN_ADDR \
1966 (cfun->machine->frame_info.save_return_addr)
1967
1968/* Return non-zero if there are registers to be saved or loaded using
1969 millicode thunks. We can only use consecutive sequences starting
1970 with r13, and not going beyond r25.
1971 GMASK is a bitmask of registers to save. This function sets
1972 FRAME->millicod_start_reg .. FRAME->millicode_end_reg to the range
1973 of registers to be saved / restored with a millicode call. */
1974
1975static int
1976arc_compute_millicode_save_restore_regs (unsigned int gmask,
1977 struct arc_frame_info *frame)
1978{
1979 int regno;
1980
1981 int start_reg = 13, end_reg = 25;
1982
1983 for (regno = start_reg; regno <= end_reg && (gmask & (1L << regno));)
1984 regno++;
1985 end_reg = regno - 1;
1986 /* There is no point in using millicode thunks if we don't save/restore
1987 at least three registers. For non-leaf functions we also have the
1988 blink restore. */
1989 if (regno - start_reg >= 3 - (crtl->is_leaf == 0))
1990 {
1991 frame->millicode_start_reg = 13;
1992 frame->millicode_end_reg = regno - 1;
1993 return 1;
1994 }
1995 return 0;
1996}
1997
1998/* Return the bytes needed to compute the frame pointer from the current
1999 stack pointer.
2000
2001 SIZE is the size needed for local variables. */
2002
2003unsigned int
2004arc_compute_frame_size (int size) /* size = # of var. bytes allocated. */
2005{
2006 int regno;
2007 unsigned int total_size, var_size, args_size, pretend_size, extra_size;
2008 unsigned int reg_size, reg_offset;
2009 unsigned int gmask;
2010 enum arc_function_type fn_type;
2011 int interrupt_p;
2012 struct arc_frame_info *frame_info = &cfun->machine->frame_info;
2013
2014 size = ARC_STACK_ALIGN (size);
2015
2016 /* 1) Size of locals and temporaries */
2017 var_size = size;
2018
2019 /* 2) Size of outgoing arguments */
2020 args_size = crtl->outgoing_args_size;
2021
2022 /* 3) Calculate space needed for saved registers.
2023 ??? We ignore the extension registers for now. */
2024
2025 /* See if this is an interrupt handler. Call used registers must be saved
2026 for them too. */
2027
2028 reg_size = 0;
2029 gmask = 0;
2030 fn_type = arc_compute_function_type (cfun);
2031 interrupt_p = ARC_INTERRUPT_P (fn_type);
2032
2033 for (regno = 0; regno <= 31; regno++)
2034 {
2035 if (MUST_SAVE_REGISTER (regno, interrupt_p))
2036 {
2037 reg_size += UNITS_PER_WORD;
2038 gmask |= 1 << regno;
2039 }
2040 }
2041
2042 /* 4) Space for back trace data structure.
2043 <return addr reg size> (if required) + <fp size> (if required). */
2044 frame_info->save_return_addr
2045 = (!crtl->is_leaf || df_regs_ever_live_p (RETURN_ADDR_REGNUM));
2046 /* Saving blink reg in case of leaf function for millicode thunk calls. */
2047 if (optimize_size && !TARGET_NO_MILLICODE_THUNK_SET)
2048 {
2049 if (arc_compute_millicode_save_restore_regs (gmask, frame_info))
2050 frame_info->save_return_addr = true;
2051 }
2052
2053 extra_size = 0;
2054 if (MUST_SAVE_RETURN_ADDR)
2055 extra_size = 4;
2056 if (frame_pointer_needed)
2057 extra_size += 4;
2058
2059 /* 5) Space for variable arguments passed in registers */
2060 pretend_size = crtl->args.pretend_args_size;
2061
2062 /* Ensure everything before the locals is aligned appropriately. */
2063 {
2064 unsigned int extra_plus_reg_size;
2065 unsigned int extra_plus_reg_size_aligned;
2066
2067 extra_plus_reg_size = extra_size + reg_size;
2068 extra_plus_reg_size_aligned = ARC_STACK_ALIGN(extra_plus_reg_size);
2069 reg_size = extra_plus_reg_size_aligned - extra_size;
2070 }
2071
2072 /* Compute total frame size. */
2073 total_size = var_size + args_size + extra_size + pretend_size + reg_size;
2074
2075 total_size = ARC_STACK_ALIGN (total_size);
2076
2077 /* Compute offset of register save area from stack pointer:
2078 A5 Frame: pretend_size <blink> reg_size <fp> var_size args_size <--sp
2079 */
2080 reg_offset = (total_size - (pretend_size + reg_size + extra_size)
2081 + (frame_pointer_needed ? 4 : 0));
2082
2083 /* Save computed information. */
2084 frame_info->total_size = total_size;
2085 frame_info->extra_size = extra_size;
2086 frame_info->pretend_size = pretend_size;
2087 frame_info->var_size = var_size;
2088 frame_info->args_size = args_size;
2089 frame_info->reg_size = reg_size;
2090 frame_info->reg_offset = reg_offset;
2091 frame_info->gmask = gmask;
2092 frame_info->initialized = reload_completed;
2093
2094 /* Ok, we're done. */
2095 return total_size;
2096}
2097
2098/* Common code to save/restore registers. */
2099/* BASE_REG is the base register to use for addressing and to adjust.
2100 GMASK is a bitmask of general purpose registers to save/restore.
2101 epilogue_p 0: prologue 1:epilogue 2:epilogue, sibling thunk
2102 If *FIRST_OFFSET is non-zero, add it first to BASE_REG - preferably
2103 using a pre-modify for the first memory access. *FIRST_OFFSET is then
2104 zeroed. */
2105
2106static void
2107arc_save_restore (rtx base_reg,
2108 unsigned int gmask, int epilogue_p, int *first_offset)
2109{
2110 unsigned int offset = 0;
2111 int regno;
2112 struct arc_frame_info *frame = &cfun->machine->frame_info;
2113 rtx sibthunk_insn = NULL_RTX;
2114
2115 if (gmask)
2116 {
2117 /* Millicode thunks implementation:
2118 Generates calls to millicodes for registers starting from r13 to r25
2119 Present Limitations:
2120 - Only one range supported. The remaining regs will have the ordinary
2121 st and ld instructions for store and loads. Hence a gmask asking
2122 to store r13-14, r16-r25 will only generate calls to store and
2123 load r13 to r14 while store and load insns will be generated for
2124 r16 to r25 in the prologue and epilogue respectively.
2125
2126 - Presently library only supports register ranges starting from r13.
2127 */
2128 if (epilogue_p == 2 || frame->millicode_end_reg > 14)
2129 {
2130 int start_call = frame->millicode_start_reg;
2131 int end_call = frame->millicode_end_reg;
2132 int n_regs = end_call - start_call + 1;
2133 int i = 0, r, off = 0;
2134 rtx insn;
2135 rtx ret_addr = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
2136
2137 if (*first_offset)
2138 {
2139 /* "reg_size" won't be more than 127 . */
6ace1161 2140 gcc_assert (epilogue_p || abs (*first_offset) <= 127);
526b7aee
SV
2141 frame_add (base_reg, *first_offset);
2142 *first_offset = 0;
2143 }
2144 insn = gen_rtx_PARALLEL
2145 (VOIDmode, rtvec_alloc ((epilogue_p == 2) + n_regs + 1));
2146 if (epilogue_p == 2)
2147 i += 2;
2148 else
2149 XVECEXP (insn, 0, n_regs) = gen_rtx_CLOBBER (VOIDmode, ret_addr);
2150 for (r = start_call; r <= end_call; r++, off += UNITS_PER_WORD, i++)
2151 {
2152 rtx reg = gen_rtx_REG (SImode, r);
2153 rtx mem
2154 = gen_frame_mem (SImode, plus_constant (Pmode, base_reg, off));
2155
2156 if (epilogue_p)
2157 XVECEXP (insn, 0, i) = gen_rtx_SET (VOIDmode, reg, mem);
2158 else
2159 XVECEXP (insn, 0, i) = gen_rtx_SET (VOIDmode, mem, reg);
2160 gmask = gmask & ~(1L << r);
2161 }
2162 if (epilogue_p == 2)
2163 sibthunk_insn = insn;
2164 else
2165 frame_insn (insn);
2166 offset += off;
2167 }
2168
2169 for (regno = 0; regno <= 31; regno++)
2170 {
2171 if ((gmask & (1L << regno)) != 0)
2172 {
2173 rtx reg = gen_rtx_REG (SImode, regno);
2174 rtx addr, mem;
2175
2176 if (*first_offset)
2177 {
2178 gcc_assert (!offset);
2179 addr = plus_constant (Pmode, base_reg, *first_offset);
2180 addr = gen_rtx_PRE_MODIFY (Pmode, base_reg, addr);
2181 *first_offset = 0;
2182 }
2183 else
2184 {
2185 gcc_assert (SMALL_INT (offset));
2186 addr = plus_constant (Pmode, base_reg, offset);
2187 }
2188 mem = gen_frame_mem (SImode, addr);
2189 if (epilogue_p)
2190 frame_move_inc (reg, mem, base_reg, addr);
2191 else
2192 frame_move_inc (mem, reg, base_reg, addr);
2193 offset += UNITS_PER_WORD;
2194 } /* if */
2195 } /* for */
2196 }/* if */
2197 if (sibthunk_insn)
2198 {
2199 rtx r12 = gen_rtx_REG (Pmode, 12);
2200
2201 frame_insn (gen_rtx_SET (VOIDmode, r12, GEN_INT (offset)));
2202 XVECEXP (sibthunk_insn, 0, 0) = ret_rtx;
2203 XVECEXP (sibthunk_insn, 0, 1)
2204 = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
2205 gen_rtx_PLUS (Pmode, stack_pointer_rtx, r12));
2206 sibthunk_insn = emit_jump_insn (sibthunk_insn);
2207 RTX_FRAME_RELATED_P (sibthunk_insn) = 1;
2208 }
2209} /* arc_save_restore */
2210
2211
2212int arc_return_address_regs[4]
2213 = {0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM};
2214
2215/* Set up the stack and frame pointer (if desired) for the function. */
2216
2217void
2218arc_expand_prologue (void)
2219{
2220 int size = get_frame_size ();
2221 unsigned int gmask = cfun->machine->frame_info.gmask;
2222 /* unsigned int frame_pointer_offset;*/
2223 unsigned int frame_size_to_allocate;
2224 /* (FIXME: The first store will use a PRE_MODIFY; this will usually be r13.
2225 Change the stack layout so that we rather store a high register with the
2226 PRE_MODIFY, thus enabling more short insn generation.) */
2227 int first_offset = 0;
2228
2229 size = ARC_STACK_ALIGN (size);
2230
2231 /* Compute/get total frame size. */
2232 size = (!cfun->machine->frame_info.initialized
2233 ? arc_compute_frame_size (size)
2234 : cfun->machine->frame_info.total_size);
2235
2236 if (flag_stack_usage_info)
2237 current_function_static_stack_size = size;
2238
2239 /* Keep track of frame size to be allocated. */
2240 frame_size_to_allocate = size;
2241
2242 /* These cases shouldn't happen. Catch them now. */
2243 gcc_assert (!(size == 0 && gmask));
2244
2245 /* Allocate space for register arguments if this is a variadic function. */
2246 if (cfun->machine->frame_info.pretend_size != 0)
2247 {
2248 /* Ensure pretend_size is maximum of 8 * word_size. */
2249 gcc_assert (cfun->machine->frame_info.pretend_size <= 32);
2250
2251 frame_stack_add (-(HOST_WIDE_INT)cfun->machine->frame_info.pretend_size);
2252 frame_size_to_allocate -= cfun->machine->frame_info.pretend_size;
2253 }
2254
2255 /* The home-grown ABI says link register is saved first. */
2256 if (MUST_SAVE_RETURN_ADDR)
2257 {
2258 rtx ra = gen_rtx_REG (SImode, RETURN_ADDR_REGNUM);
2259 rtx mem = gen_frame_mem (Pmode, gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
2260
2261 frame_move_inc (mem, ra, stack_pointer_rtx, 0);
2262 frame_size_to_allocate -= UNITS_PER_WORD;
2263
2264 } /* MUST_SAVE_RETURN_ADDR */
2265
2266 /* Save any needed call-saved regs (and call-used if this is an
2267 interrupt handler) for ARCompact ISA. */
2268 if (cfun->machine->frame_info.reg_size)
2269 {
2270 first_offset = -cfun->machine->frame_info.reg_size;
2271 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
2272 arc_save_restore (stack_pointer_rtx, gmask, 0, &first_offset);
2273 frame_size_to_allocate -= cfun->machine->frame_info.reg_size;
2274 }
2275
2276
2277 /* Save frame pointer if needed. */
2278 if (frame_pointer_needed)
2279 {
2280 rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2281 GEN_INT (-UNITS_PER_WORD + first_offset));
2282 rtx mem = gen_frame_mem (Pmode, gen_rtx_PRE_MODIFY (Pmode,
2283 stack_pointer_rtx,
2284 addr));
2285 frame_move_inc (mem, frame_pointer_rtx, stack_pointer_rtx, 0);
2286 frame_size_to_allocate -= UNITS_PER_WORD;
2287 first_offset = 0;
2288 frame_move (frame_pointer_rtx, stack_pointer_rtx);
2289 }
2290
2291 /* ??? We don't handle the case where the saved regs are more than 252
2292 bytes away from sp. This can be handled by decrementing sp once, saving
2293 the regs, and then decrementing it again. The epilogue doesn't have this
2294 problem as the `ld' insn takes reg+limm values (though it would be more
2295 efficient to avoid reg+limm). */
2296
2297 frame_size_to_allocate -= first_offset;
2298 /* Allocate the stack frame. */
2299 if (frame_size_to_allocate > 0)
2300 frame_stack_add ((HOST_WIDE_INT) 0 - frame_size_to_allocate);
2301
2302 /* Setup the gp register, if needed. */
2303 if (crtl->uses_pic_offset_table)
2304 arc_finalize_pic ();
2305}
2306
2307/* Do any necessary cleanup after a function to restore stack, frame,
2308 and regs. */
2309
2310void
2311arc_expand_epilogue (int sibcall_p)
2312{
2313 int size = get_frame_size ();
2314 enum arc_function_type fn_type = arc_compute_function_type (cfun);
2315
2316 size = ARC_STACK_ALIGN (size);
2317 size = (!cfun->machine->frame_info.initialized
2318 ? arc_compute_frame_size (size)
2319 : cfun->machine->frame_info.total_size);
2320
5719867d
JR
2321 unsigned int pretend_size = cfun->machine->frame_info.pretend_size;
2322 unsigned int frame_size;
2323 unsigned int size_to_deallocate;
2324 int restored;
2325 int can_trust_sp_p = !cfun->calls_alloca;
2326 int first_offset = 0;
2327 int millicode_p = cfun->machine->frame_info.millicode_end_reg > 0;
526b7aee 2328
5719867d 2329 size_to_deallocate = size;
526b7aee 2330
5719867d
JR
2331 frame_size = size - (pretend_size +
2332 cfun->machine->frame_info.reg_size +
2333 cfun->machine->frame_info.extra_size);
526b7aee 2334
5719867d
JR
2335 /* ??? There are lots of optimizations that can be done here.
2336 EG: Use fp to restore regs if it's closer.
2337 Maybe in time we'll do them all. For now, always restore regs from
2338 sp, but don't restore sp if we don't have to. */
526b7aee 2339
5719867d
JR
2340 if (!can_trust_sp_p)
2341 gcc_assert (frame_pointer_needed);
526b7aee 2342
5719867d
JR
2343 /* Restore stack pointer to the beginning of saved register area for
2344 ARCompact ISA. */
2345 if (frame_size)
2346 {
526b7aee 2347 if (frame_pointer_needed)
5719867d
JR
2348 frame_move (stack_pointer_rtx, frame_pointer_rtx);
2349 else
2350 first_offset = frame_size;
2351 size_to_deallocate -= frame_size;
2352 }
2353 else if (!can_trust_sp_p)
2354 frame_stack_add (-frame_size);
526b7aee 2355
526b7aee 2356
5719867d
JR
2357 /* Restore any saved registers. */
2358 if (frame_pointer_needed)
2359 {
2360 rtx addr = gen_rtx_POST_INC (Pmode, stack_pointer_rtx);
2361
2362 frame_move_inc (frame_pointer_rtx, gen_frame_mem (Pmode, addr),
2363 stack_pointer_rtx, 0);
2364 size_to_deallocate -= UNITS_PER_WORD;
2365 }
2366
2367 /* Load blink after the calls to thunk calls in case of optimize size. */
2368 if (millicode_p)
2369 {
2370 int sibthunk_p = (!sibcall_p
2371 && fn_type == ARC_FUNCTION_NORMAL
2372 && !cfun->machine->frame_info.pretend_size);
2373
2374 gcc_assert (!(cfun->machine->frame_info.gmask
2375 & (FRAME_POINTER_MASK | RETURN_ADDR_MASK)));
2376 arc_save_restore (stack_pointer_rtx,
2377 cfun->machine->frame_info.gmask,
2378 1 + sibthunk_p, &first_offset);
2379 if (sibthunk_p)
2380 goto epilogue_done;
2381 }
2382 /* If we are to restore registers, and first_offset would require
2383 a limm to be encoded in a PRE_MODIFY, yet we can add it with a
2384 fast add to the stack pointer, do this now. */
2385 if ((!SMALL_INT (first_offset)
2386 && cfun->machine->frame_info.gmask
2387 && ((TARGET_ARC700 && !optimize_size)
2388 ? first_offset <= 0x800
2389 : satisfies_constraint_C2a (GEN_INT (first_offset))))
2390 /* Also do this if we have both gprs and return
2391 address to restore, and they both would need a LIMM. */
2392 || (MUST_SAVE_RETURN_ADDR
2393 && !SMALL_INT ((cfun->machine->frame_info.reg_size + first_offset) >> 2)
2394 && cfun->machine->frame_info.gmask))
2395 {
2396 frame_stack_add (first_offset);
2397 first_offset = 0;
2398 }
2399 if (MUST_SAVE_RETURN_ADDR)
2400 {
2401 rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
2402 int ra_offs = cfun->machine->frame_info.reg_size + first_offset;
2403 rtx addr = plus_constant (Pmode, stack_pointer_rtx, ra_offs);
2404
2405 /* If the load of blink would need a LIMM, but we can add
2406 the offset quickly to sp, do the latter. */
2407 if (!SMALL_INT (ra_offs >> 2)
2408 && !cfun->machine->frame_info.gmask
2409 && ((TARGET_ARC700 && !optimize_size)
2410 ? ra_offs <= 0x800
2411 : satisfies_constraint_C2a (GEN_INT (ra_offs))))
526b7aee 2412 {
5719867d
JR
2413 size_to_deallocate -= ra_offs - first_offset;
2414 first_offset = 0;
2415 frame_stack_add (ra_offs);
2416 ra_offs = 0;
2417 addr = stack_pointer_rtx;
526b7aee 2418 }
5719867d
JR
2419 /* See if we can combine the load of the return address with the
2420 final stack adjustment.
2421 We need a separate load if there are still registers to
2422 restore. We also want a separate load if the combined insn
2423 would need a limm, but a separate load doesn't. */
2424 if (ra_offs
2425 && !cfun->machine->frame_info.gmask
2426 && (SMALL_INT (ra_offs) || !SMALL_INT (ra_offs >> 2)))
526b7aee 2427 {
5719867d 2428 addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx, addr);
526b7aee 2429 first_offset = 0;
5719867d 2430 size_to_deallocate -= cfun->machine->frame_info.reg_size;
526b7aee 2431 }
5719867d 2432 else if (!ra_offs && size_to_deallocate == UNITS_PER_WORD)
526b7aee 2433 {
5719867d
JR
2434 addr = gen_rtx_POST_INC (Pmode, addr);
2435 size_to_deallocate = 0;
526b7aee 2436 }
5719867d
JR
2437 frame_move_inc (ra, gen_frame_mem (Pmode, addr), stack_pointer_rtx, addr);
2438 }
526b7aee 2439
5719867d
JR
2440 if (!millicode_p)
2441 {
2442 if (cfun->machine->frame_info.reg_size)
2443 arc_save_restore (stack_pointer_rtx,
2444 /* The zeroing of these two bits is unnecessary, but leave this in for clarity. */
2445 cfun->machine->frame_info.gmask
2446 & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK), 1, &first_offset);
2447 }
526b7aee
SV
2448
2449
5719867d
JR
2450 /* The rest of this function does the following:
2451 ARCompact : handle epilogue_delay, restore sp (phase-2), return
2452 */
526b7aee 2453
5719867d
JR
2454 /* Keep track of how much of the stack pointer we've restored.
2455 It makes the following a lot more readable. */
2456 size_to_deallocate += first_offset;
2457 restored = size - size_to_deallocate;
526b7aee 2458
5719867d
JR
2459 if (size > restored)
2460 frame_stack_add (size - restored);
2461 /* Emit the return instruction. */
2462 if (sibcall_p == FALSE)
2463 emit_jump_insn (gen_simple_return ());
526b7aee
SV
2464 epilogue_done:
2465 if (!TARGET_EPILOGUE_CFI)
2466 {
b32d5189 2467 rtx_insn *insn;
526b7aee
SV
2468
2469 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2470 RTX_FRAME_RELATED_P (insn) = 0;
2471 }
2472}
2473
2474/* Return the offset relative to the stack pointer where the return address
2475 is stored, or -1 if it is not stored. */
2476
2477int
2478arc_return_slot_offset ()
2479{
2480 struct arc_frame_info *afi = &cfun->machine->frame_info;
2481
2482 return (afi->save_return_addr
2483 ? afi->total_size - afi->pretend_size - afi->extra_size : -1);
2484}
2485
2486/* PIC */
2487
2488/* Emit special PIC prologues and epilogues. */
2489/* If the function has any GOTOFF relocations, then the GOTBASE
2490 register has to be setup in the prologue
2491 The instruction needed at the function start for setting up the
2492 GOTBASE register is
2493 add rdest, pc,
2494 ----------------------------------------------------------
2495 The rtl to be emitted for this should be:
2496 set (reg basereg)
2497 (plus (reg pc)
2498 (const (unspec (symref _DYNAMIC) 3)))
2499 ---------------------------------------------------------- */
2500
2501static void
2502arc_finalize_pic (void)
2503{
2504 rtx pat;
2505 rtx baseptr_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
2506
2507 if (crtl->uses_pic_offset_table == 0)
2508 return;
2509
2510 gcc_assert (flag_pic != 0);
2511
2512 pat = gen_rtx_SYMBOL_REF (Pmode, "_DYNAMIC");
2513 pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, pat), ARC_UNSPEC_GOT);
2514 pat = gen_rtx_CONST (Pmode, pat);
2515
2516 pat = gen_rtx_SET (VOIDmode, baseptr_rtx, pat);
2517
2518 emit_insn (pat);
2519}
2520\f
2521/* !TARGET_BARREL_SHIFTER support. */
2522/* Emit a shift insn to set OP0 to OP1 shifted by OP2; CODE specifies what
2523 kind of shift. */
2524
2525void
2526emit_shift (enum rtx_code code, rtx op0, rtx op1, rtx op2)
2527{
2528 rtx shift = gen_rtx_fmt_ee (code, SImode, op1, op2);
2529 rtx pat
2530 = ((shift4_operator (shift, SImode) ? gen_shift_si3 : gen_shift_si3_loop)
2531 (op0, op1, op2, shift));
2532 emit_insn (pat);
2533}
2534
2535/* Output the assembler code for doing a shift.
2536 We go to a bit of trouble to generate efficient code as the ARC601 only has
2537 single bit shifts. This is taken from the h8300 port. We only have one
2538 mode of shifting and can't access individual bytes like the h8300 can, so
2539 this is greatly simplified (at the expense of not generating hyper-
2540 efficient code).
2541
2542 This function is not used if the variable shift insns are present. */
2543
2544/* FIXME: This probably can be done using a define_split in arc.md.
2545 Alternately, generate rtx rather than output instructions. */
2546
2547const char *
2548output_shift (rtx *operands)
2549{
2550 /* static int loopend_lab;*/
2551 rtx shift = operands[3];
2552 enum machine_mode mode = GET_MODE (shift);
2553 enum rtx_code code = GET_CODE (shift);
2554 const char *shift_one;
2555
2556 gcc_assert (mode == SImode);
2557
2558 switch (code)
2559 {
2560 case ASHIFT: shift_one = "add %0,%1,%1"; break;
2561 case ASHIFTRT: shift_one = "asr %0,%1"; break;
2562 case LSHIFTRT: shift_one = "lsr %0,%1"; break;
2563 default: gcc_unreachable ();
2564 }
2565
2566 if (GET_CODE (operands[2]) != CONST_INT)
2567 {
2568 output_asm_insn ("and.f lp_count,%2, 0x1f", operands);
2569 goto shiftloop;
2570 }
2571 else
2572 {
2573 int n;
2574
2575 n = INTVAL (operands[2]);
2576
2577 /* Only consider the lower 5 bits of the shift count. */
2578 n = n & 0x1f;
2579
2580 /* First see if we can do them inline. */
2581 /* ??? We could get better scheduling & shorter code (using short insns)
2582 by using splitters. Alas, that'd be even more verbose. */
2583 if (code == ASHIFT && n <= 9 && n > 2
2584 && dest_reg_operand (operands[4], SImode))
2585 {
2586 output_asm_insn ("mov %4,0\n\tadd3 %0,%4,%1", operands);
2587 for (n -=3 ; n >= 3; n -= 3)
2588 output_asm_insn ("add3 %0,%4,%0", operands);
2589 if (n == 2)
2590 output_asm_insn ("add2 %0,%4,%0", operands);
2591 else if (n)
2592 output_asm_insn ("add %0,%0,%0", operands);
2593 }
2594 else if (n <= 4)
2595 {
2596 while (--n >= 0)
2597 {
2598 output_asm_insn (shift_one, operands);
2599 operands[1] = operands[0];
2600 }
2601 }
2602 /* See if we can use a rotate/and. */
2603 else if (n == BITS_PER_WORD - 1)
2604 {
2605 switch (code)
2606 {
2607 case ASHIFT :
2608 output_asm_insn ("and %0,%1,1\n\tror %0,%0", operands);
2609 break;
2610 case ASHIFTRT :
2611 /* The ARC doesn't have a rol insn. Use something else. */
2612 output_asm_insn ("add.f 0,%1,%1\n\tsbc %0,%0,%0", operands);
2613 break;
2614 case LSHIFTRT :
2615 /* The ARC doesn't have a rol insn. Use something else. */
2616 output_asm_insn ("add.f 0,%1,%1\n\trlc %0,0", operands);
2617 break;
2618 default:
2619 break;
2620 }
2621 }
2622 else if (n == BITS_PER_WORD - 2 && dest_reg_operand (operands[4], SImode))
2623 {
2624 switch (code)
2625 {
2626 case ASHIFT :
2627 output_asm_insn ("and %0,%1,3\n\tror %0,%0\n\tror %0,%0", operands);
2628 break;
2629 case ASHIFTRT :
2630#if 1 /* Need some scheduling comparisons. */
2631 output_asm_insn ("add.f %4,%1,%1\n\tsbc %0,%0,%0\n\t"
2632 "add.f 0,%4,%4\n\trlc %0,%0", operands);
2633#else
2634 output_asm_insn ("add.f %4,%1,%1\n\tbxor %0,%4,31\n\t"
2635 "sbc.f %0,%0,%4\n\trlc %0,%0", operands);
2636#endif
2637 break;
2638 case LSHIFTRT :
2639#if 1
2640 output_asm_insn ("add.f %4,%1,%1\n\trlc %0,0\n\t"
2641 "add.f 0,%4,%4\n\trlc %0,%0", operands);
2642#else
2643 output_asm_insn ("add.f %0,%1,%1\n\trlc.f %0,0\n\t"
2644 "and %0,%0,1\n\trlc %0,%0", operands);
2645#endif
2646 break;
2647 default:
2648 break;
2649 }
2650 }
2651 else if (n == BITS_PER_WORD - 3 && code == ASHIFT)
2652 output_asm_insn ("and %0,%1,7\n\tror %0,%0\n\tror %0,%0\n\tror %0,%0",
2653 operands);
2654 /* Must loop. */
2655 else
2656 {
2657 operands[2] = GEN_INT (n);
2658 output_asm_insn ("mov.f lp_count, %2", operands);
2659
2660 shiftloop:
2661 {
2662 output_asm_insn ("lpnz\t2f", operands);
2663 output_asm_insn (shift_one, operands);
2664 output_asm_insn ("nop", operands);
2665 fprintf (asm_out_file, "2:\t%s end single insn loop\n",
2666 ASM_COMMENT_START);
2667 }
2668 }
2669 }
2670
2671 return "";
2672}
2673\f
2674/* Nested function support. */
2675
2676/* Directly store VALUE into memory object BLOCK at OFFSET. */
2677
2678static void
2679emit_store_direct (rtx block, int offset, int value)
2680{
2681 emit_insn (gen_store_direct (adjust_address (block, SImode, offset),
2682 force_reg (SImode,
2683 gen_int_mode (value, SImode))));
2684}
2685
2686/* Emit RTL insns to initialize the variable parts of a trampoline.
2687 FNADDR is an RTX for the address of the function's pure code.
2688 CXT is an RTX for the static chain value for the function. */
2689/* With potentially multiple shared objects loaded, and multiple stacks
2690 present for multiple thereds where trampolines might reside, a simple
2691 range check will likely not suffice for the profiler to tell if a callee
2692 is a trampoline. We a speedier check by making the trampoline start at
2693 an address that is not 4-byte aligned.
2694 A trampoline looks like this:
2695
2696 nop_s 0x78e0
2697entry:
2698 ld_s r12,[pcl,12] 0xd403
2699 ld r11,[pcl,12] 0x170c 700b
2700 j_s [r12] 0x7c00
2701 nop_s 0x78e0
2702
2703 The fastest trampoline to execute for trampolines within +-8KB of CTX
2704 would be:
2705 add2 r11,pcl,s12
2706 j [limm] 0x20200f80 limm
2707 and that would also be faster to write to the stack by computing the offset
2708 from CTX to TRAMP at compile time. However, it would really be better to
2709 get rid of the high cost of cache invalidation when generating trampolines,
2710 which requires that the code part of trampolines stays constant, and
2711 additionally either
2712 - making sure that no executable code but trampolines is on the stack,
2713 no icache entries linger for the area of the stack from when before the
2714 stack was allocated, and allocating trampolines in trampoline-only
2715 cache lines
2716 or
2717 - allocate trampolines fram a special pool of pre-allocated trampolines. */
2718
2719static void
2720arc_initialize_trampoline (rtx tramp, tree fndecl, rtx cxt)
2721{
2722 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
2723
2724 emit_store_direct (tramp, 0, TARGET_BIG_ENDIAN ? 0x78e0d403 : 0xd40378e0);
2725 emit_store_direct (tramp, 4, TARGET_BIG_ENDIAN ? 0x170c700b : 0x700b170c);
2726 emit_store_direct (tramp, 8, TARGET_BIG_ENDIAN ? 0x7c0078e0 : 0x78e07c00);
2727 emit_move_insn (adjust_address (tramp, SImode, 12), fnaddr);
2728 emit_move_insn (adjust_address (tramp, SImode, 16), cxt);
2729 emit_insn (gen_flush_icache (adjust_address (tramp, SImode, 0)));
2730}
2731
2732/* Allow the profiler to easily distinguish trampolines from normal
2733 functions. */
2734
2735static rtx
2736arc_trampoline_adjust_address (rtx addr)
2737{
2738 return plus_constant (Pmode, addr, 2);
2739}
2740
2741/* This is set briefly to 1 when we output a ".as" address modifer, and then
2742 reset when we output the scaled address. */
2743static int output_scaled = 0;
2744
2745/* Print operand X (an rtx) in assembler syntax to file FILE.
2746 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2747 For `%' followed by punctuation, CODE is the punctuation and X is null. */
2748/* In final.c:output_asm_insn:
2749 'l' : label
2750 'a' : address
2751 'c' : constant address if CONSTANT_ADDRESS_P
2752 'n' : negative
2753 Here:
2754 'Z': log2(x+1)-1
2755 'z': log2
2756 'M': log2(~x)
2757 '#': condbranch delay slot suffix
2758 '*': jump delay slot suffix
2759 '?' : nonjump-insn suffix for conditional execution or short instruction
2760 '!' : jump / call suffix for conditional execution or short instruction
2761 '`': fold constant inside unary o-perator, re-recognize, and emit.
2762 'd'
2763 'D'
2764 'R': Second word
2765 'S'
2766 'B': Branch comparison operand - suppress sda reference
2767 'H': Most significant word
2768 'L': Least significant word
2769 'A': ASCII decimal representation of floating point value
2770 'U': Load/store update or scaling indicator
2771 'V': cache bypass indicator for volatile
2772 'P'
2773 'F'
2774 '^'
2775 'O': Operator
2776 'o': original symbol - no @ prepending. */
2777
2778void
2779arc_print_operand (FILE *file, rtx x, int code)
2780{
2781 switch (code)
2782 {
2783 case 'Z':
2784 if (GET_CODE (x) == CONST_INT)
2785 fprintf (file, "%d",exact_log2(INTVAL (x) + 1) - 1 );
2786 else
2787 output_operand_lossage ("invalid operand to %%Z code");
2788
2789 return;
2790
2791 case 'z':
2792 if (GET_CODE (x) == CONST_INT)
2793 fprintf (file, "%d",exact_log2(INTVAL (x)) );
2794 else
2795 output_operand_lossage ("invalid operand to %%z code");
2796
2797 return;
2798
2799 case 'M':
2800 if (GET_CODE (x) == CONST_INT)
2801 fprintf (file, "%d",exact_log2(~INTVAL (x)) );
2802 else
2803 output_operand_lossage ("invalid operand to %%M code");
2804
2805 return;
2806
2807 case '#' :
2808 /* Conditional branches depending on condition codes.
2809 Note that this is only for branches that were known to depend on
2810 condition codes before delay slot scheduling;
2811 out-of-range brcc / bbit expansions should use '*'.
2812 This distinction is important because of the different
2813 allowable delay slot insns and the output of the delay suffix
2814 for TARGET_AT_DBR_COND_EXEC. */
2815 case '*' :
2816 /* Unconditional branches / branches not depending on condition codes.
2817 This could also be a CALL_INSN.
2818 Output the appropriate delay slot suffix. */
2819 if (final_sequence && XVECLEN (final_sequence, 0) != 1)
2820 {
2821 rtx jump = XVECEXP (final_sequence, 0, 0);
2822 rtx delay = XVECEXP (final_sequence, 0, 1);
2823
2824 /* For TARGET_PAD_RETURN we might have grabbed the delay insn. */
2825 if (INSN_DELETED_P (delay))
2826 return;
2827 if (JUMP_P (jump) && INSN_ANNULLED_BRANCH_P (jump))
2828 fputs (INSN_FROM_TARGET_P (delay) ? ".d"
2829 : TARGET_AT_DBR_CONDEXEC && code == '#' ? ".d"
2830 : get_attr_type (jump) == TYPE_RETURN && code == '#' ? ""
2831 : ".nd",
2832 file);
2833 else
2834 fputs (".d", file);
2835 }
2836 return;
2837 case '?' : /* with leading "." */
2838 case '!' : /* without leading "." */
2839 /* This insn can be conditionally executed. See if the ccfsm machinery
2840 says it should be conditionalized.
2841 If it shouldn't, we'll check the compact attribute if this insn
2842 has a short variant, which may be used depending on code size and
2843 alignment considerations. */
2844 if (current_insn_predicate)
2845 arc_ccfsm_current.cc
2846 = get_arc_condition_code (current_insn_predicate);
2847 if (ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current))
2848 {
2849 /* Is this insn in a delay slot sequence? */
2850 if (!final_sequence || XVECLEN (final_sequence, 0) < 2
2851 || current_insn_predicate
68a1a6c0
DM
2852 || CALL_P (final_sequence->insn (0))
2853 || simplejump_p (final_sequence->insn (0)))
526b7aee
SV
2854 {
2855 /* This insn isn't in a delay slot sequence, or conditionalized
2856 independently of its position in a delay slot. */
2857 fprintf (file, "%s%s",
2858 code == '?' ? "." : "",
2859 arc_condition_codes[arc_ccfsm_current.cc]);
2860 /* If this is a jump, there are still short variants. However,
2861 only beq_s / bne_s have the same offset range as b_s,
2862 and the only short conditional returns are jeq_s and jne_s. */
2863 if (code == '!'
2864 && (arc_ccfsm_current.cc == ARC_CC_EQ
2865 || arc_ccfsm_current.cc == ARC_CC_NE
2866 || 0 /* FIXME: check if branch in 7 bit range. */))
2867 output_short_suffix (file);
2868 }
2869 else if (code == '!') /* Jump with delay slot. */
2870 fputs (arc_condition_codes[arc_ccfsm_current.cc], file);
2871 else /* An Instruction in a delay slot of a jump or call. */
2872 {
2873 rtx jump = XVECEXP (final_sequence, 0, 0);
2874 rtx insn = XVECEXP (final_sequence, 0, 1);
2875
2876 /* If the insn is annulled and is from the target path, we need
2877 to inverse the condition test. */
2878 if (JUMP_P (jump) && INSN_ANNULLED_BRANCH_P (jump))
2879 {
2880 if (INSN_FROM_TARGET_P (insn))
2881 fprintf (file, "%s%s",
2882 code == '?' ? "." : "",
2883 arc_condition_codes[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current.cc)]);
2884 else
2885 fprintf (file, "%s%s",
2886 code == '?' ? "." : "",
2887 arc_condition_codes[arc_ccfsm_current.cc]);
2888 if (arc_ccfsm_current.state == 5)
2889 arc_ccfsm_current.state = 0;
2890 }
2891 else
2892 /* This insn is executed for either path, so don't
2893 conditionalize it at all. */
2894 output_short_suffix (file);
2895
2896 }
2897 }
2898 else
2899 output_short_suffix (file);
2900 return;
2901 case'`':
2902 /* FIXME: fold constant inside unary operator, re-recognize, and emit. */
2903 gcc_unreachable ();
2904 case 'd' :
2905 fputs (arc_condition_codes[get_arc_condition_code (x)], file);
2906 return;
2907 case 'D' :
2908 fputs (arc_condition_codes[ARC_INVERSE_CONDITION_CODE
2909 (get_arc_condition_code (x))],
2910 file);
2911 return;
2912 case 'R' :
2913 /* Write second word of DImode or DFmode reference,
2914 register or memory. */
2915 if (GET_CODE (x) == REG)
2916 fputs (reg_names[REGNO (x)+1], file);
2917 else if (GET_CODE (x) == MEM)
2918 {
2919 fputc ('[', file);
2920
2921 /* Handle possible auto-increment. For PRE_INC / PRE_DEC /
2922 PRE_MODIFY, we will have handled the first word already;
2923 For POST_INC / POST_DEC / POST_MODIFY, the access to the
2924 first word will be done later. In either case, the access
2925 to the first word will do the modify, and we only have
2926 to add an offset of four here. */
2927 if (GET_CODE (XEXP (x, 0)) == PRE_INC
2928 || GET_CODE (XEXP (x, 0)) == PRE_DEC
2929 || GET_CODE (XEXP (x, 0)) == PRE_MODIFY
2930 || GET_CODE (XEXP (x, 0)) == POST_INC
2931 || GET_CODE (XEXP (x, 0)) == POST_DEC
2932 || GET_CODE (XEXP (x, 0)) == POST_MODIFY)
2933 output_address (plus_constant (Pmode, XEXP (XEXP (x, 0), 0), 4));
2934 else if (output_scaled)
2935 {
2936 rtx addr = XEXP (x, 0);
2937 int size = GET_MODE_SIZE (GET_MODE (x));
2938
2939 output_address (plus_constant (Pmode, XEXP (addr, 0),
2940 ((INTVAL (XEXP (addr, 1)) + 4)
2941 >> (size == 2 ? 1 : 2))));
2942 output_scaled = 0;
2943 }
2944 else
2945 output_address (plus_constant (Pmode, XEXP (x, 0), 4));
2946 fputc (']', file);
2947 }
2948 else
2949 output_operand_lossage ("invalid operand to %%R code");
2950 return;
2951 case 'S' :
2952 /* FIXME: remove %S option. */
2953 break;
2954 case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
2955 if (CONSTANT_P (x))
2956 {
2957 output_addr_const (file, x);
2958 return;
2959 }
2960 break;
2961 case 'H' :
2962 case 'L' :
2963 if (GET_CODE (x) == REG)
2964 {
2965 /* L = least significant word, H = most significant word. */
2966 if ((WORDS_BIG_ENDIAN != 0) ^ (code == 'L'))
2967 fputs (reg_names[REGNO (x)], file);
2968 else
2969 fputs (reg_names[REGNO (x)+1], file);
2970 }
2971 else if (GET_CODE (x) == CONST_INT
2972 || GET_CODE (x) == CONST_DOUBLE)
2973 {
2974 rtx first, second;
2975
2976 split_double (x, &first, &second);
2977
2978 if((WORDS_BIG_ENDIAN) == 0)
dfca07ea 2979 fprintf (file, "0x%08" PRIx64,
526b7aee
SV
2980 code == 'L' ? INTVAL (first) : INTVAL (second));
2981 else
dfca07ea 2982 fprintf (file, "0x%08" PRIx64,
526b7aee
SV
2983 code == 'L' ? INTVAL (second) : INTVAL (first));
2984
2985
2986 }
2987 else
2988 output_operand_lossage ("invalid operand to %%H/%%L code");
2989 return;
2990 case 'A' :
2991 {
2992 char str[30];
2993
2994 gcc_assert (GET_CODE (x) == CONST_DOUBLE
2995 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT);
2996
2997 real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x), sizeof (str), 0, 1);
2998 fprintf (file, "%s", str);
2999 return;
3000 }
3001 case 'U' :
3002 /* Output a load/store with update indicator if appropriate. */
3003 if (GET_CODE (x) == MEM)
3004 {
3005 rtx addr = XEXP (x, 0);
3006 switch (GET_CODE (addr))
3007 {
3008 case PRE_INC: case PRE_DEC: case PRE_MODIFY:
3009 fputs (".a", file); break;
3010 case POST_INC: case POST_DEC: case POST_MODIFY:
3011 fputs (".ab", file); break;
3012 case PLUS:
3013 /* Are we using a scaled index? */
3014 if (GET_CODE (XEXP (addr, 0)) == MULT)
3015 fputs (".as", file);
3016 /* Can we use a scaled offset? */
3017 else if (CONST_INT_P (XEXP (addr, 1))
3018 && GET_MODE_SIZE (GET_MODE (x)) > 1
3019 && (!(INTVAL (XEXP (addr, 1))
3020 & (GET_MODE_SIZE (GET_MODE (x)) - 1) & 3))
3021 /* Does it make a difference? */
3022 && !SMALL_INT_RANGE(INTVAL (XEXP (addr, 1)),
3023 GET_MODE_SIZE (GET_MODE (x)) - 2, 0))
3024 {
3025 fputs (".as", file);
3026 output_scaled = 1;
3027 }
3028 break;
3029 case REG:
3030 break;
3031 default:
3032 gcc_assert (CONSTANT_P (addr)); break;
3033 }
3034 }
3035 else
3036 output_operand_lossage ("invalid operand to %%U code");
3037 return;
3038 case 'V' :
3039 /* Output cache bypass indicator for a load/store insn. Volatile memory
3040 refs are defined to use the cache bypass mechanism. */
3041 if (GET_CODE (x) == MEM)
3042 {
3043 if (MEM_VOLATILE_P (x) && !TARGET_VOLATILE_CACHE_SET )
3044 fputs (".di", file);
3045 }
3046 else
3047 output_operand_lossage ("invalid operand to %%V code");
3048 return;
3049 /* plt code. */
3050 case 'P':
3051 case 0 :
3052 /* Do nothing special. */
3053 break;
3054 case 'F':
3055 fputs (reg_names[REGNO (x)]+1, file);
3056 return;
3057 case '^':
3058 /* This punctuation character is needed because label references are
3059 printed in the output template using %l. This is a front end
3060 character, and when we want to emit a '@' before it, we have to use
3061 this '^'. */
3062
3063 fputc('@',file);
3064 return;
3065 case 'O':
3066 /* Output an operator. */
3067 switch (GET_CODE (x))
3068 {
3069 case PLUS: fputs ("add", file); return;
3070 case SS_PLUS: fputs ("adds", file); return;
3071 case AND: fputs ("and", file); return;
3072 case IOR: fputs ("or", file); return;
3073 case XOR: fputs ("xor", file); return;
3074 case MINUS: fputs ("sub", file); return;
3075 case SS_MINUS: fputs ("subs", file); return;
3076 case ASHIFT: fputs ("asl", file); return;
3077 case ASHIFTRT: fputs ("asr", file); return;
3078 case LSHIFTRT: fputs ("lsr", file); return;
3079 case ROTATERT: fputs ("ror", file); return;
3080 case MULT: fputs ("mpy", file); return;
3081 case ABS: fputs ("abs", file); return; /* Unconditional. */
3082 case NEG: fputs ("neg", file); return;
3083 case SS_NEG: fputs ("negs", file); return;
3084 case NOT: fputs ("not", file); return; /* Unconditional. */
3085 case ZERO_EXTEND:
3086 fputs ("ext", file); /* bmsk allows predication. */
3087 goto size_suffix;
3088 case SIGN_EXTEND: /* Unconditional. */
3089 fputs ("sex", file);
3090 size_suffix:
3091 switch (GET_MODE (XEXP (x, 0)))
3092 {
3093 case QImode: fputs ("b", file); return;
3094 case HImode: fputs ("w", file); return;
3095 default: break;
3096 }
3097 break;
3098 case SS_TRUNCATE:
3099 if (GET_MODE (x) != HImode)
3100 break;
3101 fputs ("sat16", file);
3102 default: break;
3103 }
3104 output_operand_lossage ("invalid operand to %%O code"); return;
3105 case 'o':
3106 if (GET_CODE (x) == SYMBOL_REF)
3107 {
3108 assemble_name (file, XSTR (x, 0));
3109 return;
3110 }
3111 break;
3112 case '&':
3113 if (TARGET_ANNOTATE_ALIGN && cfun->machine->size_reason)
3114 fprintf (file, "; unalign: %d", cfun->machine->unalign);
3115 return;
3116 default :
3117 /* Unknown flag. */
3118 output_operand_lossage ("invalid operand output code");
3119 }
3120
3121 switch (GET_CODE (x))
3122 {
3123 case REG :
3124 fputs (reg_names[REGNO (x)], file);
3125 break;
3126 case MEM :
3127 {
3128 rtx addr = XEXP (x, 0);
3129 int size = GET_MODE_SIZE (GET_MODE (x));
3130
3131 fputc ('[', file);
3132
3133 switch (GET_CODE (addr))
3134 {
3135 case PRE_INC: case POST_INC:
3136 output_address (plus_constant (Pmode, XEXP (addr, 0), size)); break;
3137 case PRE_DEC: case POST_DEC:
3138 output_address (plus_constant (Pmode, XEXP (addr, 0), -size));
3139 break;
3140 case PRE_MODIFY: case POST_MODIFY:
3141 output_address (XEXP (addr, 1)); break;
3142 case PLUS:
3143 if (output_scaled)
3144 {
3145 output_address (plus_constant (Pmode, XEXP (addr, 0),
3146 (INTVAL (XEXP (addr, 1))
3147 >> (size == 2 ? 1 : 2))));
3148 output_scaled = 0;
3149 }
3150 else
3151 output_address (addr);
3152 break;
3153 default:
3154 if (flag_pic && CONSTANT_ADDRESS_P (addr))
3155 arc_output_pic_addr_const (file, addr, code);
3156 else
3157 output_address (addr);
3158 break;
3159 }
3160 fputc (']', file);
3161 break;
3162 }
3163 case CONST_DOUBLE :
3164 /* We handle SFmode constants here as output_addr_const doesn't. */
3165 if (GET_MODE (x) == SFmode)
3166 {
3167 REAL_VALUE_TYPE d;
3168 long l;
3169
3170 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
3171 REAL_VALUE_TO_TARGET_SINGLE (d, l);
3172 fprintf (file, "0x%08lx", l);
3173 break;
3174 }
3175 /* Fall through. Let output_addr_const deal with it. */
3176 default :
3177 if (flag_pic)
3178 arc_output_pic_addr_const (file, x, code);
3179 else
3180 {
3181 /* FIXME: Dirty way to handle @var@sda+const. Shd be handled
3182 with asm_output_symbol_ref */
3183 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
3184 {
3185 x = XEXP (x, 0);
3186 output_addr_const (file, XEXP (x, 0));
3187 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF && SYMBOL_REF_SMALL_P (XEXP (x, 0)))
3188 fprintf (file, "@sda");
3189
3190 if (GET_CODE (XEXP (x, 1)) != CONST_INT
3191 || INTVAL (XEXP (x, 1)) >= 0)
3192 fprintf (file, "+");
3193 output_addr_const (file, XEXP (x, 1));
3194 }
3195 else
3196 output_addr_const (file, x);
3197 }
3198 if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_SMALL_P (x))
3199 fprintf (file, "@sda");
3200 break;
3201 }
3202}
3203
3204/* Print a memory address as an operand to reference that memory location. */
3205
3206void
3207arc_print_operand_address (FILE *file , rtx addr)
3208{
3209 register rtx base, index = 0;
3210
3211 switch (GET_CODE (addr))
3212 {
3213 case REG :
3214 fputs (reg_names[REGNO (addr)], file);
3215 break;
3216 case SYMBOL_REF :
3217 output_addr_const (file, addr);
3218 if (SYMBOL_REF_SMALL_P (addr))
3219 fprintf (file, "@sda");
3220 break;
3221 case PLUS :
3222 if (GET_CODE (XEXP (addr, 0)) == MULT)
3223 index = XEXP (XEXP (addr, 0), 0), base = XEXP (addr, 1);
3224 else if (CONST_INT_P (XEXP (addr, 0)))
3225 index = XEXP (addr, 0), base = XEXP (addr, 1);
3226 else
3227 base = XEXP (addr, 0), index = XEXP (addr, 1);
3228
3229 gcc_assert (OBJECT_P (base));
3230 arc_print_operand_address (file, base);
3231 if (CONSTANT_P (base) && CONST_INT_P (index))
3232 fputc ('+', file);
3233 else
3234 fputc (',', file);
3235 gcc_assert (OBJECT_P (index));
3236 arc_print_operand_address (file, index);
3237 break;
3238 case CONST:
3239 {
3240 rtx c = XEXP (addr, 0);
3241
3242 gcc_assert (GET_CODE (XEXP (c, 0)) == SYMBOL_REF);
3243 gcc_assert (GET_CODE (XEXP (c, 1)) == CONST_INT);
3244
3245 output_address(XEXP(addr,0));
3246
3247 break;
3248 }
3249 case PRE_INC :
3250 case PRE_DEC :
3251 /* We shouldn't get here as we've lost the mode of the memory object
3252 (which says how much to inc/dec by. */
3253 gcc_unreachable ();
3254 break;
3255 default :
3256 if (flag_pic)
3257 arc_output_pic_addr_const (file, addr, 0);
3258 else
3259 output_addr_const (file, addr);
3260 break;
3261 }
3262}
3263
3264/* Called via walk_stores. DATA points to a hash table we can use to
3265 establish a unique SYMBOL_REF for each counter, which corresponds to
3266 a caller-callee pair.
3267 X is a store which we want to examine for an UNSPEC_PROF, which
3268 would be an address loaded into a register, or directly used in a MEM.
3269 If we found an UNSPEC_PROF, if we encounter a new counter the first time,
3270 write out a description and a data allocation for a 32 bit counter.
3271 Also, fill in the appropriate symbol_ref into each UNSPEC_PROF instance. */
3272
3273static void
3274write_profile_sections (rtx dest ATTRIBUTE_UNUSED, rtx x, void *data)
3275{
3276 rtx *srcp, src;
3277 htab_t htab = (htab_t) data;
3278 rtx *slot;
3279
3280 if (GET_CODE (x) != SET)
3281 return;
3282 srcp = &SET_SRC (x);
3283 if (MEM_P (*srcp))
3284 srcp = &XEXP (*srcp, 0);
3285 else if (MEM_P (SET_DEST (x)))
3286 srcp = &XEXP (SET_DEST (x), 0);
3287 src = *srcp;
3288 if (GET_CODE (src) != CONST)
3289 return;
3290 src = XEXP (src, 0);
3291 if (GET_CODE (src) != UNSPEC || XINT (src, 1) != UNSPEC_PROF)
3292 return;
3293
3294 gcc_assert (XVECLEN (src, 0) == 3);
3295 if (!htab_elements (htab))
3296 {
3297 output_asm_insn (".section .__arc_profile_desc, \"a\"\n"
3298 "\t.long %0 + 1\n",
3299 &XVECEXP (src, 0, 0));
3300 }
3301 slot = (rtx *) htab_find_slot (htab, src, INSERT);
3302 if (*slot == HTAB_EMPTY_ENTRY)
3303 {
3304 static int count_nr;
3305 char buf[24];
3306 rtx count;
3307
3308 *slot = src;
3309 sprintf (buf, "__prof_count%d", count_nr++);
3310 count = gen_rtx_SYMBOL_REF (Pmode, xstrdup (buf));
3311 XVECEXP (src, 0, 2) = count;
3312 output_asm_insn (".section\t.__arc_profile_desc, \"a\"\n"
3313 "\t.long\t%1\n"
3314 "\t.section\t.__arc_profile_counters, \"aw\"\n"
3315 "\t.type\t%o2, @object\n"
3316 "\t.size\t%o2, 4\n"
3317 "%o2:\t.zero 4",
3318 &XVECEXP (src, 0, 0));
3319 *srcp = count;
3320 }
3321 else
3322 *srcp = XVECEXP (*slot, 0, 2);
3323}
3324
3325/* Hash function for UNSPEC_PROF htab. Use both the caller's name and
3326 the callee's name (if known). */
3327
3328static hashval_t
3329unspec_prof_hash (const void *x)
3330{
3331 const_rtx u = (const_rtx) x;
3332 const_rtx s1 = XVECEXP (u, 0, 1);
3333
3334 return (htab_hash_string (XSTR (XVECEXP (u, 0, 0), 0))
3335 ^ (s1->code == SYMBOL_REF ? htab_hash_string (XSTR (s1, 0)) : 0));
3336}
3337
3338/* Equality function for UNSPEC_PROF htab. Two pieces of UNSPEC_PROF rtl
3339 shall refer to the same counter if both caller name and callee rtl
3340 are identical. */
3341
3342static int
3343unspec_prof_htab_eq (const void *x, const void *y)
3344{
3345 const_rtx u0 = (const_rtx) x;
3346 const_rtx u1 = (const_rtx) y;
3347 const_rtx s01 = XVECEXP (u0, 0, 1);
3348 const_rtx s11 = XVECEXP (u1, 0, 1);
3349
3350 return (!strcmp (XSTR (XVECEXP (u0, 0, 0), 0),
3351 XSTR (XVECEXP (u1, 0, 0), 0))
3352 && rtx_equal_p (s01, s11));
3353}
3354
3355/* Conditional execution support.
3356
3357 This is based on the ARM port but for now is much simpler.
3358
3359 A finite state machine takes care of noticing whether or not instructions
3360 can be conditionally executed, and thus decrease execution time and code
3361 size by deleting branch instructions. The fsm is controlled by
3362 arc_ccfsm_advance (called by arc_final_prescan_insn), and controls the
3363 actions of PRINT_OPERAND. The patterns in the .md file for the branch
3364 insns also have a hand in this. */
3365/* The way we leave dealing with non-anulled or annull-false delay slot
3366 insns to the consumer is awkward. */
3367
3368/* The state of the fsm controlling condition codes are:
3369 0: normal, do nothing special
3370 1: don't output this insn
3371 2: don't output this insn
3372 3: make insns conditional
3373 4: make insns conditional
3374 5: make insn conditional (only for outputting anulled delay slot insns)
3375
3376 special value for cfun->machine->uid_ccfsm_state:
3377 6: return with but one insn before it since function start / call
3378
3379 State transitions (state->state by whom, under what condition):
3380 0 -> 1 arc_ccfsm_advance, if insn is a conditional branch skipping over
3381 some instructions.
3382 0 -> 2 arc_ccfsm_advance, if insn is a conditional branch followed
3383 by zero or more non-jump insns and an unconditional branch with
3384 the same target label as the condbranch.
3385 1 -> 3 branch patterns, after having not output the conditional branch
3386 2 -> 4 branch patterns, after having not output the conditional branch
3387 0 -> 5 branch patterns, for anulled delay slot insn.
3388 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL, if the `target' label is reached
3389 (the target label has CODE_LABEL_NUMBER equal to
3390 arc_ccfsm_target_label).
3391 4 -> 0 arc_ccfsm_advance, if `target' unconditional branch is reached
3392 3 -> 1 arc_ccfsm_advance, finding an 'else' jump skipping over some insns.
3393 5 -> 0 when outputting the delay slot insn
3394
3395 If the jump clobbers the conditions then we use states 2 and 4.
3396
3397 A similar thing can be done with conditional return insns.
3398
3399 We also handle separating branches from sets of the condition code.
3400 This is done here because knowledge of the ccfsm state is required,
3401 we may not be outputting the branch. */
3402
3403/* arc_final_prescan_insn calls arc_ccfsm_advance to adjust arc_ccfsm_current,
3404 before letting final output INSN. */
3405
3406static void
b3458f61 3407arc_ccfsm_advance (rtx_insn *insn, struct arc_ccfsm *state)
526b7aee
SV
3408{
3409 /* BODY will hold the body of INSN. */
3410 register rtx body;
3411
3412 /* This will be 1 if trying to repeat the trick (ie: do the `else' part of
3413 an if/then/else), and things need to be reversed. */
3414 int reverse = 0;
3415
3416 /* If we start with a return insn, we only succeed if we find another one. */
3417 int seeking_return = 0;
3418
3419 /* START_INSN will hold the insn from where we start looking. This is the
3420 first insn after the following code_label if REVERSE is true. */
b3458f61 3421 rtx_insn *start_insn = insn;
526b7aee
SV
3422
3423 /* Type of the jump_insn. Brcc insns don't affect ccfsm changes,
3424 since they don't rely on a cmp preceding the. */
3425 enum attr_type jump_insn_type;
3426
3427 /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
3428 We can't do this in macro FINAL_PRESCAN_INSN because its called from
3429 final_scan_insn which has `optimize' as a local. */
3430 if (optimize < 2 || TARGET_NO_COND_EXEC)
3431 return;
3432
3433 /* Ignore notes and labels. */
3434 if (!INSN_P (insn))
3435 return;
3436 body = PATTERN (insn);
3437 /* If in state 4, check if the target branch is reached, in order to
3438 change back to state 0. */
3439 if (state->state == 4)
3440 {
3441 if (insn == state->target_insn)
3442 {
3443 state->target_insn = NULL;
3444 state->state = 0;
3445 }
3446 return;
3447 }
3448
3449 /* If in state 3, it is possible to repeat the trick, if this insn is an
3450 unconditional branch to a label, and immediately following this branch
3451 is the previous target label which is only used once, and the label this
3452 branch jumps to is not too far off. Or in other words "we've done the
3453 `then' part, see if we can do the `else' part." */
3454 if (state->state == 3)
3455 {
3456 if (simplejump_p (insn))
3457 {
3458 start_insn = next_nonnote_insn (start_insn);
3459 if (GET_CODE (start_insn) == BARRIER)
3460 {
3461 /* ??? Isn't this always a barrier? */
3462 start_insn = next_nonnote_insn (start_insn);
3463 }
3464 if (GET_CODE (start_insn) == CODE_LABEL
3465 && CODE_LABEL_NUMBER (start_insn) == state->target_label
3466 && LABEL_NUSES (start_insn) == 1)
3467 reverse = TRUE;
3468 else
3469 return;
3470 }
3471 else if (GET_CODE (body) == SIMPLE_RETURN)
3472 {
3473 start_insn = next_nonnote_insn (start_insn);
3474 if (GET_CODE (start_insn) == BARRIER)
3475 start_insn = next_nonnote_insn (start_insn);
3476 if (GET_CODE (start_insn) == CODE_LABEL
3477 && CODE_LABEL_NUMBER (start_insn) == state->target_label
3478 && LABEL_NUSES (start_insn) == 1)
3479 {
3480 reverse = TRUE;
3481 seeking_return = 1;
3482 }
3483 else
3484 return;
3485 }
3486 else
3487 return;
3488 }
3489
3490 if (GET_CODE (insn) != JUMP_INSN
3491 || GET_CODE (PATTERN (insn)) == ADDR_VEC
3492 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
3493 return;
3494
3495 /* We can't predicate BRCC or loop ends.
3496 Also, when generating PIC code, and considering a medium range call,
3497 we can't predicate the call. */
3498 jump_insn_type = get_attr_type (insn);
3499 if (jump_insn_type == TYPE_BRCC
3500 || jump_insn_type == TYPE_BRCC_NO_DELAY_SLOT
3501 || jump_insn_type == TYPE_LOOP_END
3502 || (jump_insn_type == TYPE_CALL && !get_attr_predicable (insn)))
3503 return;
3504
3505 /* This jump might be paralleled with a clobber of the condition codes,
3506 the jump should always come first. */
3507 if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0)
3508 body = XVECEXP (body, 0, 0);
3509
3510 if (reverse
3511 || (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == PC
3512 && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE))
3513 {
3514 int insns_skipped = 0, fail = FALSE, succeed = FALSE;
3515 /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
3516 int then_not_else = TRUE;
3517 /* Nonzero if next insn must be the target label. */
3518 int next_must_be_target_label_p;
b3458f61
DM
3519 rtx_insn *this_insn = start_insn;
3520 rtx label = 0;
526b7aee
SV
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;
b3458f61 3729 state->target_insn = NULL;
526b7aee
SV
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
b32d5189 3738arc_ccfsm_record_condition (rtx cond, bool reverse, rtx_insn *jump,
526b7aee
SV
3739 struct arc_ccfsm *state)
3740{
b3458f61 3741 rtx_insn *seq_insn = NEXT_INSN (PREV_INSN (jump));
526b7aee
SV
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
b3458f61 3773arc_ccfsm_post_advance (rtx_insn *insn, struct arc_ccfsm *state)
526b7aee 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
b3458f61
DM
3831static rtx_insn *
3832arc_next_active_insn (rtx_insn *insn, struct arc_ccfsm *statep)
526b7aee
SV
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))
b3458f61 3842 return NULL;
526b7aee
SV
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)
b3458f61 3857 return NULL;
526b7aee 3858 if (GET_CODE (pat) == SEQUENCE)
b3458f61 3859 return as_a <rtx_insn *> (XVECEXP (pat, 0, 0));
526b7aee
SV
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
b3458f61 3889arc_verify_short (rtx_insn *insn, int, int check_attr)
526b7aee
SV
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{
b3458f61 3915 rtx_insn *insn = current_output_insn;
526b7aee
SV
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
b3458f61 3929arc_final_prescan_insn (rtx_insn *insn, rtx *opvec ATTRIBUTE_UNUSED,
526b7aee
SV
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);
b3458f61 3947 current_output_insn = insn;
526b7aee
SV
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]);
dfca07ea 5523 asm_fprintf (file, "\tadd\t%s, %s, " HOST_WIDE_INT_PRINT_DEC "\n",
526b7aee
SV
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 *
ac44248e 5723arc_invalid_within_doloop (const rtx_insn *insn)
526b7aee
SV
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{
b3458f61
DM
5737 rtx_insn *insn;
5738 rtx pattern;
526b7aee
SV
5739 rtx pc_target;
5740 long offset;
5741 int changed;
5742
5743 cfun->machine->arc_reorg_started = 1;
5744 arc_reorg_in_progress = 1;
5745
5746 /* Emit special sections for profiling. */
5747 if (crtl->profile)
5748 {
5749 section *save_text_section;
b3458f61 5750 rtx_insn *insn;
526b7aee
SV
5751 int size = get_max_uid () >> 4;
5752 htab_t htab = htab_create (size, unspec_prof_hash, unspec_prof_htab_eq,
5753 NULL);
5754
5755 save_text_section = in_section;
5756 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5757 if (NONJUMP_INSN_P (insn))
5758 walk_stores (PATTERN (insn), write_profile_sections, htab);
5759 if (htab_elements (htab))
5760 in_section = 0;
5761 switch_to_section (save_text_section);
5762 htab_delete (htab);
5763 }
5764
5765 /* Link up loop ends with their loop start. */
5766 {
5767 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5768 if (GET_CODE (insn) == JUMP_INSN
5769 && recog_memoized (insn) == CODE_FOR_doloop_end_i)
5770 {
b3458f61
DM
5771 rtx_insn *top_label
5772 = as_a <rtx_insn *> (XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0));
526b7aee 5773 rtx num = GEN_INT (CODE_LABEL_NUMBER (top_label));
b3458f61
DM
5774 rtx_insn *lp, *prev = prev_nonnote_insn (top_label);
5775 rtx_insn *lp_simple = NULL;
5776 rtx_insn *next = NULL;
526b7aee
SV
5777 rtx op0 = XEXP (XVECEXP (PATTERN (insn), 0, 1), 0);
5778 HOST_WIDE_INT loop_end_id
5779 = -INTVAL (XEXP (XVECEXP (PATTERN (insn), 0, 4), 0));
5780 int seen_label = 0;
5781
5782 for (lp = prev;
5783 (lp && NONJUMP_INSN_P (lp)
5784 && recog_memoized (lp) != CODE_FOR_doloop_begin_i);
5785 lp = prev_nonnote_insn (lp))
5786 ;
5787 if (!lp || !NONJUMP_INSN_P (lp)
5788 || dead_or_set_regno_p (lp, LP_COUNT))
5789 {
b3458f61 5790 for (prev = next = insn, lp = NULL ; prev || next;)
526b7aee
SV
5791 {
5792 if (prev)
5793 {
5794 if (NONJUMP_INSN_P (prev)
5795 && recog_memoized (prev) == CODE_FOR_doloop_begin_i
5796 && (INTVAL (XEXP (XVECEXP (PATTERN (prev), 0, 5), 0))
5797 == loop_end_id))
5798 {
5799 lp = prev;
5800 break;
5801 }
5802 else if (LABEL_P (prev))
5803 seen_label = 1;
5804 prev = prev_nonnote_insn (prev);
5805 }
5806 if (next)
5807 {
5808 if (NONJUMP_INSN_P (next)
5809 && recog_memoized (next) == CODE_FOR_doloop_begin_i
5810 && (INTVAL (XEXP (XVECEXP (PATTERN (next), 0, 5), 0))
5811 == loop_end_id))
5812 {
5813 lp = next;
5814 break;
5815 }
5816 next = next_nonnote_insn (next);
5817 }
5818 }
b3458f61 5819 prev = NULL;
526b7aee
SV
5820 }
5821 else
5822 lp_simple = lp;
5823 if (lp && !dead_or_set_regno_p (lp, LP_COUNT))
5824 {
5825 rtx begin_cnt = XEXP (XVECEXP (PATTERN (lp), 0 ,3), 0);
5826 if (INTVAL (XEXP (XVECEXP (PATTERN (lp), 0, 4), 0)))
5827 /* The loop end insn has been duplicated. That can happen
5828 when there is a conditional block at the very end of
5829 the loop. */
5830 goto failure;
5831 /* If Register allocation failed to allocate to the right
5832 register, There is no point into teaching reload to
5833 fix this up with reloads, as that would cost more
5834 than using an ordinary core register with the
5835 doloop_fallback pattern. */
5836 if ((true_regnum (op0) != LP_COUNT || !REG_P (begin_cnt))
5837 /* Likewise, if the loop setup is evidently inside the loop,
5838 we loose. */
5839 || (!lp_simple && lp != next && !seen_label))
5840 {
5841 remove_insn (lp);
5842 goto failure;
5843 }
5844 /* It is common that the optimizers copy the loop count from
5845 another register, and doloop_begin_i is stuck with the
5846 source of the move. Making doloop_begin_i only accept "l"
5847 is nonsentical, as this then makes reload evict the pseudo
5848 used for the loop end. The underlying cause is that the
5849 optimizers don't understand that the register allocation for
5850 doloop_begin_i should be treated as part of the loop.
5851 Try to work around this problem by verifying the previous
5852 move exists. */
5853 if (true_regnum (begin_cnt) != LP_COUNT)
5854 {
b3458f61
DM
5855 rtx_insn *mov;
5856 rtx set, note;
526b7aee
SV
5857
5858 for (mov = prev_nonnote_insn (lp); mov;
5859 mov = prev_nonnote_insn (mov))
5860 {
5861 if (!NONJUMP_INSN_P (mov))
5862 mov = 0;
5863 else if ((set = single_set (mov))
5864 && rtx_equal_p (SET_SRC (set), begin_cnt)
5865 && rtx_equal_p (SET_DEST (set), op0))
5866 break;
5867 }
5868 if (mov)
5869 {
5870 XEXP (XVECEXP (PATTERN (lp), 0 ,3), 0) = op0;
5871 note = find_regno_note (lp, REG_DEAD, REGNO (begin_cnt));
5872 if (note)
5873 remove_note (lp, note);
5874 }
5875 else
5876 {
5877 remove_insn (lp);
5878 goto failure;
5879 }
5880 }
5881 XEXP (XVECEXP (PATTERN (insn), 0, 4), 0) = num;
5882 XEXP (XVECEXP (PATTERN (lp), 0, 4), 0) = num;
5883 if (next == lp)
5884 XEXP (XVECEXP (PATTERN (lp), 0, 6), 0) = const2_rtx;
5885 else if (!lp_simple)
5886 XEXP (XVECEXP (PATTERN (lp), 0, 6), 0) = const1_rtx;
5887 else if (prev != lp)
5888 {
5889 remove_insn (lp);
5890 add_insn_after (lp, prev, NULL);
5891 }
5892 if (!lp_simple)
5893 {
5894 XEXP (XVECEXP (PATTERN (lp), 0, 7), 0)
5895 = gen_rtx_LABEL_REF (Pmode, top_label);
5896 add_reg_note (lp, REG_LABEL_OPERAND, top_label);
5897 LABEL_NUSES (top_label)++;
5898 }
5899 /* We can avoid tedious loop start / end setting for empty loops
5900 be merely setting the loop count to its final value. */
5901 if (next_active_insn (top_label) == insn)
5902 {
5903 rtx lc_set
5904 = gen_rtx_SET (VOIDmode,
5905 XEXP (XVECEXP (PATTERN (lp), 0, 3), 0),
5906 const0_rtx);
5907
b3458f61 5908 rtx_insn *lc_set_insn = emit_insn_before (lc_set, insn);
526b7aee
SV
5909 delete_insn (lp);
5910 delete_insn (insn);
b3458f61 5911 insn = lc_set_insn;
526b7aee
SV
5912 }
5913 /* If the loop is non-empty with zero length, we can't make it
5914 a zero-overhead loop. That can happen for empty asms. */
5915 else
5916 {
b3458f61 5917 rtx_insn *scan;
526b7aee
SV
5918
5919 for (scan = top_label;
5920 (scan && scan != insn
5921 && (!NONJUMP_INSN_P (scan) || !get_attr_length (scan)));
5922 scan = NEXT_INSN (scan));
5923 if (scan == insn)
5924 {
5925 remove_insn (lp);
5926 goto failure;
5927 }
5928 }
5929 }
5930 else
5931 {
5932 /* Sometimes the loop optimizer makes a complete hash of the
5933 loop. If it were only that the loop is not entered at the
5934 top, we could fix this up by setting LP_START with SR .
5935 However, if we can't find the loop begin were it should be,
5936 chances are that it does not even dominate the loop, but is
5937 inside the loop instead. Using SR there would kill
5938 performance.
5939 We use the doloop_fallback pattern here, which executes
5940 in two cycles on the ARC700 when predicted correctly. */
5941 failure:
5942 if (!REG_P (op0))
5943 {
5944 rtx op3 = XEXP (XVECEXP (PATTERN (insn), 0, 5), 0);
5945
5946 emit_insn_before (gen_move_insn (op3, op0), insn);
5947 PATTERN (insn)
5948 = gen_doloop_fallback_m (op3, JUMP_LABEL (insn), op0);
5949 }
5950 else
5951 XVEC (PATTERN (insn), 0)
5952 = gen_rtvec (2, XVECEXP (PATTERN (insn), 0, 0),
5953 XVECEXP (PATTERN (insn), 0, 1));
5954 INSN_CODE (insn) = -1;
5955 }
5956 }
5957 }
5958
5959/* FIXME: should anticipate ccfsm action, generate special patterns for
5960 to-be-deleted branches that have no delay slot and have at least the
5961 length of the size increase forced on other insns that are conditionalized.
5962 This can also have an insn_list inside that enumerates insns which are
5963 not actually conditionalized because the destinations are dead in the
5964 not-execute case.
5965 Could also tag branches that we want to be unaligned if they get no delay
5966 slot, or even ones that we don't want to do delay slot sheduling for
5967 because we can unalign them.
5968
5969 However, there are cases when conditional execution is only possible after
5970 delay slot scheduling:
5971
5972 - If a delay slot is filled with a nocond/set insn from above, the previous
5973 basic block can become elegible for conditional execution.
5974 - If a delay slot is filled with a nocond insn from the fall-through path,
5975 the branch with that delay slot can become eligble for conditional
5976 execution (however, with the same sort of data flow analysis that dbr
5977 does, we could have figured out before that we don't need to
5978 conditionalize this insn.)
5979 - If a delay slot insn is filled with an insn from the target, the
5980 target label gets its uses decremented (even deleted if falling to zero),
5981 thus possibly creating more condexec opportunities there.
5982 Therefore, we should still be prepared to apply condexec optimization on
5983 non-prepared branches if the size increase of conditionalized insns is no
5984 more than the size saved from eliminating the branch. An invocation option
5985 could also be used to reserve a bit of extra size for condbranches so that
5986 this'll work more often (could also test in arc_reorg if the block is
5987 'close enough' to be eligible for condexec to make this likely, and
5988 estimate required size increase). */
5989 /* Generate BRcc insns, by combining cmp and Bcc insns wherever possible. */
5990 if (TARGET_NO_BRCC_SET)
5991 return;
5992
5993 do
5994 {
5995 init_insn_lengths();
5996 changed = 0;
5997
5998 if (optimize > 1 && !TARGET_NO_COND_EXEC)
5999 {
6000 arc_ifcvt ();
6001 unsigned int flags = pass_data_arc_ifcvt.todo_flags_finish;
6002 df_finish_pass ((flags & TODO_df_verify) != 0);
6003 }
6004
6005 /* Call shorten_branches to calculate the insn lengths. */
6006 shorten_branches (get_insns());
6007 cfun->machine->ccfsm_current_insn = NULL_RTX;
6008
6009 if (!INSN_ADDRESSES_SET_P())
6010 fatal_error ("Insn addresses not set after shorten_branches");
6011
6012 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
6013 {
6014 rtx label;
6015 enum attr_type insn_type;
6016
6017 /* If a non-jump insn (or a casesi jump table), continue. */
6018 if (GET_CODE (insn) != JUMP_INSN ||
6019 GET_CODE (PATTERN (insn)) == ADDR_VEC
6020 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
6021 continue;
6022
6023 /* If we already have a brcc, note if it is suitable for brcc_s.
6024 Be a bit generous with the brcc_s range so that we can take
6025 advantage of any code shortening from delay slot scheduling. */
6026 if (recog_memoized (insn) == CODE_FOR_cbranchsi4_scratch)
6027 {
6028 rtx pat = PATTERN (insn);
6029 rtx op = XEXP (SET_SRC (XVECEXP (pat, 0, 0)), 0);
6030 rtx *ccp = &XEXP (XVECEXP (pat, 0, 1), 0);
6031
6032 offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
6033 if ((offset >= -140 && offset < 140)
6034 && rtx_equal_p (XEXP (op, 1), const0_rtx)
6035 && compact_register_operand (XEXP (op, 0), VOIDmode)
6036 && equality_comparison_operator (op, VOIDmode))
6037 PUT_MODE (*ccp, CC_Zmode);
6038 else if (GET_MODE (*ccp) == CC_Zmode)
6039 PUT_MODE (*ccp, CC_ZNmode);
6040 continue;
6041 }
6042 if ((insn_type = get_attr_type (insn)) == TYPE_BRCC
6043 || insn_type == TYPE_BRCC_NO_DELAY_SLOT)
6044 continue;
6045
6046 /* OK. so we have a jump insn. */
6047 /* We need to check that it is a bcc. */
6048 /* Bcc => set (pc) (if_then_else ) */
6049 pattern = PATTERN (insn);
6050 if (GET_CODE (pattern) != SET
6051 || GET_CODE (SET_SRC (pattern)) != IF_THEN_ELSE
6052 || ANY_RETURN_P (XEXP (SET_SRC (pattern), 1)))
6053 continue;
6054
6055 /* Now check if the jump is beyond the s9 range. */
339ba33b 6056 if (CROSSING_JUMP_P (insn))
526b7aee
SV
6057 continue;
6058 offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
6059
6060 if(offset > 253 || offset < -254)
6061 continue;
6062
6063 pc_target = SET_SRC (pattern);
6064
6065 /* Now go back and search for the set cc insn. */
6066
6067 label = XEXP (pc_target, 1);
6068
6069 {
b3458f61
DM
6070 rtx pat;
6071 rtx_insn *scan, *link_insn = NULL;
526b7aee
SV
6072
6073 for (scan = PREV_INSN (insn);
6074 scan && GET_CODE (scan) != CODE_LABEL;
6075 scan = PREV_INSN (scan))
6076 {
6077 if (! INSN_P (scan))
6078 continue;
6079 pat = PATTERN (scan);
6080 if (GET_CODE (pat) == SET
6081 && cc_register (SET_DEST (pat), VOIDmode))
6082 {
6083 link_insn = scan;
6084 break;
6085 }
6086 }
6087 if (! link_insn)
6088 continue;
6089 else
6090 /* Check if this is a data dependency. */
6091 {
6092 rtx op, cc_clob_rtx, op0, op1, brcc_insn, note;
6093 rtx cmp0, cmp1;
6094
6095 /* Ok this is the set cc. copy args here. */
6096 op = XEXP (pc_target, 0);
6097
6098 op0 = cmp0 = XEXP (SET_SRC (pat), 0);
6099 op1 = cmp1 = XEXP (SET_SRC (pat), 1);
6100 if (GET_CODE (op0) == ZERO_EXTRACT
6101 && XEXP (op0, 1) == const1_rtx
6102 && (GET_CODE (op) == EQ
6103 || GET_CODE (op) == NE))
6104 {
6105 /* btst / b{eq,ne} -> bbit{0,1} */
6106 op0 = XEXP (cmp0, 0);
6107 op1 = XEXP (cmp0, 2);
6108 }
6109 else if (!register_operand (op0, VOIDmode)
6110 || !general_operand (op1, VOIDmode))
6111 continue;
6112 /* Be careful not to break what cmpsfpx_raw is
6113 trying to create for checking equality of
6114 single-precision floats. */
6115 else if (TARGET_SPFP
6116 && GET_MODE (op0) == SFmode
6117 && GET_MODE (op1) == SFmode)
6118 continue;
6119
6120 /* None of the two cmp operands should be set between the
6121 cmp and the branch. */
6122 if (reg_set_between_p (op0, link_insn, insn))
6123 continue;
6124
6125 if (reg_set_between_p (op1, link_insn, insn))
6126 continue;
6127
6128 /* Since the MODE check does not work, check that this is
6129 CC reg's last set location before insn, and also no
6130 instruction between the cmp and branch uses the
6131 condition codes. */
6132 if ((reg_set_between_p (SET_DEST (pat), link_insn, insn))
6133 || (reg_used_between_p (SET_DEST (pat), link_insn, insn)))
6134 continue;
6135
6136 /* CC reg should be dead after insn. */
6137 if (!find_regno_note (insn, REG_DEAD, CC_REG))
6138 continue;
6139
6140 op = gen_rtx_fmt_ee (GET_CODE (op),
6141 GET_MODE (op), cmp0, cmp1);
6142 /* If we create a LIMM where there was none before,
6143 we only benefit if we can avoid a scheduling bubble
6144 for the ARC600. Otherwise, we'd only forgo chances
6145 at short insn generation, and risk out-of-range
6146 branches. */
6147 if (!brcc_nolimm_operator (op, VOIDmode)
6148 && !long_immediate_operand (op1, VOIDmode)
6149 && (TARGET_ARC700
6150 || next_active_insn (link_insn) != insn))
6151 continue;
6152
6153 /* Emit bbit / brcc (or brcc_s if possible).
6154 CC_Zmode indicates that brcc_s is possible. */
6155
6156 if (op0 != cmp0)
6157 cc_clob_rtx = gen_rtx_REG (CC_ZNmode, CC_REG);
6158 else if ((offset >= -140 && offset < 140)
6159 && rtx_equal_p (op1, const0_rtx)
6160 && compact_register_operand (op0, VOIDmode)
6161 && (GET_CODE (op) == EQ
6162 || GET_CODE (op) == NE))
6163 cc_clob_rtx = gen_rtx_REG (CC_Zmode, CC_REG);
6164 else
6165 cc_clob_rtx = gen_rtx_REG (CCmode, CC_REG);
6166
6167 brcc_insn
6168 = gen_rtx_IF_THEN_ELSE (VOIDmode, op, label, pc_rtx);
6169 brcc_insn = gen_rtx_SET (VOIDmode, pc_rtx, brcc_insn);
6170 cc_clob_rtx = gen_rtx_CLOBBER (VOIDmode, cc_clob_rtx);
6171 brcc_insn
6172 = gen_rtx_PARALLEL
6173 (VOIDmode, gen_rtvec (2, brcc_insn, cc_clob_rtx));
6174 brcc_insn = emit_jump_insn_before (brcc_insn, insn);
6175
6176 JUMP_LABEL (brcc_insn) = JUMP_LABEL (insn);
6177 note = find_reg_note (insn, REG_BR_PROB, 0);
6178 if (note)
6179 {
6180 XEXP (note, 1) = REG_NOTES (brcc_insn);
6181 REG_NOTES (brcc_insn) = note;
6182 }
6183 note = find_reg_note (link_insn, REG_DEAD, op0);
6184 if (note)
6185 {
6186 remove_note (link_insn, note);
6187 XEXP (note, 1) = REG_NOTES (brcc_insn);
6188 REG_NOTES (brcc_insn) = note;
6189 }
6190 note = find_reg_note (link_insn, REG_DEAD, op1);
6191 if (note)
6192 {
6193 XEXP (note, 1) = REG_NOTES (brcc_insn);
6194 REG_NOTES (brcc_insn) = note;
6195 }
6196
6197 changed = 1;
6198
6199 /* Delete the bcc insn. */
6200 set_insn_deleted (insn);
6201
6202 /* Delete the cmp insn. */
6203 set_insn_deleted (link_insn);
6204
6205 }
6206 }
6207 }
6208 /* Clear out insn_addresses. */
6209 INSN_ADDRESSES_FREE ();
6210
6211 } while (changed);
6212
6213 if (INSN_ADDRESSES_SET_P())
6214 fatal_error ("insn addresses not freed");
6215
6216 arc_reorg_in_progress = 0;
6217}
6218
6219 /* Check if the operands are valid for BRcc.d generation
6220 Valid Brcc.d patterns are
6221 Brcc.d b, c, s9
6222 Brcc.d b, u6, s9
6223
6224 For cc={GT, LE, GTU, LEU}, u6=63 can not be allowed,
6225 since they are encoded by the assembler as {GE, LT, HS, LS} 64, which
6226 does not have a delay slot
6227
6228 Assumed precondition: Second operand is either a register or a u6 value. */
6229
6230bool
6231valid_brcc_with_delay_p (rtx *operands)
6232{
6233 if (optimize_size && GET_MODE (operands[4]) == CC_Zmode)
6234 return false;
6235 return brcc_nolimm_operator (operands[0], VOIDmode);
6236}
6237
6238/* ??? Hack. This should no really be here. See PR32143. */
6239static bool
6240arc_decl_anon_ns_mem_p (const_tree decl)
6241{
6242 while (1)
6243 {
6244 if (decl == NULL_TREE || decl == error_mark_node)
6245 return false;
6246 if (TREE_CODE (decl) == NAMESPACE_DECL
6247 && DECL_NAME (decl) == NULL_TREE)
6248 return true;
6249 /* Classes and namespaces inside anonymous namespaces have
6250 TREE_PUBLIC == 0, so we can shortcut the search. */
6251 else if (TYPE_P (decl))
6252 return (TREE_PUBLIC (TYPE_NAME (decl)) == 0);
6253 else if (TREE_CODE (decl) == NAMESPACE_DECL)
6254 return (TREE_PUBLIC (decl) == 0);
6255 else
6256 decl = DECL_CONTEXT (decl);
6257 }
6258}
6259
6260/* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
6261 access DECL using %gp_rel(...)($gp). */
6262
6263static bool
6264arc_in_small_data_p (const_tree decl)
6265{
6266 HOST_WIDE_INT size;
6267
6268 if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL)
6269 return false;
6270
6271
6272 /* We don't yet generate small-data references for -mabicalls. See related
6273 -G handling in override_options. */
6274 if (TARGET_NO_SDATA_SET)
6275 return false;
6276
6277 if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0)
6278 {
6279 const char *name;
6280
6281 /* Reject anything that isn't in a known small-data section. */
f961457f 6282 name = DECL_SECTION_NAME (decl);
526b7aee
SV
6283 if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0)
6284 return false;
6285
6286 /* If a symbol is defined externally, the assembler will use the
6287 usual -G rules when deciding how to implement macros. */
6288 if (!DECL_EXTERNAL (decl))
6289 return true;
6290 }
6291 /* Only global variables go into sdata section for now. */
6292 else if (1)
6293 {
6294 /* Don't put constants into the small data section: we want them
6295 to be in ROM rather than RAM. */
6296 if (TREE_CODE (decl) != VAR_DECL)
6297 return false;
6298
6299 if (TREE_READONLY (decl)
6300 && !TREE_SIDE_EFFECTS (decl)
6301 && (!DECL_INITIAL (decl) || TREE_CONSTANT (DECL_INITIAL (decl))))
6302 return false;
6303
6304 /* TREE_PUBLIC might change after the first call, because of the patch
6305 for PR19238. */
6306 if (default_binds_local_p_1 (decl, 1)
6307 || arc_decl_anon_ns_mem_p (decl))
6308 return false;
6309
6310 /* To ensure -mvolatile-cache works
6311 ld.di does not have a gp-relative variant. */
6312 if (TREE_THIS_VOLATILE (decl))
6313 return false;
6314 }
6315
6316 /* Disable sdata references to weak variables. */
6317 if (DECL_WEAK (decl))
6318 return false;
6319
6320 size = int_size_in_bytes (TREE_TYPE (decl));
6321
6322/* if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) */
6323/* return false; */
6324
6325 /* Allow only <=4B long data types into sdata. */
6326 return (size > 0 && size <= 4);
6327}
6328
6329/* Return true if X is a small data address that can be rewritten
6330 as a gp+symref. */
6331
6332static bool
6333arc_rewrite_small_data_p (rtx x)
6334{
6335 if (GET_CODE (x) == CONST)
6336 x = XEXP (x, 0);
6337
6338 if (GET_CODE (x) == PLUS)
6339 {
6340 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
6341 x = XEXP (x, 0);
6342 }
6343
6344 return (GET_CODE (x) == SYMBOL_REF
6345 && SYMBOL_REF_SMALL_P(x));
6346}
6347
6348/* A for_each_rtx callback, used by arc_rewrite_small_data. */
6349
6350static int
6351arc_rewrite_small_data_1 (rtx *loc, void *data)
6352{
6353 if (arc_rewrite_small_data_p (*loc))
6354 {
6355 rtx top;
6356
6357 gcc_assert (SDATA_BASE_REGNUM == PIC_OFFSET_TABLE_REGNUM);
6358 *loc = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, *loc);
6359 if (loc == data)
6360 return -1;
6361 top = *(rtx*) data;
6362 if (GET_CODE (top) == MEM && &XEXP (top, 0) == loc)
6363 ; /* OK. */
6364 else if (GET_CODE (top) == MEM
6365 && GET_CODE (XEXP (top, 0)) == PLUS
6366 && GET_CODE (XEXP (XEXP (top, 0), 0)) == MULT)
6367 *loc = force_reg (Pmode, *loc);
6368 else
6369 gcc_unreachable ();
6370 return -1;
6371 }
6372
6373 if (GET_CODE (*loc) == PLUS
6374 && rtx_equal_p (XEXP (*loc, 0), pic_offset_table_rtx))
6375 return -1;
6376
6377 return 0;
6378}
6379
6380/* If possible, rewrite OP so that it refers to small data using
6381 explicit relocations. */
6382
6383rtx
6384arc_rewrite_small_data (rtx op)
6385{
6386 op = copy_insn (op);
6387 for_each_rtx (&op, arc_rewrite_small_data_1, &op);
6388 return op;
6389}
6390
6391/* A for_each_rtx callback for small_data_pattern. */
6392
6393static int
6394small_data_pattern_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
6395{
6396 if (GET_CODE (*loc) == PLUS
6397 && rtx_equal_p (XEXP (*loc, 0), pic_offset_table_rtx))
6398 return -1;
6399
6400 return arc_rewrite_small_data_p (*loc);
6401}
6402
6403/* Return true if OP refers to small data symbols directly, not through
6404 a PLUS. */
6405
6406bool
6407small_data_pattern (rtx op, enum machine_mode)
6408{
6409 return (GET_CODE (op) != SEQUENCE
6410 && for_each_rtx (&op, small_data_pattern_1, 0));
6411}
6412
6413/* Return true if OP is an acceptable memory operand for ARCompact
6414 16-bit gp-relative load instructions.
6415 op shd look like : [r26, symref@sda]
6416 i.e. (mem (plus (reg 26) (symref with smalldata flag set))
6417 */
6418/* volatile cache option still to be handled. */
6419
6420bool
6421compact_sda_memory_operand (rtx op, enum machine_mode mode)
6422{
6423 rtx addr;
6424 int size;
6425
6426 /* Eliminate non-memory operations. */
6427 if (GET_CODE (op) != MEM)
6428 return false;
6429
6430 if (mode == VOIDmode)
6431 mode = GET_MODE (op);
6432
6433 size = GET_MODE_SIZE (mode);
6434
6435 /* dword operations really put out 2 instructions, so eliminate them. */
6436 if (size > UNITS_PER_WORD)
6437 return false;
6438
6439 /* Decode the address now. */
6440 addr = XEXP (op, 0);
6441
6442 return LEGITIMATE_SMALL_DATA_ADDRESS_P (addr);
6443}
6444
6445/* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */
6446
6447void
6448arc_asm_output_aligned_decl_local (FILE * stream, tree decl, const char * name,
6449 unsigned HOST_WIDE_INT size,
6450 unsigned HOST_WIDE_INT align,
6451 unsigned HOST_WIDE_INT globalize_p)
6452{
6453 int in_small_data = arc_in_small_data_p (decl);
6454
6455 if (in_small_data)
6456 switch_to_section (get_named_section (NULL, ".sbss", 0));
6457 /* named_section (0,".sbss",0); */
6458 else
6459 switch_to_section (bss_section);
6460
6461 if (globalize_p)
6462 (*targetm.asm_out.globalize_label) (stream, name);
6463
6464 ASM_OUTPUT_ALIGN (stream, floor_log2 ((align) / BITS_PER_UNIT));
6465 ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "object");
6466 ASM_OUTPUT_SIZE_DIRECTIVE (stream, name, size);
6467 ASM_OUTPUT_LABEL (stream, name);
6468
6469 if (size != 0)
6470 ASM_OUTPUT_SKIP (stream, size);
6471}
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506/* SIMD builtins support. */
6507enum simd_insn_args_type {
6508 Va_Vb_Vc,
6509 Va_Vb_rlimm,
6510 Va_Vb_Ic,
6511 Va_Vb_u6,
6512 Va_Vb_u8,
6513 Va_rlimm_u8,
6514
6515 Va_Vb,
6516
6517 void_rlimm,
6518 void_u6,
6519
6520 Da_u3_rlimm,
6521 Da_rlimm_rlimm,
6522
6523 Va_Ib_u8,
6524 void_Va_Ib_u8,
6525
6526 Va_Vb_Ic_u8,
6527 void_Va_u3_Ib_u8
6528};
6529
6530struct builtin_description
6531{
6532 enum simd_insn_args_type args_type;
6533 const enum insn_code icode;
6534 const char * const name;
6535 const enum arc_builtins code;
6536};
6537
6538static const struct builtin_description arc_simd_builtin_desc_list[] =
6539{
6540 /* VVV builtins go first. */
6541#define SIMD_BUILTIN(type, code, string, builtin) \
6542 { type,CODE_FOR_##code, "__builtin_arc_" string, \
6543 ARC_SIMD_BUILTIN_##builtin },
6544
6545 SIMD_BUILTIN (Va_Vb_Vc, vaddaw_insn, "vaddaw", VADDAW)
6546 SIMD_BUILTIN (Va_Vb_Vc, vaddw_insn, "vaddw", VADDW)
6547 SIMD_BUILTIN (Va_Vb_Vc, vavb_insn, "vavb", VAVB)
6548 SIMD_BUILTIN (Va_Vb_Vc, vavrb_insn, "vavrb", VAVRB)
6549 SIMD_BUILTIN (Va_Vb_Vc, vdifaw_insn, "vdifaw", VDIFAW)
6550 SIMD_BUILTIN (Va_Vb_Vc, vdifw_insn, "vdifw", VDIFW)
6551 SIMD_BUILTIN (Va_Vb_Vc, vmaxaw_insn, "vmaxaw", VMAXAW)
6552 SIMD_BUILTIN (Va_Vb_Vc, vmaxw_insn, "vmaxw", VMAXW)
6553 SIMD_BUILTIN (Va_Vb_Vc, vminaw_insn, "vminaw", VMINAW)
6554 SIMD_BUILTIN (Va_Vb_Vc, vminw_insn, "vminw", VMINW)
6555 SIMD_BUILTIN (Va_Vb_Vc, vmulaw_insn, "vmulaw", VMULAW)
6556 SIMD_BUILTIN (Va_Vb_Vc, vmulfaw_insn, "vmulfaw", VMULFAW)
6557 SIMD_BUILTIN (Va_Vb_Vc, vmulfw_insn, "vmulfw", VMULFW)
6558 SIMD_BUILTIN (Va_Vb_Vc, vmulw_insn, "vmulw", VMULW)
6559 SIMD_BUILTIN (Va_Vb_Vc, vsubaw_insn, "vsubaw", VSUBAW)
6560 SIMD_BUILTIN (Va_Vb_Vc, vsubw_insn, "vsubw", VSUBW)
6561 SIMD_BUILTIN (Va_Vb_Vc, vsummw_insn, "vsummw", VSUMMW)
6562 SIMD_BUILTIN (Va_Vb_Vc, vand_insn, "vand", VAND)
6563 SIMD_BUILTIN (Va_Vb_Vc, vandaw_insn, "vandaw", VANDAW)
6564 SIMD_BUILTIN (Va_Vb_Vc, vbic_insn, "vbic", VBIC)
6565 SIMD_BUILTIN (Va_Vb_Vc, vbicaw_insn, "vbicaw", VBICAW)
6566 SIMD_BUILTIN (Va_Vb_Vc, vor_insn, "vor", VOR)
6567 SIMD_BUILTIN (Va_Vb_Vc, vxor_insn, "vxor", VXOR)
6568 SIMD_BUILTIN (Va_Vb_Vc, vxoraw_insn, "vxoraw", VXORAW)
6569 SIMD_BUILTIN (Va_Vb_Vc, veqw_insn, "veqw", VEQW)
6570 SIMD_BUILTIN (Va_Vb_Vc, vlew_insn, "vlew", VLEW)
6571 SIMD_BUILTIN (Va_Vb_Vc, vltw_insn, "vltw", VLTW)
6572 SIMD_BUILTIN (Va_Vb_Vc, vnew_insn, "vnew", VNEW)
6573 SIMD_BUILTIN (Va_Vb_Vc, vmr1aw_insn, "vmr1aw", VMR1AW)
6574 SIMD_BUILTIN (Va_Vb_Vc, vmr1w_insn, "vmr1w", VMR1W)
6575 SIMD_BUILTIN (Va_Vb_Vc, vmr2aw_insn, "vmr2aw", VMR2AW)
6576 SIMD_BUILTIN (Va_Vb_Vc, vmr2w_insn, "vmr2w", VMR2W)
6577 SIMD_BUILTIN (Va_Vb_Vc, vmr3aw_insn, "vmr3aw", VMR3AW)
6578 SIMD_BUILTIN (Va_Vb_Vc, vmr3w_insn, "vmr3w", VMR3W)
6579 SIMD_BUILTIN (Va_Vb_Vc, vmr4aw_insn, "vmr4aw", VMR4AW)
6580 SIMD_BUILTIN (Va_Vb_Vc, vmr4w_insn, "vmr4w", VMR4W)
6581 SIMD_BUILTIN (Va_Vb_Vc, vmr5aw_insn, "vmr5aw", VMR5AW)
6582 SIMD_BUILTIN (Va_Vb_Vc, vmr5w_insn, "vmr5w", VMR5W)
6583 SIMD_BUILTIN (Va_Vb_Vc, vmr6aw_insn, "vmr6aw", VMR6AW)
6584 SIMD_BUILTIN (Va_Vb_Vc, vmr6w_insn, "vmr6w", VMR6W)
6585 SIMD_BUILTIN (Va_Vb_Vc, vmr7aw_insn, "vmr7aw", VMR7AW)
6586 SIMD_BUILTIN (Va_Vb_Vc, vmr7w_insn, "vmr7w", VMR7W)
6587 SIMD_BUILTIN (Va_Vb_Vc, vmrb_insn, "vmrb", VMRB)
6588 SIMD_BUILTIN (Va_Vb_Vc, vh264f_insn, "vh264f", VH264F)
6589 SIMD_BUILTIN (Va_Vb_Vc, vh264ft_insn, "vh264ft", VH264FT)
6590 SIMD_BUILTIN (Va_Vb_Vc, vh264fw_insn, "vh264fw", VH264FW)
6591 SIMD_BUILTIN (Va_Vb_Vc, vvc1f_insn, "vvc1f", VVC1F)
6592 SIMD_BUILTIN (Va_Vb_Vc, vvc1ft_insn, "vvc1ft", VVC1FT)
6593
6594 SIMD_BUILTIN (Va_Vb_rlimm, vbaddw_insn, "vbaddw", VBADDW)
6595 SIMD_BUILTIN (Va_Vb_rlimm, vbmaxw_insn, "vbmaxw", VBMAXW)
6596 SIMD_BUILTIN (Va_Vb_rlimm, vbminw_insn, "vbminw", VBMINW)
6597 SIMD_BUILTIN (Va_Vb_rlimm, vbmulaw_insn, "vbmulaw", VBMULAW)
6598 SIMD_BUILTIN (Va_Vb_rlimm, vbmulfw_insn, "vbmulfw", VBMULFW)
6599 SIMD_BUILTIN (Va_Vb_rlimm, vbmulw_insn, "vbmulw", VBMULW)
6600 SIMD_BUILTIN (Va_Vb_rlimm, vbrsubw_insn, "vbrsubw", VBRSUBW)
6601 SIMD_BUILTIN (Va_Vb_rlimm, vbsubw_insn, "vbsubw", VBSUBW)
6602
6603 /* Va, Vb, Ic instructions. */
6604 SIMD_BUILTIN (Va_Vb_Ic, vasrw_insn, "vasrw", VASRW)
6605 SIMD_BUILTIN (Va_Vb_Ic, vsr8_insn, "vsr8", VSR8)
6606 SIMD_BUILTIN (Va_Vb_Ic, vsr8aw_insn, "vsr8aw", VSR8AW)
6607
6608 /* Va, Vb, u6 instructions. */
6609 SIMD_BUILTIN (Va_Vb_u6, vasrrwi_insn, "vasrrwi", VASRRWi)
6610 SIMD_BUILTIN (Va_Vb_u6, vasrsrwi_insn, "vasrsrwi", VASRSRWi)
6611 SIMD_BUILTIN (Va_Vb_u6, vasrwi_insn, "vasrwi", VASRWi)
6612 SIMD_BUILTIN (Va_Vb_u6, vasrpwbi_insn, "vasrpwbi", VASRPWBi)
6613 SIMD_BUILTIN (Va_Vb_u6, vasrrpwbi_insn,"vasrrpwbi", VASRRPWBi)
6614 SIMD_BUILTIN (Va_Vb_u6, vsr8awi_insn, "vsr8awi", VSR8AWi)
6615 SIMD_BUILTIN (Va_Vb_u6, vsr8i_insn, "vsr8i", VSR8i)
6616
6617 /* Va, Vb, u8 (simm) instructions. */
6618 SIMD_BUILTIN (Va_Vb_u8, vmvaw_insn, "vmvaw", VMVAW)
6619 SIMD_BUILTIN (Va_Vb_u8, vmvw_insn, "vmvw", VMVW)
6620 SIMD_BUILTIN (Va_Vb_u8, vmvzw_insn, "vmvzw", VMVZW)
6621 SIMD_BUILTIN (Va_Vb_u8, vd6tapf_insn, "vd6tapf", VD6TAPF)
6622
6623 /* Va, rlimm, u8 (simm) instructions. */
6624 SIMD_BUILTIN (Va_rlimm_u8, vmovaw_insn, "vmovaw", VMOVAW)
6625 SIMD_BUILTIN (Va_rlimm_u8, vmovw_insn, "vmovw", VMOVW)
6626 SIMD_BUILTIN (Va_rlimm_u8, vmovzw_insn, "vmovzw", VMOVZW)
6627
6628 /* Va, Vb instructions. */
6629 SIMD_BUILTIN (Va_Vb, vabsaw_insn, "vabsaw", VABSAW)
6630 SIMD_BUILTIN (Va_Vb, vabsw_insn, "vabsw", VABSW)
6631 SIMD_BUILTIN (Va_Vb, vaddsuw_insn, "vaddsuw", VADDSUW)
6632 SIMD_BUILTIN (Va_Vb, vsignw_insn, "vsignw", VSIGNW)
6633 SIMD_BUILTIN (Va_Vb, vexch1_insn, "vexch1", VEXCH1)
6634 SIMD_BUILTIN (Va_Vb, vexch2_insn, "vexch2", VEXCH2)
6635 SIMD_BUILTIN (Va_Vb, vexch4_insn, "vexch4", VEXCH4)
6636 SIMD_BUILTIN (Va_Vb, vupbaw_insn, "vupbaw", VUPBAW)
6637 SIMD_BUILTIN (Va_Vb, vupbw_insn, "vupbw", VUPBW)
6638 SIMD_BUILTIN (Va_Vb, vupsbaw_insn, "vupsbaw", VUPSBAW)
6639 SIMD_BUILTIN (Va_Vb, vupsbw_insn, "vupsbw", VUPSBW)
6640
6641 /* DIb, rlimm, rlimm instructions. */
6642 SIMD_BUILTIN (Da_rlimm_rlimm, vdirun_insn, "vdirun", VDIRUN)
6643 SIMD_BUILTIN (Da_rlimm_rlimm, vdorun_insn, "vdorun", VDORUN)
6644
6645 /* DIb, limm, rlimm instructions. */
6646 SIMD_BUILTIN (Da_u3_rlimm, vdiwr_insn, "vdiwr", VDIWR)
6647 SIMD_BUILTIN (Da_u3_rlimm, vdowr_insn, "vdowr", VDOWR)
6648
6649 /* rlimm instructions. */
6650 SIMD_BUILTIN (void_rlimm, vrec_insn, "vrec", VREC)
6651 SIMD_BUILTIN (void_rlimm, vrun_insn, "vrun", VRUN)
6652 SIMD_BUILTIN (void_rlimm, vrecrun_insn, "vrecrun", VRECRUN)
6653 SIMD_BUILTIN (void_rlimm, vendrec_insn, "vendrec", VENDREC)
6654
6655 /* Va, [Ib,u8] instructions. */
6656 SIMD_BUILTIN (Va_Vb_Ic_u8, vld32wh_insn, "vld32wh", VLD32WH)
6657 SIMD_BUILTIN (Va_Vb_Ic_u8, vld32wl_insn, "vld32wl", VLD32WL)
6658 SIMD_BUILTIN (Va_Vb_Ic_u8, vld64_insn, "vld64", VLD64)
6659 SIMD_BUILTIN (Va_Vb_Ic_u8, vld32_insn, "vld32", VLD32)
6660
6661 SIMD_BUILTIN (Va_Ib_u8, vld64w_insn, "vld64w", VLD64W)
6662 SIMD_BUILTIN (Va_Ib_u8, vld128_insn, "vld128", VLD128)
6663 SIMD_BUILTIN (void_Va_Ib_u8, vst128_insn, "vst128", VST128)
6664 SIMD_BUILTIN (void_Va_Ib_u8, vst64_insn, "vst64", VST64)
6665
6666 /* Va, [Ib, u8] instructions. */
6667 SIMD_BUILTIN (void_Va_u3_Ib_u8, vst16_n_insn, "vst16_n", VST16_N)
6668 SIMD_BUILTIN (void_Va_u3_Ib_u8, vst32_n_insn, "vst32_n", VST32_N)
6669
6670 SIMD_BUILTIN (void_u6, vinti_insn, "vinti", VINTI)
6671};
6672
6673static void
6674arc_init_simd_builtins (void)
6675{
6676 int i;
6677 tree endlink = void_list_node;
6678 tree V8HI_type_node = build_vector_type_for_mode (intHI_type_node, V8HImode);
6679
6680 tree v8hi_ftype_v8hi_v8hi
6681 = build_function_type (V8HI_type_node,
6682 tree_cons (NULL_TREE, V8HI_type_node,
6683 tree_cons (NULL_TREE, V8HI_type_node,
6684 endlink)));
6685 tree v8hi_ftype_v8hi_int
6686 = build_function_type (V8HI_type_node,
6687 tree_cons (NULL_TREE, V8HI_type_node,
6688 tree_cons (NULL_TREE, integer_type_node,
6689 endlink)));
6690
6691 tree v8hi_ftype_v8hi_int_int
6692 = build_function_type (V8HI_type_node,
6693 tree_cons (NULL_TREE, V8HI_type_node,
6694 tree_cons (NULL_TREE, integer_type_node,
6695 tree_cons (NULL_TREE,
6696 integer_type_node,
6697 endlink))));
6698
6699 tree void_ftype_v8hi_int_int
6700 = build_function_type (void_type_node,
6701 tree_cons (NULL_TREE, V8HI_type_node,
6702 tree_cons (NULL_TREE, integer_type_node,
6703 tree_cons (NULL_TREE,
6704 integer_type_node,
6705 endlink))));
6706
6707 tree void_ftype_v8hi_int_int_int
6708 = (build_function_type
6709 (void_type_node,
6710 tree_cons (NULL_TREE, V8HI_type_node,
6711 tree_cons (NULL_TREE, integer_type_node,
6712 tree_cons (NULL_TREE, integer_type_node,
6713 tree_cons (NULL_TREE,
6714 integer_type_node,
6715 endlink))))));
6716
6717 tree v8hi_ftype_int_int
6718 = build_function_type (V8HI_type_node,
6719 tree_cons (NULL_TREE, integer_type_node,
6720 tree_cons (NULL_TREE, integer_type_node,
6721 endlink)));
6722
6723 tree void_ftype_int_int
6724 = build_function_type (void_type_node,
6725 tree_cons (NULL_TREE, integer_type_node,
6726 tree_cons (NULL_TREE, integer_type_node,
6727 endlink)));
6728
6729 tree void_ftype_int
6730 = build_function_type (void_type_node,
6731 tree_cons (NULL_TREE, integer_type_node, endlink));
6732
6733 tree v8hi_ftype_v8hi
6734 = build_function_type (V8HI_type_node, tree_cons (NULL_TREE, V8HI_type_node,
6735 endlink));
6736
6737 /* These asserts have been introduced to ensure that the order of builtins
6738 does not get messed up, else the initialization goes wrong. */
6739 gcc_assert (arc_simd_builtin_desc_list [0].args_type == Va_Vb_Vc);
6740 for (i=0; arc_simd_builtin_desc_list [i].args_type == Va_Vb_Vc; i++)
6741 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6742 v8hi_ftype_v8hi_v8hi, arc_simd_builtin_desc_list[i].code);
6743
6744 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_rlimm);
6745 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_rlimm; i++)
6746 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6747 v8hi_ftype_v8hi_int, arc_simd_builtin_desc_list[i].code);
6748
6749 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_Ic);
6750 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_Ic; i++)
6751 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6752 v8hi_ftype_v8hi_int, arc_simd_builtin_desc_list[i].code);
6753
6754 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_u6);
6755 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_u6; i++)
6756 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6757 v8hi_ftype_v8hi_int, arc_simd_builtin_desc_list[i].code);
6758
6759 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_u8);
6760 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_u8; i++)
6761 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6762 v8hi_ftype_v8hi_int, arc_simd_builtin_desc_list[i].code);
6763
6764 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_rlimm_u8);
6765 for (; arc_simd_builtin_desc_list [i].args_type == Va_rlimm_u8; i++)
6766 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6767 v8hi_ftype_int_int, arc_simd_builtin_desc_list[i].code);
6768
6769 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb);
6770 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb; i++)
6771 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6772 v8hi_ftype_v8hi, arc_simd_builtin_desc_list[i].code);
6773
6774 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Da_rlimm_rlimm);
6775 for (; arc_simd_builtin_desc_list [i].args_type == Da_rlimm_rlimm; i++)
6776 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list [i].name,
6777 void_ftype_int_int, arc_simd_builtin_desc_list[i].code);
6778
6779 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Da_u3_rlimm);
6780 for (; arc_simd_builtin_desc_list [i].args_type == Da_u3_rlimm; i++)
6781 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6782 void_ftype_int_int, arc_simd_builtin_desc_list[i].code);
6783
6784 gcc_assert (arc_simd_builtin_desc_list [i].args_type == void_rlimm);
6785 for (; arc_simd_builtin_desc_list [i].args_type == void_rlimm; i++)
6786 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6787 void_ftype_int, arc_simd_builtin_desc_list[i].code);
6788
6789 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_Ic_u8);
6790 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_Ic_u8; i++)
6791 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6792 v8hi_ftype_v8hi_int_int, arc_simd_builtin_desc_list[i].code);
6793
6794 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Ib_u8);
6795 for (; arc_simd_builtin_desc_list [i].args_type == Va_Ib_u8; i++)
6796 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6797 v8hi_ftype_int_int, arc_simd_builtin_desc_list[i].code);
6798
6799 gcc_assert (arc_simd_builtin_desc_list [i].args_type == void_Va_Ib_u8);
6800 for (; arc_simd_builtin_desc_list [i].args_type == void_Va_Ib_u8; i++)
6801 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list [i].name,
6802 void_ftype_v8hi_int_int, arc_simd_builtin_desc_list[i].code);
6803
6804 gcc_assert (arc_simd_builtin_desc_list [i].args_type == void_Va_u3_Ib_u8);
6805 for (; arc_simd_builtin_desc_list [i].args_type == void_Va_u3_Ib_u8; i++)
6806 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6807 void_ftype_v8hi_int_int_int,
6808 arc_simd_builtin_desc_list[i].code);
6809
6810 gcc_assert (arc_simd_builtin_desc_list [i].args_type == void_u6);
6811 for (; arc_simd_builtin_desc_list [i].args_type == void_u6; i++)
6812 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6813 void_ftype_int, arc_simd_builtin_desc_list[i].code);
6814
6815 gcc_assert(i == ARRAY_SIZE (arc_simd_builtin_desc_list));
6816}
6817
6818/* Helper function of arc_expand_builtin; has the same parameters,
6819 except that EXP is now known to be a call to a simd builtin. */
6820
6821static rtx
6822arc_expand_simd_builtin (tree exp,
6823 rtx target,
6824 rtx subtarget ATTRIBUTE_UNUSED,
6825 enum machine_mode mode ATTRIBUTE_UNUSED,
6826 int ignore ATTRIBUTE_UNUSED)
6827{
6828 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
6829 tree arg0;
6830 tree arg1;
6831 tree arg2;
6832 tree arg3;
6833 rtx op0;
6834 rtx op1;
6835 rtx op2;
6836 rtx op3;
6837 rtx op4;
6838 rtx pat;
6839 unsigned int i;
6840 int fcode = DECL_FUNCTION_CODE (fndecl);
6841 int icode;
6842 enum machine_mode mode0;
6843 enum machine_mode mode1;
6844 enum machine_mode mode2;
6845 enum machine_mode mode3;
6846 enum machine_mode mode4;
6847 const struct builtin_description * d;
6848
6849 for (i = 0, d = arc_simd_builtin_desc_list;
6850 i < ARRAY_SIZE (arc_simd_builtin_desc_list); i++, d++)
6851 if (d->code == (const enum arc_builtins) fcode)
6852 break;
6853
6854 /* We must get an entry here. */
6855 gcc_assert (i < ARRAY_SIZE (arc_simd_builtin_desc_list));
6856
6857 switch (d->args_type)
6858 {
6859 case Va_Vb_rlimm:
6860 icode = d->icode;
6861 arg0 = CALL_EXPR_ARG (exp, 0);
6862 arg1 = CALL_EXPR_ARG (exp, 1);
6863 op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
6864 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
6865
6866 target = gen_reg_rtx (V8HImode);
6867 mode0 = insn_data[icode].operand[1].mode;
6868 mode1 = insn_data[icode].operand[2].mode;
6869
6870 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6871 op0 = copy_to_mode_reg (mode0, op0);
6872
6873 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
6874 op1 = copy_to_mode_reg (mode1, op1);
6875
6876 pat = GEN_FCN (icode) (target, op0, op1);
6877 if (! pat)
6878 return 0;
6879
6880 emit_insn (pat);
6881 return target;
6882
6883 case Va_Vb_u6:
6884 case Va_Vb_u8:
6885 icode = d->icode;
6886 arg0 = CALL_EXPR_ARG (exp, 0);
6887 arg1 = CALL_EXPR_ARG (exp, 1);
6888 op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
6889 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
6890
6891 target = gen_reg_rtx (V8HImode);
6892 mode0 = insn_data[icode].operand[1].mode;
6893 mode1 = insn_data[icode].operand[2].mode;
6894
6895 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6896 op0 = copy_to_mode_reg (mode0, op0);
6897
6898 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)
6899 || (d->args_type == Va_Vb_u6 && !UNSIGNED_INT6 (INTVAL (op1)))
6900 || (d->args_type == Va_Vb_u8 && !UNSIGNED_INT8 (INTVAL (op1))))
6901 error ("operand 2 of %s instruction should be an unsigned %d-bit value",
6902 d->name,
6903 (d->args_type == Va_Vb_u6)? 6: 8);
6904
6905 pat = GEN_FCN (icode) (target, op0, op1);
6906 if (! pat)
6907 return 0;
6908
6909 emit_insn (pat);
6910 return target;
6911
6912 case Va_rlimm_u8:
6913 icode = d->icode;
6914 arg0 = CALL_EXPR_ARG (exp, 0);
6915 arg1 = CALL_EXPR_ARG (exp, 1);
6916 op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
6917 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
6918
6919 target = gen_reg_rtx (V8HImode);
6920 mode0 = insn_data[icode].operand[1].mode;
6921 mode1 = insn_data[icode].operand[2].mode;
6922
6923 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6924 op0 = copy_to_mode_reg (mode0, op0);
6925
6926 if ( (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
6927 || !(UNSIGNED_INT8 (INTVAL (op1))))
6928 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
6929 d->name);
6930
6931 pat = GEN_FCN (icode) (target, op0, op1);
6932 if (! pat)
6933 return 0;
6934
6935 emit_insn (pat);
6936 return target;
6937
6938 case Va_Vb_Ic:
6939 icode = d->icode;
6940 arg0 = CALL_EXPR_ARG (exp, 0);
6941 arg1 = CALL_EXPR_ARG (exp, 1);
6942 op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
6943 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
6944 op2 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG);
6945
6946 target = gen_reg_rtx (V8HImode);
6947 mode0 = insn_data[icode].operand[1].mode;
6948 mode1 = insn_data[icode].operand[2].mode;
6949
6950 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6951 op0 = copy_to_mode_reg (mode0, op0);
6952
6953 if ( (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
6954 || !(UNSIGNED_INT3 (INTVAL (op1))))
6955 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
6956 d->name);
6957
6958 pat = GEN_FCN (icode) (target, op0, op1, op2);
6959 if (! pat)
6960 return 0;
6961
6962 emit_insn (pat);
6963 return target;
6964
6965 case Va_Vb_Vc:
6966 icode = d->icode;
6967 arg0 = CALL_EXPR_ARG (exp, 0);
6968 arg1 = CALL_EXPR_ARG (exp, 1);
6969 op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
6970 op1 = expand_expr (arg1, NULL_RTX, V8HImode, EXPAND_NORMAL);
6971
6972 target = gen_reg_rtx (V8HImode);
6973 mode0 = insn_data[icode].operand[1].mode;
6974 mode1 = insn_data[icode].operand[2].mode;
6975
6976 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6977 op0 = copy_to_mode_reg (mode0, op0);
6978
6979 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
6980 op1 = copy_to_mode_reg (mode1, op1);
6981
6982 pat = GEN_FCN (icode) (target, op0, op1);
6983 if (! pat)
6984 return 0;
6985
6986 emit_insn (pat);
6987 return target;
6988
6989 case Va_Vb:
6990 icode = d->icode;
6991 arg0 = CALL_EXPR_ARG (exp, 0);
6992 op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
6993
6994 target = gen_reg_rtx (V8HImode);
6995 mode0 = insn_data[icode].operand[1].mode;
6996
6997 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6998 op0 = copy_to_mode_reg (mode0, op0);
6999
7000 pat = GEN_FCN (icode) (target, op0);
7001 if (! pat)
7002 return 0;
7003
7004 emit_insn (pat);
7005 return target;
7006
7007 case Da_rlimm_rlimm:
7008 icode = d->icode;
7009 arg0 = CALL_EXPR_ARG (exp, 0);
7010 arg1 = CALL_EXPR_ARG (exp, 1);
7011 op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
7012 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
7013
7014
7015 if (icode == CODE_FOR_vdirun_insn)
7016 target = gen_rtx_REG (SImode, 131);
7017 else if (icode == CODE_FOR_vdorun_insn)
7018 target = gen_rtx_REG (SImode, 139);
7019 else
7020 gcc_unreachable ();
7021
7022 mode0 = insn_data[icode].operand[1].mode;
7023 mode1 = insn_data[icode].operand[2].mode;
7024
7025 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
7026 op0 = copy_to_mode_reg (mode0, op0);
7027
7028 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
7029 op1 = copy_to_mode_reg (mode1, op1);
7030
7031
7032 pat = GEN_FCN (icode) (target, op0, op1);
7033 if (! pat)
7034 return 0;
7035
7036 emit_insn (pat);
7037 return NULL_RTX;
7038
7039 case Da_u3_rlimm:
7040 icode = d->icode;
7041 arg0 = CALL_EXPR_ARG (exp, 0);
7042 arg1 = CALL_EXPR_ARG (exp, 1);
7043 op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
7044 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
7045
7046
7047 if (! (GET_CODE (op0) == CONST_INT)
7048 || !(UNSIGNED_INT3 (INTVAL (op0))))
7049 error ("operand 1 of %s instruction should be an unsigned 3-bit value (DR0-DR7)",
7050 d->name);
7051
7052 mode1 = insn_data[icode].operand[1].mode;
7053
7054 if (icode == CODE_FOR_vdiwr_insn)
7055 target = gen_rtx_REG (SImode,
7056 ARC_FIRST_SIMD_DMA_CONFIG_IN_REG + INTVAL (op0));
7057 else if (icode == CODE_FOR_vdowr_insn)
7058 target = gen_rtx_REG (SImode,
7059 ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG + INTVAL (op0));
7060 else
7061 gcc_unreachable ();
7062
7063 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
7064 op1 = copy_to_mode_reg (mode1, op1);
7065
7066 pat = GEN_FCN (icode) (target, op1);
7067 if (! pat)
7068 return 0;
7069
7070 emit_insn (pat);
7071 return NULL_RTX;
7072
7073 case void_u6:
7074 icode = d->icode;
7075 arg0 = CALL_EXPR_ARG (exp, 0);
7076
7077 fold (arg0);
7078
7079 op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
7080 mode0 = insn_data[icode].operand[0].mode;
7081
7082 /* op0 should be u6. */
7083 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)
7084 || !(UNSIGNED_INT6 (INTVAL (op0))))
7085 error ("operand of %s instruction should be an unsigned 6-bit value",
7086 d->name);
7087
7088 pat = GEN_FCN (icode) (op0);
7089 if (! pat)
7090 return 0;
7091
7092 emit_insn (pat);
7093 return NULL_RTX;
7094
7095 case void_rlimm:
7096 icode = d->icode;
7097 arg0 = CALL_EXPR_ARG (exp, 0);
7098
7099 fold (arg0);
7100
7101 op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
7102 mode0 = insn_data[icode].operand[0].mode;
7103
7104 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
7105 op0 = copy_to_mode_reg (mode0, op0);
7106
7107 pat = GEN_FCN (icode) (op0);
7108 if (! pat)
7109 return 0;
7110
7111 emit_insn (pat);
7112 return NULL_RTX;
7113
7114 case Va_Vb_Ic_u8:
7115 {
7116 rtx src_vreg;
7117 icode = d->icode;
7118 arg0 = CALL_EXPR_ARG (exp, 0); /* source vreg */
7119 arg1 = CALL_EXPR_ARG (exp, 1); /* [I]0-7 */
7120 arg2 = CALL_EXPR_ARG (exp, 2); /* u8 */
7121
7122 src_vreg = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
7123 op0 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL); /* [I]0-7 */
7124 op1 = expand_expr (arg2, NULL_RTX, SImode, EXPAND_NORMAL); /* u8 */
7125 op2 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG); /* VR0 */
7126
7127 /* target <- src vreg */
7128 emit_insn (gen_move_insn (target, src_vreg));
7129
7130 /* target <- vec_concat: target, mem(Ib, u8) */
7131 mode0 = insn_data[icode].operand[3].mode;
7132 mode1 = insn_data[icode].operand[1].mode;
7133
7134 if ( (!(*insn_data[icode].operand[3].predicate) (op0, mode0))
7135 || !(UNSIGNED_INT3 (INTVAL (op0))))
7136 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7137 d->name);
7138
7139 if ( (!(*insn_data[icode].operand[1].predicate) (op1, mode1))
7140 || !(UNSIGNED_INT8 (INTVAL (op1))))
7141 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7142 d->name);
7143
7144 pat = GEN_FCN (icode) (target, op1, op2, op0);
7145 if (! pat)
7146 return 0;
7147
7148 emit_insn (pat);
7149 return target;
7150 }
7151
7152 case void_Va_Ib_u8:
7153 icode = d->icode;
7154 arg0 = CALL_EXPR_ARG (exp, 0); /* src vreg */
7155 arg1 = CALL_EXPR_ARG (exp, 1); /* [I]0-7 */
7156 arg2 = CALL_EXPR_ARG (exp, 2); /* u8 */
7157
7158 op0 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG); /* VR0 */
7159 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL); /* I[0-7] */
7160 op2 = expand_expr (arg2, NULL_RTX, SImode, EXPAND_NORMAL); /* u8 */
7161 op3 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL); /* Vdest */
7162
7163 mode0 = insn_data[icode].operand[0].mode;
7164 mode1 = insn_data[icode].operand[1].mode;
7165 mode2 = insn_data[icode].operand[2].mode;
7166 mode3 = insn_data[icode].operand[3].mode;
7167
7168 if ( (!(*insn_data[icode].operand[1].predicate) (op1, mode1))
7169 || !(UNSIGNED_INT3 (INTVAL (op1))))
7170 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7171 d->name);
7172
7173 if ( (!(*insn_data[icode].operand[2].predicate) (op2, mode2))
7174 || !(UNSIGNED_INT8 (INTVAL (op2))))
7175 error ("operand 3 of %s instruction should be an unsigned 8-bit value",
7176 d->name);
7177
7178 if (!(*insn_data[icode].operand[3].predicate) (op3, mode3))
7179 op3 = copy_to_mode_reg (mode3, op3);
7180
7181 pat = GEN_FCN (icode) (op0, op1, op2, op3);
7182 if (! pat)
7183 return 0;
7184
7185 emit_insn (pat);
7186 return NULL_RTX;
7187
7188 case Va_Ib_u8:
7189 icode = d->icode;
7190 arg0 = CALL_EXPR_ARG (exp, 0); /* dest vreg */
7191 arg1 = CALL_EXPR_ARG (exp, 1); /* [I]0-7 */
7192
7193 op0 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG); /* VR0 */
7194 op1 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL); /* I[0-7] */
7195 op2 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL); /* u8 */
7196
7197 /* target <- src vreg */
7198 target = gen_reg_rtx (V8HImode);
7199
7200 /* target <- vec_concat: target, mem(Ib, u8) */
7201 mode0 = insn_data[icode].operand[1].mode;
7202 mode1 = insn_data[icode].operand[2].mode;
7203 mode2 = insn_data[icode].operand[3].mode;
7204
7205 if ( (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
7206 || !(UNSIGNED_INT3 (INTVAL (op1))))
7207 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7208 d->name);
7209
7210 if ( (!(*insn_data[icode].operand[3].predicate) (op2, mode2))
7211 || !(UNSIGNED_INT8 (INTVAL (op2))))
7212 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7213 d->name);
7214
7215 pat = GEN_FCN (icode) (target, op0, op1, op2);
7216 if (! pat)
7217 return 0;
7218
7219 emit_insn (pat);
7220 return target;
7221
7222 case void_Va_u3_Ib_u8:
7223 icode = d->icode;
7224 arg0 = CALL_EXPR_ARG (exp, 0); /* source vreg */
7225 arg1 = CALL_EXPR_ARG (exp, 1); /* u3 */
7226 arg2 = CALL_EXPR_ARG (exp, 2); /* [I]0-7 */
7227 arg3 = CALL_EXPR_ARG (exp, 3); /* u8 */
7228
7229 op0 = expand_expr (arg3, NULL_RTX, SImode, EXPAND_NORMAL); /* u8 */
7230 op1 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG); /* VR */
7231 op2 = expand_expr (arg2, NULL_RTX, SImode, EXPAND_NORMAL); /* [I]0-7 */
7232 op3 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);/* vreg to be stored */
7233 op4 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL); /* vreg 0-7 subreg no. */
7234
7235 mode0 = insn_data[icode].operand[0].mode;
7236 mode2 = insn_data[icode].operand[2].mode;
7237 mode3 = insn_data[icode].operand[3].mode;
7238 mode4 = insn_data[icode].operand[4].mode;
7239
7240 /* Do some correctness checks for the operands. */
7241 if ( (!(*insn_data[icode].operand[0].predicate) (op0, mode0))
7242 || !(UNSIGNED_INT8 (INTVAL (op0))))
7243 error ("operand 4 of %s instruction should be an unsigned 8-bit value (0-255)",
7244 d->name);
7245
7246 if ( (!(*insn_data[icode].operand[2].predicate) (op2, mode2))
7247 || !(UNSIGNED_INT3 (INTVAL (op2))))
7248 error ("operand 3 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7249 d->name);
7250
7251 if (!(*insn_data[icode].operand[3].predicate) (op3, mode3))
7252 op3 = copy_to_mode_reg (mode3, op3);
7253
7254 if ( (!(*insn_data[icode].operand[4].predicate) (op4, mode4))
7255 || !(UNSIGNED_INT3 (INTVAL (op4))))
7256 error ("operand 2 of %s instruction should be an unsigned 3-bit value (subreg 0-7)",
7257 d->name);
7258 else if (icode == CODE_FOR_vst32_n_insn
7259 && ((INTVAL(op4) % 2 ) != 0))
7260 error ("operand 2 of %s instruction should be an even 3-bit value (subreg 0,2,4,6)",
7261 d->name);
7262
7263 pat = GEN_FCN (icode) (op0, op1, op2, op3, op4);
7264 if (! pat)
7265 return 0;
7266
7267 emit_insn (pat);
7268 return NULL_RTX;
7269
7270 default:
7271 gcc_unreachable ();
7272 }
7273 return NULL_RTX;
7274}
7275
7276static bool
7277arc_preserve_reload_p (rtx in)
7278{
7279 return (GET_CODE (in) == PLUS
7280 && RTX_OK_FOR_BASE_P (XEXP (in, 0), true)
7281 && CONST_INT_P (XEXP (in, 1))
7282 && !((INTVAL (XEXP (in, 1)) & 511)));
7283}
7284
7285int
7286arc_register_move_cost (enum machine_mode,
7287 enum reg_class from_class, enum reg_class to_class)
7288{
7289 /* The ARC600 has no bypass for extension registers, hence a nop might be
7290 needed to be inserted after a write so that reads are safe. */
7291 if (TARGET_ARC600)
7292 {
7293 if (to_class == MPY_WRITABLE_CORE_REGS)
7294 return 3;
7295 /* Instructions modifying LP_COUNT need 4 additional cycles before
7296 the register will actually contain the value. */
7297 else if (to_class == LPCOUNT_REG)
7298 return 6;
7299 else if (to_class == WRITABLE_CORE_REGS)
7300 return 6;
7301 }
7302
7303 /* The ARC700 stalls for 3 cycles when *reading* from lp_count. */
7304 if (TARGET_ARC700
7305 && (from_class == LPCOUNT_REG || from_class == ALL_CORE_REGS
7306 || from_class == WRITABLE_CORE_REGS))
7307 return 8;
7308
7309 /* Force an attempt to 'mov Dy,Dx' to spill. */
7310 if (TARGET_ARC700 && TARGET_DPFP
7311 && from_class == DOUBLE_REGS && to_class == DOUBLE_REGS)
7312 return 100;
7313
7314 return 2;
7315}
7316
7317/* Emit code for an addsi3 instruction with OPERANDS.
7318 COND_P indicates if this will use conditional execution.
7319 Return the length of the instruction.
7320 If OUTPUT_P is false, don't actually output the instruction, just return
7321 its length. */
7322int
7323arc_output_addsi (rtx *operands, bool cond_p, bool output_p)
7324{
7325 char format[32];
7326
7327 int match = operands_match_p (operands[0], operands[1]);
7328 int match2 = operands_match_p (operands[0], operands[2]);
7329 int intval = (REG_P (operands[2]) ? 1
7330 : CONST_INT_P (operands[2]) ? INTVAL (operands[2]) : 0xbadc057);
7331 int neg_intval = -intval;
7332 int short_0 = satisfies_constraint_Rcq (operands[0]);
7333 int short_p = (!cond_p && short_0 && satisfies_constraint_Rcq (operands[1]));
7334 int ret = 0;
7335
7336#define ADDSI_OUTPUT1(FORMAT) do {\
7337 if (output_p) \
7338 output_asm_insn (FORMAT, operands);\
7339 return ret; \
7340} while (0)
7341#define ADDSI_OUTPUT(LIST) do {\
7342 if (output_p) \
7343 sprintf LIST;\
7344 ADDSI_OUTPUT1 (format);\
7345 return ret; \
7346} while (0)
7347
7348 /* First try to emit a 16 bit insn. */
7349 ret = 2;
7350 if (!cond_p
7351 /* If we are actually about to output this insn, don't try a 16 bit
7352 variant if we already decided that we don't want that
7353 (I.e. we upsized this insn to align some following insn.)
7354 E.g. add_s r0,sp,70 is 16 bit, but add r0,sp,70 requires a LIMM -
7355 but add1 r0,sp,35 doesn't. */
7356 && (!output_p || (get_attr_length (current_output_insn) & 2)))
7357 {
7358 if (short_p
7359 && (REG_P (operands[2])
7360 ? (match || satisfies_constraint_Rcq (operands[2]))
7361 : (unsigned) intval <= (match ? 127 : 7)))
7362 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7363 if (short_0 && REG_P (operands[1]) && match2)
7364 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7365 if ((short_0 || REGNO (operands[0]) == STACK_POINTER_REGNUM)
7366 && REGNO (operands[1]) == STACK_POINTER_REGNUM && !(intval & ~124))
7367 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7368
7369 if ((short_p && (unsigned) neg_intval <= (match ? 31 : 7))
7370 || (REGNO (operands[0]) == STACK_POINTER_REGNUM
7371 && match && !(neg_intval & ~124)))
7372 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7373 }
7374
7375 /* Now try to emit a 32 bit insn without long immediate. */
7376 ret = 4;
7377 if (!match && match2 && REG_P (operands[1]))
7378 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7379 if (match || !cond_p)
7380 {
7381 int limit = (match && !cond_p) ? 0x7ff : 0x3f;
7382 int range_factor = neg_intval & intval;
7383 int shift;
7384
7385 if (intval == -1 << 31)
7386 ADDSI_OUTPUT1 ("bxor%? %0,%1,31");
7387
7388 /* If we can use a straight add / sub instead of a {add,sub}[123] of
7389 same size, do, so - the insn latency is lower. */
7390 /* -0x800 is a 12-bit constant for add /add3 / sub / sub3, but
7391 0x800 is not. */
7392 if ((intval >= 0 && intval <= limit)
7393 || (intval == -0x800 && limit == 0x7ff))
7394 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7395 else if ((intval < 0 && neg_intval <= limit)
7396 || (intval == 0x800 && limit == 0x7ff))
7397 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7398 shift = range_factor >= 8 ? 3 : (range_factor >> 1);
7399 gcc_assert (shift == 0 || shift == 1 || shift == 2 || shift == 3);
7400 gcc_assert ((((1 << shift) - 1) & intval) == 0);
7401 if (((intval < 0 && intval != -0x4000)
7402 /* sub[123] is slower than add_s / sub, only use it if it
7403 avoids a long immediate. */
7404 && neg_intval <= limit << shift)
7405 || (intval == 0x4000 && limit == 0x7ff))
7406 ADDSI_OUTPUT ((format, "sub%d%%? %%0,%%1,%d",
7407 shift, neg_intval >> shift));
7408 else if ((intval >= 0 && intval <= limit << shift)
7409 || (intval == -0x4000 && limit == 0x7ff))
7410 ADDSI_OUTPUT ((format, "add%d%%? %%0,%%1,%d", shift, intval >> shift));
7411 }
7412 /* Try to emit a 16 bit opcode with long immediate. */
7413 ret = 6;
7414 if (short_p && match)
7415 ADDSI_OUTPUT1 ("add%? %0,%1,%S2");
7416
7417 /* We have to use a 32 bit opcode, and with a long immediate. */
7418 ret = 8;
7419 ADDSI_OUTPUT1 (intval < 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%S2");
7420}
7421
7422/* Emit code for an commutative_cond_exec instruction with OPERANDS.
7423 Return the length of the instruction.
7424 If OUTPUT_P is false, don't actually output the instruction, just return
7425 its length. */
7426int
7427arc_output_commutative_cond_exec (rtx *operands, bool output_p)
7428{
7429 enum rtx_code commutative_op = GET_CODE (operands[3]);
7430 const char *pat = NULL;
7431
7432 /* Canonical rtl should not have a constant in the first operand position. */
7433 gcc_assert (!CONSTANT_P (operands[1]));
7434
7435 switch (commutative_op)
7436 {
7437 case AND:
7438 if (satisfies_constraint_C1p (operands[2]))
7439 pat = "bmsk%? %0,%1,%Z2";
7440 else if (satisfies_constraint_Ccp (operands[2]))
7441 pat = "bclr%? %0,%1,%M2";
7442 else if (satisfies_constraint_CnL (operands[2]))
7443 pat = "bic%? %0,%1,%n2-1";
7444 break;
7445 case IOR:
7446 if (satisfies_constraint_C0p (operands[2]))
7447 pat = "bset%? %0,%1,%z2";
7448 break;
7449 case XOR:
7450 if (satisfies_constraint_C0p (operands[2]))
7451 pat = "bxor%? %0,%1,%z2";
7452 break;
7453 case PLUS:
7454 return arc_output_addsi (operands, true, output_p);
7455 default: break;
7456 }
7457 if (output_p)
7458 output_asm_insn (pat ? pat : "%O3.%d5 %0,%1,%2", operands);
7459 if (pat || REG_P (operands[2]) || satisfies_constraint_L (operands[2]))
7460 return 4;
7461 return 8;
7462}
7463
7464/* Helper function of arc_expand_movmem. ADDR points to a chunk of memory.
7465 Emit code and return an potentially modified address such that offsets
7466 up to SIZE are can be added to yield a legitimate address.
7467 if REUSE is set, ADDR is a register that may be modified. */
7468
7469static rtx
7470force_offsettable (rtx addr, HOST_WIDE_INT size, bool reuse)
7471{
7472 rtx base = addr;
7473 rtx offs = const0_rtx;
7474
7475 if (GET_CODE (base) == PLUS)
7476 {
7477 offs = XEXP (base, 1);
7478 base = XEXP (base, 0);
7479 }
7480 if (!REG_P (base)
7481 || (REGNO (base) != STACK_POINTER_REGNUM
7482 && REGNO_PTR_FRAME_P (REGNO (addr)))
7483 || !CONST_INT_P (offs) || !SMALL_INT (INTVAL (offs))
7484 || !SMALL_INT (INTVAL (offs) + size))
7485 {
7486 if (reuse)
7487 emit_insn (gen_add2_insn (addr, offs));
7488 else
7489 addr = copy_to_mode_reg (Pmode, addr);
7490 }
7491 return addr;
7492}
7493
7494/* Like move_by_pieces, but take account of load latency,
7495 and actual offset ranges.
7496 Return true on success. */
7497
7498bool
7499arc_expand_movmem (rtx *operands)
7500{
7501 rtx dst = operands[0];
7502 rtx src = operands[1];
7503 rtx dst_addr, src_addr;
7504 HOST_WIDE_INT size;
7505 int align = INTVAL (operands[3]);
7506 unsigned n_pieces;
7507 int piece = align;
7508 rtx store[2];
7509 rtx tmpx[2];
7510 int i;
7511
7512 if (!CONST_INT_P (operands[2]))
7513 return false;
7514 size = INTVAL (operands[2]);
7515 /* move_by_pieces_ninsns is static, so we can't use it. */
7516 if (align >= 4)
7517 n_pieces = (size + 2) / 4U + (size & 1);
7518 else if (align == 2)
7519 n_pieces = (size + 1) / 2U;
7520 else
7521 n_pieces = size;
7522 if (n_pieces >= (unsigned int) (optimize_size ? 3 : 15))
7523 return false;
7524 if (piece > 4)
7525 piece = 4;
7526 dst_addr = force_offsettable (XEXP (operands[0], 0), size, 0);
7527 src_addr = force_offsettable (XEXP (operands[1], 0), size, 0);
7528 store[0] = store[1] = NULL_RTX;
7529 tmpx[0] = tmpx[1] = NULL_RTX;
7530 for (i = 0; size > 0; i ^= 1, size -= piece)
7531 {
7532 rtx tmp;
7533 enum machine_mode mode;
7534
7535 if (piece > size)
7536 piece = size & -size;
7537 mode = smallest_mode_for_size (piece * BITS_PER_UNIT, MODE_INT);
7538 /* If we don't re-use temporaries, the scheduler gets carried away,
7539 and the register pressure gets unnecessarily high. */
7540 if (0 && tmpx[i] && GET_MODE (tmpx[i]) == mode)
7541 tmp = tmpx[i];
7542 else
7543 tmpx[i] = tmp = gen_reg_rtx (mode);
7544 dst_addr = force_offsettable (dst_addr, piece, 1);
7545 src_addr = force_offsettable (src_addr, piece, 1);
7546 if (store[i])
7547 emit_insn (store[i]);
7548 emit_move_insn (tmp, change_address (src, mode, src_addr));
7549 store[i] = gen_move_insn (change_address (dst, mode, dst_addr), tmp);
7550 dst_addr = plus_constant (Pmode, dst_addr, piece);
7551 src_addr = plus_constant (Pmode, src_addr, piece);
7552 }
7553 if (store[i])
7554 emit_insn (store[i]);
7555 if (store[i^1])
7556 emit_insn (store[i^1]);
7557 return true;
7558}
7559
7560/* Prepare operands for move in MODE. Return true iff the move has
7561 been emitted. */
7562
7563bool
7564prepare_move_operands (rtx *operands, enum machine_mode mode)
7565{
7566 /* We used to do this only for MODE_INT Modes, but addresses to floating
7567 point variables may well be in the small data section. */
7568 if (1)
7569 {
7570 if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[0], Pmode))
7571 operands[0] = arc_rewrite_small_data (operands[0]);
7572 else if (mode == SImode && flag_pic && SYMBOLIC_CONST (operands[1]))
7573 {
7574 emit_pic_move (operands, SImode);
7575
7576 /* Disable any REG_EQUALs associated with the symref
7577 otherwise the optimization pass undoes the work done
7578 here and references the variable directly. */
7579 }
7580 else if (GET_CODE (operands[0]) != MEM
7581 && !TARGET_NO_SDATA_SET
7582 && small_data_pattern (operands[1], Pmode))
7583 {
7584 /* This is to take care of address calculations involving sdata
7585 variables. */
7586 operands[1] = arc_rewrite_small_data (operands[1]);
7587
7588 emit_insn (gen_rtx_SET (mode, operands[0],operands[1]));
7589 /* ??? This note is useless, since it only restates the set itself.
7590 We should rather use the original SYMBOL_REF. However, there is
7591 the problem that we are lying to the compiler about these
7592 SYMBOL_REFs to start with. symbol@sda should be encoded specially
7593 so that we can tell it apart from an actual symbol. */
7594 set_unique_reg_note (get_last_insn (), REG_EQUAL, operands[1]);
7595
7596 /* Take care of the REG_EQUAL note that will be attached to mark the
7597 output reg equal to the initial symbol_ref after this code is
7598 executed. */
7599 emit_move_insn (operands[0], operands[0]);
7600 return true;
7601 }
7602 }
7603
7604 if (MEM_P (operands[0])
7605 && !(reload_in_progress || reload_completed))
7606 {
7607 operands[1] = force_reg (mode, operands[1]);
7608 if (!move_dest_operand (operands[0], mode))
7609 {
7610 rtx addr = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
7611 /* This is like change_address_1 (operands[0], mode, 0, 1) ,
7612 except that we can't use that function because it is static. */
7613 rtx pat = change_address (operands[0], mode, addr);
7614 MEM_COPY_ATTRIBUTES (pat, operands[0]);
7615 operands[0] = pat;
7616 }
7617 if (!cse_not_expected)
7618 {
7619 rtx pat = XEXP (operands[0], 0);
7620
7621 pat = arc_legitimize_address_0 (pat, pat, mode);
7622 if (pat)
7623 {
7624 pat = change_address (operands[0], mode, pat);
7625 MEM_COPY_ATTRIBUTES (pat, operands[0]);
7626 operands[0] = pat;
7627 }
7628 }
7629 }
7630
7631 if (MEM_P (operands[1]) && !cse_not_expected)
7632 {
7633 rtx pat = XEXP (operands[1], 0);
7634
7635 pat = arc_legitimize_address_0 (pat, pat, mode);
7636 if (pat)
7637 {
7638 pat = change_address (operands[1], mode, pat);
7639 MEM_COPY_ATTRIBUTES (pat, operands[1]);
7640 operands[1] = pat;
7641 }
7642 }
7643
7644 return false;
7645}
7646
7647/* Prepare OPERANDS for an extension using CODE to OMODE.
7648 Return true iff the move has been emitted. */
7649
7650bool
7651prepare_extend_operands (rtx *operands, enum rtx_code code,
7652 enum machine_mode omode)
7653{
7654 if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[1], Pmode))
7655 {
7656 /* This is to take care of address calculations involving sdata
7657 variables. */
7658 operands[1]
7659 = gen_rtx_fmt_e (code, omode, arc_rewrite_small_data (operands[1]));
7660 emit_insn (gen_rtx_SET (omode, operands[0], operands[1]));
7661 set_unique_reg_note (get_last_insn (), REG_EQUAL, operands[1]);
7662
7663 /* Take care of the REG_EQUAL note that will be attached to mark the
7664 output reg equal to the initial extension after this code is
7665 executed. */
7666 emit_move_insn (operands[0], operands[0]);
7667 return true;
7668 }
7669 return false;
7670}
7671
7672/* Output a library call to a function called FNAME that has been arranged
7673 to be local to any dso. */
7674
7675const char *
7676arc_output_libcall (const char *fname)
7677{
7678 unsigned len = strlen (fname);
7679 static char buf[64];
7680
7681 gcc_assert (len < sizeof buf - 35);
7682 if (TARGET_LONG_CALLS_SET
7683 || (TARGET_MEDIUM_CALLS && arc_ccfsm_cond_exec_p ()))
7684 {
7685 if (flag_pic)
7686 sprintf (buf, "add r12,pcl,@%s-(.&-4)\n\tjl%%!%%* [r12]", fname);
7687 else
7688 sprintf (buf, "jl%%! @%s", fname);
7689 }
7690 else
7691 sprintf (buf, "bl%%!%%* @%s", fname);
7692 return buf;
7693}
7694
7695/* Return the SImode highpart of the DImode value IN. */
7696
7697rtx
7698disi_highpart (rtx in)
7699{
7700 return simplify_gen_subreg (SImode, in, DImode, TARGET_BIG_ENDIAN ? 0 : 4);
7701}
7702
7703/* Called by arc600_corereg_hazard via for_each_rtx.
7704 If a hazard is found, return a conservative estimate of the required
7705 length adjustment to accomodate a nop. */
7706
7707static int
7708arc600_corereg_hazard_1 (rtx *xp, void *data)
7709{
7710 rtx x = *xp;
7711 rtx dest;
7712 rtx pat = (rtx) data;
7713
7714 switch (GET_CODE (x))
7715 {
7716 case SET: case POST_INC: case POST_DEC: case PRE_INC: case PRE_DEC:
7717 break;
7718 default:
7719 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
7720 return 0;
7721 }
7722 dest = XEXP (x, 0);
7723 /* Check if this sets a an extension register. N.B. we use 61 for the
7724 condition codes, which is definitely not an extension register. */
7725 if (REG_P (dest) && REGNO (dest) >= 32 && REGNO (dest) < 61
7726 /* Check if the same register is used by the PAT. */
7727 && (refers_to_regno_p
7728 (REGNO (dest),
7729 REGNO (dest) + (GET_MODE_SIZE (GET_MODE (dest)) + 3) / 4U, pat, 0)))
7730 return 4;
7731
7732 return 0;
7733}
7734
7735/* Return length adjustment for INSN.
7736 For ARC600:
7737 A write to a core reg greater or equal to 32 must not be immediately
7738 followed by a use. Anticipate the length requirement to insert a nop
7739 between PRED and SUCC to prevent a hazard. */
7740
7741static int
7742arc600_corereg_hazard (rtx pred, rtx succ)
7743{
7744 if (!TARGET_ARC600)
7745 return 0;
7746 /* If SUCC is a doloop_end_i with a preceding label, we must output a nop
7747 in front of SUCC anyway, so there will be separation between PRED and
7748 SUCC. */
7749 if (recog_memoized (succ) == CODE_FOR_doloop_end_i
7750 && LABEL_P (prev_nonnote_insn (succ)))
7751 return 0;
7752 if (recog_memoized (succ) == CODE_FOR_doloop_begin_i)
7753 return 0;
7754 if (GET_CODE (PATTERN (pred)) == SEQUENCE)
7755 pred = XVECEXP (PATTERN (pred), 0, 1);
7756 if (GET_CODE (PATTERN (succ)) == SEQUENCE)
7757 succ = XVECEXP (PATTERN (succ), 0, 0);
7758 if (recog_memoized (pred) == CODE_FOR_mulsi_600
7759 || recog_memoized (pred) == CODE_FOR_umul_600
7760 || recog_memoized (pred) == CODE_FOR_mac_600
7761 || recog_memoized (pred) == CODE_FOR_mul64_600
7762 || recog_memoized (pred) == CODE_FOR_mac64_600
7763 || recog_memoized (pred) == CODE_FOR_umul64_600
7764 || recog_memoized (pred) == CODE_FOR_umac64_600)
7765 return 0;
7766 return for_each_rtx (&PATTERN (pred), arc600_corereg_hazard_1,
7767 PATTERN (succ));
7768}
7769
7770/* For ARC600:
7771 A write to a core reg greater or equal to 32 must not be immediately
7772 followed by a use. Anticipate the length requirement to insert a nop
7773 between PRED and SUCC to prevent a hazard. */
7774
7775int
7776arc_hazard (rtx pred, rtx succ)
7777{
7778 if (!TARGET_ARC600)
7779 return 0;
7780 if (!pred || !INSN_P (pred) || !succ || !INSN_P (succ))
7781 return 0;
7782 /* We might have a CALL to a non-returning function before a loop end.
7783 ??? Although the manual says that's OK (the target is outside the loop,
7784 and the loop counter unused there), the assembler barfs on this, so we
7785 must instert a nop before such a call too. */
7786 if (recog_memoized (succ) == CODE_FOR_doloop_end_i
7787 && (JUMP_P (pred) || CALL_P (pred)
7788 || GET_CODE (PATTERN (pred)) == SEQUENCE))
7789 return 4;
7790 return arc600_corereg_hazard (pred, succ);
7791}
7792
7793/* Return length adjustment for INSN. */
7794
7795int
7796arc_adjust_insn_length (rtx insn, int len, bool)
7797{
7798 if (!INSN_P (insn))
7799 return len;
7800 /* We already handle sequences by ignoring the delay sequence flag. */
7801 if (GET_CODE (PATTERN (insn)) == SEQUENCE)
7802 return len;
7803
7804 /* It is impossible to jump to the very end of a Zero-Overhead Loop, as
7805 the ZOL mechanism only triggers when advancing to the end address,
7806 so if there's a label at the end of a ZOL, we need to insert a nop.
7807 The ARC600 ZOL also has extra restrictions on jumps at the end of a
7808 loop. */
7809 if (recog_memoized (insn) == CODE_FOR_doloop_end_i)
7810 {
b3458f61 7811 rtx_insn *prev = prev_nonnote_insn (insn);
526b7aee
SV
7812
7813 return ((LABEL_P (prev)
7814 || (TARGET_ARC600
7815 && (JUMP_P (prev)
7816 || CALL_P (prev) /* Could be a noreturn call. */
7817 || (NONJUMP_INSN_P (prev)
7818 && GET_CODE (PATTERN (prev)) == SEQUENCE))))
7819 ? len + 4 : len);
7820 }
7821
7822 /* Check for return with but one preceding insn since function
7823 start / call. */
7824 if (TARGET_PAD_RETURN
7825 && JUMP_P (insn)
7826 && GET_CODE (PATTERN (insn)) != ADDR_VEC
7827 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
7828 && get_attr_type (insn) == TYPE_RETURN)
7829 {
7830 rtx prev = prev_active_insn (insn);
7831
7832 if (!prev || !(prev = prev_active_insn (prev))
7833 || ((NONJUMP_INSN_P (prev)
7834 && GET_CODE (PATTERN (prev)) == SEQUENCE)
7835 ? CALL_ATTR (XVECEXP (PATTERN (prev), 0, 0), NON_SIBCALL)
7836 : CALL_ATTR (prev, NON_SIBCALL)))
7837 return len + 4;
7838 }
7839 if (TARGET_ARC600)
7840 {
b3458f61 7841 rtx_insn *succ = next_real_insn (insn);
526b7aee
SV
7842
7843 /* One the ARC600, a write to an extension register must be separated
7844 from a read. */
7845 if (succ && INSN_P (succ))
7846 len += arc600_corereg_hazard (insn, succ);
7847 }
7848
7849 /* Restore extracted operands - otherwise splitters like the addsi3_mixed one
7850 can go awry. */
7851 extract_constrain_insn_cached (insn);
7852
7853 return len;
7854}
7855
7856/* Values for length_sensitive. */
7857enum
7858{
7859 ARC_LS_NONE,// Jcc
7860 ARC_LS_25, // 25 bit offset, B
7861 ARC_LS_21, // 21 bit offset, Bcc
7862 ARC_LS_U13,// 13 bit unsigned offset, LP
7863 ARC_LS_10, // 10 bit offset, B_s, Beq_s, Bne_s
7864 ARC_LS_9, // 9 bit offset, BRcc
7865 ARC_LS_8, // 8 bit offset, BRcc_s
7866 ARC_LS_U7, // 7 bit unsigned offset, LPcc
7867 ARC_LS_7 // 7 bit offset, Bcc_s
7868};
7869
7870/* While the infrastructure patch is waiting for review, duplicate the
7871 struct definitions, to allow this file to compile. */
7872#if 1
7873typedef struct
7874{
7875 unsigned align_set;
7876 /* Cost as a branch / call target or call return address. */
7877 int target_cost;
7878 int fallthrough_cost;
7879 int branch_cost;
7880 int length;
7881 /* 0 for not length sensitive, 1 for largest offset range,
7882 * 2 for next smaller etc. */
7883 unsigned length_sensitive : 8;
7884 bool enabled;
7885} insn_length_variant_t;
7886
7887typedef struct insn_length_parameters_s
7888{
7889 int align_unit_log;
7890 int align_base_log;
7891 int max_variants;
7892 int (*get_variants) (rtx, int, bool, bool, insn_length_variant_t *);
7893} insn_length_parameters_t;
7894
7895static void
7896arc_insn_length_parameters (insn_length_parameters_t *ilp) ATTRIBUTE_UNUSED;
7897#endif
7898
7899static int
7900arc_get_insn_variants (rtx insn, int len, bool, bool target_p,
7901 insn_length_variant_t *ilv)
7902{
7903 if (!NONDEBUG_INSN_P (insn))
7904 return 0;
7905 enum attr_type type;
7906 /* shorten_branches doesn't take optimize_size into account yet for the
7907 get_variants mechanism, so turn this off for now. */
7908 if (optimize_size)
7909 return 0;
7910 if (GET_CODE (PATTERN (insn)) == SEQUENCE)
7911 {
7912 /* The interaction of a short delay slot insn with a short branch is
7913 too weird for shorten_branches to piece together, so describe the
7914 entire SEQUENCE. */
7915 rtx pat, inner;
7916 if (TARGET_UPSIZE_DBR
7917 && get_attr_length (XVECEXP ((pat = PATTERN (insn)), 0, 1)) <= 2
7918 && (((type = get_attr_type (inner = XVECEXP (pat, 0, 0)))
7919 == TYPE_UNCOND_BRANCH)
7920 || type == TYPE_BRANCH)
7921 && get_attr_delay_slot_filled (inner) == DELAY_SLOT_FILLED_YES)
7922 {
7923 int n_variants
7924 = arc_get_insn_variants (inner, get_attr_length (inner), true,
7925 target_p, ilv+1);
7926 /* The short variant gets split into a higher-cost aligned
7927 and a lower cost unaligned variant. */
7928 gcc_assert (n_variants);
7929 gcc_assert (ilv[1].length_sensitive == ARC_LS_7
7930 || ilv[1].length_sensitive == ARC_LS_10);
7931 gcc_assert (ilv[1].align_set == 3);
7932 ilv[0] = ilv[1];
7933 ilv[0].align_set = 1;
7934 ilv[0].branch_cost += 1;
7935 ilv[1].align_set = 2;
7936 n_variants++;
7937 for (int i = 0; i < n_variants; i++)
7938 ilv[i].length += 2;
7939 /* In case an instruction with aligned size is wanted, and
7940 the short variants are unavailable / too expensive, add
7941 versions of long branch + long delay slot. */
7942 for (int i = 2, end = n_variants; i < end; i++, n_variants++)
7943 {
7944 ilv[n_variants] = ilv[i];
7945 ilv[n_variants].length += 2;
7946 }
7947 return n_variants;
7948 }
7949 return 0;
7950 }
7951 insn_length_variant_t *first_ilv = ilv;
7952 type = get_attr_type (insn);
7953 bool delay_filled
7954 = (get_attr_delay_slot_filled (insn) == DELAY_SLOT_FILLED_YES);
7955 int branch_align_cost = delay_filled ? 0 : 1;
7956 int branch_unalign_cost = delay_filled ? 0 : TARGET_UNALIGN_BRANCH ? 0 : 1;
7957 /* If the previous instruction is an sfunc call, this insn is always
7958 a target, even though the middle-end is unaware of this. */
7959 bool force_target = false;
b3458f61 7960 rtx_insn *prev = prev_active_insn (insn);
526b7aee
SV
7961 if (prev && arc_next_active_insn (prev, 0) == insn
7962 && ((NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE)
7963 ? CALL_ATTR (XVECEXP (PATTERN (prev), 0, 0), NON_SIBCALL)
7964 : (CALL_ATTR (prev, NON_SIBCALL)
7965 && NEXT_INSN (PREV_INSN (prev)) == prev)))
7966 force_target = true;
7967
7968 switch (type)
7969 {
7970 case TYPE_BRCC:
7971 /* Short BRCC only comes in no-delay-slot version, and without limm */
7972 if (!delay_filled)
7973 {
7974 ilv->align_set = 3;
7975 ilv->length = 2;
7976 ilv->branch_cost = 1;
7977 ilv->enabled = (len == 2);
7978 ilv->length_sensitive = ARC_LS_8;
7979 ilv++;
7980 }
7981 /* Fall through. */
7982 case TYPE_BRCC_NO_DELAY_SLOT:
7983 /* doloop_fallback* patterns are TYPE_BRCC_NO_DELAY_SLOT for
7984 (delay slot) scheduling purposes, but they are longer. */
7985 if (GET_CODE (PATTERN (insn)) == PARALLEL
7986 && GET_CODE (XVECEXP (PATTERN (insn), 0, 1)) == SET)
7987 return 0;
7988 /* Standard BRCC: 4 bytes, or 8 bytes with limm. */
7989 ilv->length = ((type == TYPE_BRCC) ? 4 : 8);
7990 ilv->align_set = 3;
7991 ilv->branch_cost = branch_align_cost;
7992 ilv->enabled = (len <= ilv->length);
7993 ilv->length_sensitive = ARC_LS_9;
7994 if ((target_p || force_target)
7995 || (!delay_filled && TARGET_UNALIGN_BRANCH))
7996 {
7997 ilv[1] = *ilv;
7998 ilv->align_set = 1;
7999 ilv++;
8000 ilv->align_set = 2;
8001 ilv->target_cost = 1;
8002 ilv->branch_cost = branch_unalign_cost;
8003 }
8004 ilv++;
8005
8006 rtx op, op0;
8007 op = XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 0);
8008 op0 = XEXP (op, 0);
8009
8010 if (GET_CODE (op0) == ZERO_EXTRACT
8011 && satisfies_constraint_L (XEXP (op0, 2)))
8012 op0 = XEXP (op0, 0);
8013 if (satisfies_constraint_Rcq (op0))
8014 {
8015 ilv->length = ((type == TYPE_BRCC) ? 6 : 10);
8016 ilv->align_set = 3;
8017 ilv->branch_cost = 1 + branch_align_cost;
8018 ilv->fallthrough_cost = 1;
8019 ilv->enabled = true;
8020 ilv->length_sensitive = ARC_LS_21;
8021 if (!delay_filled && TARGET_UNALIGN_BRANCH)
8022 {
8023 ilv[1] = *ilv;
8024 ilv->align_set = 1;
8025 ilv++;
8026 ilv->align_set = 2;
8027 ilv->branch_cost = 1 + branch_unalign_cost;
8028 }
8029 ilv++;
8030 }
8031 ilv->length = ((type == TYPE_BRCC) ? 8 : 12);
8032 ilv->align_set = 3;
8033 ilv->branch_cost = 1 + branch_align_cost;
8034 ilv->fallthrough_cost = 1;
8035 ilv->enabled = true;
8036 ilv->length_sensitive = ARC_LS_21;
8037 if ((target_p || force_target)
8038 || (!delay_filled && TARGET_UNALIGN_BRANCH))
8039 {
8040 ilv[1] = *ilv;
8041 ilv->align_set = 1;
8042 ilv++;
8043 ilv->align_set = 2;
8044 ilv->target_cost = 1;
8045 ilv->branch_cost = 1 + branch_unalign_cost;
8046 }
8047 ilv++;
8048 break;
8049
8050 case TYPE_SFUNC:
8051 ilv->length = 12;
8052 goto do_call;
8053 case TYPE_CALL_NO_DELAY_SLOT:
8054 ilv->length = 8;
8055 goto do_call;
8056 case TYPE_CALL:
8057 ilv->length = 4;
8058 ilv->length_sensitive
8059 = GET_CODE (PATTERN (insn)) == COND_EXEC ? ARC_LS_21 : ARC_LS_25;
8060 do_call:
8061 ilv->align_set = 3;
8062 ilv->fallthrough_cost = branch_align_cost;
8063 ilv->enabled = true;
8064 if ((target_p || force_target)
8065 || (!delay_filled && TARGET_UNALIGN_BRANCH))
8066 {
8067 ilv[1] = *ilv;
8068 ilv->align_set = 1;
8069 ilv++;
8070 ilv->align_set = 2;
8071 ilv->target_cost = 1;
8072 ilv->fallthrough_cost = branch_unalign_cost;
8073 }
8074 ilv++;
8075 break;
8076 case TYPE_UNCOND_BRANCH:
8077 /* Strictly speaking, this should be ARC_LS_10 for equality comparisons,
8078 but that makes no difference at the moment. */
8079 ilv->length_sensitive = ARC_LS_7;
8080 ilv[1].length_sensitive = ARC_LS_25;
8081 goto do_branch;
8082 case TYPE_BRANCH:
8083 ilv->length_sensitive = ARC_LS_10;
8084 ilv[1].length_sensitive = ARC_LS_21;
8085 do_branch:
8086 ilv->align_set = 3;
8087 ilv->length = 2;
8088 ilv->branch_cost = branch_align_cost;
8089 ilv->enabled = (len == ilv->length);
8090 ilv++;
8091 ilv->length = 4;
8092 ilv->align_set = 3;
8093 ilv->branch_cost = branch_align_cost;
8094 ilv->enabled = true;
8095 if ((target_p || force_target)
8096 || (!delay_filled && TARGET_UNALIGN_BRANCH))
8097 {
8098 ilv[1] = *ilv;
8099 ilv->align_set = 1;
8100 ilv++;
8101 ilv->align_set = 2;
8102 ilv->target_cost = 1;
8103 ilv->branch_cost = branch_unalign_cost;
8104 }
8105 ilv++;
8106 break;
8107 case TYPE_JUMP:
8108 return 0;
8109 default:
8110 /* For every short insn, there is generally also a long insn.
8111 trap_s is an exception. */
8112 if ((len & 2) == 0 || recog_memoized (insn) == CODE_FOR_trap_s)
8113 return 0;
8114 ilv->align_set = 3;
8115 ilv->length = len;
8116 ilv->enabled = 1;
8117 ilv++;
8118 ilv->align_set = 3;
8119 ilv->length = len + 2;
8120 ilv->enabled = 1;
8121 if (target_p || force_target)
8122 {
8123 ilv[1] = *ilv;
8124 ilv->align_set = 1;
8125 ilv++;
8126 ilv->align_set = 2;
8127 ilv->target_cost = 1;
8128 }
8129 ilv++;
8130 }
8131 /* If the previous instruction is an sfunc call, this insn is always
8132 a target, even though the middle-end is unaware of this.
8133 Therefore, if we have a call predecessor, transfer the target cost
8134 to the fallthrough and branch costs. */
8135 if (force_target)
8136 {
8137 for (insn_length_variant_t *p = first_ilv; p < ilv; p++)
8138 {
8139 p->fallthrough_cost += p->target_cost;
8140 p->branch_cost += p->target_cost;
8141 p->target_cost = 0;
8142 }
8143 }
8144
8145 return ilv - first_ilv;
8146}
8147
8148static void
8149arc_insn_length_parameters (insn_length_parameters_t *ilp)
8150{
8151 ilp->align_unit_log = 1;
8152 ilp->align_base_log = 1;
8153 ilp->max_variants = 7;
8154 ilp->get_variants = arc_get_insn_variants;
8155}
8156
8157/* Return a copy of COND from *STATEP, inverted if that is indicated by the
8158 CC field of *STATEP. */
8159
8160static rtx
8161arc_get_ccfsm_cond (struct arc_ccfsm *statep, bool reverse)
8162{
8163 rtx cond = statep->cond;
8164 int raw_cc = get_arc_condition_code (cond);
8165 if (reverse)
8166 raw_cc = ARC_INVERSE_CONDITION_CODE (raw_cc);
8167
8168 if (statep->cc == raw_cc)
8169 return copy_rtx (cond);
8170
8171 gcc_assert (ARC_INVERSE_CONDITION_CODE (raw_cc) == statep->cc);
8172
8173 enum machine_mode ccm = GET_MODE (XEXP (cond, 0));
8174 enum rtx_code code = reverse_condition (GET_CODE (cond));
8175 if (code == UNKNOWN || ccm == CC_FP_GTmode || ccm == CC_FP_GEmode)
8176 code = reverse_condition_maybe_unordered (GET_CODE (cond));
8177
8178 return gen_rtx_fmt_ee (code, GET_MODE (cond),
8179 copy_rtx (XEXP (cond, 0)), copy_rtx (XEXP (cond, 1)));
8180}
8181
bae56bbb
JR
8182/* Return version of PAT conditionalized with COND, which is part of INSN.
8183 ANNULLED indicates if INSN is an annulled delay-slot insn.
8184 Register further changes if necessary. */
8185static rtx
8186conditionalize_nonjump (rtx pat, rtx cond, rtx insn, bool annulled)
8187{
8188 /* For commutative operators, we generally prefer to have
8189 the first source match the destination. */
8190 if (GET_CODE (pat) == SET)
8191 {
8192 rtx src = SET_SRC (pat);
8193
8194 if (COMMUTATIVE_P (src))
8195 {
8196 rtx src0 = XEXP (src, 0);
8197 rtx src1 = XEXP (src, 1);
8198 rtx dst = SET_DEST (pat);
8199
8200 if (rtx_equal_p (src1, dst) && !rtx_equal_p (src0, dst)
8201 /* Leave add_n alone - the canonical form is to
8202 have the complex summand first. */
8203 && REG_P (src0))
8204 pat = gen_rtx_SET (VOIDmode, dst,
8205 gen_rtx_fmt_ee (GET_CODE (src), GET_MODE (src),
8206 src1, src0));
8207 }
8208 }
8209
8210 /* dwarf2out.c:dwarf2out_frame_debug_expr doesn't know
8211 what to do with COND_EXEC. */
8212 if (RTX_FRAME_RELATED_P (insn))
8213 {
8214 /* If this is the delay slot insn of an anulled branch,
8215 dwarf2out.c:scan_trace understands the anulling semantics
8216 without the COND_EXEC. */
8217 gcc_assert (annulled);
8218 rtx note = alloc_reg_note (REG_FRAME_RELATED_EXPR, pat,
8219 REG_NOTES (insn));
8220 validate_change (insn, &REG_NOTES (insn), note, 1);
8221 }
8222 pat = gen_rtx_COND_EXEC (VOIDmode, cond, pat);
8223 return pat;
8224}
8225
526b7aee
SV
8226/* Use the ccfsm machinery to do if conversion. */
8227
8228static unsigned
8229arc_ifcvt (void)
8230{
8231 struct arc_ccfsm *statep = &cfun->machine->ccfsm_current;
8232 basic_block merge_bb = 0;
8233
8234 memset (statep, 0, sizeof *statep);
b3458f61 8235 for (rtx_insn *insn = get_insns (); insn; insn = next_insn (insn))
526b7aee
SV
8236 {
8237 arc_ccfsm_advance (insn, statep);
8238
8239 switch (statep->state)
8240 {
8241 case 0:
8242 if (JUMP_P (insn))
8243 merge_bb = 0;
8244 break;
8245 case 1: case 2:
8246 {
8247 /* Deleted branch. */
8248 gcc_assert (!merge_bb);
8249 merge_bb = BLOCK_FOR_INSN (insn);
8250 basic_block succ_bb
8251 = BLOCK_FOR_INSN (NEXT_INSN (NEXT_INSN (PREV_INSN (insn))));
8252 arc_ccfsm_post_advance (insn, statep);
53ea364f 8253 gcc_assert (!IN_RANGE (statep->state, 1, 2));
b3458f61 8254 rtx_insn *seq = NEXT_INSN (PREV_INSN (insn));
526b7aee
SV
8255 if (seq != insn)
8256 {
8257 rtx slot = XVECEXP (PATTERN (seq), 0, 1);
8258 rtx pat = PATTERN (slot);
8259 if (INSN_ANNULLED_BRANCH_P (insn))
8260 {
8261 rtx cond
8262 = arc_get_ccfsm_cond (statep, INSN_FROM_TARGET_P (slot));
8263 pat = gen_rtx_COND_EXEC (VOIDmode, cond, pat);
8264 }
8265 if (!validate_change (seq, &PATTERN (seq), pat, 0))
8266 gcc_unreachable ();
8267 PUT_CODE (slot, NOTE);
8268 NOTE_KIND (slot) = NOTE_INSN_DELETED;
8269 if (merge_bb && succ_bb)
8270 merge_blocks (merge_bb, succ_bb);
8271 }
8272 else if (merge_bb && succ_bb)
8273 {
8274 set_insn_deleted (insn);
8275 merge_blocks (merge_bb, succ_bb);
8276 }
8277 else
8278 {
8279 PUT_CODE (insn, NOTE);
8280 NOTE_KIND (insn) = NOTE_INSN_DELETED;
8281 }
8282 continue;
8283 }
8284 case 3:
8285 if (LABEL_P (insn)
8286 && statep->target_label == CODE_LABEL_NUMBER (insn))
8287 {
8288 arc_ccfsm_post_advance (insn, statep);
8289 basic_block succ_bb = BLOCK_FOR_INSN (insn);
8290 if (merge_bb && succ_bb)
8291 merge_blocks (merge_bb, succ_bb);
8292 else if (--LABEL_NUSES (insn) == 0)
8293 {
8294 const char *name = LABEL_NAME (insn);
8295 PUT_CODE (insn, NOTE);
8296 NOTE_KIND (insn) = NOTE_INSN_DELETED_LABEL;
8297 NOTE_DELETED_LABEL_NAME (insn) = name;
8298 }
8299 merge_bb = 0;
8300 continue;
8301 }
8302 /* Fall through. */
8303 case 4: case 5:
8304 if (!NONDEBUG_INSN_P (insn))
8305 break;
8306
8307 /* Conditionalized insn. */
8308
b3458f61
DM
8309 rtx_insn *prev, *pprev;
8310 rtx *patp, pat, cond;
bae56bbb 8311 bool annulled; annulled = false;
526b7aee
SV
8312
8313 /* If this is a delay slot insn in a non-annulled branch,
8314 don't conditionalize it. N.B., this should be fine for
8315 conditional return too. However, don't do this for
8316 unconditional branches, as these would be encountered when
8317 processing an 'else' part. */
8318 prev = PREV_INSN (insn);
8319 pprev = PREV_INSN (prev);
8320 if (pprev && NEXT_INSN (NEXT_INSN (pprev)) == NEXT_INSN (insn)
bae56bbb
JR
8321 && JUMP_P (prev) && get_attr_cond (prev) == COND_USE)
8322 {
8323 if (!INSN_ANNULLED_BRANCH_P (prev))
8324 break;
8325 annulled = true;
8326 }
526b7aee
SV
8327
8328 patp = &PATTERN (insn);
8329 pat = *patp;
8330 cond = arc_get_ccfsm_cond (statep, INSN_FROM_TARGET_P (insn));
8331 if (NONJUMP_INSN_P (insn) || CALL_P (insn))
8332 {
8333 /* ??? don't conditionalize if all side effects are dead
8334 in the not-execute case. */
9bf218f9 8335
bae56bbb 8336 pat = conditionalize_nonjump (pat, cond, insn, annulled);
526b7aee
SV
8337 }
8338 else if (simplejump_p (insn))
8339 {
8340 patp = &SET_SRC (pat);
8341 pat = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, *patp, pc_rtx);
8342 }
8343 else if (JUMP_P (insn) && ANY_RETURN_P (PATTERN (insn)))
8344 {
8345 pat = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, pat, pc_rtx);
8346 pat = gen_rtx_SET (VOIDmode, pc_rtx, pat);
8347 }
8348 else
8349 gcc_unreachable ();
8350 validate_change (insn, patp, pat, 1);
8351 if (!apply_change_group ())
8352 gcc_unreachable ();
8353 if (JUMP_P (insn))
8354 {
b3458f61 8355 rtx_insn *next = next_nonnote_insn (insn);
526b7aee
SV
8356 if (GET_CODE (next) == BARRIER)
8357 delete_insn (next);
8358 if (statep->state == 3)
8359 continue;
8360 }
8361 break;
8362 default:
8363 gcc_unreachable ();
8364 }
8365 arc_ccfsm_post_advance (insn, statep);
8366 }
8367 return 0;
8368}
8369
0bc69b81
JR
8370/* Find annulled delay insns and convert them to use the appropriate predicate.
8371 This allows branch shortening to size up these insns properly. */
8372
8373static unsigned
8374arc_predicate_delay_insns (void)
8375{
b3458f61 8376 for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
0bc69b81
JR
8377 {
8378 rtx pat, jump, dlay, src, cond, *patp;
8379 int reverse;
8380
8381 if (!NONJUMP_INSN_P (insn)
8382 || GET_CODE (pat = PATTERN (insn)) != SEQUENCE)
8383 continue;
8384 jump = XVECEXP (pat, 0, 0);
8385 dlay = XVECEXP (pat, 0, 1);
8386 if (!JUMP_P (jump) || !INSN_ANNULLED_BRANCH_P (jump))
8387 continue;
8388 /* If the branch insn does the annulling, leave the delay insn alone. */
8389 if (!TARGET_AT_DBR_CONDEXEC && !INSN_FROM_TARGET_P (dlay))
8390 continue;
8391 /* ??? Could also leave DLAY un-conditionalized if its target is dead
8392 on the other path. */
8393 gcc_assert (GET_CODE (PATTERN (jump)) == SET);
8394 gcc_assert (SET_DEST (PATTERN (jump)) == pc_rtx);
8395 src = SET_SRC (PATTERN (jump));
8396 gcc_assert (GET_CODE (src) == IF_THEN_ELSE);
8397 cond = XEXP (src, 0);
8398 if (XEXP (src, 2) == pc_rtx)
8399 reverse = 0;
8400 else if (XEXP (src, 1) == pc_rtx)
8401 reverse = 1;
8402 else
8403 gcc_unreachable ();
9af539fe 8404 if (reverse != !INSN_FROM_TARGET_P (dlay))
0bc69b81
JR
8405 {
8406 enum machine_mode ccm = GET_MODE (XEXP (cond, 0));
8407 enum rtx_code code = reverse_condition (GET_CODE (cond));
8408 if (code == UNKNOWN || ccm == CC_FP_GTmode || ccm == CC_FP_GEmode)
8409 code = reverse_condition_maybe_unordered (GET_CODE (cond));
8410
8411 cond = gen_rtx_fmt_ee (code, GET_MODE (cond),
8412 copy_rtx (XEXP (cond, 0)),
8413 copy_rtx (XEXP (cond, 1)));
8414 }
8415 else
8416 cond = copy_rtx (cond);
8417 patp = &PATTERN (dlay);
8418 pat = *patp;
eeac7d15 8419 pat = conditionalize_nonjump (pat, cond, dlay, true);
0bc69b81
JR
8420 validate_change (dlay, patp, pat, 1);
8421 if (!apply_change_group ())
8422 gcc_unreachable ();
8423 }
8424 return 0;
8425}
8426
526b7aee
SV
8427/* For ARC600: If a write to a core reg >=32 appears in a delay slot
8428 (other than of a forward brcc), it creates a hazard when there is a read
8429 of the same register at the branch target. We can't know what is at the
8430 branch target of calls, and for branches, we don't really know before the
8431 end of delay slot scheduling, either. Not only can individual instruction
8432 be hoisted out into a delay slot, a basic block can also be emptied this
8433 way, and branch and/or fall through targets be redirected. Hence we don't
8434 want such writes in a delay slot. */
8435/* Called by arc_write_ext_corereg via for_each_rtx. */
8436
8437static int
8438write_ext_corereg_1 (rtx *xp, void *data ATTRIBUTE_UNUSED)
8439{
8440 rtx x = *xp;
8441 rtx dest;
8442
8443 switch (GET_CODE (x))
8444 {
8445 case SET: case POST_INC: case POST_DEC: case PRE_INC: case PRE_DEC:
8446 break;
8447 default:
8448 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
8449 return 0;
8450 }
8451 dest = XEXP (x, 0);
8452 if (REG_P (dest) && REGNO (dest) >= 32 && REGNO (dest) < 61)
8453 return 1;
8454 return 0;
8455}
8456
8457/* Return nonzreo iff INSN writes to an extension core register. */
8458
8459int
8460arc_write_ext_corereg (rtx insn)
8461{
8462 return for_each_rtx (&PATTERN (insn), write_ext_corereg_1, 0);
8463}
8464
8465/* This is like the hook, but returns NULL when it can't / won't generate
8466 a legitimate address. */
8467
8468static rtx
8469arc_legitimize_address_0 (rtx x, rtx oldx ATTRIBUTE_UNUSED,
8470 enum machine_mode mode)
8471{
8472 rtx addr, inner;
8473
8474 if (flag_pic && SYMBOLIC_CONST (x))
8475 (x) = arc_legitimize_pic_address (x, 0);
8476 addr = x;
8477 if (GET_CODE (addr) == CONST)
8478 addr = XEXP (addr, 0);
8479 if (GET_CODE (addr) == PLUS
8480 && CONST_INT_P (XEXP (addr, 1))
8481 && ((GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
8482 && !SYMBOL_REF_FUNCTION_P (XEXP (addr, 0)))
8483 || (REG_P (XEXP (addr, 0))
8484 && (INTVAL (XEXP (addr, 1)) & 252))))
8485 {
8486 HOST_WIDE_INT offs, upper;
8487 int size = GET_MODE_SIZE (mode);
8488
8489 offs = INTVAL (XEXP (addr, 1));
8490 upper = (offs + 256 * size) & ~511 * size;
8491 inner = plus_constant (Pmode, XEXP (addr, 0), upper);
8492#if 0 /* ??? this produces worse code for EEMBC idctrn01 */
8493 if (GET_CODE (x) == CONST)
8494 inner = gen_rtx_CONST (Pmode, inner);
8495#endif
8496 addr = plus_constant (Pmode, force_reg (Pmode, inner), offs - upper);
8497 x = addr;
8498 }
8499 else if (GET_CODE (addr) == SYMBOL_REF && !SYMBOL_REF_FUNCTION_P (addr))
8500 x = force_reg (Pmode, x);
8501 if (memory_address_p ((enum machine_mode) mode, x))
8502 return x;
8503 return NULL_RTX;
8504}
8505
8506static rtx
8507arc_legitimize_address (rtx orig_x, rtx oldx, enum machine_mode mode)
8508{
8509 rtx new_x = arc_legitimize_address_0 (orig_x, oldx, mode);
8510
8511 if (new_x)
8512 return new_x;
8513 return orig_x;
8514}
8515
8516static rtx
8517arc_delegitimize_address_0 (rtx x)
8518{
8519 rtx u, gp;
8520
8521 if (GET_CODE (x) == CONST && GET_CODE (u = XEXP (x, 0)) == UNSPEC)
8522 {
8523 if (XINT (u, 1) == ARC_UNSPEC_GOT)
8524 return XVECEXP (u, 0, 0);
8525 }
8526 else if (GET_CODE (x) == PLUS
8527 && ((REG_P (gp = XEXP (x, 0))
8528 && REGNO (gp) == PIC_OFFSET_TABLE_REGNUM)
8529 || (GET_CODE (gp) == CONST
8530 && GET_CODE (u = XEXP (gp, 0)) == UNSPEC
8531 && XINT (u, 1) == ARC_UNSPEC_GOT
8532 && GET_CODE (XVECEXP (u, 0, 0)) == SYMBOL_REF
8533 && !strcmp (XSTR (XVECEXP (u, 0, 0), 0), "_DYNAMIC")))
8534 && GET_CODE (XEXP (x, 1)) == CONST
8535 && GET_CODE (u = XEXP (XEXP (x, 1), 0)) == UNSPEC
8536 && XINT (u, 1) == ARC_UNSPEC_GOTOFF)
8537 return XVECEXP (u, 0, 0);
8538 else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
8539 && ((REG_P (gp = XEXP (XEXP (x, 0), 1))
8540 && REGNO (gp) == PIC_OFFSET_TABLE_REGNUM)
8541 || (GET_CODE (gp) == CONST
8542 && GET_CODE (u = XEXP (gp, 0)) == UNSPEC
8543 && XINT (u, 1) == ARC_UNSPEC_GOT
8544 && GET_CODE (XVECEXP (u, 0, 0)) == SYMBOL_REF
8545 && !strcmp (XSTR (XVECEXP (u, 0, 0), 0), "_DYNAMIC")))
8546 && GET_CODE (XEXP (x, 1)) == CONST
8547 && GET_CODE (u = XEXP (XEXP (x, 1), 0)) == UNSPEC
8548 && XINT (u, 1) == ARC_UNSPEC_GOTOFF)
8549 return gen_rtx_PLUS (GET_MODE (x), XEXP (XEXP (x, 0), 0),
8550 XVECEXP (u, 0, 0));
8551 else if (GET_CODE (x) == PLUS
8552 && (u = arc_delegitimize_address_0 (XEXP (x, 1))))
8553 return gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0), u);
8554 return NULL_RTX;
8555}
8556
8557static rtx
8558arc_delegitimize_address (rtx x)
8559{
8560 rtx orig_x = x = delegitimize_mem_from_attrs (x);
8561 if (GET_CODE (x) == MEM)
8562 x = XEXP (x, 0);
8563 x = arc_delegitimize_address_0 (x);
8564 if (x)
8565 {
8566 if (MEM_P (orig_x))
8567 x = replace_equiv_address_nv (orig_x, x);
8568 return x;
8569 }
8570 return orig_x;
8571}
8572
8573/* Return a REG rtx for acc1. N.B. the gcc-internal representation may
8574 differ from the hardware register number in order to allow the generic
8575 code to correctly split the concatenation of acc1 and acc2. */
8576
8577rtx
8578gen_acc1 (void)
8579{
8580 return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 56: 57);
8581}
8582
8583/* Return a REG rtx for acc2. N.B. the gcc-internal representation may
8584 differ from the hardware register number in order to allow the generic
8585 code to correctly split the concatenation of acc1 and acc2. */
8586
8587rtx
8588gen_acc2 (void)
8589{
8590 return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 57: 56);
8591}
8592
8593/* Return a REG rtx for mlo. N.B. the gcc-internal representation may
8594 differ from the hardware register number in order to allow the generic
8595 code to correctly split the concatenation of mhi and mlo. */
8596
8597rtx
8598gen_mlo (void)
8599{
8600 return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 59: 58);
8601}
8602
8603/* Return a REG rtx for mhi. N.B. the gcc-internal representation may
8604 differ from the hardware register number in order to allow the generic
8605 code to correctly split the concatenation of mhi and mlo. */
8606
8607rtx
8608gen_mhi (void)
8609{
8610 return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 58: 59);
8611}
8612
8613/* FIXME: a parameter should be added, and code added to final.c,
8614 to reproduce this functionality in shorten_branches. */
8615#if 0
8616/* Return nonzero iff BRANCH should be unaligned if possible by upsizing
8617 a previous instruction. */
8618int
8619arc_unalign_branch_p (rtx branch)
8620{
8621 rtx note;
8622
8623 if (!TARGET_UNALIGN_BRANCH)
8624 return 0;
8625 /* Do not do this if we have a filled delay slot. */
8626 if (get_attr_delay_slot_filled (branch) == DELAY_SLOT_FILLED_YES
8627 && !INSN_DELETED_P (NEXT_INSN (branch)))
8628 return 0;
8629 note = find_reg_note (branch, REG_BR_PROB, 0);
8630 return (!note
8631 || (arc_unalign_prob_threshold && !br_prob_note_reliable_p (note))
8632 || INTVAL (XEXP (note, 0)) < arc_unalign_prob_threshold);
8633}
8634#endif
8635
8636/* When estimating sizes during arc_reorg, when optimizing for speed, there
8637 are three reasons why we need to consider branches to be length 6:
8638 - annull-false delay slot insns are implemented using conditional execution,
8639 thus preventing short insn formation where used.
8640 - for ARC600: annul-true delay slot insns are implemented where possible
8641 using conditional execution, preventing short insn formation where used.
8642 - for ARC700: likely or somewhat likely taken branches are made long and
8643 unaligned if possible to avoid branch penalty. */
8644
8645bool
8646arc_branch_size_unknown_p (void)
8647{
8648 return !optimize_size && arc_reorg_in_progress;
8649}
8650
8651/* We are about to output a return insn. Add padding if necessary to avoid
8652 a mispredict. A return could happen immediately after the function
8653 start, but after a call we know that there will be at least a blink
8654 restore. */
8655
8656void
8657arc_pad_return (void)
8658{
fa7af581 8659 rtx_insn *insn = current_output_insn;
b3458f61 8660 rtx_insn *prev = prev_active_insn (insn);
526b7aee
SV
8661 int want_long;
8662
8663 if (!prev)
8664 {
8665 fputs ("\tnop_s\n", asm_out_file);
8666 cfun->machine->unalign ^= 2;
8667 want_long = 1;
8668 }
8669 /* If PREV is a sequence, we know it must be a branch / jump or a tailcall,
8670 because after a call, we'd have to restore blink first. */
8671 else if (GET_CODE (PATTERN (prev)) == SEQUENCE)
8672 return;
8673 else
8674 {
8675 want_long = (get_attr_length (prev) == 2);
8676 prev = prev_active_insn (prev);
8677 }
8678 if (!prev
8679 || ((NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE)
8680 ? CALL_ATTR (XVECEXP (PATTERN (prev), 0, 0), NON_SIBCALL)
8681 : CALL_ATTR (prev, NON_SIBCALL)))
8682 {
8683 if (want_long)
8684 cfun->machine->size_reason
8685 = "call/return and return/return must be 6 bytes apart to avoid mispredict";
8686 else if (TARGET_UNALIGN_BRANCH && cfun->machine->unalign)
8687 {
8688 cfun->machine->size_reason
8689 = "Long unaligned jump avoids non-delay slot penalty";
8690 want_long = 1;
8691 }
8692 /* Disgorge delay insn, if there is any, and it may be moved. */
8693 if (final_sequence
8694 /* ??? Annulled would be OK if we can and do conditionalize
8695 the delay slot insn accordingly. */
8696 && !INSN_ANNULLED_BRANCH_P (insn)
8697 && (get_attr_cond (insn) != COND_USE
8698 || !reg_set_p (gen_rtx_REG (CCmode, CC_REG),
8699 XVECEXP (final_sequence, 0, 1))))
8700 {
b3458f61 8701 prev = as_a <rtx_insn *> (XVECEXP (final_sequence, 0, 1));
526b7aee
SV
8702 gcc_assert (!prev_real_insn (insn)
8703 || !arc_hazard (prev_real_insn (insn), prev));
8704 cfun->machine->force_short_suffix = !want_long;
8705 rtx save_pred = current_insn_predicate;
8706 final_scan_insn (prev, asm_out_file, optimize, 1, NULL);
8707 cfun->machine->force_short_suffix = -1;
8708 INSN_DELETED_P (prev) = 1;
8709 current_output_insn = insn;
8710 current_insn_predicate = save_pred;
8711 }
8712 else if (want_long)
8713 fputs ("\tnop\n", asm_out_file);
8714 else
8715 {
8716 fputs ("\tnop_s\n", asm_out_file);
8717 cfun->machine->unalign ^= 2;
8718 }
8719 }
8720 return;
8721}
8722
8723/* The usual; we set up our machine_function data. */
8724
8725static struct machine_function *
8726arc_init_machine_status (void)
8727{
8728 struct machine_function *machine;
766090c2 8729 machine = ggc_cleared_alloc<machine_function> ();
526b7aee
SV
8730 machine->fn_type = ARC_FUNCTION_UNKNOWN;
8731 machine->force_short_suffix = -1;
8732
8733 return machine;
8734}
8735
8736/* Implements INIT_EXPANDERS. We just set up to call the above
8737 function. */
8738
8739void
8740arc_init_expanders (void)
8741{
8742 init_machine_status = arc_init_machine_status;
8743}
8744
8745/* Check if OP is a proper parallel of a millicode call pattern. OFFSET
8746 indicates a number of elements to ignore - that allows to have a
8747 sibcall pattern that starts with (return). LOAD_P is zero for store
8748 multiple (for prologues), and one for load multiples (for epilogues),
8749 and two for load multiples where no final clobber of blink is required.
8750 We also skip the first load / store element since this is supposed to
8751 be checked in the instruction pattern. */
8752
8753int
8754arc_check_millicode (rtx op, int offset, int load_p)
8755{
8756 int len = XVECLEN (op, 0) - offset;
8757 int i;
8758
8759 if (load_p == 2)
8760 {
8761 if (len < 2 || len > 13)
8762 return 0;
8763 load_p = 1;
8764 }
8765 else
8766 {
8767 rtx elt = XVECEXP (op, 0, --len);
8768
8769 if (GET_CODE (elt) != CLOBBER
8770 || !REG_P (XEXP (elt, 0))
8771 || REGNO (XEXP (elt, 0)) != RETURN_ADDR_REGNUM
8772 || len < 3 || len > 13)
8773 return 0;
8774 }
8775 for (i = 1; i < len; i++)
8776 {
8777 rtx elt = XVECEXP (op, 0, i + offset);
8778 rtx reg, mem, addr;
8779
8780 if (GET_CODE (elt) != SET)
8781 return 0;
8782 mem = XEXP (elt, load_p);
8783 reg = XEXP (elt, 1-load_p);
8784 if (!REG_P (reg) || REGNO (reg) != 13U+i || !MEM_P (mem))
8785 return 0;
8786 addr = XEXP (mem, 0);
8787 if (GET_CODE (addr) != PLUS
8788 || !rtx_equal_p (stack_pointer_rtx, XEXP (addr, 0))
8789 || !CONST_INT_P (XEXP (addr, 1)) || INTVAL (XEXP (addr, 1)) != i*4)
8790 return 0;
8791 }
8792 return 1;
8793}
8794
8795/* Accessor functions for cfun->machine->unalign. */
8796
8797int
8798arc_get_unalign (void)
8799{
8800 return cfun->machine->unalign;
8801}
8802
8803void
8804arc_clear_unalign (void)
8805{
8806 if (cfun)
8807 cfun->machine->unalign = 0;
8808}
8809
8810void
8811arc_toggle_unalign (void)
8812{
8813 cfun->machine->unalign ^= 2;
8814}
8815
8816/* Operands 0..2 are the operands of a addsi which uses a 12 bit
8817 constant in operand 2, but which would require a LIMM because of
8818 operand mismatch.
8819 operands 3 and 4 are new SET_SRCs for operands 0. */
8820
8821void
8822split_addsi (rtx *operands)
8823{
8824 int val = INTVAL (operands[2]);
8825
8826 /* Try for two short insns first. Lengths being equal, we prefer
8827 expansions with shorter register lifetimes. */
8828 if (val > 127 && val <= 255
8829 && satisfies_constraint_Rcq (operands[0]))
8830 {
8831 operands[3] = operands[2];
8832 operands[4] = gen_rtx_PLUS (SImode, operands[0], operands[1]);
8833 }
8834 else
8835 {
8836 operands[3] = operands[1];
8837 operands[4] = gen_rtx_PLUS (SImode, operands[0], operands[2]);
8838 }
8839}
8840
8841/* Operands 0..2 are the operands of a subsi which uses a 12 bit
8842 constant in operand 1, but which would require a LIMM because of
8843 operand mismatch.
8844 operands 3 and 4 are new SET_SRCs for operands 0. */
8845
8846void
8847split_subsi (rtx *operands)
8848{
8849 int val = INTVAL (operands[1]);
8850
8851 /* Try for two short insns first. Lengths being equal, we prefer
8852 expansions with shorter register lifetimes. */
8853 if (satisfies_constraint_Rcq (operands[0])
8854 && satisfies_constraint_Rcq (operands[2]))
8855 {
8856 if (val >= -31 && val <= 127)
8857 {
8858 operands[3] = gen_rtx_NEG (SImode, operands[2]);
8859 operands[4] = gen_rtx_PLUS (SImode, operands[0], operands[1]);
8860 return;
8861 }
8862 else if (val >= 0 && val < 255)
8863 {
8864 operands[3] = operands[1];
8865 operands[4] = gen_rtx_MINUS (SImode, operands[0], operands[2]);
8866 return;
8867 }
8868 }
8869 /* If the destination is not an ARCompact16 register, we might
8870 still have a chance to make a short insn if the source is;
8871 we need to start with a reg-reg move for this. */
8872 operands[3] = operands[2];
8873 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[0]);
8874}
8875
8876/* Handle DOUBLE_REGS uses.
8877 Operand 0: destination register
8878 Operand 1: source register */
8879
8880static rtx
8881arc_process_double_reg_moves (rtx *operands)
8882{
8883 rtx dest = operands[0];
8884 rtx src = operands[1];
8885 rtx val;
8886
8887 enum usesDxState { none, srcDx, destDx, maxDx };
8888 enum usesDxState state = none;
8889
8890 if (refers_to_regno_p (40, 44, src, 0))
8891 state = srcDx;
8892 if (refers_to_regno_p (40, 44, dest, 0))
8893 {
8894 /* Via arc_register_move_cost, we should never see D,D moves. */
8895 gcc_assert (state == none);
8896 state = destDx;
8897 }
8898
8899 if (state == none)
8900 return NULL_RTX;
8901
8902 start_sequence ();
8903
8904 if (state == srcDx)
8905 {
8906 /* Without the LR insn, we need to split this into a
8907 sequence of insns which will use the DEXCLx and DADDHxy
8908 insns to be able to read the Dx register in question. */
8909 if (TARGET_DPFP_DISABLE_LRSR)
8910 {
8911 /* gen *movdf_insn_nolrsr */
8912 rtx set = gen_rtx_SET (VOIDmode, dest, src);
8913 rtx use1 = gen_rtx_USE (VOIDmode, const1_rtx);
8914 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, use1)));
8915 }
8916 else
8917 {
8918 /* When we have 'mov D, r' or 'mov D, D' then get the target
8919 register pair for use with LR insn. */
8920 rtx destHigh = simplify_gen_subreg(SImode, dest, DFmode, 4);
8921 rtx destLow = simplify_gen_subreg(SImode, dest, DFmode, 0);
8922
8923 /* Produce the two LR insns to get the high and low parts. */
8924 emit_insn (gen_rtx_SET (VOIDmode,
8925 destHigh,
8926 gen_rtx_UNSPEC_VOLATILE (Pmode, gen_rtvec (1, src),
8927 VUNSPEC_LR_HIGH)));
8928 emit_insn (gen_rtx_SET (VOIDmode,
8929 destLow,
8930 gen_rtx_UNSPEC_VOLATILE (Pmode, gen_rtvec (1, src),
8931 VUNSPEC_LR)));
8932 }
8933 }
8934 else if (state == destDx)
8935 {
8936 /* When we have 'mov r, D' or 'mov D, D' and we have access to the
8937 LR insn get the target register pair. */
8938 rtx srcHigh = simplify_gen_subreg(SImode, src, DFmode, 4);
8939 rtx srcLow = simplify_gen_subreg(SImode, src, DFmode, 0);
8940
8941 emit_insn (gen_rtx_UNSPEC_VOLATILE (Pmode,
8942 gen_rtvec (3, dest, srcHigh, srcLow),
8943 VUNSPEC_DEXCL_NORES));
8944
8945 }
8946 else
8947 gcc_unreachable ();
8948
8949 val = get_insns ();
8950 end_sequence ();
8951 return val;
8952}
8953
8954/* operands 0..1 are the operands of a 64 bit move instruction.
8955 split it into two moves with operands 2/3 and 4/5. */
8956
8957rtx
8958arc_split_move (rtx *operands)
8959{
8960 enum machine_mode mode = GET_MODE (operands[0]);
8961 int i;
8962 int swap = 0;
8963 rtx xop[4];
8964 rtx val;
8965
8966 if (TARGET_DPFP)
8967 {
8968 val = arc_process_double_reg_moves (operands);
8969 if (val)
8970 return val;
8971 }
8972
8973 for (i = 0; i < 2; i++)
8974 {
8975 if (MEM_P (operands[i]) && auto_inc_p (XEXP (operands[i], 0)))
8976 {
8977 rtx addr = XEXP (operands[i], 0);
8978 rtx r, o;
8979 enum rtx_code code;
8980
8981 gcc_assert (!reg_overlap_mentioned_p (operands[0], addr));
8982 switch (GET_CODE (addr))
8983 {
8984 case PRE_DEC: o = GEN_INT (-8); goto pre_modify;
8985 case PRE_INC: o = GEN_INT (8); goto pre_modify;
8986 case PRE_MODIFY: o = XEXP (XEXP (addr, 1), 1);
8987 pre_modify:
8988 code = PRE_MODIFY;
8989 break;
8990 case POST_DEC: o = GEN_INT (-8); goto post_modify;
8991 case POST_INC: o = GEN_INT (8); goto post_modify;
8992 case POST_MODIFY: o = XEXP (XEXP (addr, 1), 1);
8993 post_modify:
8994 code = POST_MODIFY;
8995 swap = 2;
8996 break;
8997 default:
8998 gcc_unreachable ();
8999 }
9000 r = XEXP (addr, 0);
9001 xop[0+i] = adjust_automodify_address_nv
9002 (operands[i], SImode,
9003 gen_rtx_fmt_ee (code, Pmode, r,
9004 gen_rtx_PLUS (Pmode, r, o)),
9005 0);
9006 xop[2+i] = adjust_automodify_address_nv
9007 (operands[i], SImode, plus_constant (Pmode, r, 4), 4);
9008 }
9009 else
9010 {
9011 xop[0+i] = operand_subword (operands[i], 0, 0, mode);
9012 xop[2+i] = operand_subword (operands[i], 1, 0, mode);
9013 }
9014 }
9015 if (reg_overlap_mentioned_p (xop[0], xop[3]))
9016 {
9017 swap = 2;
9018 gcc_assert (!reg_overlap_mentioned_p (xop[2], xop[1]));
9019 }
9020 operands[2+swap] = xop[0];
9021 operands[3+swap] = xop[1];
9022 operands[4-swap] = xop[2];
9023 operands[5-swap] = xop[3];
9024
9025 start_sequence ();
9026 emit_insn (gen_rtx_SET (VOIDmode, operands[2], operands[3]));
9027 emit_insn (gen_rtx_SET (VOIDmode, operands[4], operands[5]));
9028 val = get_insns ();
9029 end_sequence ();
9030
9031 return val;
9032}
9033
9034/* Select between the instruction output templates s_tmpl (for short INSNs)
9035 and l_tmpl (for long INSNs). */
9036
9037const char *
b3458f61 9038arc_short_long (rtx_insn *insn, const char *s_tmpl, const char *l_tmpl)
526b7aee
SV
9039{
9040 int is_short = arc_verify_short (insn, cfun->machine->unalign, -1);
9041
9042 extract_constrain_insn_cached (insn);
9043 return is_short ? s_tmpl : l_tmpl;
9044}
9045
9046/* Searches X for any reference to REGNO, returning the rtx of the
9047 reference found if any. Otherwise, returns NULL_RTX. */
9048
9049rtx
9050arc_regno_use_in (unsigned int regno, rtx x)
9051{
9052 const char *fmt;
9053 int i, j;
9054 rtx tem;
9055
9056 if (REG_P (x) && refers_to_regno_p (regno, regno+1, x, (rtx *) 0))
9057 return x;
9058
9059 fmt = GET_RTX_FORMAT (GET_CODE (x));
9060 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
9061 {
9062 if (fmt[i] == 'e')
9063 {
9064 if ((tem = regno_use_in (regno, XEXP (x, i))))
9065 return tem;
9066 }
9067 else if (fmt[i] == 'E')
9068 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
9069 if ((tem = regno_use_in (regno , XVECEXP (x, i, j))))
9070 return tem;
9071 }
9072
9073 return NULL_RTX;
9074}
9075
9076/* Return the integer value of the "type" attribute for INSN, or -1 if
9077 INSN can't have attributes. */
9078
9079int
9080arc_attr_type (rtx insn)
9081{
9082 if (NONJUMP_INSN_P (insn)
9083 ? (GET_CODE (PATTERN (insn)) == USE
9084 || GET_CODE (PATTERN (insn)) == CLOBBER)
9085 : JUMP_P (insn)
9086 ? (GET_CODE (PATTERN (insn)) == ADDR_VEC
9087 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
9088 : !CALL_P (insn))
9089 return -1;
9090 return get_attr_type (insn);
9091}
9092
9093/* Return true if insn sets the condition codes. */
9094
9095bool
9096arc_sets_cc_p (rtx insn)
9097{
9098 if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
9099 insn = XVECEXP (PATTERN (insn), 0, XVECLEN (PATTERN (insn), 0) - 1);
9100 return arc_attr_type (insn) == TYPE_COMPARE;
9101}
9102
9103/* Return true if INSN is an instruction with a delay slot we may want
9104 to fill. */
9105
9106bool
b3458f61 9107arc_need_delay (rtx_insn *insn)
526b7aee 9108{
b3458f61 9109 rtx_insn *next;
526b7aee
SV
9110
9111 if (!flag_delayed_branch)
9112 return false;
9113 /* The return at the end of a function needs a delay slot. */
9114 if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
9115 && (!(next = next_active_insn (insn))
9116 || ((!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) != SEQUENCE)
9117 && arc_attr_type (next) == TYPE_RETURN))
9118 && (!TARGET_PAD_RETURN
9119 || (prev_active_insn (insn)
9120 && prev_active_insn (prev_active_insn (insn))
9121 && prev_active_insn (prev_active_insn (prev_active_insn (insn))))))
9122 return true;
9123 if (NONJUMP_INSN_P (insn)
9124 ? (GET_CODE (PATTERN (insn)) == USE
9125 || GET_CODE (PATTERN (insn)) == CLOBBER
9126 || GET_CODE (PATTERN (insn)) == SEQUENCE)
9127 : JUMP_P (insn)
9128 ? (GET_CODE (PATTERN (insn)) == ADDR_VEC
9129 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
9130 : !CALL_P (insn))
9131 return false;
9132 return num_delay_slots (insn) != 0;
9133}
9134
9135/* Return true if the scheduling pass(es) has/have already run,
9136 i.e. where possible, we should try to mitigate high latencies
9137 by different instruction selection. */
9138
9139bool
9140arc_scheduling_not_expected (void)
9141{
9142 return cfun->machine->arc_reorg_started;
9143}
9144
9145/* Oddly enough, sometimes we get a zero overhead loop that branch
9146 shortening doesn't think is a loop - observed with compile/pr24883.c
9147 -O3 -fomit-frame-pointer -funroll-loops. Make sure to include the
9148 alignment visible for branch shortening (we actually align the loop
9149 insn before it, but that is equivalent since the loop insn is 4 byte
9150 long.) */
9151
9152int
9153arc_label_align (rtx label)
9154{
9155 int loop_align = LOOP_ALIGN (LABEL);
9156
9157 if (loop_align > align_labels_log)
9158 {
b3458f61 9159 rtx_insn *prev = prev_nonnote_insn (label);
526b7aee
SV
9160
9161 if (prev && NONJUMP_INSN_P (prev)
9162 && GET_CODE (PATTERN (prev)) == PARALLEL
9163 && recog_memoized (prev) == CODE_FOR_doloop_begin_i)
9164 return loop_align;
9165 }
9166 /* Code has a minimum p2 alignment of 1, which we must restore after an
9167 ADDR_DIFF_VEC. */
9168 if (align_labels_log < 1)
9169 {
b3458f61 9170 rtx_insn *next = next_nonnote_nondebug_insn (label);
526b7aee
SV
9171 if (INSN_P (next) && recog_memoized (next) >= 0)
9172 return 1;
9173 }
9174 return align_labels_log;
9175}
9176
9177/* Return true if LABEL is in executable code. */
9178
9179bool
b32d5189 9180arc_text_label (rtx_insn *label)
526b7aee 9181{
b3458f61 9182 rtx_insn *next;
526b7aee
SV
9183
9184 /* ??? We use deleted labels like they were still there, see
9185 gcc.c-torture/compile/20000326-2.c . */
9186 gcc_assert (GET_CODE (label) == CODE_LABEL
9187 || (GET_CODE (label) == NOTE
9188 && NOTE_KIND (label) == NOTE_INSN_DELETED_LABEL));
9189 next = next_nonnote_insn (label);
9190 if (next)
9191 return (!JUMP_TABLE_DATA_P (next)
9192 || GET_CODE (PATTERN (next)) != ADDR_VEC);
9193 else if (!PREV_INSN (label))
9194 /* ??? sometimes text labels get inserted very late, see
9195 gcc.dg/torture/stackalign/comp-goto-1.c */
9196 return true;
9197 return false;
9198}
9199
9200/* Return the size of the pretend args for DECL. */
9201
9202int
9203arc_decl_pretend_args (tree decl)
9204{
9205 /* struct function is in DECL_STRUCT_FUNCTION (decl), but no
9206 pretend_args there... See PR38391. */
9207 gcc_assert (decl == current_function_decl);
9208 return crtl->args.pretend_args_size;
9209}
9210
9211/* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
9212 when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
339ba33b 9213 -D_PROFILE_USE; delay branch scheduling then follows a crossing jump
526b7aee
SV
9214 to redirect two breqs. */
9215
9216static bool
9217arc_can_follow_jump (const_rtx follower, const_rtx followee)
9218{
9219 /* ??? get_attr_type is declared to take an rtx. */
9220 union { const_rtx c; rtx r; } u;
9221
9222 u.c = follower;
339ba33b 9223 if (CROSSING_JUMP_P (followee))
526b7aee
SV
9224 switch (get_attr_type (u.r))
9225 {
9226 case TYPE_BRCC:
9227 case TYPE_BRCC_NO_DELAY_SLOT:
9228 return false;
9229 default:
9230 return true;
9231 }
9232 return true;
9233}
9234
9235/* Implement EPILOGUE__USES.
9236 Return true if REGNO should be added to the deemed uses of the epilogue.
9237
9238 We use the return address
9239 arc_return_address_regs[arc_compute_function_type (cfun)] .
9240 But also, we have to make sure all the register restore instructions
9241 are known to be live in interrupt functions. */
9242
9243bool
9244arc_epilogue_uses (int regno)
9245{
9246 if (reload_completed)
9247 {
9248 if (ARC_INTERRUPT_P (cfun->machine->fn_type))
9249 {
9250 if (!fixed_regs[regno])
9251 return true;
9252 return regno == arc_return_address_regs[cfun->machine->fn_type];
9253 }
9254 else
9255 return regno == RETURN_ADDR_REGNUM;
9256 }
9257 else
9258 return regno == arc_return_address_regs[arc_compute_function_type (cfun)];
9259}
9260
9261#ifndef TARGET_NO_LRA
9262#define TARGET_NO_LRA !TARGET_LRA
9263#endif
9264
9265static bool
9266arc_lra_p (void)
9267{
9268 return !TARGET_NO_LRA;
9269}
9270
9271/* ??? Should we define TARGET_REGISTER_PRIORITY? We might perfer to use
9272 Rcq registers, because some insn are shorter with them. OTOH we already
9273 have separate alternatives for this purpose, and other insns don't
9274 mind, so maybe we should rather prefer the other registers?
9275 We need more data, and we can only get that if we allow people to
9276 try all options. */
9277static int
9278arc_register_priority (int r)
9279{
9280 switch (arc_lra_priority_tag)
9281 {
9282 case ARC_LRA_PRIORITY_NONE:
9283 return 0;
9284 case ARC_LRA_PRIORITY_NONCOMPACT:
9285 return ((((r & 7) ^ 4) - 4) & 15) != r;
9286 case ARC_LRA_PRIORITY_COMPACT:
9287 return ((((r & 7) ^ 4) - 4) & 15) == r;
9288 default:
9289 gcc_unreachable ();
9290 }
9291}
9292
9293static reg_class_t
9294arc_spill_class (reg_class_t /* orig_class */, enum machine_mode)
9295{
9296 return GENERAL_REGS;
9297}
9298
9299bool
9300arc_legitimize_reload_address (rtx *p, enum machine_mode mode, int opnum,
9301 int itype)
9302{
9303 rtx x = *p;
9304 enum reload_type type = (enum reload_type) itype;
9305
9306 if (GET_CODE (x) == PLUS
9307 && CONST_INT_P (XEXP (x, 1))
9308 && (RTX_OK_FOR_BASE_P (XEXP (x, 0), true)
9309 || (REG_P (XEXP (x, 0))
9310 && reg_equiv_constant (REGNO (XEXP (x, 0))))))
9311 {
9312 int scale = GET_MODE_SIZE (mode);
9313 int shift;
9314 rtx index_rtx = XEXP (x, 1);
9315 HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base;
9316 rtx reg, sum, sum2;
9317
9318 if (scale > 4)
9319 scale = 4;
9320 if ((scale-1) & offset)
9321 scale = 1;
9322 shift = scale >> 1;
9323 offset_base = (offset + (256 << shift)) & (-512 << shift);
9324 /* Sometimes the normal form does not suit DImode. We
9325 could avoid that by using smaller ranges, but that
9326 would give less optimized code when SImode is
9327 prevalent. */
9328 if (GET_MODE_SIZE (mode) + offset - offset_base <= (256 << shift))
9329 {
9330 int regno;
9331
9332 reg = XEXP (x, 0);
9333 regno = REGNO (reg);
9334 sum2 = sum = plus_constant (Pmode, reg, offset_base);
9335
9336 if (reg_equiv_constant (regno))
9337 {
9338 sum2 = plus_constant (Pmode, reg_equiv_constant (regno),
9339 offset_base);
9340 if (GET_CODE (sum2) == PLUS)
9341 sum2 = gen_rtx_CONST (Pmode, sum2);
9342 }
9343 *p = gen_rtx_PLUS (Pmode, sum, GEN_INT (offset - offset_base));
9344 push_reload (sum2, NULL_RTX, &XEXP (*p, 0), NULL,
9345 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, opnum,
9346 type);
9347 return true;
9348 }
9349 }
9350 /* We must re-recognize what we created before. */
9351 else if (GET_CODE (x) == PLUS
9352 && GET_CODE (XEXP (x, 0)) == PLUS
9353 && CONST_INT_P (XEXP (XEXP (x, 0), 1))
9354 && REG_P (XEXP (XEXP (x, 0), 0))
9355 && CONST_INT_P (XEXP (x, 1)))
9356 {
9357 /* Because this address is so complex, we know it must have
9358 been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,
9359 it is already unshared, and needs no further unsharing. */
9360 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
9361 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, opnum, type);
9362 return true;
9363 }
9364 return false;
9365}
9366
9367struct gcc_target targetm = TARGET_INITIALIZER;
9368
9369#include "gt-arc.h"