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