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