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