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